[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200124093200.766629221@linuxfoundation.org>
Date: Fri, 24 Jan 2020 10:32:20 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org,
"Aneesh Kumar K.V" <aneesh.kumar@...ux.ibm.com>,
Michael Ellerman <mpe@...erman.id.au>,
Sasha Levin <sashal@...nel.org>
Subject: [PATCH 4.19 570/639] powerpc/mm/mce: Keep irqs disabled during lockless page table walk
From: Aneesh Kumar K.V <aneesh.kumar@...ux.ibm.com>
[ Upstream commit d9101bfa6adc831bda8836c4d774820553c14942 ]
__find_linux_mm_pte() returns a page table entry pointer after walking
the page table without holding locks. To make it safe against a THP
split and/or collapse, we disable interrupts around the lockless page
table walk. However we need to keep interrupts disabled as long as we
use the page table entry pointer that is returned.
Fix addr_to_pfn() to do that.
Fixes: ba41e1e1ccb9 ("powerpc/mce: Hookup derror (load/store) UE errors")
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@...ux.ibm.com>
[mpe: Rearrange code slightly and tweak change log wording]
Signed-off-by: Michael Ellerman <mpe@...erman.id.au>
Link: https://lore.kernel.org/r/20190918145328.28602-1-aneesh.kumar@linux.ibm.com
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
arch/powerpc/kernel/mce_power.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 37a110b8e7e17..ecb3750406378 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -40,7 +40,7 @@ static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
{
pte_t *ptep;
unsigned int shift;
- unsigned long flags;
+ unsigned long pfn, flags;
struct mm_struct *mm;
if (user_mode(regs))
@@ -50,18 +50,22 @@ static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
local_irq_save(flags);
ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift);
- local_irq_restore(flags);
- if (!ptep || pte_special(*ptep))
- return ULONG_MAX;
+ if (!ptep || pte_special(*ptep)) {
+ pfn = ULONG_MAX;
+ goto out;
+ }
- if (shift > PAGE_SHIFT) {
+ if (shift <= PAGE_SHIFT)
+ pfn = pte_pfn(*ptep);
+ else {
unsigned long rpnmask = (1ul << shift) - PAGE_SIZE;
-
- return pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask)));
+ pfn = pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask)));
}
- return pte_pfn(*ptep);
+out:
+ local_irq_restore(flags);
+ return pfn;
}
/* flush SLBs and reload */
--
2.20.1
Powered by blists - more mailing lists