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