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