[coreboot] FILO: read time of LPC flash

Nikolay Petukhov nikolaypetukhov at gmail.com
Thu Mar 13 12:00:12 CET 2008


Hi, all.

Here is simple measure time of reading memory device.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
        int fd_mem;
        volatile char *pchar;
        volatile int *pint;
        char *buffer;
        int *buffer_int;
        struct timeval t1, t2;
        long time_transfer;
        int i;
        int size;

        if (argc != 2) {
                fprintf(stderr, "Usage: %s size Kb\n", argv[0]);
                return 0;
        }

        size = atoi (argv[1]);

        if (!size || size > 2048)
                size = 512;

        size *= 1024;

        if (getuid()) {
                fprintf(stderr, "Run me as root, I need access to /dev/mem.\n");
        }

        fd_mem = open("/dev/mem", O_RDWR);
        if (fd_mem < 0) {
                perror("Could not open /dev/mem:");
                exit(1);
        }

        pchar = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
                         fd_mem, (off_t) (0xFFFFFFFF - size + 1));

        if (pchar == MAP_FAILED) {
                perror("Can't mmap registers using /dev/mem");
                exit(1);
        }

        buffer = (char *)malloc (size);

        gettimeofday(&t1, NULL);
        memcpy (buffer, pchar, size);
        gettimeofday(&t2, NULL);

        time_transfer = (t2.tv_sec - t1.tv_sec)*1000 + (t2.tv_usec -
t1.tv_usec)/1000;
        printf ("memcpy time_transfer %d KB for %ld ms\n", size, time_transfer);

        gettimeofday(&t1, NULL);
        for (i = 0; i < size; i++)
                buffer[i] = pchar[i];
        gettimeofday(&t2, NULL);

        time_transfer = (t2.tv_sec - t1.tv_sec)*1000 + (t2.tv_usec -
t1.tv_usec)/1000;
        printf ("char time_transfer %d KB for %ld ms\n", size, time_transfer);

        pint = (int *)pchar;
        buffer_int = (int *)buffer;

        gettimeofday(&t1, NULL);
        for (i = 0; i < size/4; i++) {

                buffer_int[i] = pint[i];
        }
        gettimeofday(&t2, NULL);

        time_transfer = (t2.tv_sec - t1.tv_sec)*1000 + (t2.tv_usec -
t1.tv_usec)/1000;
        printf ("int time_transfer %d KB for %ld ms\n", size, time_transfer);

        free (buffer);

        close(fd_mem);

        return 0;
}



Result of tests:

1. Board iei/pcisa-lx-800 (AMD LX800 + CS5536), flash sst49lf016c (2048 KB).

./testmem 2048
memcpy time_transfer 2097152 KB for 3478 ms
char time_transfer 2097152 KB for 3592 ms
int time_transfer 2097152 KB for 2086 ms

./testmem 1024
memcpy time_transfer 1048576 KB for 1740 ms
char time_transfer 1048576 KB for 1795 ms
int time_transfer 1048576 KB for 1041 ms

./testmem 512
memcpy time_transfer 524288 KB for 873 ms
char time_transfer 524288 KB for 898 ms
int time_transfer 524288 KB for 521 ms

2. Board iei/pcisa-lx-800(AMD LX800 + CS5536)), flash pm49fl004 (512 KB).

./testmem 512
memcpy time_transfer 524288 KB for 868 ms
char time_transfer 524288 KB for 897 ms
int time_transfer 524288 KB for 524 ms


Conclusion:
For large amounts of speed reading memory flash limited to memcpy () function.
The FILO also use memcpy() for reading memory flash.

This patch add macro READ_OVER_MEMCPY in FILO Config and some code to
blockdev.c. With this patch loading time of kernel and initrd (1.9MB)
redused by 1.5sec.

diff -Nru filo-0.5/defconfig filo-0.5-memcpy/defconfig
--- filo-0.5/defconfig  2008-01-16 19:19:17.000000000 +0500
+++ filo-0.5-memcpy/defconfig   2008-03-13 13:03:14.000000000 +0500
@@ -93,3 +93,6 @@
 #DEBUG_USB = 1
 #DEBUG_ELTORITO = 1

+#Read flash memory
+#READ_OVER_MEMCPY=1
+
diff -Nru filo-0.5/fs/blockdev.c filo-0.5-memcpy/fs/blockdev.c
--- filo-0.5/fs/blockdev.c      2006-04-29 04:53:26.000000000 +0600
+++ filo-0.5-memcpy/fs/blockdev.c       2008-03-13 13:03:08.000000000 +0500
@@ -361,7 +361,21 @@
        len = 512 - byte_offset;
        if (len > byte_len)
            len = byte_len;
-       memcpy(dest, sector_buffer + byte_offset, len);
+
+#ifdef READ_OVER_MEMCPY
+       if (dev_type == DISK_MEM) {
+
+               int * src_int = (int *)(sector_buffer + byte_offset);
+               int * dest_int = (int *)dest;
+               int i;
+
+               for (i = 0; i < len/4; i++)
+                       dest_int[i] = src_int[i];
+       }
+       else
+#endif
+               memcpy(dest, sector_buffer + byte_offset, len);
+
        sector++;
        byte_offset = 0;
        byte_len -= len;

-- 
Nikolay




More information about the coreboot mailing list