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, ¬e, 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, ¬e, 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