powerpc/crashdump : Fix page frame number check in copy_oldmem_page
In copy_oldmem_page, the current check using max_pfn and min_low_pfn to decide if the page is backed or not, is not valid when the memory layout is not continuous. This happens when running as a QEMU/KVM guest, where RTAS is mapped higher in the memory. In that case max_pfn points to the end of RTAS, and a hole between the end of the kdump kernel and RTAS is not backed by PTEs. As a consequence, the kdump kernel is crashing in copy_oldmem_page when accessing in a direct way the pages in that hole. This fix relies on the memblock's service memblock_is_region_memory to check if the read page is part or not of the directly accessible memory. Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> Tested-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> CC: <stable@vger.kernel.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
committed by
Benjamin Herrenschmidt
parent
41dd03a94c
commit
f5295bd8ea
@@ -98,17 +98,19 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
|||||||
size_t csize, unsigned long offset, int userbuf)
|
size_t csize, unsigned long offset, int userbuf)
|
||||||
{
|
{
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
|
phys_addr_t paddr;
|
||||||
|
|
||||||
if (!csize)
|
if (!csize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
csize = min_t(size_t, csize, PAGE_SIZE);
|
csize = min_t(size_t, csize, PAGE_SIZE);
|
||||||
|
paddr = pfn << PAGE_SHIFT;
|
||||||
|
|
||||||
if ((min_low_pfn < pfn) && (pfn < max_pfn)) {
|
if (memblock_is_region_memory(paddr, csize)) {
|
||||||
vaddr = __va(pfn << PAGE_SHIFT);
|
vaddr = __va(paddr);
|
||||||
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
|
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
|
||||||
} else {
|
} else {
|
||||||
vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
|
vaddr = __ioremap(paddr, PAGE_SIZE, 0);
|
||||||
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
|
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
|
||||||
iounmap(vaddr);
|
iounmap(vaddr);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user