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