Introduce optimized iomemcpy function for copying from io memory.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 5 Dec 2009 23:51:53 +0000 (18:51 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 5 Dec 2009 23:51:53 +0000 (18:51 -0500)
Reading from IO memory (pci rom or flash) is very slow, so add
   iomemcpy() which will yield during copy.  Use a 4 byte copy to
   optimize accesses.
Also, decompress cbfs data files from a temp memory buffer so that
   ulzma doesn't read from slow IO memory.

src/coreboot.c
src/optionroms.c
src/util.c
src/util.h

index 7e0e361aa6658a8888f903a6f8c71f19cf6752f2..7fa18e4da0698b6806a11997e970de5efc50522e 100644 (file)
@@ -513,9 +513,18 @@ cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen)
 
     u32 size = ntohl(file->len);
     void *src = (void*)file + ntohl(file->offset);
-    if (cbfs_iscomp(file))
-        // Compressed.
-        return ulzma(dst, maxlen, src, size);
+    if (cbfs_iscomp(file)) {
+        // Compressed - copy to temp ram and uncompress it.
+        u32 asize = ALIGN(size, 4);
+        void *temp = malloc_tmphigh(asize);
+        if (!temp)
+            return -1;
+        iomemcpy(temp, src, asize);
+        int ret = ulzma(dst, maxlen, temp, size);
+        yield();
+        free(temp);
+        return ret;
+    }
 
     // Not compressed.
     dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
@@ -523,7 +532,7 @@ cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen)
         dprintf(1, "File too big to copy\n");
         return -1;
     }
-    memcpy(dst, src, size);
+    iomemcpy(dst, src, size);
     return size;
 }
 
index bdc0cb5f1247003eb4f6a0439aaf5e27a2d1c3e3..4dd53cbbb1c9a2317c35668b364b6bce05b7d9fd 100644 (file)
@@ -187,7 +187,7 @@ copy_rom(struct rom_header *rom)
     }
     dprintf(4, "Copying option rom (size %d) from %p to %x\n"
             , romsize, rom, RomEnd);
-    memcpy((void*)RomEnd, rom, romsize);
+    iomemcpy((void*)RomEnd, rom, romsize);
     return (void*)RomEnd;
 }
 
index 36f32e43208265d89322c21036d788fdd629a951..ec2054ca6fc4c416e3c3ca6ade1f08100d748165 100644 (file)
@@ -376,6 +376,26 @@ memcpy(void *d1, const void *s1, size_t len)
     return d1;
 }
 
+// Copy from memory mapped IO.  IO mem is very slow, so yield
+// periodically.  'len' must be 4 byte aligned.
+void
+iomemcpy(void *d, const void *s, u32 len)
+{
+    yield();
+    while (len) {
+        u32 copylen = len;
+        if (copylen > 1024)
+            copylen = 1024;
+        len -= copylen;
+        copylen /= 4;
+        asm volatile(
+            "rep movsl (%%esi),%%es:(%%edi)"
+            : "+c"(copylen), "+S"(s), "+D"(d)
+            : : "cc", "memory");
+        yield();
+    }
+}
+
 void *
 memmove(void *d, const void *s, size_t len)
 {
index c3ecb41079e6b6210e6bb15974f5094516dbe41e..3ab791edaeb3b94d91a03a5b0c1bf3bff9ae5d23 100644 (file)
@@ -164,6 +164,7 @@ void *memcpy(void *d1, const void *s1, size_t len);
 #endif
 inline void memcpy_far(u16 d_seg, void *d_far
                        , u16 s_seg, const void *s_far, size_t len);
+void iomemcpy(void *d, const void *s, u32 len);
 void *memmove(void *d, const void *s, size_t len);
 char *strtcpy(char *dest, const char *src, size_t len);
 struct bregs;