]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - mm/memtest.c
memtest: use kstrtouint instead of simple_strtoul
[mirror_ubuntu-zesty-kernel.git] / 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>
a9ce6bc1 9#include <linux/memblock.h>
1f067167 10
6d74171b 11static u64 patterns[] __initdata = {
20bf062c 12 /* The first entry has to be 0 to leave memtest with zeroed memory */
6d74171b
AH
13 0,
14 0xffffffffffffffffULL,
15 0x5555555555555555ULL,
16 0xaaaaaaaaaaaaaaaaULL,
63823126
AH
17 0x1111111111111111ULL,
18 0x2222222222222222ULL,
19 0x4444444444444444ULL,
20 0x8888888888888888ULL,
21 0x3333333333333333ULL,
22 0x6666666666666666ULL,
23 0x9999999999999999ULL,
24 0xccccccccccccccccULL,
25 0x7777777777777777ULL,
26 0xbbbbbbbbbbbbbbbbULL,
27 0xddddddddddddddddULL,
28 0xeeeeeeeeeeeeeeeeULL,
29 0x7a6c7258554e494cULL, /* yeah ;-) */
6d74171b 30};
40823f73 31
7f70baee 32static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
7dad169e 33{
570c9e69
AH
34 printk(KERN_INFO " %016llx bad mem addr %010llx - %010llx reserved\n",
35 (unsigned long long) pattern,
36 (unsigned long long) start_bad,
37 (unsigned long long) end_bad);
24aa0788 38 memblock_reserve(start_bad, end_bad - start_bad);
7dad169e
AH
39}
40
7f70baee 41static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size)
1f067167 42{
9866b7e8 43 u64 *p, *start, *end;
7f70baee
VM
44 phys_addr_t start_bad, last_bad;
45 phys_addr_t start_phys_aligned;
9866b7e8 46 const size_t incr = sizeof(pattern);
1f067167 47
1f067167 48 start_phys_aligned = ALIGN(start_phys, incr);
1f067167 49 start = __va(start_phys_aligned);
9866b7e8 50 end = start + (size - (start_phys_aligned - start_phys)) / incr;
1f067167
YL
51 start_bad = 0;
52 last_bad = 0;
53
c9690998
AH
54 for (p = start; p < end; p++)
55 *p = pattern;
9866b7e8 56
c9690998
AH
57 for (p = start; p < end; p++, start_phys_aligned += incr) {
58 if (*p == pattern)
7dad169e
AH
59 continue;
60 if (start_phys_aligned == last_bad + incr) {
61 last_bad += incr;
62 continue;
1f067167 63 }
7dad169e
AH
64 if (start_bad)
65 reserve_bad_mem(pattern, start_bad, last_bad + incr);
66 start_bad = last_bad = start_phys_aligned;
1f067167 67 }
7dad169e
AH
68 if (start_bad)
69 reserve_bad_mem(pattern, start_bad, last_bad + incr);
1f067167
YL
70}
71
7f70baee 72static void __init do_one_pass(u64 pattern, phys_addr_t start, phys_addr_t end)
bfb4dc0d 73{
8d89ac80
TH
74 u64 i;
75 phys_addr_t this_start, this_end;
76
fc6daaf9
TL
77 for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &this_start,
78 &this_end, NULL) {
7f70baee
VM
79 this_start = clamp(this_start, start, end);
80 this_end = clamp(this_end, start, end);
8d89ac80
TH
81 if (this_start < this_end) {
82 printk(KERN_INFO " %010llx - %010llx pattern %016llx\n",
83 (unsigned long long)this_start,
84 (unsigned long long)this_end,
85 (unsigned long long)cpu_to_be64(pattern));
86 memtest(pattern, this_start, this_end - this_start);
87 }
bfb4dc0d
AH
88 }
89}
90
1f067167 91/* default is disabled */
06f80596 92static unsigned int memtest_pattern __initdata;
1f067167
YL
93
94static int __init parse_memtest(char *arg)
95{
06f80596
VM
96 int ret = 0;
97
1f067167 98 if (arg)
06f80596 99 ret = kstrtouint(arg, 0, &memtest_pattern);
d1a8e779
YL
100 else
101 memtest_pattern = ARRAY_SIZE(patterns);
102
06f80596 103 return ret;
1f067167
YL
104}
105
106early_param("memtest", parse_memtest);
107
7f70baee 108void __init early_memtest(phys_addr_t start, phys_addr_t end)
1f067167 109{
6d74171b 110 unsigned int i;
bfb4dc0d 111 unsigned int idx = 0;
1f067167
YL
112
113 if (!memtest_pattern)
114 return;
115
570c9e69 116 printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
20bf062c 117 for (i = memtest_pattern-1; i < UINT_MAX; --i) {
bfb4dc0d
AH
118 idx = i % ARRAY_SIZE(patterns);
119 do_one_pass(patterns[idx], start, end);
120 }
1f067167 121}