diff options
Diffstat (limited to 'arch/powerpc/kernel/mce_power.c')
-rw-r--r-- | arch/powerpc/kernel/mce_power.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 37a110b8e7e1..ecb375040637 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) | |||
40 | { | 40 | { |
41 | pte_t *ptep; | 41 | pte_t *ptep; |
42 | unsigned int shift; | 42 | unsigned int shift; |
43 | unsigned long flags; | 43 | unsigned long pfn, flags; |
44 | struct mm_struct *mm; | 44 | struct mm_struct *mm; |
45 | 45 | ||
46 | if (user_mode(regs)) | 46 | if (user_mode(regs)) |
@@ -50,18 +50,22 @@ static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) | |||
50 | 50 | ||
51 | local_irq_save(flags); | 51 | local_irq_save(flags); |
52 | ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift); | 52 | ptep = __find_linux_pte(mm->pgd, addr, NULL, &shift); |
53 | local_irq_restore(flags); | ||
54 | 53 | ||
55 | if (!ptep || pte_special(*ptep)) | 54 | if (!ptep || pte_special(*ptep)) { |
56 | return ULONG_MAX; | 55 | pfn = ULONG_MAX; |
56 | goto out; | ||
57 | } | ||
57 | 58 | ||
58 | if (shift > PAGE_SHIFT) { | 59 | if (shift <= PAGE_SHIFT) |
60 | pfn = pte_pfn(*ptep); | ||
61 | else { | ||
59 | unsigned long rpnmask = (1ul << shift) - PAGE_SIZE; | 62 | unsigned long rpnmask = (1ul << shift) - PAGE_SIZE; |
60 | 63 | pfn = pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask))); | |
61 | return pte_pfn(__pte(pte_val(*ptep) | (addr & rpnmask))); | ||
62 | } | 64 | } |
63 | 65 | ||
64 | return pte_pfn(*ptep); | 66 | out: |
67 | local_irq_restore(flags); | ||
68 | return pfn; | ||
65 | } | 69 | } |
66 | 70 | ||
67 | /* flush SLBs and reload */ | 71 | /* flush SLBs and reload */ |