Commit a3483c3d authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

powerpc/code-patching: Fix unmap_patch_area() error handling

pXd_offset() doesn't return NULL. When the base is NULL, it
still adds the offset.

Use pXd_none() to check validity instead. It also improves
performance by folding out none existing levels as pXd_none()
always returns 0 in that case.

Such an error is unexpected, use WARN_ON() so that the caller
doesn't have to worry about it, and drop the returned value.

And now that unmap_patch_area() doesn't return error, we can
take into account the error returned by __patch_instruction().

While at it, remove the 'inline' property which is useless.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/299804b117fae35c786c827536c91f25352e279b.1638446239.git.christophe.leroy@csgroup.eu
parent 285672f9
...@@ -94,7 +94,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr) ...@@ -94,7 +94,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr)
return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL); return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
} }
static inline int unmap_patch_area(unsigned long addr) static void unmap_patch_area(unsigned long addr)
{ {
pte_t *ptep; pte_t *ptep;
pmd_t *pmdp; pmd_t *pmdp;
...@@ -103,32 +103,30 @@ static inline int unmap_patch_area(unsigned long addr) ...@@ -103,32 +103,30 @@ static inline int unmap_patch_area(unsigned long addr)
pgd_t *pgdp; pgd_t *pgdp;
pgdp = pgd_offset_k(addr); pgdp = pgd_offset_k(addr);
if (unlikely(!pgdp)) if (WARN_ON(pgd_none(*pgdp)))
return -EINVAL; return;
p4dp = p4d_offset(pgdp, addr); p4dp = p4d_offset(pgdp, addr);
if (unlikely(!p4dp)) if (WARN_ON(p4d_none(*p4dp)))
return -EINVAL; return;
pudp = pud_offset(p4dp, addr); pudp = pud_offset(p4dp, addr);
if (unlikely(!pudp)) if (WARN_ON(pud_none(*pudp)))
return -EINVAL; return;
pmdp = pmd_offset(pudp, addr); pmdp = pmd_offset(pudp, addr);
if (unlikely(!pmdp)) if (WARN_ON(pmd_none(*pmdp)))
return -EINVAL; return;
ptep = pte_offset_kernel(pmdp, addr); ptep = pte_offset_kernel(pmdp, addr);
if (unlikely(!ptep)) if (WARN_ON(pte_none(*ptep)))
return -EINVAL; return;
/* /*
* In hash, pte_clear flushes the tlb, in radix, we have to * In hash, pte_clear flushes the tlb, in radix, we have to
*/ */
pte_clear(&init_mm, addr, ptep); pte_clear(&init_mm, addr, ptep);
flush_tlb_kernel_range(addr, addr + PAGE_SIZE); flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
return 0;
} }
static int do_patch_instruction(u32 *addr, ppc_inst_t instr) static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
...@@ -156,11 +154,9 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr) ...@@ -156,11 +154,9 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
patch_addr = (u32 *)(text_poke_addr + (kaddr & ~PAGE_MASK)); patch_addr = (u32 *)(text_poke_addr + (kaddr & ~PAGE_MASK));
__patch_instruction(addr, instr, patch_addr); err = __patch_instruction(addr, instr, patch_addr);
err = unmap_patch_area(text_poke_addr); unmap_patch_area(text_poke_addr);
if (err)
pr_warn("failed to unmap %lx\n", text_poke_addr);
out: out:
local_irq_restore(flags); local_irq_restore(flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment