]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - arch/x86/mm/memtest.c
x86: memtest: reuse test patterns when memtest parameter exceeds number of available...
[mirror_ubuntu-kernels.git] / arch / x86 / mm / memtest.c
CommitLineData
1f067167
YL
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
40823f73
AH
12#define _MAX_MEM_PATTERNS 4
13
1f067167
YL
14static void __init memtest(unsigned long start_phys, unsigned long size,
15 unsigned pattern)
16{
17 unsigned long i;
18 unsigned long *start;
19 unsigned long start_bad;
20 unsigned long last_bad;
21 unsigned long val;
22 unsigned long start_phys_aligned;
23 unsigned long count;
24 unsigned long incr;
25
40823f73
AH
26 pattern = pattern % _MAX_MEM_PATTERNS;
27
1f067167
YL
28 switch (pattern) {
29 case 0:
30 val = 0UL;
31 break;
32 case 1:
33 val = -1UL;
34 break;
35 case 2:
36#ifdef CONFIG_X86_64
37 val = 0x5555555555555555UL;
38#else
39 val = 0x55555555UL;
40#endif
41 break;
42 case 3:
43#ifdef CONFIG_X86_64
44 val = 0xaaaaaaaaaaaaaaaaUL;
45#else
46 val = 0xaaaaaaaaUL;
47#endif
48 break;
49 default:
50 return;
51 }
52
53 incr = sizeof(unsigned long);
54 start_phys_aligned = ALIGN(start_phys, incr);
55 count = (size - (start_phys_aligned - start_phys))/incr;
56 start = __va(start_phys_aligned);
57 start_bad = 0;
58 last_bad = 0;
59
60 for (i = 0; i < count; i++)
61 start[i] = val;
62 for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
63 if (*start != val) {
64 if (start_phys_aligned == last_bad + incr) {
65 last_bad += incr;
66 } else {
67 if (start_bad) {
2cb0ebee 68 printk(KERN_CONT "\n %016lx bad mem addr %010lx - %010lx reserved",
1f067167 69 val, start_bad, last_bad + incr);
2cb0ebee 70 reserve_early(start_bad, last_bad + incr, "BAD RAM");
1f067167
YL
71 }
72 start_bad = last_bad = start_phys_aligned;
73 }
74 }
75 }
76 if (start_bad) {
77 printk(KERN_CONT "\n %016lx bad mem addr %010lx - %010lx reserved",
78 val, start_bad, last_bad + incr);
2cb0ebee 79 reserve_early(start_bad, last_bad + incr, "BAD RAM");
1f067167 80 }
1f067167
YL
81}
82
83/* default is disabled */
84static int memtest_pattern __initdata;
85
86static int __init parse_memtest(char *arg)
87{
88 if (arg)
89 memtest_pattern = simple_strtoul(arg, NULL, 0);
90 return 0;
91}
92
93early_param("memtest", parse_memtest);
94
95void __init early_memtest(unsigned long start, unsigned long end)
96{
97 u64 t_start, t_size;
98 unsigned pattern;
99
100 if (!memtest_pattern)
101 return;
102
103 printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
104 for (pattern = 0; pattern < memtest_pattern; pattern++) {
105 t_start = start;
106 t_size = 0;
107 while (t_start < end) {
108 t_start = find_e820_area_size(t_start, &t_size, 1);
109
110 /* done ? */
111 if (t_start >= end)
112 break;
113 if (t_start + t_size > end)
114 t_size = end - t_start;
115
116 printk(KERN_CONT "\n %010llx - %010llx pattern %d",
40823f73
AH
117 (unsigned long long)t_start,
118 (unsigned long long)t_start + t_size,
119 pattern % _MAX_MEM_PATTERNS);
1f067167
YL
120
121 memtest(t_start, t_size, pattern);
122
123 t_start += t_size;
124 }
125 }
126 printk(KERN_CONT "\n");
127}