[Crash-utility] [PATCH 2/2] arm64: fix the "pud page" crash for live system

Huang Shijie shijie at os.amperecomputing.com
Tue Mar 22 16:03:28 UTC 2022


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).

Thanks
Huang Shijie



More information about the Crash-utility mailing list