mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
powerpc/fault: Perform exception fixup in do_page_fault()
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
This commit is contained in:
parent
cbd7e6ca02
commit
5f1888a077
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
@ -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)) {
|
||||
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user