powerpc/mce: Fix MCE handling for huge pages
The current code would fail on huge pages addresses, since the shift would
be incorrect. Use the correct page shift value returned by
__find_linux_pte() to get the correct physical address. The code is more
generic and can handle both regular and compound pages.
Fixes: ba41e1e1cc
("powerpc/mce: Hookup derror (load/store) UE errors")
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
[arbab@linux.ibm.com: Fixup pseries_do_memory_failure()]
Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
Tested-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
Cc: stable@vger.kernel.org # v4.15+
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190820081352.8641-3-santosh@fossix.org
This commit is contained in:
parent
b5bda6263c
commit
99ead78afd
|
@ -26,6 +26,7 @@
|
|||
unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
|
||||
{
|
||||
pte_t *ptep;
|
||||
unsigned int shift;
|
||||
unsigned long flags;
|
||||
struct mm_struct *mm;
|
||||
|
||||
|
@ -35,13 +36,18 @@ unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
|
|||
mm = &init_mm;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (mm == current->mm)
|
||||
ptep = find_current_mm_pte(mm->pgd, addr, NULL, NULL);
|
||||
else
|
||||
ptep = find_init_mm_pte(addr, NULL);
|
||||
ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift);
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (!ptep || pte_special(*ptep))
|
||||
return ULONG_MAX;
|
||||
|
||||
if (shift > PAGE_SHIFT) {
|
||||
unsigned long rpnmask = (1ul << shift) - PAGE_SIZE;
|
||||
|
||||
return pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask)));
|
||||
}
|
||||
|
||||
return pte_pfn(*ptep);
|
||||
}
|
||||
|
||||
|
@ -344,7 +350,7 @@ static const struct mce_derror_table mce_p9_derror_table[] = {
|
|||
MCE_INITIATOR_CPU, MCE_SEV_SEVERE, true },
|
||||
{ 0, false, 0, 0, 0, 0, 0 } };
|
||||
|
||||
static int mce_find_instr_ea_and_pfn(struct pt_regs *regs, uint64_t *addr,
|
||||
static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
|
||||
uint64_t *phys_addr)
|
||||
{
|
||||
/*
|
||||
|
@ -541,7 +547,8 @@ static int mce_handle_derror(struct pt_regs *regs,
|
|||
* kernel/exception-64s.h
|
||||
*/
|
||||
if (get_paca()->in_mce < MAX_MCE_DEPTH)
|
||||
mce_find_instr_ea_and_pfn(regs, addr, phys_addr);
|
||||
mce_find_instr_ea_and_phys(regs, addr,
|
||||
phys_addr);
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue