]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - mm/memtest.c
mm: move memtest under mm
[mirror_ubuntu-jammy-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
570c9e69 32static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 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
570c9e69 41static void __init memtest(u64 pattern, u64 start_phys, u64 size)
1f067167 42{
9866b7e8 43 u64 *p, *start, *end;
570c9e69
AH
44 u64 start_bad, last_bad;
45 u64 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
bfb4dc0d
AH
72static void __init do_one_pass(u64 pattern, u64 start, u64 end)
73{
8d89ac80
TH
74 u64 i;
75 phys_addr_t this_start, this_end;
76
9a28f9dc 77 for_each_free_mem_range(i, NUMA_NO_NODE, &this_start, &this_end, NULL) {
8d89ac80
TH
78 this_start = clamp_t(phys_addr_t, this_start, start, end);
79 this_end = clamp_t(phys_addr_t, this_end, start, end);
80 if (this_start < this_end) {
81 printk(KERN_INFO " %010llx - %010llx pattern %016llx\n",
82 (unsigned long long)this_start,
83 (unsigned long long)this_end,
84 (unsigned long long)cpu_to_be64(pattern));
85 memtest(pattern, this_start, this_end - this_start);
86 }
bfb4dc0d
AH
87 }
88}
89
1f067167
YL
90/* default is disabled */
91static int memtest_pattern __initdata;
92
93static int __init parse_memtest(char *arg)
94{
95 if (arg)
96 memtest_pattern = simple_strtoul(arg, NULL, 0);
d1a8e779
YL
97 else
98 memtest_pattern = ARRAY_SIZE(patterns);
99
1f067167
YL
100 return 0;
101}
102
103early_param("memtest", parse_memtest);
104
105void __init early_memtest(unsigned long start, unsigned long end)
106{
6d74171b 107 unsigned int i;
bfb4dc0d 108 unsigned int idx = 0;
1f067167
YL
109
110 if (!memtest_pattern)
111 return;
112
570c9e69 113 printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
20bf062c 114 for (i = memtest_pattern-1; i < UINT_MAX; --i) {
bfb4dc0d
AH
115 idx = i % ARRAY_SIZE(patterns);
116 do_one_pass(patterns[idx], start, end);
117 }
1f067167 118}