The kernel vmcore may contain a new elf-note of type NT_NOCOREDUMP. Include this
new note, whose address and length are made available at
/sys/kernel/nt_nocoredump, while loading elf-headers.
Signed-off-by: K.Prasad <prasad(a)linux.vnet.ibm.com>
---
diff --git a/kexec/crashdump-elf.c b/kexec/crashdump-elf.c
index 8d82db9..b009227 100644
--- a/kexec/crashdump-elf.c
+++ b/kexec/crashdump-elf.c
@@ -39,7 +39,9 @@ int FUNC(struct kexec_info *info,
long int nr_cpus = 0;
uint64_t notes_addr, notes_len;
uint64_t vmcoreinfo_addr, vmcoreinfo_len;
+ uint64_t nt_nocoredump_addr, nt_nocoredump_len;
int has_vmcoreinfo = 0;
+ int has_nt_nocoredump = 0;
uint64_t vmcoreinfo_addr_xen, vmcoreinfo_len_xen;
int has_vmcoreinfo_xen = 0;
int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len);
@@ -57,6 +59,9 @@ int FUNC(struct kexec_info *info,
has_vmcoreinfo = 1;
}
+ if (get_kernel_nt_nocoredump(&nt_nocoredump_addr, &nt_nocoredump_len) == 0)
+ has_nt_nocoredump = 1;
+
if (xen_present() &&
get_xen_vmcoreinfo(&vmcoreinfo_addr_xen, &vmcoreinfo_len_xen) == 0) {
has_vmcoreinfo_xen = 1;
@@ -179,6 +184,21 @@ int FUNC(struct kexec_info *info,
dbgprintf_phdr("vmcoreinfo header", phdr);
}
+ if (has_nt_nocoredump && !(info->kexec_flags & KEXEC_PRESERVE_CONTEXT))
{
+ phdr = (PHDR *) bufp;
+ bufp += sizeof(PHDR);
+ phdr->p_type = PT_NOTE;
+ phdr->p_flags = 0;
+ phdr->p_offset = phdr->p_paddr = nt_nocoredump_addr;
+ phdr->p_vaddr = 0;
+ phdr->p_filesz = phdr->p_memsz = nt_nocoredump_len;
+ /* Do we need any alignment of segments? */
+ phdr->p_align = 0;
+
+ (elf->e_phnum)++;
+ dbgprintf_phdr("nocoredump note present", phdr);
+ }
+
if (has_vmcoreinfo_xen) {
phdr = (PHDR *) bufp;
bufp += sizeof(PHDR);
diff --git a/kexec/crashdump.c b/kexec/crashdump.c
index 945b052..0ee05f0 100644
--- a/kexec/crashdump.c
+++ b/kexec/crashdump.c
@@ -136,12 +136,43 @@ static int get_vmcoreinfo(const char *kdump_info, uint64_t *addr,
uint64_t *len)
return 0;
}
+static int get_nt_nocoredump(const char *kdump_info, uint64_t *addr, uint64_t *len)
+{
+ char line[MAX_LINE];
+ int count;
+ FILE *fp;
+ unsigned int temp2;
+ unsigned long long temp;
+
+ *addr = 0;
+ *len = 0;
+
+ if (!(fp = fopen(kdump_info, "r")))
+ return -1;
+ if (!fgets(line, sizeof(line), fp))
+ die("Cannot parse %s: %s\n", kdump_info, strerror(errno));
+ count = sscanf(line, "%Lx %x", &temp, &temp2);
+ if (count != 2)
+ die("Cannot parse %s: %s\n", kdump_info, strerror(errno));
+
+ *addr = (uint64_t) temp;
+ *len = (uint64_t) temp2;
+
+ fclose(fp);
+ return 0;
+}
/* Returns the physical address of start of crash notes buffer for a kernel. */
int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len)
{
return get_vmcoreinfo("/sys/kernel/vmcoreinfo", addr, len);
}
+/* Returns the physical address of start of nocoredump buffer for a kernel. */
+int get_kernel_nt_nocoredump(uint64_t *addr, uint64_t *len)
+{
+ return get_nt_nocoredump("/sys/kernel/nt_nocoredump", addr, len);
+}
+
int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len)
{
return get_vmcoreinfo("/sys/hypervisor/vmcoreinfo", addr, len);
--
1.7.4.1