teknoraver icon

test_memcpy

teknoraver | PRO | 06/26/21 06:45:48 PM UTC (Edited) | 0 ⭐ | 2102 👁️ | Never ⏰ | []
C |

1.52 KB

|

None

|

0 👍

/

0 👎

// SPDX-License-Identifier: GPL-2.0-only
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/timekeeping.h>
#include <linux/string.h>
 
#ifdef CONFIG_X86
#include <asm/cacheflush.h>
#endif
 
#define NUM_PAGES   (1 << (MAX_ORDER + 5))
#define PG_SIZE     (PAGE_SIZE * NUM_PAGES)
 
static __init int memcpy_align_selftest(void)
{
    struct page *page1, *page2;
    char *dst, *src;
    ktime_t t0, t1;
    int err = 0;
    int i, j;
 
    page1 = alloc_contig_pages(NUM_PAGES, GFP_KERNEL, NUMA_NO_NODE, 0);
    if (!page1)
        return 1;
 
    page2 = alloc_contig_pages(NUM_PAGES, GFP_KERNEL, NUMA_NO_NODE, 0);
    if (!page2) {
        err = 1;
        goto free1;
    }
 
    printk("Strings selftest: memcpy testing with size: %lu Mb\n", PG_SIZE >> 20);
 
    src = page_to_virt(page1);
    dst = page_to_virt(page2);
 
    preempt_disable();
 
    for (i = 0; i < sizeof(void*); i++) {
#ifdef CONFIG_X86
        for (j = 0; j < PG_SIZE; j += L1_CACHE_BYTES) {
            clflush(src + j);
            clflush(dst + j);
            cond_resched();
        }
#endif
        for (j = 0; j < sizeof(void*); j++) {
            t0 = ktime_get();
            memcpy(dst + i, src + j, PG_SIZE - max(i, j));
            t1 = ktime_get();
            printk("Strings selftest: memcpy(dst+%d, src+%d), distance %lu: %llu Mb/s\n",
                   i, j, (j - i) % sizeof(long),
                   PG_SIZE * (1000000000l / 1048576l) / (t1-t0));
            cond_resched();
        }
        printk("\n");
    }
 
    preempt_enable();
 
    free_contig_range(page_to_pfn(page2), NUM_PAGES);
 
free1:
    free_contig_range(page_to_pfn(page1), NUM_PAGES);
 
    return err;
}
 

Comments