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