-----Original Message-----
Hi Kazu,
On Tue, Mar 22, 2022 at 07:29:41AM +0000, HAGIO KAZUHITO(萩尾 一仁) wrote:
> -----Original Message-----
> > 1.) When I tested live system with "crash vmlinux /proc/kcore" in
kernel v5.7,
> > I met the following crash issue:
> > ........................................
> > crash: seek error: kernel virtual address: ffff75e9fffff000 type:
"pud page"
> > ........................................
> >
> > 2.) The root cause is the PTOV does not work correctly for some kernel,
> > and then arm64_vtop_4level_4k() does not work correctly too.
> >
> > Why PTOV does not work?
> >
> > The PHYS_OFFSET is just wrapper of memstart_addr.
> > ...............................
> > #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr;
})
> > ...............................
> >
> > Because memstart_addr is changed after physvirt_offset is initialized.
> > so the NUMBER(PHYS_OFFSET) does not return the correct value.
>
> Hmm, it looks like arm64_PTOV() uses the physvirt_offset if available
> (5.4 <= kernel < 5.10), I'm still not sure why it does not work
correctly.
> Would you please explain the issue in more detail?
In arm64_calc_physvirt_offset(void), we try to read out the
physvirt_offset from the live system, and we call read_proc_kcore().
In the read_proc_kcore:
................................................
if (paddr == KCORE_USE_VADDR)
kvaddr = addr;
else
kvaddr = PTOV((ulong)paddr);
................................................
We need the PTOV (arm64_PTOV()) to work correctly.
Unfortunately, arm64_PTOV() uses the ms->phys_offset again..
................................................
ulong arm64_PTOV(ulong paddr)
{
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:
* #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
*/
if (!(machdep->flags & HAS_PHYSVIRT_OFFSET))
return (paddr - ms->phys_offset) | PAGE_OFFSET;
else
return paddr - ms->physvirt_offset;
}
................................................
So the physvirt_offset depends on the NUMBER(PHYS_OFFSET).
Thank you for the explanation.
So does using symbol_value_from_proc_kallsyms() and KCORE_USE_VADDR work?
Several functions in arm64.c already use this way:
if (kernel_symbol_exists("vabits_actual")) {
if (pc->flags & PROC_KCORE) {
vabits_actual =
symbol_value_from_proc_kallsyms("vabits_actual");
if ((vabits_actual != BADVAL) && (READMEM(pc->mfd,
&value, sizeof(ulong),
vabits_actual, KCORE_USE_VADDR) > 0)) {
Thanks,
Kazu