]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/x86/mm/memtest.c
x86: memtest: wipe out test pattern from memory
[linux-2.6-omap-h63xx.git] / arch / x86 / mm / memtest.c
1 #include <linux/kernel.h>
2 #include <linux/errno.h>
3 #include <linux/string.h>
4 #include <linux/types.h>
5 #include <linux/mm.h>
6 #include <linux/smp.h>
7 #include <linux/init.h>
8 #include <linux/pfn.h>
9
10 #include <asm/e820.h>
11
12 static u64 patterns[] __initdata = {
13         0,
14         0xffffffffffffffffULL,
15         0x5555555555555555ULL,
16         0xaaaaaaaaaaaaaaaaULL,
17 };
18
19 static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
20 {
21         printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
22                (unsigned long long) pattern,
23                (unsigned long long) start_bad,
24                (unsigned long long) end_bad);
25         reserve_early(start_bad, end_bad, "BAD RAM");
26 }
27
28 static void __init memtest(u64 pattern, u64 start_phys, u64 size)
29 {
30         u64 i, count;
31         u64 *start;
32         u64 start_bad, last_bad;
33         u64 start_phys_aligned;
34         size_t incr;
35
36         incr = sizeof(pattern);
37         start_phys_aligned = ALIGN(start_phys, incr);
38         count = (size - (start_phys_aligned - start_phys))/incr;
39         start = __va(start_phys_aligned);
40         start_bad = 0;
41         last_bad = 0;
42
43         for (i = 0; i < count; i++)
44                 start[i] = pattern;
45         for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
46                 if (*start == pattern)
47                         continue;
48                 if (start_phys_aligned == last_bad + incr) {
49                         last_bad += incr;
50                         continue;
51                 }
52                 if (start_bad)
53                         reserve_bad_mem(pattern, start_bad, last_bad + incr);
54                 start_bad = last_bad = start_phys_aligned;
55         }
56         if (start_bad)
57                 reserve_bad_mem(pattern, start_bad, last_bad + incr);
58 }
59
60 static void __init do_one_pass(u64 pattern, u64 start, u64 end)
61 {
62         u64 size = 0;
63
64         while (start < end) {
65                 start = find_e820_area_size(start, &size, 1);
66
67                 /* done ? */
68                 if (start >= end)
69                         break;
70                 if (start + size > end)
71                         size = end - start;
72
73                 printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
74                        (unsigned long long) start,
75                        (unsigned long long) start + size,
76                        (unsigned long long) cpu_to_be64(pattern));
77                 memtest(pattern, start, size);
78
79                 start += size;
80         }
81 }
82
83 /* default is disabled */
84 static int memtest_pattern __initdata;
85
86 static int __init parse_memtest(char *arg)
87 {
88         if (arg)
89                 memtest_pattern = simple_strtoul(arg, NULL, 0);
90         return 0;
91 }
92
93 early_param("memtest", parse_memtest);
94
95 void __init early_memtest(unsigned long start, unsigned long end)
96 {
97         unsigned int i;
98         unsigned int idx = 0;
99
100         if (!memtest_pattern)
101                 return;
102
103         printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
104         for (i = 0; i < memtest_pattern; i++) {
105                 idx = i % ARRAY_SIZE(patterns);
106                 do_one_pass(patterns[idx], start, end);
107         }
108
109         if (idx > 0) {
110                 printk(KERN_INFO "early_memtest: wipe out "
111                        "test pattern from memory\n");
112                 /* additional test with pattern 0 will do this */
113                 do_one_pass(0, start, end);
114         }
115 }