Linux 4.18 kernels introduced a new CONFIG_PROC_VMCORE_DEVICE_DUMP

configuration in commit 2724273e8fd00b512596a77ee063f49b25f36507,
titled "vmcore: add API to collect hardware dump in second kernel",
in which device drivers may collect a device specific snapshot of the
hardware/firmware state of their underlying devices, and export the
data as a kdump ELF note with type NT_VMCOREDD.  This patch
recognizes the new ELF note(s) in both ELF and compressed kdump
vmcore dumpfiles.  The "help -[nD]" option shows basic information
about each note, and two new "dev" command options have been
introduced.  The "dev -V" option displays an indexed list of each
note, showing the device name, the dumpfile offset, and the size
of each note.  The "dev -v index [file]" option either dumps the
contents of a note to the display screen in a human-readable format,
or copies the note data directly to a specified file.
(surendra@chelsio.com)
This commit is contained in:
Dave Anderson 2019-04-23 14:36:56 -04:00
parent dc70e6a5e0
commit 71a4f36767
9 changed files with 393 additions and 10 deletions

View File

@ -49,7 +49,7 @@ LDFLAGS=
GENERIC_HFILES=defs.h xen_hyper_defs.h xen_dom0.h
MCORE_HFILES=va_server.h vas_crash.h
REDHAT_HFILES=netdump.h diskdump.h makedumpfile.h xendump.h kvmdump.h qemu-load.h
REDHAT_HFILES=netdump.h diskdump.h makedumpfile.h xendump.h kvmdump.h qemu-load.h vmcore.h
LKCD_DUMP_HFILES=lkcd_vmdump_v1.h lkcd_vmdump_v2_v3.h lkcd_dump_v5.h \
lkcd_dump_v7.h lkcd_dump_v8.h
LKCD_OBSOLETE_HFILES=lkcd_fix_mem.h
@ -392,7 +392,7 @@ lkcd_v8.o: ${GENERIC_HFILES} ${LKCD_DUMP_HFILES} lkcd_v8.c
net.o: ${GENERIC_HFILES} net.c
${CC} -c ${CRASH_CFLAGS} net.c ${WARNING_OPTIONS} ${WARNING_ERROR}
dev.o: ${GENERIC_HFILES} dev.c
dev.o: ${GENERIC_HFILES} ${REDHAT_HFILES} dev.c
${CC} -c ${CRASH_CFLAGS} dev.c ${WARNING_OPTIONS} ${WARNING_ERROR}
# remote.c functionality has been deprecated

10
defs.h
View File

@ -148,6 +148,8 @@
#define NR_CPUS (4096)
#endif
#define NR_DEVICE_DUMPS (64)
/* Some architectures require memory accesses to be aligned. */
#if defined(SPARC64)
#define NEED_ALIGNED_MEM_ACCESS
@ -5276,6 +5278,7 @@ char *format_stack_entry(struct bt_info *bt, char *, ulong, ulong);
int in_user_stack(ulong, ulong);
int dump_inode_page(ulong);
ulong valid_section_nr(ulong);
void display_memory_from_file_offset(ulonglong, long, void *);
/*
@ -5685,6 +5688,8 @@ enum {
*/
void dev_init(void);
void dump_dev_table(void);
void devdump_extract(void *, ulonglong, char *, FILE *);
void devdump_info(void *, ulonglong, FILE *);
/*
* ipcs.c
@ -6397,7 +6402,10 @@ void display_regs_from_elf_notes(int, FILE *);
void display_ELF_note(int, int, void *, FILE *);
void *netdump_get_prstatus_percpu(int);
int kdump_kaslr_check(void);
void display_vmcoredd_note(void *ptr, FILE *ofp);
QEMUCPUState *kdump_get_qemucpustate(int);
void kdump_device_dump_info(FILE *);
void kdump_device_dump_extract(int, char *, FILE *);
#define PRSTATUS_NOTE (1)
#define QEMU_NOTE (2)
@ -6443,6 +6451,8 @@ void process_elf64_notes(void *, ulong);
void dump_registers_for_compressed_kdump(void);
int diskdump_kaslr_check(void);
QEMUCPUState *diskdump_get_qemucpustate(int);
void diskdump_device_dump_info(FILE *);
void diskdump_device_dump_extract(int, char *, FILE *);
/*
* makedumpfile.c

98
dev.c
View File

@ -16,6 +16,7 @@
*/
#include "defs.h"
#include "vmcore.h"
static void dump_blkdevs(ulong);
static void dump_chrdevs(ulong);
@ -104,12 +105,14 @@ dev_init(void)
void
cmd_dev(void)
{
int c;
int c;
int dd_index = -1;
char *outputfile = NULL;
ulong flags;
flags = 0;
while ((c = getopt(argcnt, args, "dDpi")) != EOF) {
while ((c = getopt(argcnt, args, "dDpiVv:")) != EOF) {
switch(c)
{
case 'd':
@ -137,6 +140,21 @@ cmd_dev(void)
option_not_supported(c);
return;
case 'V':
if (KDUMP_DUMPFILE())
kdump_device_dump_info(fp);
else if (DISKDUMP_DUMPFILE())
diskdump_device_dump_info(fp);
else if (ACTIVE())
error(INFO, "-V option not supported on a live system\n");
else
error(INFO, "-V option not supported on this dumpfile type\n");
return;
case 'v':
dd_index = atoi(optarg);
break;
default:
argerrs++;
break;
@ -146,6 +164,29 @@ cmd_dev(void)
if (argerrs)
cmd_usage(pc->curcmd, SYNOPSIS);
while (args[optind]) {
if (dd_index >= 0) {
if (!outputfile)
outputfile = args[optind];
else
cmd_usage(pc->curcmd, SYNOPSIS);
} else
cmd_usage(pc->curcmd, SYNOPSIS);
optind++;
}
if (dd_index >= 0) {
if (KDUMP_DUMPFILE())
kdump_device_dump_extract(dd_index, outputfile, fp);
else if (DISKDUMP_DUMPFILE())
diskdump_device_dump_extract(dd_index, outputfile, fp);
else if (ACTIVE())
error(INFO, "-v option not supported on a live system\n");
else
error(INFO, "-v option not supported on this dumpfile type\n");
return;
}
dump_chrdevs(flags);
fprintf(fp, "\n");
dump_blkdevs(flags);
@ -4549,3 +4590,56 @@ diskio_option(ulong flags)
diskio_init();
display_all_diskio(flags);
}
void
devdump_extract(void *_note, ulonglong offset, char *dump_file, FILE *ofp)
{
struct vmcoredd_header *vh = (struct vmcoredd_header *)_note;
ulong dump_size, count;
FILE *tmpfp;
if (vh->n_type != NT_VMCOREDD)
error(FATAL, "unsupported note type: 0x%x", vh->n_type);
dump_size = vh->n_descsz - VMCOREDD_MAX_NAME_BYTES;
if (dump_file) {
tmpfp = fopen(dump_file, "w");
if (!tmpfp) {
error(FATAL, "cannot open output file: %s\n",
dump_file);
return;
}
set_tmpfile2(tmpfp);
}
fprintf(ofp, "DEVICE: %s\n", vh->dump_name);
if (dump_file)
count = dump_size;
else
count = dump_size/sizeof(uint64_t) +
(dump_size % sizeof(uint64_t) ? 1 : 0);
display_memory_from_file_offset(offset + sizeof(struct vmcoredd_header),
count, dump_file);
}
void
devdump_info(void *_note, ulonglong offset, FILE *ofp)
{
struct vmcoredd_header *vh = (struct vmcoredd_header *)_note;
char buf[BUFSIZE];
ulong dump_size;
if (vh->n_type != NT_VMCOREDD)
return;
dump_size = vh->n_descsz - VMCOREDD_MAX_NAME_BYTES;
offset += sizeof(struct vmcoredd_header);
fprintf(ofp, "0x%s ", mkstring(buf, LONG_LONG_PRLEN, LJUST | LONGLONG_HEX,
MKSTR(&offset)));
fprintf(ofp, "%s ", mkstring(buf, LONG_PRLEN, LJUST | LONG_DEC,
MKSTR(dump_size)));
fprintf(ofp, "%s\n", vh->dump_name);
}

View File

@ -26,6 +26,7 @@
#include "defs.h"
#include "diskdump.h"
#include "xen_dom0.h"
#include "vmcore.h"
#define BITMAP_SECT_LEN 4096
@ -58,6 +59,8 @@ struct diskdump_data {
void **nt_qemu_percpu;
void **nt_qemucs_percpu;
uint num_qemu_notes;
void **nt_vmcoredd_array;
uint num_vmcoredd_notes;
/* page cache */
struct page_cache_hdr { /* header for each cached page */
@ -279,6 +282,7 @@ process_elf32_notes(void *note_buf, unsigned long size_note)
Elf32_Nhdr *nt;
size_t index, len = 0;
int num = 0;
int vmcoredd_num = 0;
int qemu_num = 0;
for (index = 0; index < size_note; index += len) {
@ -304,6 +308,12 @@ process_elf32_notes(void *note_buf, unsigned long size_note)
process_xen_note(nt->n_type, data, nt->n_descsz);
}
if (nt->n_type == NT_VMCOREDD &&
vmcoredd_num < NR_DEVICE_DUMPS) {
dd->nt_vmcoredd_array[vmcoredd_num] = nt;
vmcoredd_num++;
}
len = roundup(len + nt->n_namesz, 4);
len = roundup(len + nt->n_descsz, 4);
}
@ -317,6 +327,9 @@ process_elf32_notes(void *note_buf, unsigned long size_note)
pc->flags2 |= QEMU_MEM_DUMP_COMPRESSED;
dd->num_qemu_notes = qemu_num;
}
if (vmcoredd_num > 0)
dd->num_vmcoredd_notes = vmcoredd_num;
return;
}
@ -326,6 +339,7 @@ process_elf64_notes(void *note_buf, unsigned long size_note)
Elf64_Nhdr *nt;
size_t index, len = 0;
int num = 0;
int vmcoredd_num = 0;
int qemu_num = 0;
for (index = 0; index < size_note; index += len) {
@ -357,6 +371,12 @@ process_elf64_notes(void *note_buf, unsigned long size_note)
process_xen_note(nt->n_type, data, nt->n_descsz);
}
if (nt->n_type == NT_VMCOREDD &&
vmcoredd_num < NR_DEVICE_DUMPS) {
dd->nt_vmcoredd_array[vmcoredd_num] = nt;
vmcoredd_num++;
}
len = roundup(len + nt->n_namesz, 4);
len = roundup(len + nt->n_descsz, 4);
}
@ -370,6 +390,9 @@ process_elf64_notes(void *note_buf, unsigned long size_note)
pc->flags2 |= QEMU_MEM_DUMP_COMPRESSED;
dd->num_qemu_notes = qemu_num;
}
if (vmcoredd_num > 0)
dd->num_vmcoredd_notes = vmcoredd_num;
return;
}
@ -778,6 +801,10 @@ restart:
error(FATAL, "qemu mem dump compressed: cannot malloc pointer"
" to QEMUCS notes\n");
if ((dd->nt_vmcoredd_array = malloc(NR_DEVICE_DUMPS * sizeof(void *))) == NULL)
error(FATAL, "compressed kdump: cannot malloc array for "
"vmcore device dump notes\n");
if (FLAT_FORMAT()) {
if (!read_flattened_format(dd->dfd, offset, dd->notes_buf, size)) {
error(INFO, "compressed kdump: cannot read notes data"
@ -875,6 +902,8 @@ err:
free(dd->nt_qemu_percpu);
if (dd->nt_qemucs_percpu)
free(dd->nt_qemucs_percpu);
if (dd->nt_vmcoredd_array)
free(dd->nt_vmcoredd_array);
dd->flags &= ~(DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL);
pc->flags2 &= ~ELF_NOTES;
@ -1948,6 +1977,15 @@ __diskdump_memory_dump(FILE *fp)
dd->sub_header_kdump->size_note);
fprintf(fp, " notes_buf: %lx\n",
(ulong)dd->notes_buf);
fprintf(fp, " num_vmcoredd_notes: %d\n",
dd->num_vmcoredd_notes);
for (i = 0; i < dd->num_vmcoredd_notes; i++) {
fprintf(fp, " notes[%d]: %lx %s\n",
i, (ulong)dd->nt_vmcoredd_array[i],
dd->nt_vmcoredd_array[i] ? "(NT_VMCOREDD)" : "");
display_vmcoredd_note(dd->nt_vmcoredd_array[i], fp);
}
fprintf(fp, " num_prstatus_notes: %d\n",
dd->num_prstatus_notes);
for (i = 0; i < dd->num_prstatus_notes; i++) {
@ -2500,3 +2538,50 @@ diskdump_get_qemucpustate(int cpu)
return (QEMUCPUState *)dd->nt_qemucs_percpu[cpu];
}
#endif
/*
* extract hardware specific device dumps from coredump.
*/
void
diskdump_device_dump_extract(int index, char *outfile, FILE *ofp)
{
ulonglong offset;
if (!dd->num_vmcoredd_notes)
error(FATAL, "no device dumps found in this dumpfile\n");
else if (index >= dd->num_vmcoredd_notes)
error(FATAL, "no device dump found at index: %d", index);
offset = dd->sub_header_kdump->offset_note +
((unsigned char *)dd->nt_vmcoredd_array[index] -
dd->notes_buf);
devdump_extract(dd->nt_vmcoredd_array[index], offset, outfile, ofp);
}
/*
* list all hardware specific device dumps present in coredump.
*/
void
diskdump_device_dump_info(FILE *ofp)
{
ulonglong offset;
char buf[BUFSIZE];
ulong i;
if (!dd->num_vmcoredd_notes)
error(FATAL, "no device dumps found in this dumpfile\n");
fprintf(fp, "%s ", mkstring(buf, strlen("INDEX"), LJUST, "INDEX"));
fprintf(fp, " %s ", mkstring(buf, LONG_LONG_PRLEN, LJUST, "OFFSET"));
fprintf(fp, " %s ", mkstring(buf, LONG_PRLEN, LJUST, "SIZE"));
fprintf(fp, "NAME\n");
for (i = 0; i < dd->num_vmcoredd_notes; i++) {
fprintf(fp, "%s ", mkstring(buf, strlen("INDEX"), CENTER | INT_DEC, MKSTR(i)));
offset = dd->sub_header_kdump->offset_note +
((unsigned char *)dd->nt_vmcoredd_array[i] -
dd->notes_buf);
devdump_info(dd->nt_vmcoredd_array[i], offset, ofp);
}
}

39
help.c
View File

@ -3207,7 +3207,7 @@ NULL
char *help_dev[] = {
"dev",
"device data",
"[-i | -p | -d | -D]",
"[-i | -p | -d | -D ] [-V | -v index [file]]",
" If no argument is entered, this command dumps character and block",
" device data.\n",
" -i display I/O port usage; on 2.4 kernels, also display I/O memory usage.",
@ -3222,6 +3222,16 @@ char *help_dev[] = {
" If the device driver uses blk-mq interface, this field",
" shows N/A(MQ). If not available, this column is not shown.",
" -D same as -d, but filter out disks with no in-progress I/O requests.",
" ",
" If the dumpfile contains device dumps:",
" -V display an indexed list of all device dumps present in the vmcore,",
" showing their file offset, size and name.",
" -v index select and display one device dump based upon an index value",
" shown by the -V option, shown in a default human-readable format;",
" alternatively, the \"rd -f\" option along with its various format",
" options may be used to further tailor the output.",
" file only used with -v, copy the device dump data to a file.",
"\nEXAMPLES",
" Display character and block device data:\n",
" %s> dev",
@ -3353,6 +3363,33 @@ char *help_dev[] = {
" 8 ffff81012dc77000 sdb ffff81012d8b5740 0 0 0 0",
" 8 ffff81012d8d0c00 sdc ffff81012d8ae9c0 0 0 0 0",
"\n Display the available device dumps:\n",
" %s> dev -V",
" INDEX OFFSET SIZE NAME",
" 0 0x240 33558464 cxgb4_0000:02:00.4",
" 1 0x2001240 33558464 cxgb4_0000:03:00.4",
"\n Extract a specified device dump to file:\n",
" %s> dev -v 0 -r device_dump_0.bin",
" DEVICE: cxgb4_0000:02:00.4",
" 33558464 bytes copied from 0x240 to device_dump_0.bin",
"\n Format and display a device's dump data to the screen using the \"rd\" command:\n",
" %s> rd -f 0x240 -32 8",
" 240: 040b69e2 00000038 000e0001 00675fd4 .i..8........_g.",
" 250: 00000000 21600047 00000000 00000000 ....G.`!........",
"\n Display a device's dump data to the screen using the default format:\n",
" %s> dev -v 1",
" DEVICE: cxgb4_0000:03:00.4",
" 2001240: 00000038040b69e2 00af985c000e0001 .i..8.......\\...",
" 2001250: 2150004700000000 0000000000000000 ....G.P!........",
" 2001260: 0000000000000000 0000000000000000 ................",
" 2001270: 0000000000000000 0002fccc00000001 ................",
" 2001280: 00000000000027b0 0000000000000000 .'..............",
" ...",
NULL
};

View File

@ -1793,6 +1793,16 @@ display_memory(ulonglong addr, long count, ulong flag, int memtype, void *opt)
fprintf(fp,"\n");
}
void
display_memory_from_file_offset(ulonglong addr, long count, void *file)
{
if (file)
display_memory(addr, count, DISPLAY_RAW, FILEADDR, file);
else
display_memory(addr, count, DISPLAY_64|ASCII_ENDLINE|HEXADECIMAL,
FILEADDR, file);
}
/*
* cmd_wr() is the sister routine of cmd_rd(), used to modify the contents
* of memory. Like the "rd" command, the starting address may be entered

118
netdump.c
View File

@ -1185,9 +1185,9 @@ netdump_memory_dump(FILE *fp)
if (machine_type("ARM64"))
netdump_print("%016lx\n"
" CONFIG_ARM64_VA_BITS: %ld\n"
" VA_BITS_ACTUAL: %ld\n",
" VA_BITS_ACTUAL: %lld\n",
nd->arch_data2, nd->arch_data2 & 0xffffffff,
(nd->arch_data2 >> 32));
((ulonglong)nd->arch_data2 >> 32));
else
netdump_print("%016lx (?)\n", nd->arch_data2);
} else
@ -1810,7 +1810,7 @@ vmcoreinfo_read_string(const char *key)
}
if (STREQ(key, "NUMBER(VA_BITS_ACTUAL)") && nd->arch_data2) {
value = calloc(VADDR_PRLEN+1, sizeof(char));
sprintf(value, "%ld", (nd->arch_data2 >> 32) & 0xffffffff);
sprintf(value, "%lld", ((ulonglong)nd->arch_data2 >> 32) & 0xffffffff);
pc->read_vmcoreinfo = no_vmcoreinfo;
return value;
}
@ -1898,6 +1898,21 @@ vmcoreinfo_read_integer(const char *key, long default_value)
return retval;
}
void
display_vmcoredd_note(void *ptr, FILE *ofp)
{
int sp;
unsigned int dump_size;
struct vmcoredd_header *vh;
sp = VMCORE_VALID() ? 25 : 22;
vh = (struct vmcoredd_header *)ptr;
dump_size = vh->n_descsz - VMCOREDD_MAX_NAME_BYTES;
fprintf(ofp, "%sname: \"%s\"\n", space(sp), vh->dump_name);
fprintf(ofp, "%ssize: %u\n", space(sp), dump_size);
}
/*
* Dump a note section header -- the actual data is defined by netdump
*/
@ -2002,6 +2017,18 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
}
break;
#endif
case NT_VMCOREDD:
netdump_print("(NT_VMCOREDD)\n");
if (store) {
for (i = 0; i < NR_DEVICE_DUMPS; i++) {
if (!nd->nt_vmcoredd_array[i]) {
nd->nt_vmcoredd_array[i] = (void *)note;
nd->num_vmcoredd_notes++;
break;
}
}
}
break;
default:
xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
if (STRNEQ(buf, "VMCOREINFO_XEN"))
@ -2092,6 +2119,9 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
netdump_print(" ");
}
lf = 0;
} else if (note->n_type == NT_VMCOREDD) {
if (nd->ofp)
display_vmcoredd_note(note, nd->ofp);
} else {
if (nd->ofp && !XEN_CORE_DUMPFILE() && !(pc->flags2 & LIVE_DUMP)) {
if (machine_type("X86")) {
@ -2126,7 +2156,7 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
static size_t
dump_Elf64_Nhdr(Elf64_Off offset, int store)
{
int i, lf;
int i = 0, lf = 0;
Elf64_Nhdr *note;
size_t len;
char buf[BUFSIZE];
@ -2271,6 +2301,18 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
}
break;
#endif
case NT_VMCOREDD:
netdump_print("(NT_VMCOREDD)\n");
if (store) {
for (i = 0; i < NR_DEVICE_DUMPS; i++) {
if (!nd->nt_vmcoredd_array[i]) {
nd->nt_vmcoredd_array[i] = (void *)note;
nd->num_vmcoredd_notes++;
break;
}
}
}
break;
default:
xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
if (STRNEQ(buf, "VMCOREINFO_XEN"))
@ -2364,7 +2406,10 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
}
}
if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS) || qemuinfo)) {
if (note->n_type == NT_VMCOREDD) {
if (nd->ofp)
display_vmcoredd_note(note, nd->ofp);
} else if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS) || qemuinfo)) {
if (nd->ofp && !XEN_CORE_DUMPFILE() && !(pc->flags2 & LIVE_DUMP)) {
if (machine_type("X86")) {
if (note->n_type == NT_PRSTATUS)
@ -5037,3 +5082,66 @@ kdump_get_qemucpustate(int cpu)
return (QEMUCPUState *)nd->nt_qemu_percpu[cpu];
}
#endif
static void *
get_kdump_device_dump_offset(void)
{
void *elf_base = NULL;
if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF64)
elf_base = (void *)nd->elf64;
else if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF32)
elf_base = (void *)nd->elf32;
else
error(FATAL, "no device dumps found in this dumpfile\n");
return elf_base;
}
/*
* extract hardware specific device dumps from coredump.
*/
void
kdump_device_dump_extract(int index, char *outfile, FILE *ofp)
{
ulonglong offset;
void *elf_base;
if (!nd->num_vmcoredd_notes)
error(FATAL, "no device dumps found in this dumpfile\n");
else if (index >= nd->num_vmcoredd_notes)
error(FATAL, "no device dump found at index: %d", index);
elf_base = get_kdump_device_dump_offset();
offset = nd->nt_vmcoredd_array[index] - elf_base;
devdump_extract(nd->nt_vmcoredd_array[index], offset, outfile, ofp);
}
/*
* list all hardware specific device dumps present in coredump.
*/
void kdump_device_dump_info(FILE *ofp)
{
ulonglong offset;
char buf[BUFSIZE];
void *elf_base;
ulong i;
if (!nd->num_vmcoredd_notes)
error(FATAL, "no device dumps found in this dumpfile\n");
fprintf(fp, "%s ", mkstring(buf, strlen("INDEX"), LJUST, "INDEX"));
fprintf(fp, " %s ", mkstring(buf, LONG_LONG_PRLEN, LJUST, "OFFSET"));
fprintf(fp, " %s ", mkstring(buf, LONG_PRLEN, LJUST, "SIZE"));
fprintf(fp, "NAME\n");
elf_base = get_kdump_device_dump_offset();
for (i = 0; i < nd->num_vmcoredd_notes; i++) {
fprintf(fp, "%s ", mkstring(buf, strlen("INDEX"), CENTER | INT_DEC, MKSTR(i)));
offset = nd->nt_vmcoredd_array[i] - elf_base;
devdump_info(nd->nt_vmcoredd_array[i], offset, ofp);
}
}

View File

@ -17,6 +17,7 @@
*/
#include <elf.h>
#include "vmcore.h"
#define MIN_NETDUMP_ELF32_HEADER_SIZE \
sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)+sizeof(Elf32_Phdr)
@ -81,6 +82,8 @@ struct vmcore_data {
#define arch_data1 arch_data
ulong phys_base;
ulong arch_data2;
void *nt_vmcoredd_array[NR_DEVICE_DUMPS];
uint num_vmcoredd_notes;
};
#define DUMP_ELF_INCOMPLETE 0x1 /* dumpfile is incomplete */

36
vmcore.h Normal file
View File

@ -0,0 +1,36 @@
/*
* vmcore.h
*
* Copyright (C) 2019 Chelsio Communications. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _VMCORE_H
#define _VMCORE_H
#include <linux/types.h>
#ifndef NT_VMCOREDD
#define NT_VMCOREDD 0x700
#endif
#define VMCOREDD_NOTE_NAME "LINUX"
#define VMCOREDD_MAX_NAME_BYTES 44
struct vmcoredd_header {
__u32 n_namesz; /* Name size */
__u32 n_descsz; /* Content size */
__u32 n_type; /* NT_VMCOREDD */
__u8 name[8]; /* LINUX\0\0\0 */
__u8 dump_name[VMCOREDD_MAX_NAME_BYTES]; /* Device dump's name */
};
#endif /* _VMCORE_H */