diff options
Diffstat (limited to 'arch/x86/mm/pageattr-test.c')
-rw-r--r-- | arch/x86/mm/pageattr-test.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index 4b22eb47f23..c58fab06176 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c @@ -4,36 +4,36 @@ * Clears the global bit on random pages in the direct mapping, then reverts * and compares page tables forwards and afterwards. */ - -#include <linux/mm.h> +#include <linux/bootmem.h> #include <linux/random.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/bootmem.h> +#include <linux/mm.h> + #include <asm/cacheflush.h> #include <asm/pgtable.h> #include <asm/kdebug.h> enum { - NTEST = 400, + NTEST = 400, #ifdef CONFIG_X86_64 - LOWEST_LEVEL = 4, - LPS = (1 << PMD_SHIFT), + LOWEST_LEVEL = 4, + LPS = (1 << PMD_SHIFT), #elif defined(CONFIG_X86_PAE) - LOWEST_LEVEL = 3, - LPS = (1 << PMD_SHIFT), + LOWEST_LEVEL = 3, + LPS = (1 << PMD_SHIFT), #else - LOWEST_LEVEL = 3, /* lookup_address lies here */ - LPS = (1 << 22), + LOWEST_LEVEL = 3, /* lookup_address lies here */ + LPS = (1 << 22), #endif - GPS = (1<<30) + GPS = (1<<30) }; #ifdef CONFIG_X86_64 -#include <asm/proto.h> -#define max_mapped end_pfn_map +# include <asm/proto.h> +# define max_mapped end_pfn_map #else -#define max_mapped max_low_pfn +# define max_mapped max_low_pfn #endif struct split_state { @@ -43,23 +43,24 @@ struct split_state { static __init int print_split(struct split_state *s) { - int printed = 0; long i, expected, missed = 0; + int printed = 0; int err = 0; s->lpg = s->gpg = s->spg = s->exec = 0; s->min_exec = ~0UL; s->max_exec = 0; for (i = 0; i < max_mapped; ) { + unsigned long addr = (unsigned long)__va(i << PAGE_SHIFT); int level; pte_t *pte; - unsigned long adr = (unsigned long)__va(i << PAGE_SHIFT); - pte = lookup_address(adr, &level); + pte = lookup_address(addr, &level); if (!pte) { if (!printed) { - dump_pagetable(adr); - printk("CPA %lx no pte level %d\n", adr, level); + dump_pagetable(addr); + printk(KERN_INFO "CPA %lx no pte level %d\n", + addr, level); printed = 1; } missed++; @@ -72,8 +73,9 @@ static __init int print_split(struct split_state *s) i += GPS/PAGE_SIZE; } else if (level != LOWEST_LEVEL) { if (!(pte_val(*pte) & _PAGE_PSE)) { - printk("%lx level %d but not PSE %Lx\n", - adr, level, (u64)pte_val(*pte)); + printk(KERN_ERR + "%lx level %d but not PSE %Lx\n", + addr, level, (u64)pte_val(*pte)); err = 1; } s->lpg++; @@ -84,18 +86,20 @@ static __init int print_split(struct split_state *s) } if (!(pte_val(*pte) & _PAGE_NX)) { s->exec++; - if (adr < s->min_exec) - s->min_exec = adr; - if (adr > s->max_exec) - s->max_exec = adr; + if (addr < s->min_exec) + s->min_exec = addr; + if (addr > s->max_exec) + s->max_exec = addr; } } - printk("CPA mapping 4k %lu large %lu gb %lu x %lu[%lx-%lx] miss %lu\n", + printk(KERN_INFO + "CPA mapping 4k %lu large %lu gb %lu x %lu[%lx-%lx] miss %lu\n", s->spg, s->lpg, s->gpg, s->exec, s->min_exec != ~0UL ? s->min_exec : 0, s->max_exec, missed); + expected = (s->gpg*GPS + s->lpg*LPS)/PAGE_SIZE + s->spg + missed; if (expected != i) { - printk("CPA max_mapped %lu but expected %lu\n", + printk(KERN_ERR "CPA max_mapped %lu but expected %lu\n", max_mapped, expected); return 1; } @@ -105,56 +109,62 @@ static __init int print_split(struct split_state *s) static __init int state_same(struct split_state *a, struct split_state *b) { return a->lpg == b->lpg && a->gpg == b->gpg && a->spg == b->spg && - a->exec == b->exec; + a->exec == b->exec; } -static unsigned long addr[NTEST] __initdata; -static unsigned len[NTEST] __initdata; +static unsigned long __initdata addr[NTEST]; +static unsigned int __initdata len[NTEST]; /* Change the global bit on random pages in the direct mapping */ static __init int exercise_pageattr(void) { - int i, k; + struct split_state sa, sb, sc; + unsigned long *bm; pte_t *pte, pte0; + int failed = 0; int level; + int i, k; int err; - struct split_state sa, sb, sc; - int failed = 0; - unsigned long *bm; - printk("CPA exercising pageattr\n"); + printk(KERN_INFO "CPA exercising pageattr\n"); bm = vmalloc((max_mapped + 7) / 8); if (!bm) { - printk("CPA Cannot vmalloc bitmap\n"); + printk(KERN_ERR "CPA Cannot vmalloc bitmap\n"); return -ENOMEM; } memset(bm, 0, (max_mapped + 7) / 8); failed += print_split(&sa); srandom32(100); + for (i = 0; i < NTEST; i++) { unsigned long pfn = random32() % max_mapped; + addr[i] = (unsigned long)__va(pfn << PAGE_SHIFT); len[i] = random32() % 100; len[i] = min_t(unsigned long, len[i], max_mapped - pfn - 1); + if (len[i] == 0) len[i] = 1; pte = NULL; pte0 = pfn_pte(0, __pgprot(0)); /* shut gcc up */ + for (k = 0; k < len[i]; k++) { pte = lookup_address(addr[i] + k*PAGE_SIZE, &level); if (!pte || pgprot_val(pte_pgprot(*pte)) == 0) { addr[i] = 0; break; } - if (k == 0) + if (k == 0) { pte0 = *pte; - else if (pgprot_val(pte_pgprot(*pte)) != + } else { + if (pgprot_val(pte_pgprot(*pte)) != pgprot_val(pte_pgprot(pte0))) { - len[i] = k; - break; + len[i] = k; + break; + } } if (test_bit(pfn + k, bm)) { len[i] = k; @@ -170,19 +180,19 @@ static __init int exercise_pageattr(void) err = change_page_attr(virt_to_page(addr[i]), len[i], pte_pgprot(pte_clrhuge(pte_clrglobal(pte0)))); if (err < 0) { - printk("CPA %d failed %d\n", i, err); + printk(KERN_ERR "CPA %d failed %d\n", i, err); failed++; } pte = lookup_address(addr[i], &level); if (!pte || pte_global(*pte) || pte_huge(*pte)) { - printk("CPA %lx: bad pte %Lx\n", addr[i], + printk(KERN_ERR "CPA %lx: bad pte %Lx\n", addr[i], pte ? (u64)pte_val(*pte) : 0ULL); failed++; } if (level != LOWEST_LEVEL) { - printk("CPA %lx: unexpected level %d\n", addr[i], - level); + printk(KERN_ERR "CPA %lx: unexpected level %d\n", + addr[i], level); failed++; } @@ -192,26 +202,26 @@ static __init int exercise_pageattr(void) failed += print_split(&sb); - printk("CPA reverting everything\n"); + printk(KERN_INFO "CPA reverting everything\n"); for (i = 0; i < NTEST; i++) { if (!addr[i]) continue; pte = lookup_address(addr[i], &level); if (!pte) { - printk("CPA lookup of %lx failed\n", addr[i]); + printk(KERN_ERR "CPA lookup of %lx failed\n", addr[i]); failed++; continue; } err = change_page_attr(virt_to_page(addr[i]), len[i], pte_pgprot(pte_mkglobal(*pte))); if (err < 0) { - printk("CPA reverting failed: %d\n", err); + printk(KERN_ERR "CPA reverting failed: %d\n", err); failed++; } pte = lookup_address(addr[i], &level); if (!pte || !pte_global(*pte)) { - printk("CPA %lx: bad pte after revert %Lx\n", addr[i], - pte ? (u64)pte_val(*pte) : 0ULL); + printk(KERN_ERR "CPA %lx: bad pte after revert %Lx\n", + addr[i], pte ? (u64)pte_val(*pte) : 0ULL); failed++; } @@ -223,11 +233,10 @@ static __init int exercise_pageattr(void) failed++; if (failed) - printk("CPA selftests NOT PASSED. Please report.\n"); + printk(KERN_ERR "CPA selftests NOT PASSED. Please report.\n"); else - printk("CPA selftests PASSED\n"); + printk(KERN_INFO "CPA selftests PASSED\n"); return 0; } - module_init(exercise_pageattr); |