Skip to content

Commit

Permalink
powerpc/fault: Perform exception fixup in do_page_fault()
Browse files Browse the repository at this point in the history
Exception fixup doesn't require the heady full regs saving,
do it from do_page_fault() directly.

For that, split bad_page_fault() in two parts.

As bad_page_fault() can also be called from other places than
handle_page_fault(), it will still perform exception fixup and
fallback on __bad_page_fault().

handle_page_fault() directly calls __bad_page_fault() as the
exception fixup will now be done by do_page_fault()

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/bd07d6fef9237614cd6d318d8f19faeeadaa816b.1607491748.git.christophe.leroy@csgroup.eu
  • Loading branch information
Christophe Leroy authored and Michael Ellerman committed Dec 9, 2020
1 parent cbd7e6c commit 5f1888a
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 12 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/bug.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
struct pt_regs;
extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
extern void bad_page_fault(struct pt_regs *, unsigned long, int);
void __bad_page_fault(struct pt_regs *regs, unsigned long address, int sig);
extern void _exception(int, struct pt_regs *, int, unsigned long);
extern void _exception_pkey(struct pt_regs *, unsigned long, int);
extern void die(const char *, struct pt_regs *, long);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ handle_page_fault:
mr r5,r3
addi r3,r1,STACK_FRAME_OVERHEAD
lwz r4,_DAR(r1)
bl bad_page_fault
bl __bad_page_fault
b ret_from_except_full

#ifdef CONFIG_PPC_BOOK3S_32
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/exceptions-64e.S
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ storage_fault_common:
mr r5,r3
addi r3,r1,STACK_FRAME_OVERHEAD
ld r4,_DAR(r1)
bl bad_page_fault
bl __bad_page_fault
b ret_from_except

/*
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/exceptions-64s.S
Original file line number Diff line number Diff line change
Expand Up @@ -3259,7 +3259,7 @@ handle_page_fault:
mr r5,r3
addi r3,r1,STACK_FRAME_OVERHEAD
ld r4,_DAR(r1)
bl bad_page_fault
bl __bad_page_fault
b interrupt_return

/* We have a data breakpoint exception - handle it */
Expand Down
33 changes: 24 additions & 9 deletions arch/powerpc/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,10 +545,20 @@ NOKPROBE_SYMBOL(__do_page_fault);
int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
const struct exception_table_entry *entry;
enum ctx_state prev_state = exception_enter();
int rc = __do_page_fault(regs, address, error_code);
exception_exit(prev_state);
return rc;
if (likely(!rc))
return 0;

entry = search_exception_tables(regs->nip);
if (unlikely(!entry))
return rc;

instruction_pointer_set(regs, extable_fixup(entry));

return 0;
}
NOKPROBE_SYMBOL(do_page_fault);

Expand All @@ -557,17 +567,10 @@ NOKPROBE_SYMBOL(do_page_fault);
* It is called from the DSI and ISI handlers in head.S and from some
* of the procedures in traps.c.
*/
void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
void __bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
{
const struct exception_table_entry *entry;
int is_write = page_fault_is_write(regs->dsisr);

/* Are we prepared to handle this fault? */
if ((entry = search_exception_tables(regs->nip)) != NULL) {
regs->nip = extable_fixup(entry);
return;
}

/* kernel has accessed a bad area */

switch (TRAP(regs)) {
Expand Down Expand Up @@ -601,3 +604,15 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)

die("Kernel access of bad area", regs, sig);
}

void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
{
const struct exception_table_entry *entry;

/* Are we prepared to handle this fault? */
entry = search_exception_tables(instruction_pointer(regs));
if (entry)
instruction_pointer_set(regs, extable_fixup(entry));
else
__bad_page_fault(regs, address, sig);
}

0 comments on commit 5f1888a

Please sign in to comment.