-----Original Message----- > > > @@ -1033,7 +1050,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; > > > } > > > > If it's /dev/mem (not /proc/kcore), the memstart_addr value is still negative? > > It's no problem? > > I have no big picture about /dev/mem. > But for the value, memstart_addr's calculation is done by > arch/arm64/mm/init.c:349: memstart_addr -= _PAGE_OFFSET(48) - _PAGE_OFFSET(52); > in arm64_memblock_init(). > > Does it raise issue for /dev/mem ? Could you enlighten me about your idea? Recently /proc/kcore has had ELF note vmcoreinfo, so crash can read it, but in case of /dev/mem, it cannot be used and crash will read the memstart_addr value with the following READMEM(). In this case, I thought that the same offset adjustment would be needed in theory. if (ACTIVE()) { ... if ((machdep->flags & NEW_VMEMMAP) && 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_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; } vaddr = symbol_value_from_proc_kallsyms("memstart_addr"); if (vaddr == BADVAL) vaddr = sp->value; paddr = KCORE_USE_VADDR; } else { vaddr = sp->value; paddr = sp->value - machdep->machspec->kimage_voffset; } if (READMEM(pc->mfd, &phys_offset, sizeof(phys_offset), vaddr, paddr) > 0) { ms->phys_offset = phys_offset; <<-- read from memstart_addr return; } > > > > > @@ -1085,7 +1106,18 @@ arm64_calc_phys_offset(void) > > > } else if (DISKDUMP_DUMPFILE() && diskdump_phys_base(&phys_offset)) { > > > ms->phys_offset = phys_offset; > > > > makedumpfile also set kdump_sub_header.phys_base to NUMBER(PHYS_OFFSET) ? > > I miss this diskdump. It should also have the same logic. > > diff --git a/arm64.c b/arm64.c > index 6346753..cd84a74 100644 > --- a/arm64.c > +++ b/arm64.c > @@ -1108,9 +1108,8 @@ arm64_calc_phys_offset(void) > return; > > ms->phys_offset = phys_offset; > - } else if (DISKDUMP_DUMPFILE() && diskdump_phys_base(&phys_offset)) { > - ms->phys_offset = phys_offset; > - } else if (KDUMP_DUMPFILE() && arm64_kdump_phys_base(&phys_offset)) { > + } else if ((DISKDUMP_DUMPFILE() && diskdump_phys_base(&phys_offset)) || > + (KDUMP_DUMPFILE() && arm64_kdump_phys_base(&phys_offset))) { Oh, this looks nicely done. > /* > * When running a 52bits kernel on 48bits hardware. Kernel plays a trick: > * if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) > -- > 2.29.2 > > > > > > } 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"); > > > @@ -1175,6 +1207,23 @@ arm64_init_kernel_pgd(void) > > > vt->kernel_pgd[i] = value; > > > } > > > > > > +ulong arm64_PTOV(ulong paddr) > > > +{ > > > + ulong v; > > > + struct machine_specific *ms = machdep->machspec; > > > + > > > + /* > > > + * Either older kernel before kernel has 'physvirt_offset' or newer kernel which > > > + * removes 'physvirt_offset' has the same formula > > > + */ > > > + if (!(machdep->flags & HAS_PHYSVIRT_OFFSET)) > > > + v = (paddr - ms->physvirt_offset) | PAGE_OFFSET; > > > + else > > > + v = paddr - ms->physvirt_offset; > > > + > > > + return v; > > > +} > > > + > > > ulong > > > arm64_VTOP(ulong addr) > > > { > > > @@ -1185,8 +1234,20 @@ arm64_VTOP(ulong addr) > > > return addr - machdep->machspec->kimage_voffset; > > > } > > > > > > - if (addr >= machdep->machspec->page_offset) > > > - return addr + machdep->machspec->physvirt_offset; > > > + if (addr >= machdep->machspec->page_offset) { > > > + ulong paddr; > > > + > > > + if (!(machdep->flags & FLIPPED_VM) || (machdep->flags & HAS_PHYSVIRT_OFFSET)) { > > > + paddr = addr; > > > + } else { > > > + /* > > > + * #define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) > > > + */ > > > + paddr = addr & ~ _PAGE_OFFSET(machdep->machspec->CONFIG_ARM64_VA_BITS); > > > + } > > > + paddr += machdep->machspec->physvirt_offset; > > > + return paddr; > > > > Hmm, complex. It should be symmetric to PTOV, why differences? > > Not sure that I catch your meaning. Replacing _PAGE_OFFSET(machdep->machspec->CONFIG_ARM64_VA_BITS) with > PAGE_OFFSET ? > Something like this ? > > diff --git a/arm64.c b/arm64.c > index 9a77628..0917613 100644 > --- a/arm64.c > +++ b/arm64.c > @@ -1241,15 +1241,14 @@ arm64_VTOP(ulong addr) > ulong paddr; > > if (!(machdep->flags & FLIPPED_VM) || (machdep->flags & HAS_PHYSVIRT_OFFSET)) { > - paddr = addr; > + return addr + machdep->machspec->physvirt_offset; > } else { > /* > * #define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) > */ > - paddr = addr & ~ _PAGE_OFFSET(machdep->machspec->CONFIG_ARM64_VA_BITS); > + paddr = addr & ~ PAGE_OFFSET; > + return paddr + machdep->machspec->physvirt_offset; > } > - paddr += machdep->machspec->physvirt_offset; > - return paddr; Yes, it's one of them, and this looks better, but... Hmm ok, I summarized these and smy question why they're asymmetric emerged: if physvirt_offset exists // HAS_PHYSVIRT_OFFSET ms->physvirt_offset = read physvirt_offset; else if (machdep->flags & FLIPPED_VM) ms->physvirt_offset = ms->phys_offset_nominal; else // !FLIPPED_VM ms->physvirt_offset = ms->phys_offset - ms->page_offset; PTOV: if (machdep->flags & HAS_PHYSVIRT_OFFSET) v = paddr - ms->physvirt_offset; // looks ok else v = (paddr - ms->physvirt_offset) | PAGE_OFFSET; // Is this ok when !FLIPPED_VM ? VTOP: if (machdep->flags & HAS_PHYSVIRT_OFFSET || !(machdep->flags & FLIPPED_VM)) p = vaddr + ms->physvirt_offset; // looks ok else p = (vaddr & ~PAGE_OFFSET) + ms->physvirt_offset; // looks ok When !FLIPPED_VM, PTOV calculates: v = (paddr - ms->physvirt_offset) | PAGE_OFFSET = (paddr - ms->physoffset + ms->page_offset) | PAGE_OFFSET This might be not wrong in the result value because of the or operation, but looks wrong formula. So PTOV also needs the !(machdep->flags & FLIPPED_VM) condition? or I'm missing something? Thanks, Kazu > } > else if (machdep->machspec->kimage_voffset) > return addr - machdep->machspec->kimage_voffset; > > > > Again, appreciate your review. > > > Thanks, > Pingfan -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility