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