xref: /linux-6.15/kernel/crash_core.c (revision 692f66f2)
1*692f66f2SHari Bathini /*
2*692f66f2SHari Bathini  * crash.c - kernel crash support code.
3*692f66f2SHari Bathini  * Copyright (C) 2002-2004 Eric Biederman  <[email protected]>
4*692f66f2SHari Bathini  *
5*692f66f2SHari Bathini  * This source code is licensed under the GNU General Public License,
6*692f66f2SHari Bathini  * Version 2.  See the file COPYING for more details.
7*692f66f2SHari Bathini  */
8*692f66f2SHari Bathini 
9*692f66f2SHari Bathini #include <linux/crash_core.h>
10*692f66f2SHari Bathini #include <linux/utsname.h>
11*692f66f2SHari Bathini #include <linux/vmalloc.h>
12*692f66f2SHari Bathini 
13*692f66f2SHari Bathini #include <asm/page.h>
14*692f66f2SHari Bathini #include <asm/sections.h>
15*692f66f2SHari Bathini 
16*692f66f2SHari Bathini /* vmcoreinfo stuff */
17*692f66f2SHari Bathini static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
18*692f66f2SHari Bathini u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
19*692f66f2SHari Bathini size_t vmcoreinfo_size;
20*692f66f2SHari Bathini size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
21*692f66f2SHari Bathini 
22*692f66f2SHari Bathini /*
23*692f66f2SHari Bathini  * parsing the "crashkernel" commandline
24*692f66f2SHari Bathini  *
25*692f66f2SHari Bathini  * this code is intended to be called from architecture specific code
26*692f66f2SHari Bathini  */
27*692f66f2SHari Bathini 
28*692f66f2SHari Bathini 
29*692f66f2SHari Bathini /*
30*692f66f2SHari Bathini  * This function parses command lines in the format
31*692f66f2SHari Bathini  *
32*692f66f2SHari Bathini  *   crashkernel=ramsize-range:size[,...][@offset]
33*692f66f2SHari Bathini  *
34*692f66f2SHari Bathini  * The function returns 0 on success and -EINVAL on failure.
35*692f66f2SHari Bathini  */
36*692f66f2SHari Bathini static int __init parse_crashkernel_mem(char *cmdline,
37*692f66f2SHari Bathini 					unsigned long long system_ram,
38*692f66f2SHari Bathini 					unsigned long long *crash_size,
39*692f66f2SHari Bathini 					unsigned long long *crash_base)
40*692f66f2SHari Bathini {
41*692f66f2SHari Bathini 	char *cur = cmdline, *tmp;
42*692f66f2SHari Bathini 
43*692f66f2SHari Bathini 	/* for each entry of the comma-separated list */
44*692f66f2SHari Bathini 	do {
45*692f66f2SHari Bathini 		unsigned long long start, end = ULLONG_MAX, size;
46*692f66f2SHari Bathini 
47*692f66f2SHari Bathini 		/* get the start of the range */
48*692f66f2SHari Bathini 		start = memparse(cur, &tmp);
49*692f66f2SHari Bathini 		if (cur == tmp) {
50*692f66f2SHari Bathini 			pr_warn("crashkernel: Memory value expected\n");
51*692f66f2SHari Bathini 			return -EINVAL;
52*692f66f2SHari Bathini 		}
53*692f66f2SHari Bathini 		cur = tmp;
54*692f66f2SHari Bathini 		if (*cur != '-') {
55*692f66f2SHari Bathini 			pr_warn("crashkernel: '-' expected\n");
56*692f66f2SHari Bathini 			return -EINVAL;
57*692f66f2SHari Bathini 		}
58*692f66f2SHari Bathini 		cur++;
59*692f66f2SHari Bathini 
60*692f66f2SHari Bathini 		/* if no ':' is here, than we read the end */
61*692f66f2SHari Bathini 		if (*cur != ':') {
62*692f66f2SHari Bathini 			end = memparse(cur, &tmp);
63*692f66f2SHari Bathini 			if (cur == tmp) {
64*692f66f2SHari Bathini 				pr_warn("crashkernel: Memory value expected\n");
65*692f66f2SHari Bathini 				return -EINVAL;
66*692f66f2SHari Bathini 			}
67*692f66f2SHari Bathini 			cur = tmp;
68*692f66f2SHari Bathini 			if (end <= start) {
69*692f66f2SHari Bathini 				pr_warn("crashkernel: end <= start\n");
70*692f66f2SHari Bathini 				return -EINVAL;
71*692f66f2SHari Bathini 			}
72*692f66f2SHari Bathini 		}
73*692f66f2SHari Bathini 
74*692f66f2SHari Bathini 		if (*cur != ':') {
75*692f66f2SHari Bathini 			pr_warn("crashkernel: ':' expected\n");
76*692f66f2SHari Bathini 			return -EINVAL;
77*692f66f2SHari Bathini 		}
78*692f66f2SHari Bathini 		cur++;
79*692f66f2SHari Bathini 
80*692f66f2SHari Bathini 		size = memparse(cur, &tmp);
81*692f66f2SHari Bathini 		if (cur == tmp) {
82*692f66f2SHari Bathini 			pr_warn("Memory value expected\n");
83*692f66f2SHari Bathini 			return -EINVAL;
84*692f66f2SHari Bathini 		}
85*692f66f2SHari Bathini 		cur = tmp;
86*692f66f2SHari Bathini 		if (size >= system_ram) {
87*692f66f2SHari Bathini 			pr_warn("crashkernel: invalid size\n");
88*692f66f2SHari Bathini 			return -EINVAL;
89*692f66f2SHari Bathini 		}
90*692f66f2SHari Bathini 
91*692f66f2SHari Bathini 		/* match ? */
92*692f66f2SHari Bathini 		if (system_ram >= start && system_ram < end) {
93*692f66f2SHari Bathini 			*crash_size = size;
94*692f66f2SHari Bathini 			break;
95*692f66f2SHari Bathini 		}
96*692f66f2SHari Bathini 	} while (*cur++ == ',');
97*692f66f2SHari Bathini 
98*692f66f2SHari Bathini 	if (*crash_size > 0) {
99*692f66f2SHari Bathini 		while (*cur && *cur != ' ' && *cur != '@')
100*692f66f2SHari Bathini 			cur++;
101*692f66f2SHari Bathini 		if (*cur == '@') {
102*692f66f2SHari Bathini 			cur++;
103*692f66f2SHari Bathini 			*crash_base = memparse(cur, &tmp);
104*692f66f2SHari Bathini 			if (cur == tmp) {
105*692f66f2SHari Bathini 				pr_warn("Memory value expected after '@'\n");
106*692f66f2SHari Bathini 				return -EINVAL;
107*692f66f2SHari Bathini 			}
108*692f66f2SHari Bathini 		}
109*692f66f2SHari Bathini 	}
110*692f66f2SHari Bathini 
111*692f66f2SHari Bathini 	return 0;
112*692f66f2SHari Bathini }
113*692f66f2SHari Bathini 
114*692f66f2SHari Bathini /*
115*692f66f2SHari Bathini  * That function parses "simple" (old) crashkernel command lines like
116*692f66f2SHari Bathini  *
117*692f66f2SHari Bathini  *	crashkernel=size[@offset]
118*692f66f2SHari Bathini  *
119*692f66f2SHari Bathini  * It returns 0 on success and -EINVAL on failure.
120*692f66f2SHari Bathini  */
121*692f66f2SHari Bathini static int __init parse_crashkernel_simple(char *cmdline,
122*692f66f2SHari Bathini 					   unsigned long long *crash_size,
123*692f66f2SHari Bathini 					   unsigned long long *crash_base)
124*692f66f2SHari Bathini {
125*692f66f2SHari Bathini 	char *cur = cmdline;
126*692f66f2SHari Bathini 
127*692f66f2SHari Bathini 	*crash_size = memparse(cmdline, &cur);
128*692f66f2SHari Bathini 	if (cmdline == cur) {
129*692f66f2SHari Bathini 		pr_warn("crashkernel: memory value expected\n");
130*692f66f2SHari Bathini 		return -EINVAL;
131*692f66f2SHari Bathini 	}
132*692f66f2SHari Bathini 
133*692f66f2SHari Bathini 	if (*cur == '@')
134*692f66f2SHari Bathini 		*crash_base = memparse(cur+1, &cur);
135*692f66f2SHari Bathini 	else if (*cur != ' ' && *cur != '\0') {
136*692f66f2SHari Bathini 		pr_warn("crashkernel: unrecognized char: %c\n", *cur);
137*692f66f2SHari Bathini 		return -EINVAL;
138*692f66f2SHari Bathini 	}
139*692f66f2SHari Bathini 
140*692f66f2SHari Bathini 	return 0;
141*692f66f2SHari Bathini }
142*692f66f2SHari Bathini 
143*692f66f2SHari Bathini #define SUFFIX_HIGH 0
144*692f66f2SHari Bathini #define SUFFIX_LOW  1
145*692f66f2SHari Bathini #define SUFFIX_NULL 2
146*692f66f2SHari Bathini static __initdata char *suffix_tbl[] = {
147*692f66f2SHari Bathini 	[SUFFIX_HIGH] = ",high",
148*692f66f2SHari Bathini 	[SUFFIX_LOW]  = ",low",
149*692f66f2SHari Bathini 	[SUFFIX_NULL] = NULL,
150*692f66f2SHari Bathini };
151*692f66f2SHari Bathini 
152*692f66f2SHari Bathini /*
153*692f66f2SHari Bathini  * That function parses "suffix"  crashkernel command lines like
154*692f66f2SHari Bathini  *
155*692f66f2SHari Bathini  *	crashkernel=size,[high|low]
156*692f66f2SHari Bathini  *
157*692f66f2SHari Bathini  * It returns 0 on success and -EINVAL on failure.
158*692f66f2SHari Bathini  */
159*692f66f2SHari Bathini static int __init parse_crashkernel_suffix(char *cmdline,
160*692f66f2SHari Bathini 					   unsigned long long	*crash_size,
161*692f66f2SHari Bathini 					   const char *suffix)
162*692f66f2SHari Bathini {
163*692f66f2SHari Bathini 	char *cur = cmdline;
164*692f66f2SHari Bathini 
165*692f66f2SHari Bathini 	*crash_size = memparse(cmdline, &cur);
166*692f66f2SHari Bathini 	if (cmdline == cur) {
167*692f66f2SHari Bathini 		pr_warn("crashkernel: memory value expected\n");
168*692f66f2SHari Bathini 		return -EINVAL;
169*692f66f2SHari Bathini 	}
170*692f66f2SHari Bathini 
171*692f66f2SHari Bathini 	/* check with suffix */
172*692f66f2SHari Bathini 	if (strncmp(cur, suffix, strlen(suffix))) {
173*692f66f2SHari Bathini 		pr_warn("crashkernel: unrecognized char: %c\n", *cur);
174*692f66f2SHari Bathini 		return -EINVAL;
175*692f66f2SHari Bathini 	}
176*692f66f2SHari Bathini 	cur += strlen(suffix);
177*692f66f2SHari Bathini 	if (*cur != ' ' && *cur != '\0') {
178*692f66f2SHari Bathini 		pr_warn("crashkernel: unrecognized char: %c\n", *cur);
179*692f66f2SHari Bathini 		return -EINVAL;
180*692f66f2SHari Bathini 	}
181*692f66f2SHari Bathini 
182*692f66f2SHari Bathini 	return 0;
183*692f66f2SHari Bathini }
184*692f66f2SHari Bathini 
185*692f66f2SHari Bathini static __init char *get_last_crashkernel(char *cmdline,
186*692f66f2SHari Bathini 			     const char *name,
187*692f66f2SHari Bathini 			     const char *suffix)
188*692f66f2SHari Bathini {
189*692f66f2SHari Bathini 	char *p = cmdline, *ck_cmdline = NULL;
190*692f66f2SHari Bathini 
191*692f66f2SHari Bathini 	/* find crashkernel and use the last one if there are more */
192*692f66f2SHari Bathini 	p = strstr(p, name);
193*692f66f2SHari Bathini 	while (p) {
194*692f66f2SHari Bathini 		char *end_p = strchr(p, ' ');
195*692f66f2SHari Bathini 		char *q;
196*692f66f2SHari Bathini 
197*692f66f2SHari Bathini 		if (!end_p)
198*692f66f2SHari Bathini 			end_p = p + strlen(p);
199*692f66f2SHari Bathini 
200*692f66f2SHari Bathini 		if (!suffix) {
201*692f66f2SHari Bathini 			int i;
202*692f66f2SHari Bathini 
203*692f66f2SHari Bathini 			/* skip the one with any known suffix */
204*692f66f2SHari Bathini 			for (i = 0; suffix_tbl[i]; i++) {
205*692f66f2SHari Bathini 				q = end_p - strlen(suffix_tbl[i]);
206*692f66f2SHari Bathini 				if (!strncmp(q, suffix_tbl[i],
207*692f66f2SHari Bathini 					     strlen(suffix_tbl[i])))
208*692f66f2SHari Bathini 					goto next;
209*692f66f2SHari Bathini 			}
210*692f66f2SHari Bathini 			ck_cmdline = p;
211*692f66f2SHari Bathini 		} else {
212*692f66f2SHari Bathini 			q = end_p - strlen(suffix);
213*692f66f2SHari Bathini 			if (!strncmp(q, suffix, strlen(suffix)))
214*692f66f2SHari Bathini 				ck_cmdline = p;
215*692f66f2SHari Bathini 		}
216*692f66f2SHari Bathini next:
217*692f66f2SHari Bathini 		p = strstr(p+1, name);
218*692f66f2SHari Bathini 	}
219*692f66f2SHari Bathini 
220*692f66f2SHari Bathini 	if (!ck_cmdline)
221*692f66f2SHari Bathini 		return NULL;
222*692f66f2SHari Bathini 
223*692f66f2SHari Bathini 	return ck_cmdline;
224*692f66f2SHari Bathini }
225*692f66f2SHari Bathini 
226*692f66f2SHari Bathini static int __init __parse_crashkernel(char *cmdline,
227*692f66f2SHari Bathini 			     unsigned long long system_ram,
228*692f66f2SHari Bathini 			     unsigned long long *crash_size,
229*692f66f2SHari Bathini 			     unsigned long long *crash_base,
230*692f66f2SHari Bathini 			     const char *name,
231*692f66f2SHari Bathini 			     const char *suffix)
232*692f66f2SHari Bathini {
233*692f66f2SHari Bathini 	char	*first_colon, *first_space;
234*692f66f2SHari Bathini 	char	*ck_cmdline;
235*692f66f2SHari Bathini 
236*692f66f2SHari Bathini 	BUG_ON(!crash_size || !crash_base);
237*692f66f2SHari Bathini 	*crash_size = 0;
238*692f66f2SHari Bathini 	*crash_base = 0;
239*692f66f2SHari Bathini 
240*692f66f2SHari Bathini 	ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
241*692f66f2SHari Bathini 
242*692f66f2SHari Bathini 	if (!ck_cmdline)
243*692f66f2SHari Bathini 		return -EINVAL;
244*692f66f2SHari Bathini 
245*692f66f2SHari Bathini 	ck_cmdline += strlen(name);
246*692f66f2SHari Bathini 
247*692f66f2SHari Bathini 	if (suffix)
248*692f66f2SHari Bathini 		return parse_crashkernel_suffix(ck_cmdline, crash_size,
249*692f66f2SHari Bathini 				suffix);
250*692f66f2SHari Bathini 	/*
251*692f66f2SHari Bathini 	 * if the commandline contains a ':', then that's the extended
252*692f66f2SHari Bathini 	 * syntax -- if not, it must be the classic syntax
253*692f66f2SHari Bathini 	 */
254*692f66f2SHari Bathini 	first_colon = strchr(ck_cmdline, ':');
255*692f66f2SHari Bathini 	first_space = strchr(ck_cmdline, ' ');
256*692f66f2SHari Bathini 	if (first_colon && (!first_space || first_colon < first_space))
257*692f66f2SHari Bathini 		return parse_crashkernel_mem(ck_cmdline, system_ram,
258*692f66f2SHari Bathini 				crash_size, crash_base);
259*692f66f2SHari Bathini 
260*692f66f2SHari Bathini 	return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
261*692f66f2SHari Bathini }
262*692f66f2SHari Bathini 
263*692f66f2SHari Bathini /*
264*692f66f2SHari Bathini  * That function is the entry point for command line parsing and should be
265*692f66f2SHari Bathini  * called from the arch-specific code.
266*692f66f2SHari Bathini  */
267*692f66f2SHari Bathini int __init parse_crashkernel(char *cmdline,
268*692f66f2SHari Bathini 			     unsigned long long system_ram,
269*692f66f2SHari Bathini 			     unsigned long long *crash_size,
270*692f66f2SHari Bathini 			     unsigned long long *crash_base)
271*692f66f2SHari Bathini {
272*692f66f2SHari Bathini 	return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
273*692f66f2SHari Bathini 					"crashkernel=", NULL);
274*692f66f2SHari Bathini }
275*692f66f2SHari Bathini 
276*692f66f2SHari Bathini int __init parse_crashkernel_high(char *cmdline,
277*692f66f2SHari Bathini 			     unsigned long long system_ram,
278*692f66f2SHari Bathini 			     unsigned long long *crash_size,
279*692f66f2SHari Bathini 			     unsigned long long *crash_base)
280*692f66f2SHari Bathini {
281*692f66f2SHari Bathini 	return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
282*692f66f2SHari Bathini 				"crashkernel=", suffix_tbl[SUFFIX_HIGH]);
283*692f66f2SHari Bathini }
284*692f66f2SHari Bathini 
285*692f66f2SHari Bathini int __init parse_crashkernel_low(char *cmdline,
286*692f66f2SHari Bathini 			     unsigned long long system_ram,
287*692f66f2SHari Bathini 			     unsigned long long *crash_size,
288*692f66f2SHari Bathini 			     unsigned long long *crash_base)
289*692f66f2SHari Bathini {
290*692f66f2SHari Bathini 	return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
291*692f66f2SHari Bathini 				"crashkernel=", suffix_tbl[SUFFIX_LOW]);
292*692f66f2SHari Bathini }
293*692f66f2SHari Bathini 
294*692f66f2SHari Bathini static u32 *append_elf_note(u32 *buf, char *name, unsigned int type,
295*692f66f2SHari Bathini 			    void *data, size_t data_len)
296*692f66f2SHari Bathini {
297*692f66f2SHari Bathini 	struct elf_note note;
298*692f66f2SHari Bathini 
299*692f66f2SHari Bathini 	note.n_namesz = strlen(name) + 1;
300*692f66f2SHari Bathini 	note.n_descsz = data_len;
301*692f66f2SHari Bathini 	note.n_type   = type;
302*692f66f2SHari Bathini 	memcpy(buf, &note, sizeof(note));
303*692f66f2SHari Bathini 	buf += (sizeof(note) + 3)/4;
304*692f66f2SHari Bathini 	memcpy(buf, name, note.n_namesz);
305*692f66f2SHari Bathini 	buf += (note.n_namesz + 3)/4;
306*692f66f2SHari Bathini 	memcpy(buf, data, note.n_descsz);
307*692f66f2SHari Bathini 	buf += (note.n_descsz + 3)/4;
308*692f66f2SHari Bathini 
309*692f66f2SHari Bathini 	return buf;
310*692f66f2SHari Bathini }
311*692f66f2SHari Bathini 
312*692f66f2SHari Bathini static void final_note(u32 *buf)
313*692f66f2SHari Bathini {
314*692f66f2SHari Bathini 	struct elf_note note;
315*692f66f2SHari Bathini 
316*692f66f2SHari Bathini 	note.n_namesz = 0;
317*692f66f2SHari Bathini 	note.n_descsz = 0;
318*692f66f2SHari Bathini 	note.n_type   = 0;
319*692f66f2SHari Bathini 	memcpy(buf, &note, sizeof(note));
320*692f66f2SHari Bathini }
321*692f66f2SHari Bathini 
322*692f66f2SHari Bathini static void update_vmcoreinfo_note(void)
323*692f66f2SHari Bathini {
324*692f66f2SHari Bathini 	u32 *buf = vmcoreinfo_note;
325*692f66f2SHari Bathini 
326*692f66f2SHari Bathini 	if (!vmcoreinfo_size)
327*692f66f2SHari Bathini 		return;
328*692f66f2SHari Bathini 	buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
329*692f66f2SHari Bathini 			      vmcoreinfo_size);
330*692f66f2SHari Bathini 	final_note(buf);
331*692f66f2SHari Bathini }
332*692f66f2SHari Bathini 
333*692f66f2SHari Bathini void crash_save_vmcoreinfo(void)
334*692f66f2SHari Bathini {
335*692f66f2SHari Bathini 	vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds());
336*692f66f2SHari Bathini 	update_vmcoreinfo_note();
337*692f66f2SHari Bathini }
338*692f66f2SHari Bathini 
339*692f66f2SHari Bathini void vmcoreinfo_append_str(const char *fmt, ...)
340*692f66f2SHari Bathini {
341*692f66f2SHari Bathini 	va_list args;
342*692f66f2SHari Bathini 	char buf[0x50];
343*692f66f2SHari Bathini 	size_t r;
344*692f66f2SHari Bathini 
345*692f66f2SHari Bathini 	va_start(args, fmt);
346*692f66f2SHari Bathini 	r = vscnprintf(buf, sizeof(buf), fmt, args);
347*692f66f2SHari Bathini 	va_end(args);
348*692f66f2SHari Bathini 
349*692f66f2SHari Bathini 	r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
350*692f66f2SHari Bathini 
351*692f66f2SHari Bathini 	memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
352*692f66f2SHari Bathini 
353*692f66f2SHari Bathini 	vmcoreinfo_size += r;
354*692f66f2SHari Bathini }
355*692f66f2SHari Bathini 
356*692f66f2SHari Bathini /*
357*692f66f2SHari Bathini  * provide an empty default implementation here -- architecture
358*692f66f2SHari Bathini  * code may override this
359*692f66f2SHari Bathini  */
360*692f66f2SHari Bathini void __weak arch_crash_save_vmcoreinfo(void)
361*692f66f2SHari Bathini {}
362*692f66f2SHari Bathini 
363*692f66f2SHari Bathini phys_addr_t __weak paddr_vmcoreinfo_note(void)
364*692f66f2SHari Bathini {
365*692f66f2SHari Bathini 	return __pa_symbol((unsigned long)(char *)&vmcoreinfo_note);
366*692f66f2SHari Bathini }
367*692f66f2SHari Bathini 
368*692f66f2SHari Bathini static int __init crash_save_vmcoreinfo_init(void)
369*692f66f2SHari Bathini {
370*692f66f2SHari Bathini 	VMCOREINFO_OSRELEASE(init_uts_ns.name.release);
371*692f66f2SHari Bathini 	VMCOREINFO_PAGESIZE(PAGE_SIZE);
372*692f66f2SHari Bathini 
373*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(init_uts_ns);
374*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(node_online_map);
375*692f66f2SHari Bathini #ifdef CONFIG_MMU
376*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(swapper_pg_dir);
377*692f66f2SHari Bathini #endif
378*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(_stext);
379*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(vmap_area_list);
380*692f66f2SHari Bathini 
381*692f66f2SHari Bathini #ifndef CONFIG_NEED_MULTIPLE_NODES
382*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(mem_map);
383*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(contig_page_data);
384*692f66f2SHari Bathini #endif
385*692f66f2SHari Bathini #ifdef CONFIG_SPARSEMEM
386*692f66f2SHari Bathini 	VMCOREINFO_SYMBOL(mem_section);
387*692f66f2SHari Bathini 	VMCOREINFO_LENGTH(mem_section, NR_SECTION_ROOTS);
388*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(mem_section);
389*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(mem_section, section_mem_map);
390*692f66f2SHari Bathini #endif
391*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(page);
392*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(pglist_data);
393*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(zone);
394*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(free_area);
395*692f66f2SHari Bathini 	VMCOREINFO_STRUCT_SIZE(list_head);
396*692f66f2SHari Bathini 	VMCOREINFO_SIZE(nodemask_t);
397*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, flags);
398*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, _refcount);
399*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, mapping);
400*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, lru);
401*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, _mapcount);
402*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, private);
403*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, compound_dtor);
404*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, compound_order);
405*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(page, compound_head);
406*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, node_zones);
407*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, nr_zones);
408*692f66f2SHari Bathini #ifdef CONFIG_FLAT_NODE_MEM_MAP
409*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, node_mem_map);
410*692f66f2SHari Bathini #endif
411*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, node_start_pfn);
412*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, node_spanned_pages);
413*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(pglist_data, node_id);
414*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(zone, free_area);
415*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(zone, vm_stat);
416*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(zone, spanned_pages);
417*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(free_area, free_list);
418*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(list_head, next);
419*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(list_head, prev);
420*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(vmap_area, va_start);
421*692f66f2SHari Bathini 	VMCOREINFO_OFFSET(vmap_area, list);
422*692f66f2SHari Bathini 	VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
423*692f66f2SHari Bathini 	log_buf_vmcoreinfo_setup();
424*692f66f2SHari Bathini 	VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
425*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(NR_FREE_PAGES);
426*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_lru);
427*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_private);
428*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_swapcache);
429*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_slab);
430*692f66f2SHari Bathini #ifdef CONFIG_MEMORY_FAILURE
431*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_hwpoison);
432*692f66f2SHari Bathini #endif
433*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PG_head_mask);
434*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
435*692f66f2SHari Bathini #ifdef CONFIG_HUGETLB_PAGE
436*692f66f2SHari Bathini 	VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
437*692f66f2SHari Bathini #endif
438*692f66f2SHari Bathini 
439*692f66f2SHari Bathini 	arch_crash_save_vmcoreinfo();
440*692f66f2SHari Bathini 	update_vmcoreinfo_note();
441*692f66f2SHari Bathini 
442*692f66f2SHari Bathini 	return 0;
443*692f66f2SHari Bathini }
444*692f66f2SHari Bathini 
445*692f66f2SHari Bathini subsys_initcall(crash_save_vmcoreinfo_init);
446