在 2021年04月07日 17:16, Pingfan Liu 写道: > Crash encounters a bug like the following: > ... > License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> > This is free software: you are free to change and redistribute it. > There is NO WARRANTY, to the extent permitted by law. Type "show copying" > and "show warranty" for details. > This GDB was configured as "aarch64-unknown-linux-gnu"... > > crash: read error: kernel virtual address: ffff000f789c0050 type: "IRQ stack pointer" > crash: read error: kernel virtual address: ffff000f78a60050 type: "IRQ stack pointer" > crash: read error: kernel virtual address: ffff000f78b00050 type: "IRQ stack pointer" > ... > > This bug connects with kernel commit 7bc1a0f9e176 ("arm64: mm: use > single quantity to represent the PA to VA translation"), memstart_addr > can be negative, which makes it different from real phys_offset. > > In crash utility, PTOV() needs memstart_addr to calculate VA from PA, > while getting PFN offset in a dumpfile, phys_offset is required. > > To serve the different purpose, using phys_offset_nominal and > phys_offset to store them. > > Signed-off-by: Pingfan Liu <piliu@xxxxxxxxxx> > Cc: HAGIO KAZUHITO <k-hagio-ab@xxxxxxx> > Cc: Lianbo Jiang <lijiang@xxxxxxxxxx> > Cc: Bhupesh Sharma <bhupesh.sharma@xxxxxxxxxx> > Cc: Mark Salter <msalter@xxxxxxxxxx> > Cc: Mark Langsdorf <mlangsdo@xxxxxxxxxx> > Cc: Jeremy Linton <jlinton@xxxxxxxxxx> > To: crash-utility@xxxxxxxxxx > --- > v2 -> v3: > rename ms->memstart_addr as ms->phys_offset_nominal ( I keep the name > as phys_offset* since it is in accordance with other platform > conventions) > --- > arm64.c | 25 ++++++++++++++++++++++--- > defs.h | 3 +++ > 2 files changed, 25 insertions(+), 3 deletions(-) > > diff --git a/arm64.c b/arm64.c > index 37aed07..5e567ca 100644 > --- a/arm64.c > +++ b/arm64.c > @@ -24,6 +24,9 @@ > > #define NOT_IMPLEMENTED(X) error((X), "%s: function not implemented\n", __func__) > > +#define MEMSTART_ADDR_OFFSET \ > + (0xffffffffffffffff << 48 - 0xffffffffffffffff << 56) > + Since the micro 'MEMSTART_ADDR_OFFSET' is only used in the arm64_calc_phys_offset(), can we define the micro in the arm64_calc_phys_offset() as below and easily use it in this function? static void arm64_calc_phys_offset(void) { + /* + * sources: arch/arm64/include/asm/memory.h + */ + #define _PAGE_OFFSET(va) (-(UL(1) << (va))) ...... + ms->phys_offset = ms->phys_offset_nominal + (_PAGE_OFFSET(48) - _PAGE_OFFSET(56)); ...... } Thanks. Lianbo > static struct machine_specific arm64_machine_specific = { 0 }; > static int arm64_verify_symbol(const char *, ulong, char); > static void arm64_parse_cmdline_args(void); > @@ -687,6 +690,7 @@ arm64_dump_machdep_table(ulong arg) > fprintf(fp, " kimage_voffset: %016lx\n", ms->kimage_voffset); > } > fprintf(fp, " phys_offset: %lx\n", ms->phys_offset); > + fprintf(fp, " phys_offset_nominal: %lx\n", ms->phys_offset_nominal); > fprintf(fp, "__exception_text_start: %lx\n", ms->__exception_text_start); > fprintf(fp, " __exception_text_end: %lx\n", ms->__exception_text_end); > fprintf(fp, " __irqentry_text_start: %lx\n", ms->__irqentry_text_start); > @@ -987,7 +991,7 @@ arm64_calc_physvirt_offset(void) > ulong physvirt_offset; > struct syment *sp; > > - ms->physvirt_offset = ms->phys_offset - ms->page_offset; > + ms->physvirt_offset = ms->phys_offset_nominal - ms->page_offset; > > if ((sp = kernel_symbol_search("physvirt_offset")) && > machdep->machspec->kimage_voffset) { > @@ -1028,7 +1032,11 @@ arm64_calc_phys_offset(void) > ms->kimage_voffset && (sp = kernel_symbol_search("memstart_addr"))) { > if (pc->flags & PROC_KCORE) { > if ((string = pc->read_vmcoreinfo("NUMBER(PHYS_OFFSET)"))) { > - ms->phys_offset = htol(string, QUIET, NULL); > + ms->phys_offset_nominal = htol(string, QUIET, NULL); > + if (ms->phys_offset_nominal < 0) > + ms->phys_offset = ms->phys_offset_nominal + MEMSTART_ADDR_OFFSET; > + else > + ms->phys_offset = ms->phys_offset_nominal; > free(string); > return; > } > @@ -1080,7 +1088,18 @@ arm64_calc_phys_offset(void) > } else if (DISKDUMP_DUMPFILE() && diskdump_phys_base(&phys_offset)) { > ms->phys_offset = phys_offset; > } else if (KDUMP_DUMPFILE() && arm64_kdump_phys_base(&phys_offset)) { > - ms->phys_offset = phys_offset; > + /* > + * When running a 52bits kernel on 48bits hardware. Kernel plays a trick: > + * if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) > + * memstart_addr -= _PAGE_OFFSET(48) - _PAGE_OFFSET(52); > + * > + * In crash, this should be detected to get a real physical start address. > + */ > + ms->phys_offset_nominal = phys_offset; > + if ((long)phys_offset < 0) > + ms->phys_offset = phys_offset + MEMSTART_ADDR_OFFSET; > + else > + ms->phys_offset = phys_offset; > } else { > error(WARNING, > "phys_offset cannot be determined from the dumpfile.\n"); > diff --git a/defs.h b/defs.h > index 35b983a..09d58e0 100644 > --- a/defs.h > +++ b/defs.h > @@ -3289,7 +3289,10 @@ struct machine_specific { > ulong vmemmap_end; > ulong modules_vaddr; > ulong modules_end; > + /* real physical offset */ > ulong phys_offset; > + /* read from kernel symbol memstart_addr */ > + long phys_offset_nominal; > ulong __exception_text_start; > ulong __exception_text_end; > struct arm64_pt_regs *panic_task_regs; > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility