Commit 5f1888a0 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

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: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/bd07d6fef9237614cd6d318d8f19faeeadaa816b.1607491748.git.christophe.leroy@csgroup.eu
parent cbd7e6ca
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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

/*
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+24 −9
Original line number Diff line number Diff line
@@ -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);
	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);
}