Accepting request 590461 from Kernel:kdump

OBS-URL: https://build.opensuse.org/request/show/590461
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/crash?expand=0&rev=148
This commit is contained in:
2018-03-26 11:05:30 +00:00
committed by Git OBS Bridge
11 changed files with 35 additions and 937 deletions
+19
View File
@@ -1,3 +1,22 @@
-------------------------------------------------------------------
Mon Mar 19 20:42:50 UTC 2018 - dmair@suse.com
- Upgraded to 7.2.1 because it includes the fixes to support
several core cases that recently were caused tofail to open.
As a result, removed patches that were already superceded by
7.2.1 source.
Removed:
crash-ppc64-book3s-update-hash-page-table-geometry.patch
crash-x86_64_kvtop-usable-symtab_init.patch
crash-ppc64-ensure-chosen-stack-symbol-relates-to-an-actual-backtrace.patch
crash-fix-error-cannot-resolve-schedulers-0001.patch
crash-fix-error-cannot-resolve-schedulers-0002.patch
crash-extend-direct-mapping-to-5TB.patch
Modified:
crash-allow-use-of-sadump-captured-KASLR-kernel.patch
-------------------------------------------------------------------
Mon Feb 5 18:56:04 UTC 2018 - dmair@suse.com
+9 -21
View File
@@ -54,9 +54,9 @@ Name: crash
%endif
Url: http://people.redhat.com/anderson/
Summary: Crash utility for live systems; netdump, diskdump, LKCD or mcore dumpfiles
License: GPL-3.0+ and GFDL-1.2
License: GPL-3.0-or-later AND GFDL-1.2-only
Group: Development/Tools/Debuggers
Version: 7.2.0
Version: 7.2.1
Release: 0
Source: %{name}-%{version}.tar.gz
Source2: crash_whitepaper-%{whitepaper_version}.tar.bz2
@@ -83,13 +83,7 @@ Patch13: %{name}-patch-gdb.patch
Patch15: %{name}_enable_snappy_support.patch
Patch16: eppic-support-arm64.patch
Patch18: %{name}-stop_read_error_when_intent_is_retry.patch
Patch19: %{name}-ppc64-book3s-update-hash-page-table-geometry.patch
Patch20: %{name}-x86_64_kvtop-usable-symtab_init.patch
Patch21: %{name}-allow-use-of-sadump-captured-KASLR-kernel.patch
Patch22: %{name}-ppc64-ensure-chosen-stack-symbol-relates-to-an-actual-backtrace.patch
Patch23: %{name}-fix-error-cannot-resolve-schedulers-0001.patch
Patch24: %{name}-fix-error-cannot-resolve-schedulers-0002.patch
Patch25: %{name}-extend-direct-mapping-to-5TB.patch
Patch90: %{name}-sial-ps-2.6.29.diff
BuildRequires: bison
BuildRequires: flex
@@ -110,7 +104,7 @@ ExcludeArch: ppc
BuildRequires: kernel-syms
BuildRequires: module-init-tools
%if 0%{?buildrt}
%if ! 0%{?build_crash_on_obs}
%if ! 0%{?build_crash_on_obs}
BuildRequires: kernel-syms-rt
%endif
%endif
@@ -148,7 +142,7 @@ Authors:
%package doc
Requires: %{name} = %{version}
Summary: Documentation for Crash
License: GFDL-1.2
License: GFDL-1.2-only
Group: Development/Tools/Debuggers
%description doc
@@ -163,7 +157,7 @@ Authors:
%package devel
Requires: %{name} = %{version}
Summary: Development files for crash
License: GPL-2.0+
License: GPL-2.0-or-later
Group: Development/Tools/Debuggers
%description devel
@@ -190,7 +184,7 @@ Provides: %{name}-sial = %{version}
Obsoletes: %{name}-sial < %{version}
%endif
Summary: Embeddable Pre-Processor and Interpreter for C extension for crash
License: GPL-2.0+
License: GPL-2.0-or-later
Group: Development/Tools/Debuggers
%description eppic
@@ -212,7 +206,7 @@ Authors:
%package sial
Requires: %{name} = %{version}
Summary: SIAL extension for crash
License: GPL-2.0+
License: GPL-2.0-or-later
Group: Development/Tools/Debuggers
%description sial
@@ -235,7 +229,7 @@ Authors:
%package gcore
Requires: %{name} = %{version}
Summary: Gcore extension for crash
License: GPL-2.0+
License: GPL-2.0-or-later
Group: Development/Tools/Debuggers
%description gcore
@@ -254,7 +248,7 @@ Authors:
%package %kmp_pkg
Summary: Memory driver for the crash utility
License: GPL-2.0
License: GPL-2.0-only
Group: System/Kernel
%if 0%{?suse_version} < 920
Version: %{version}_%{kver_}
@@ -285,13 +279,7 @@ Authors:
%patch11 -p1
%patch13 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%if %{have_snappy}
%patch15 -p1
%endif
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
@@ -19,537 +19,13 @@ calculate kaslr_offset/phys_base using them.
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
defs.h | 4 +
sadump.c | 465 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
sadump.h | 1 +
symbols.c | 34 +++++
4 files changed, 503 insertions(+), 1 deletion(-)
symbols.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/defs.h b/defs.h
index 7768895..fd181ea 100644
--- a/defs.h
+++ b/defs.h
@@ -2590,6 +2590,9 @@ struct symbol_table_data {
ulong first_section_start;
ulong last_section_end;
ulong _stext_vmlinux;
+ ulong divide_error_vmlinux;
+ ulong idt_table_vmlinux;
+ ulong saved_command_line_vmlinux;
struct downsized downsized;
};
@@ -6309,6 +6312,7 @@ void sadump_set_zero_excluded(void);
void sadump_unset_zero_excluded(void);
struct sadump_data;
struct sadump_data *get_sadump_data(void);
+int sadump_calc_kaslr_offset(ulong *kaslr_offset);
/*
* qemu.c
diff --git a/sadump.c b/sadump.c
index a96ba9c..8d9b342 100644
--- a/sadump.c
+++ b/sadump.c
@@ -1558,12 +1558,17 @@ sadump_display_regs(int cpu, FILE *ofp)
*/
int sadump_phys_base(ulong *phys_base)
{
- if (SADUMP_VALID()) {
+ if (SADUMP_VALID() && !sd->phys_base) {
if (CRASHDEBUG(1))
error(NOTE, "sadump: does not save phys_base.\n");
return FALSE;
}
+ if (sd->phys_base) {
+ *phys_base = sd->phys_base;
+ return TRUE;
+ }
+
return FALSE;
}
@@ -1649,3 +1654,461 @@ get_sadump_data(void)
{
return sd;
}
+
+#ifdef X86_64
+static int
+get_sadump_smram_cpu_state_any(struct sadump_smram_cpu_state *smram)
+{
+ ulong offset;
+ struct sadump_header *sh = sd->dump_header;
+ int apicid;
+ struct sadump_smram_cpu_state scs, zero;
+
+ offset = sd->sub_hdr_offset + sizeof(uint32_t) +
+ sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state);
+
+ memset(&zero, 0, sizeof(zero));
+
+ for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
+ if (!read_device(&scs, sizeof(scs), &offset)) {
+ error(INFO, "sadump: cannot read sub header "
+ "cpu_state\n");
+ return FALSE;
+ }
+ if (memcmp(&scs, &zero, sizeof(scs)) != 0) {
+ *smram = scs;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Get address of vector0 interrupt handler (Devide Error) from Interrupt
+ * Descriptor Table.
+ */
+static ulong
+get_vec0_addr(ulong idtr)
+{
+ struct gate_struct64 {
+ uint16_t offset_low;
+ uint16_t segment;
+ uint32_t ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
+ uint16_t offset_middle;
+ uint32_t offset_high;
+ uint32_t zero1;
+ } __attribute__((packed)) gate;
+
+ readmem(idtr, PHYSADDR, &gate, sizeof(gate), "idt_table", FAULT_ON_ERROR);
+
+ return ((ulong)gate.offset_high << 32)
+ + ((ulong)gate.offset_middle << 16)
+ + gate.offset_low;
+}
+
+/*
+ * Parse a string of [size[KMG]@]offset[KMG]
+ * Import from Linux kernel(lib/cmdline.c)
+ */
+static ulong memparse(char *ptr, char **retptr)
+{
+ char *endptr;
+
+ unsigned long long ret = strtoull(ptr, &endptr, 0);
+
+ switch (*endptr) {
+ case 'E':
+ case 'e':
+ ret <<= 10;
+ case 'P':
+ case 'p':
+ ret <<= 10;
+ case 'T':
+ case 't':
+ ret <<= 10;
+ case 'G':
+ case 'g':
+ ret <<= 10;
+ case 'M':
+ case 'm':
+ ret <<= 10;
+ case 'K':
+ case 'k':
+ ret <<= 10;
+ endptr++;
+ default:
+ break;
+ }
+
+ if (retptr)
+ *retptr = endptr;
+
+ return ret;
+}
+
+/*
+ * Find "elfcorehdr=" in the boot parameter of kernel and return the address
+ * of elfcorehdr.
+ */
+static ulong
+get_elfcorehdr(ulong cr3, ulong kaslr_offset)
+{
+ char cmdline[BUFSIZE], *ptr;
+ ulong cmdline_vaddr;
+ ulong cmdline_paddr;
+ ulong buf_vaddr, buf_paddr;
+ char *end;
+ ulong elfcorehdr_addr = 0, elfcorehdr_size = 0;
+ int verbose = CRASHDEBUG(1)? 1: 0;
+
+ cmdline_vaddr = st->saved_command_line_vmlinux + kaslr_offset;
+ if (!kvtop(NULL, cmdline_vaddr, &cmdline_paddr, verbose))
+ return 0;
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "cmdline vaddr=%lx\n", cmdline_vaddr);
+ fprintf(fp, "cmdline paddr=%lx\n", cmdline_paddr);
+ }
+
+ if (!readmem(cmdline_paddr, PHYSADDR, &buf_vaddr, sizeof(ulong),
+ "saved_command_line", RETURN_ON_ERROR))
+ return 0;
+
+ if (!kvtop(NULL, buf_vaddr, &buf_paddr, verbose))
+ return 0;
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "cmdline buffer vaddr=%lx\n", buf_vaddr);
+ fprintf(fp, "cmdline buffer paddr=%lx\n", buf_paddr);
+ }
+
+ memset(cmdline, 0, BUFSIZE);
+ if (!readmem(buf_paddr, PHYSADDR, cmdline, BUFSIZE,
+ "saved_command_line", RETURN_ON_ERROR))
+ return 0;
+
+ ptr = strstr(cmdline, "elfcorehdr=");
+ if (!ptr)
+ return 0;
+
+ if (CRASHDEBUG(1))
+ fprintf(fp, "2nd kernel detected\n");
+
+ ptr += strlen("elfcorehdr=");
+ elfcorehdr_addr = memparse(ptr, &end);
+ if (*end == '@') {
+ elfcorehdr_size = elfcorehdr_addr;
+ elfcorehdr_addr = memparse(end + 1, &end);
+ }
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "elfcorehdr_addr=%lx\n", elfcorehdr_addr);
+ fprintf(fp, "elfcorehdr_size=%lx\n", elfcorehdr_size);
+ }
+
+ return elfcorehdr_addr;
+}
+
+ /*
+ * Get vmcoreinfo from elfcorehdr.
+ * Some codes are imported from Linux kernel(fs/proc/vmcore.c)
+ */
+static int
+get_vmcoreinfo(ulong elfcorehdr, ulong *addr, int *len)
+{
+ unsigned char e_ident[EI_NIDENT];
+ Elf64_Ehdr ehdr;
+ Elf64_Phdr phdr;
+ Elf64_Nhdr nhdr;
+ ulong ptr;
+ ulong nhdr_offset = 0;
+ int i;
+
+ if (!readmem(elfcorehdr, PHYSADDR, e_ident, EI_NIDENT,
+ "EI_NIDENT", RETURN_ON_ERROR))
+ return FALSE;
+
+ if (e_ident[EI_CLASS] != ELFCLASS64) {
+ error(INFO, "Only ELFCLASS64 is supportd\n");
+ return FALSE;
+ }
+
+ if (!readmem(elfcorehdr, PHYSADDR, &ehdr, sizeof(ehdr),
+ "Elf64_Ehdr", RETURN_ON_ERROR))
+ return FALSE;
+
+ /* Sanity Check */
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+ (ehdr.e_type != ET_CORE) ||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_version != EV_CURRENT ||
+ ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
+ ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
+ ehdr.e_phnum == 0) {
+ error(INFO, "Invalid elf header\n");
+ return FALSE;
+ }
+
+ ptr = elfcorehdr + ehdr.e_phoff;
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ ulong offset;
+ char name[16];
+
+ if (!readmem(ptr, PHYSADDR, &phdr, sizeof(phdr),
+ "Elf64_Phdr", RETURN_ON_ERROR))
+ return FALSE;
+
+ ptr += sizeof(phdr);
+ if (phdr.p_type != PT_NOTE)
+ continue;
+
+ offset = phdr.p_offset;
+ if (!readmem(offset, PHYSADDR, &nhdr, sizeof(nhdr),
+ "Elf64_Nhdr", RETURN_ON_ERROR))
+ return FALSE;
+
+ offset += DIV_ROUND_UP(sizeof(Elf64_Nhdr), sizeof(Elf64_Word))*
+ sizeof(Elf64_Word);
+ memset(name, 0, sizeof(name));
+ if (!readmem(offset, PHYSADDR, name, sizeof(name),
+ "Elf64_Nhdr name", RETURN_ON_ERROR))
+ return FALSE;
+
+ if(!strcmp(name, "VMCOREINFO")) {
+ nhdr_offset = offset;
+ break;
+ }
+ }
+
+ if (!nhdr_offset)
+ return FALSE;
+
+ *addr = nhdr_offset +
+ DIV_ROUND_UP(nhdr.n_namesz, sizeof(Elf64_Word))*
+ sizeof(Elf64_Word);
+ *len = nhdr.n_descsz;
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "vmcoreinfo addr=%lx\n", *addr);
+ fprintf(fp, "vmcoreinfo len=%d\n", *len);
+ }
+
+ return TRUE;
+}
+
+/*
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd kernel.
+ * If we are in 2nd kernel, get kaslr_offset/phys_base from vmcoreinfo.
+ *
+ * 1. Get command line and try to retrieve "elfcorehdr=" boot parameter
+ * 2. If "elfcorehdr=" is not found in command line, we are in 1st kernel.
+ * There is nothing to do.
+ * 3. If "elfcorehdr=" is found, we are in 2nd kernel. Find vmcoreinfo
+ * using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
+ */
+static int
+get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
+ ulong *kaslr_offset, ulong *phys_base)
+{
+ ulong elfcorehdr_addr = 0;
+ ulong vmcoreinfo_addr;
+ int vmcoreinfo_len;
+ char *buf, *pos;
+ int ret = FALSE;
+
+ /* Find "elfcorehdr=" in the kernel boot parameter */
+ elfcorehdr_addr = get_elfcorehdr(cr3, orig_kaslr_offset);
+ if (!elfcorehdr_addr)
+ return FALSE;
+
+ /* Get vmcoreinfo from the address of "elfcorehdr=" */
+ if (!get_vmcoreinfo(elfcorehdr_addr, &vmcoreinfo_addr, &vmcoreinfo_len))
+ return FALSE;
+
+ if (!vmcoreinfo_len)
+ return FALSE;
+
+ if (CRASHDEBUG(1))
+ fprintf(fp, "Find vmcoreinfo in kdump memory\n");
+
+ buf = GETBUF(vmcoreinfo_len);
+ if (!readmem(vmcoreinfo_addr, PHYSADDR, buf, vmcoreinfo_len,
+ "vmcoreinfo", RETURN_ON_ERROR))
+ goto quit;
+
+ /* Get phys_base form vmcoreinfo */
+ pos = strstr(buf, "NUMBER(phys_base)=");
+ if (!pos)
+ goto quit;
+ *phys_base = strtoull(pos + strlen("NUMBER(phys_base)="), NULL, 0);
+
+ /* Get kaslr_offset form vmcoreinfo */
+ pos = strstr(buf, "KERNELOFFSET=");
+ if (!pos)
+ goto quit;
+ *kaslr_offset = strtoull(pos + strlen("KERNELOFFSET="), NULL, 16);
+
+ ret = TRUE;
+
+quit:
+ FREEBUF(buf);
+ return ret;
+}
+
+/*
+ * Calculate kaslr_offset and phys_base
+ *
+ * kaslr_offset:
+ * The difference between original address in System.map or vmlinux and
+ * actual address placed randomly by kaslr feature. To be more accurate,
+ * kaslr_offset = actual address - original address
+ *
+ * phys_base:
+ * Physical address where the kerenel is placed. In other words, it's a
+ * physical address of __START_KERNEL_map. This is also decided randomly by
+ * kaslr.
+ *
+ * kaslr offset and phys_base are calculated as follows:
+ *
+ * kaslr_offset:
+ * 1) Get IDTR and CR3 value from the dump header.
+ * 2) Get a virtual address of IDT from IDTR value
+ * --- (A)
+ * 3) Translate (A) to physical address using CR3, which points a top of
+ * page table.
+ * --- (B)
+ * 4) Get an address of vector0 (Devide Error) interrupt handler from
+ * IDT, which are pointed by (B).
+ * --- (C)
+ * 5) Get an address of symbol "divide_error" form vmlinux
+ * --- (D)
+ *
+ * Now we have two addresses:
+ * (C)-> Actual address of "divide_error"
+ * (D)-> Original address of "divide_error" in the vmlinux
+ *
+ * kaslr_offset can be calculated by the difference between these two
+ * value.
+ *
+ * phys_base;
+ * 1) Get IDT virtual address from vmlinux
+ * --- (E)
+ *
+ * So phys_base can be calculated using relationship of directly mapped
+ * address.
+ *
+ * phys_base =
+ * Physical address(B) -
+ * (Virtual address(E) + kaslr_offset - __START_KERNEL_map)
+ *
+ * Note that the address (A) cannot be used instead of (E) because (A) is
+ * not direct map address, it's a fixed map address.
+ *
+ * This solution works in most every case, but does not work in the
+ * following case.
+ *
+ * 1) If the dump is captured on early stage of kernel boot, IDTR points
+ * early IDT table(early_idts) instead of normal IDT(idt_table).
+ * 2) If the dump is captured whle kdump is working, IDTR points
+ * IDT table of 2nd kernel, not 1st kernel.
+ *
+ * Current implementation does not support the case 1), need
+ * enhancement in the future. For the case 2), get kaslr_offset and
+ * phys_base as follows.
+ *
+ * 1) Get kaslr_offset and phys_base using the above solution.
+ * 2) Get kernel boot parameter from "saved_command_line"
+ * 3) If "elfcorehdr=" is not included in boot parameter, we are in the
+ * first kernel, nothing to do any more.
+ * 4) If "elfcorehdr=" is included in boot parameter, we are in the 2nd
+ * kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
+ * get kaslr_offset and phys_base from vmcoreinfo.
+ */
+int
+sadump_calc_kaslr_offset(ulong *kaslr_offset)
+{
+ ulong phys_base = 0;
+ struct sadump_smram_cpu_state scs;
+ uint64_t idtr = 0, cr3 = 0, idtr_paddr;
+ ulong divide_error_vmcore;
+ ulong kaslr_offset_kdump, phys_base_kdump;
+ int ret = FALSE;
+ int verbose = CRASHDEBUG(1)? 1: 0;
+
+ if (!machine_type("X86_64"))
+ return FALSE;
+
+ memset(&scs, 0, sizeof(scs));
+ get_sadump_smram_cpu_state_any(&scs);
+ cr3 = scs.Cr3;
+ idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
+
+ /*
+ * Set up for kvtop.
+ *
+ * calc_kaslr_offset() is called before machdep_init(PRE_GDB), so some
+ * variables are not initialized yet. Set up them here to call kvtop().
+ *
+ * TODO: XEN and 5-level is not supported
+ */
+ vt->kernel_pgd[0] = cr3;
+ machdep->machspec->last_pml4_read = vt->kernel_pgd[0];
+ machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
+ machdep->machspec->pgdir_shift = PGDIR_SHIFT;
+ if (!readmem(cr3, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
+ "cr3", RETURN_ON_ERROR))
+ goto quit;
+
+ /* Convert virtual address of IDT table to physical address */
+ if (!kvtop(NULL, idtr, &idtr_paddr, verbose))
+ goto quit;
+
+ /* Now we can calculate kaslr_offset and phys_base */
+ divide_error_vmcore = get_vec0_addr(idtr_paddr);
+ *kaslr_offset = divide_error_vmcore - st->divide_error_vmlinux;
+ phys_base = idtr_paddr -
+ (st->idt_table_vmlinux + *kaslr_offset - __START_KERNEL_map);
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr);
+ fprintf(fp, "calc_kaslr_offset: cr3=%lx\n", cr3);
+ fprintf(fp, "calc_kaslr_offset: idtr(phys)=%lx\n", idtr_paddr);
+ fprintf(fp, "calc_kaslr_offset: divide_error(vmlinux): %lx\n",
+ st->divide_error_vmlinux);
+ fprintf(fp, "calc_kaslr_offset: divide_error(vmcore): %lx\n",
+ divide_error_vmcore);
+ }
+
+ /*
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd
+ * kernel. If we are in 2nd kernel, get kaslr_offset/phys_base
+ * from vmcoreinfo
+ */
+ if (get_kaslr_offset_from_vmcoreinfo(
+ cr3, *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
+ *kaslr_offset = kaslr_offset_kdump;
+ phys_base = phys_base_kdump;
+ }
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "calc_kaslr_offset: kaslr_offset=%lx\n",
+ *kaslr_offset);
+ fprintf(fp, "calc_kaslr_offset: phys_base=%lx\n", phys_base);
+ }
+
+ sd->phys_base = phys_base;
+ ret = TRUE;
+quit:
+ vt->kernel_pgd[0] = 0;
+ machdep->machspec->last_pml4_read = 0;
+ return ret;
+}
+#else
+int
+sadump_calc_kaslr_offset(ulong *kaslr_offset)
+{
+ return FALSE;
+}
+#endif /* X86_64 */
diff --git a/sadump.h b/sadump.h
index 7f8e384..681f5e4 100644
--- a/sadump.h
+++ b/sadump.h
@@ -219,6 +219,7 @@ struct sadump_data {
ulonglong backup_offset;
uint64_t max_mapnr;
+ ulong phys_base;
};
struct sadump_data *sadump_get_sadump_data(void);
diff --git a/symbols.c b/symbols.c
index 02cb34e..e7eaac2 100644
--- a/symbols.c
+++ b/symbols.c
@@ -624,6 +624,9 @@ kaslr_init(void)
st->_stext_vmlinux = UNINITIALIZED;
@@ -1133,6 +1133,9 @@ symname_hash_install(struct syment *spn)
}
}
}
+
@@ -558,48 +34,3 @@ index 02cb34e..e7eaac2 100644
}
/*
@@ -637,6 +640,19 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
unsigned long relocate;
ulong _stext_relocated;
+ if (SADUMP_DUMPFILE()) {
+ ulong kaslr_offset = 0;
+
+ sadump_calc_kaslr_offset(&kaslr_offset);
+
+ if (kaslr_offset) {
+ kt->relocate = kaslr_offset * -1;
+ kt->flags |= RELOC_SET;
+ }
+
+ return;
+ }
+
if (ACTIVE()) {
_stext_relocated = symbol_value_from_proc_kallsyms("_stext");
if (_stext_relocated == BADVAL)
@@ -12246,6 +12262,24 @@ numeric_forward(const void *P_x, const void *P_y)
}
}
+ if (SADUMP_DUMPFILE()) {
+ /* Need for kaslr_offset and phys_base */
+ if (STREQ(x->name, "divide_error"))
+ st->divide_error_vmlinux = valueof(x);
+ else if (STREQ(y->name, "divide_error"))
+ st->divide_error_vmlinux = valueof(y);
+
+ if (STREQ(x->name, "idt_table"))
+ st->idt_table_vmlinux = valueof(x);
+ else if (STREQ(y->name, "idt_table"))
+ st->idt_table_vmlinux = valueof(y);
+
+ if (STREQ(x->name, "saved_command_line"))
+ st->saved_command_line_vmlinux = valueof(x);
+ else if (STREQ(y->name, "saved_command_line"))
+ st->saved_command_line_vmlinux = valueof(y);
+ }
+
xs = bfd_get_section(x);
ys = bfd_get_section(y);
-29
View File
@@ -1,29 +0,0 @@
From: Petr Tesarik <ptesarik@suse.com>
Subject: Extend Xen hypervisor direct mapping on x86_64
References: bsc#1073993
Upstream: merged
Git-commit: e9ae5eb9749a62060610dc29d1b2829999bc79d3
Xen commit 615588563e99a23aaf37037c3fee0c413b051f4d (Xen 4.0.0.)
extended the direct mapping to 5 TB. This area was previously
reserved for future use, so it is OK to simply change the upper
bound unconditionally.
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
xen_hyper_defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen_hyper_defs.h b/xen_hyper_defs.h
index 6d5d256..b871bdd 100644
--- a/xen_hyper_defs.h
+++ b/xen_hyper_defs.h
@@ -63,7 +63,7 @@
#define HYPERVISOR_VIRT_START (0xffff800000000000)
#define HYPERVISOR_VIRT_END (0xffff880000000000)
#define DIRECTMAP_VIRT_START (0xffff830000000000)
-#define DIRECTMAP_VIRT_END (0xffff840000000000)
+#define DIRECTMAP_VIRT_END (0xffff880000000000)
#define PAGE_OFFSET_XEN_HYPER DIRECTMAP_VIRT_START
#define XEN_VIRT_START (xht->xen_virt_start)
#define XEN_VIRT_ADDR(vaddr) \
@@ -1,80 +0,0 @@
From: Nikola Pajkovsky <npajkovsky@suse.cz>
Subject: dynamically allocate schedulers_buf
References: bsc#1073993
Upstream: merged
Git-commit: e4499a9de664826b0db2f650684959c2f3f9998c
crash can simply determinate length of xen schedulers struct.
static const struct scheduler *schedulers[] = {
...
};
Signed-off-by: Nikola Pajkovsky <npajkovsky@suse.cz>
---
xen_hyper.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/xen_hyper.c b/xen_hyper.c
index 27e44c6e733d..479aa1acfd43 100644
--- a/xen_hyper.c
+++ b/xen_hyper.c
@@ -435,7 +435,6 @@ xen_hyper_misc_init(void)
/*
* Do initialization for scheduler of Xen Hyper system here.
*/
-#define XEN_HYPER_SCHEDULERS_ARRAY_CNT 10
#define XEN_HYPER_SCHEDULER_NAME 1024
static void
@@ -443,7 +442,8 @@ xen_hyper_schedule_init(void)
{
ulong addr, opt_sched, schedulers, opt_name;
long scheduler_opt_name;
- long schedulers_buf[XEN_HYPER_SCHEDULERS_ARRAY_CNT];
+ long *schedulers_buf;
+ int nr_schedulers;
struct xen_hyper_sched_context *schc;
char *buf;
char opt_name_buf[XEN_HYPER_OPT_SCHED_SIZE];
@@ -469,15 +469,17 @@ xen_hyper_schedule_init(void)
XEN_HYPER_OPT_SCHED_SIZE, "opt_sched,", RETURN_ON_ERROR)) {
error(FATAL, "cannot read opt_sched,.\n");
}
+ nr_schedulers = get_array_length("schedulers", 0, 0);
+ schedulers_buf = (long *)GETBUF(nr_schedulers * sizeof(long));
schedulers = symbol_value("schedulers");
addr = schedulers;
while (xhscht->name == NULL) {
if (!readmem(addr, KVADDR, schedulers_buf,
- sizeof(long) * XEN_HYPER_SCHEDULERS_ARRAY_CNT,
- "schedulers", RETURN_ON_ERROR)) {
+ sizeof(long) * nr_schedulers,
+ "schedulers", RETURN_ON_ERROR)) {
error(FATAL, "cannot read schedulers.\n");
}
- for (i = 0; i < XEN_HYPER_SCHEDULERS_ARRAY_CNT; i++) {
+ for (i = 0; i < nr_schedulers; i++) {
if (schedulers_buf[i] == 0) {
error(FATAL, "schedule data not found.\n");
}
@@ -514,9 +516,10 @@ xen_hyper_schedule_init(void)
strncpy(xhscht->name, buf, strlen(buf));
break;
}
- addr += sizeof(long) * XEN_HYPER_SCHEDULERS_ARRAY_CNT;
+ addr += sizeof(long) * nr_schedulers;
}
FREEBUF(buf);
+ FREEBUF(schedulers_buf);
/* get schedule_data information */
if((xhscht->sched_context_array =
--
2.13.6
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
@@ -1,84 +0,0 @@
From: Nikola Pajkovsky <npajkovsky@suse.cz>
Subject: fix error crash: cannot resolve "schedulers"
References: bsc#1073993
Upstream: merged
Git-commit: e4499a9de664826b0db2f650684959c2f3f9998c
Since Xen commit 666aca08175b ("sched: use the auto-generated list of
schedulers") crash cannot open Xen vmcores, because symbol 'schedulers'
does not exist. Xen 4.7 implemented schedulers as its own section.
xen/arch/x86/xen.lds.S
__start_schedulers_array = .;
*(.data.schedulers)
__end_schedulers_array = .;
Crash must not look up for "schedulers" symbol and fails, if symbol is
not found. It must check if __start_schedulers_array exits, and if it
does, use it and get size of the section. Otherwise, crash fallback to
looking up "schedulers" symbol. That way, crash can open vmcore before
and after Xen 4.7.
Signed-off-by: Nikola Pajkovsky <npajkovsky@suse.cz>
---
xen_hyper.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/xen_hyper.c b/xen_hyper.c
index 479aa1acfd43..2a42e44b1f70 100644
--- a/xen_hyper.c
+++ b/xen_hyper.c
@@ -437,6 +437,16 @@ xen_hyper_misc_init(void)
*/
#define XEN_HYPER_SCHEDULER_NAME 1024
+static int section_size(char *start_section, char *end_section)
+{
+ ulong sp_start, sp_end;
+
+ sp_start = symbol_value(start_section);
+ sp_end = symbol_value(end_section);
+
+ return (sp_end - sp_start) / sizeof(long);
+}
+
static void
xen_hyper_schedule_init(void)
{
@@ -448,6 +458,7 @@ xen_hyper_schedule_init(void)
char *buf;
char opt_name_buf[XEN_HYPER_OPT_SCHED_SIZE];
int i, cpuid, flag;
+ char *sp_name;
/* get scheduler information */
if((xhscht->scheduler_struct =
@@ -469,9 +480,19 @@ xen_hyper_schedule_init(void)
XEN_HYPER_OPT_SCHED_SIZE, "opt_sched,", RETURN_ON_ERROR)) {
error(FATAL, "cannot read opt_sched,.\n");
}
- nr_schedulers = get_array_length("schedulers", 0, 0);
+
+ /* symbol exists since Xen 4.7 */
+ if (symbol_exists("__start_schedulers_array")) {
+ sp_name = "__start_schedulers_array";
+ nr_schedulers = section_size("__start_schedulers_array",
+ "__end_schedulers_array");
+ } else {
+ sp_name = "schedulers";
+ nr_schedulers = get_array_length("schedulers", 0, 0);
+ }
+
schedulers_buf = (long *)GETBUF(nr_schedulers * sizeof(long));
- schedulers = symbol_value("schedulers");
+ schedulers = symbol_value(sp_name);
addr = schedulers;
while (xhscht->name == NULL) {
if (!readmem(addr, KVADDR, schedulers_buf,
--
2.13.6
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
@@ -1,52 +0,0 @@
Update for support of Linux 4.14 and later PPC64 kernels where the
From: Dave Anderson <anderson@redhat.com>
hash page table geometry accomodates a larger virtual address range.
Without the patch, the virtual-to-physical translation of user space
virtual addresses by "vm -p", "vtop", and "rd -u" may generate an
invalid translation or otherwise fail.
(hbathini@linux.vnet.ibm.com)
---
defs.h | 3 +++
ppc64.c | 12 +++++++++---
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/defs.h b/defs.h
index 154a5b9..f2c3f50 100644
--- a/defs.h
+++ b/defs.h
@@ -3857,6 +3857,9 @@ struct efi_memory_desc_t {
#define PGD_INDEX_SIZE_L4_64K_3_10 12
#define PMD_INDEX_SIZE_L4_64K_4_6 5
#define PUD_INDEX_SIZE_L4_64K_4_6 5
+#define PMD_INDEX_SIZE_L4_64K_4_12 10
+#define PUD_INDEX_SIZE_L4_64K_4_12 7
+#define PGD_INDEX_SIZE_L4_64K_4_12 8
#define PTE_INDEX_SIZE_RADIX_64K 5
#define PMD_INDEX_SIZE_RADIX_64K 9
#define PUD_INDEX_SIZE_RADIX_64K 9
diff --git a/ppc64.c b/ppc64.c
index edf46dc..77ac09f 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -447,10 +447,16 @@ ppc64_init(int when)
} else if (!(machdep->flags & BOOK3E) &&
(THIS_KERNEL_VERSION >= LINUX(4,6,0))) {
m->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
- m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
- m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6;
- m->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10;
+ if (THIS_KERNEL_VERSION >= LINUX(4,12,0)) {
+ m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_12;
+ m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_12;
+ m->l4_index_size = PGD_INDEX_SIZE_L4_64K_4_12;
+ } else {
+ m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
+ m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6;
+ m->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10;
+ }
} else if (THIS_KERNEL_VERSION >= LINUX(3,10,0)) {
m->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
m->l2_index_size = PMD_INDEX_SIZE_L4_64K_3_10;
@@ -1,33 +0,0 @@
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Subject: ppc64: fix bt for secondary threads for NMI IPIs
References: bsc#1072718
Upstream: merged
Git-commit: ed2abb47be9846be7a47d769c420ee3992cc0196
With latest NMI IPI changes, crash_ipi_callback is found multiple times
on the stack. Ensure the chosen symbol relates to an actual backtrace.
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
ppc64.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/ppc64.c b/ppc64.c
index 672ee60..0b04187 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -2337,6 +2337,14 @@ retry:
*nip = *up;
*ksp = bt->stackbase +
((char *)(up) - 16 - bt->stackbuf);
+ /*
+ * Check whether this symbol relates to a
+ * backtrace or not
+ */
+ ur_ksp = *(ulong *)&bt->stackbuf[(*ksp) - bt->stackbase];
+ if (!INSTACK(ur_ksp, bt))
+ continue;
+
return TRUE;
}
}
@@ -1,62 +0,0 @@
This patch changes x86_64_kvtop() so that it can be called during
symtab_init().
To solve kaslr problem of sadump, kaslr offset and phys_base need to be
calculated before symbol data is loaded. This calculation needs
translation of kernel virtual address to physical address. Current
x86_64_kvtop() implementation tries to use x86_64_VTOP for translation
at first, but this does not work for this purpose because x86_64_VTOP
uses phys_base. x86_64_kvtop() need to be changed to skip x86_64_VTOP()
during sadump initialization.
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
x86_64.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/x86_64.c b/x86_64.c
index 6e60dda..2f9e6db 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -194,6 +194,9 @@ x86_64_init(int when)
machdep->machspec->kernel_image_size = dtol(string, QUIET, NULL);
free(string);
}
+ if (SADUMP_DUMPFILE())
+ /* Need for calculation of kaslr_offset and phys_base */
+ machdep->kvtop = x86_64_kvtop;
break;
case PRE_GDB:
@@ -2019,6 +2022,22 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
ulong pte;
physaddr_t physpage;
+ if (SADUMP_DUMPFILE() && !(machdep->flags & KSYMS_START)) {
+ /*
+ * In the case of sadump, to calculate kaslr_offset and
+ * phys_base, kvtop is called during symtab_init(). In this
+ * stage phys_base is not initialized yet and x86_64_VTOP()
+ * does not work. Jump to the code of pagetable translation.
+ */
+ FILL_PML4();
+ pml4 = ((ulong *)machdep->machspec->pml4) + pml4_index(kvaddr);
+ if (verbose) {
+ fprintf(fp, "PML4 DIRECTORY: %lx\n", vt->kernel_pgd[0]);
+ fprintf(fp, "PAGE DIRECTORY: %lx\n", *pml4);
+ }
+ goto start_vtop_with_pagetable;
+ }
+
if (!IS_KVADDR(kvaddr))
return FALSE;
@@ -2065,6 +2084,8 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
fprintf(fp, "PAGE DIRECTORY: %lx\n", *pml4);
}
}
+
+start_vtop_with_pagetable:
if (!(*pml4) & _PAGE_PRESENT)
goto no_kpage;
pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;