Skip to content

Commit

Permalink
powerpc/32: Dismantle EXC_XFER_STD/LITE/TEMPLATE
Browse files Browse the repository at this point in the history
In order to get more control in exception prolog, dismantle
all non standard exception macros, finishing with EXC_XFER_STD
and EXC_XFER_LITE and EXC_XFER_TEMPLATE.

Also remove transfer_to_handler_full and ret_from_except and
ret_from_except_full as they are not used anymore.

Last parameter of EXCEPTION() is now ignored, will be removed
in a later patch to avoid too much churn.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/ca5795d04a220586b7037dbbbe6951dfa9e768eb.1615552867.git.christophe.leroy@csgroup.eu
  • Loading branch information
Christophe Leroy authored and Michael Ellerman committed Mar 29, 2021
1 parent 8f6ff5b commit 4c0104a
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 106 deletions.
42 changes: 1 addition & 41 deletions arch/powerpc/kernel/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -48,44 +48,13 @@
*/
.align 12

#ifdef CONFIG_BOOKE
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
/* fall through */
_ASM_NOKPROBE_SYMBOL(mcheck_transfer_to_handler)

.globl debug_transfer_to_handler
debug_transfer_to_handler:
/* fall through */
_ASM_NOKPROBE_SYMBOL(debug_transfer_to_handler)

.globl crit_transfer_to_handler
crit_transfer_to_handler:
/* fall through */
_ASM_NOKPROBE_SYMBOL(crit_transfer_to_handler)
#endif

#ifdef CONFIG_40x
.globl crit_transfer_to_handler
crit_transfer_to_handler:
/* fall through */
_ASM_NOKPROBE_SYMBOL(crit_transfer_to_handler)
#endif

/*
* This code finishes saving the registers to the exception frame
* and jumps to the appropriate handler for the exception, turning
* on address translation.
* Note that we rely on the caller having set cr0.eq iff the exception
* occurred in kernel mode (i.e. MSR:PR = 0).
*/
.globl transfer_to_handler_full
transfer_to_handler_full:
_ASM_NOKPROBE_SYMBOL(transfer_to_handler_full)
/* fall through */

.globl transfer_to_handler
transfer_to_handler:
.globl prepare_transfer_to_handler
prepare_transfer_to_handler:
SAVE_NVGPRS(r11)
Expand Down Expand Up @@ -136,7 +105,6 @@ transfer_to_handler_cont:
b fast_exception_return
#endif
_ASM_NOKPROBE_SYMBOL(prepare_transfer_to_handler)
_ASM_NOKPROBE_SYMBOL(transfer_to_handler)
_ASM_NOKPROBE_SYMBOL(transfer_to_handler_cont)

.globl transfer_to_syscall
Expand Down Expand Up @@ -352,18 +320,10 @@ _ASM_NOKPROBE_SYMBOL(fast_exception_return)
3:
li r10,-1
stw r10,_TRAP(r11)
bl transfer_to_handler_full
prepare_transfer_to_handler
bl unrecoverable_exception
trap /* should not get here */

.globl ret_from_except_full
ret_from_except_full:
/* fall through */

.globl ret_from_except
ret_from_except:
_ASM_NOKPROBE_SYMBOL(ret_from_except)

.globl interrupt_return
interrupt_return:
lwz r4,_MSR(r1)
Expand Down
21 changes: 6 additions & 15 deletions arch/powerpc/kernel/head_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
#define EXCEPTION(n, label, hdlr, xfer) \
START_EXCEPTION(n, label) \
EXCEPTION_PROLOG n label; \
xfer(n, hdlr)

#define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \
bl tfer; \
bl hdlr; \
b ret

#define EXC_XFER_STD(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full, \
ret_from_except_full)

#define EXC_XFER_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler, \
ret_from_except)
prepare_transfer_to_handler; \
bl hdlr; \
b interrupt_return

.macro vmap_stack_overflow_exception
__HEAD
Expand All @@ -218,7 +207,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
lwz r1, emergency_ctx@l(r1)
addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
EXCEPTION_PROLOG_2 0 vmap_stack_overflow
EXC_XFER_STD(0, stack_overflow_exception)
prepare_transfer_to_handler
bl stack_overflow_exception
b interrupt_return
.endm

#endif /* __HEAD_32_H__ */
33 changes: 21 additions & 12 deletions arch/powerpc/kernel/head_40x.S
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
#define CRITICAL_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(n, label); \
CRITICAL_EXCEPTION_PROLOG n label; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
crit_transfer_to_handler, ret_from_crit_exc)
prepare_transfer_to_handler; \
bl hdlr; \
b ret_from_crit_exc

/*
* 0x0100 - Critical Interrupt Exception
Expand All @@ -209,7 +210,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
*/
START_EXCEPTION(0x0300, DataStorage)
EXCEPTION_PROLOG 0x300 DataStorage handle_dar_dsisr=1
EXC_XFER_LITE(0x300, do_page_fault)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return

/*
* 0x0400 - Instruction Storage Exception
Expand All @@ -220,7 +223,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
li r5,0
stw r5, _ESR(r11) /* Zero ESR */
stw r12, _DEAR(r11) /* SRR0 as DEAR */
EXC_XFER_LITE(0x400, do_page_fault)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return

/* 0x0500 - External Interrupt Exception */
EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
Expand Down Expand Up @@ -499,31 +504,35 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt)
/* continue normal handling for a critical exception... */
2: mfspr r4,SPRN_DBSR
stw r4,_ESR(r11) /* DebugException takes DBSR in _ESR */
EXC_XFER_TEMPLATE(DebugException, 0x2002, \
(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
crit_transfer_to_handler, ret_from_crit_exc)
prepare_transfer_to_handler
bl DebugException
b ret_from_crit_exc

/* Programmable Interval Timer (PIT) Exception. (from 0x1000) */
__HEAD
Decrementer:
EXCEPTION_PROLOG 0x1000 Decrementer
lis r0,TSR_PIS@h
mtspr SPRN_TSR,r0 /* Clear the PIT exception */
EXC_XFER_LITE(0x1000, timer_interrupt)
prepare_transfer_to_handler
bl timer_interrupt
b interrupt_return

/* Fixed Interval Timer (FIT) Exception. (from 0x1010) */
__HEAD
FITException:
EXCEPTION_PROLOG 0x1010 FITException
EXC_XFER_STD(0x1010, unknown_exception)
prepare_transfer_to_handler
bl unknown_exception
b interrupt_return

/* Watchdog Timer (WDT) Exception. (from 0x1020) */
__HEAD
WDTException:
CRITICAL_EXCEPTION_PROLOG 0x1020 WDTException
EXC_XFER_TEMPLATE(WatchdogException, 0x1020+2,
(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),
crit_transfer_to_handler, ret_from_crit_exc)
prepare_transfer_to_handler
bl WatchdogException
b ret_from_crit_exc

/* Other PowerPC processors, namely those derived from the 6xx-series
* have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
Expand Down
12 changes: 9 additions & 3 deletions arch/powerpc/kernel/head_8xx.S
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ instruction_counter:
/* Machine check */
START_EXCEPTION(0x200, MachineCheck)
EXCEPTION_PROLOG 0x200 MachineCheck handle_dar_dsisr=1
EXC_XFER_STD(0x200, machine_check_exception)
prepare_transfer_to_handler
bl machine_check_exception
b interrupt_return

/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
Expand Down Expand Up @@ -314,7 +316,9 @@ instruction_counter:
.Litlbie:
stw r12, _DAR(r11)
stw r5, _DSISR(r11)
EXC_XFER_LITE(0x400, do_page_fault)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return

/* This is the data TLB error on the MPC8xx. This could be due to
* many reasons, including a dirty update to a pte. We bail out to
Expand All @@ -335,7 +339,9 @@ DARFixed:/* Return from dcbx instruction bug workaround */
beq+ .Ldtlbie
tlbie r4
.Ldtlbie:
EXC_XFER_LITE(0x300, do_page_fault)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return

#ifdef CONFIG_VMAP_STACK
vmap_stack_overflow_exception
Expand Down
27 changes: 19 additions & 8 deletions arch/powerpc/kernel/head_book3s_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ __secondary_hold_acknowledge:
beq cr1, 1f
twi 31, 0, 0
#endif
1: EXC_XFER_STD(0x200, machine_check_exception)
1: prepare_transfer_to_handler
bl machine_check_exception
b interrupt_return

/* Data access exception. */
START_EXCEPTION(0x300, DataAccess)
Expand All @@ -296,12 +298,13 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
1: EXCEPTION_PROLOG_0 handle_dar_dsisr=1
EXCEPTION_PROLOG_1
EXCEPTION_PROLOG_2 0x300 DataAccess handle_dar_dsisr=1
prepare_transfer_to_handler
lwz r5, _DSISR(r11)
andis. r0, r5, DSISR_DABRMATCH@h
bne- 1f
EXC_XFER_LITE(0x300, do_page_fault)
1: prepare_transfer_to_handler
bl do_break
bl do_page_fault
b interrupt_return
1: bl do_break
REST_NVGPRS(r1)
b interrupt_return

Expand Down Expand Up @@ -331,7 +334,9 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
stw r5, _DSISR(r11)
stw r12, _DAR(r11)
EXC_XFER_LITE(0x400, do_page_fault)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return

/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
Expand Down Expand Up @@ -366,7 +371,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
beq 1f
bl load_up_fpu /* if from user, just load it up */
b fast_exception_return
1: EXC_XFER_LITE(0x800, kernel_fp_unavailable_exception)
1: prepare_transfer_to_handler
bl kernel_fp_unavailable_exception
b interrupt_return
#else
b ProgramCheck
#endif
Expand Down Expand Up @@ -730,12 +737,16 @@ AltiVecUnavailable:
bl load_up_altivec /* if from user, just load it up */
b fast_exception_return
#endif /* CONFIG_ALTIVEC */
1: EXC_XFER_LITE(0xf20, altivec_unavailable_exception)
1: prepare_transfer_to_handler
bl altivec_unavailable_exception
b interrupt_return

__HEAD
PerformanceMonitor:
EXCEPTION_PROLOG 0xf00 PerformanceMonitor
EXC_XFER_STD(0xf00, performance_monitor_exception)
prepare_transfer_to_handler
bl performance_monitor_exception
b interrupt_return


__HEAD
Expand Down
49 changes: 26 additions & 23 deletions arch/powerpc/kernel/head_booke.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,18 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
#define EXCEPTION(n, intno, label, hdlr, xfer) \
START_EXCEPTION(label); \
NORMAL_EXCEPTION_PROLOG(n, intno); \
xfer(n, hdlr)
prepare_transfer_to_handler; \
bl hdlr; \
b interrupt_return

#define CRITICAL_EXCEPTION(n, intno, label, hdlr) \
START_EXCEPTION(label); \
CRITICAL_EXCEPTION_PROLOG(n, intno); \
SAVE_MMU_REGS; \
SAVE_xSRR(SRR); \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
crit_transfer_to_handler, ret_from_crit_exc)
prepare_transfer_to_handler; \
bl hdlr; \
b ret_from_crit_exc

#define MCHECK_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
Expand All @@ -321,21 +324,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
SAVE_xSRR(CSRR); \
SAVE_MMU_REGS; \
SAVE_xSRR(SRR); \
EXC_XFER_TEMPLATE(hdlr, n+4, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
mcheck_transfer_to_handler, ret_from_mcheck_exc)

#define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \
bl tfer; \
prepare_transfer_to_handler; \
bl hdlr; \
b ret; \

#define EXC_XFER_STD(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler_full, \
ret_from_except_full)

#define EXC_XFER_LITE(n, hdlr) \
EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, transfer_to_handler, \
ret_from_except)
b ret_from_mcheck_exc

/* Check for a single step debug exception while in an exception
* handler before state has been saved. This is to catch the case
Expand Down Expand Up @@ -404,7 +395,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
SAVE_xSRR(CSRR); \
SAVE_MMU_REGS; \
SAVE_xSRR(SRR); \
EXC_XFER_TEMPLATE(DebugException, 0x2008, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), debug_transfer_to_handler, ret_from_debug_exc)
prepare_transfer_to_handler; \
bl DebugException; \
b ret_from_debug_exc

#define DEBUG_CRIT_EXCEPTION \
START_EXCEPTION(DebugCrit); \
Expand Down Expand Up @@ -459,7 +452,9 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
stw r4,_ESR(r11); /* DebugException takes DBSR in _ESR */\
SAVE_MMU_REGS; \
SAVE_xSRR(SRR); \
EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), crit_transfer_to_handler, ret_from_crit_exc)
prepare_transfer_to_handler; \
bl DebugException; \
b ret_from_crit_exc

#define DATA_STORAGE_EXCEPTION \
START_EXCEPTION(DataStorage) \
Expand All @@ -468,15 +463,19 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
stw r5,_ESR(r11); \
mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \
stw r4, _DEAR(r11); \
EXC_XFER_LITE(0x0300, do_page_fault)
prepare_transfer_to_handler; \
bl do_page_fault; \
b interrupt_return

#define INSTRUCTION_STORAGE_EXCEPTION \
START_EXCEPTION(InstructionStorage) \
NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \
mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
stw r5,_ESR(r11); \
stw r12, _DEAR(r11); /* Pass SRR0 as arg2 */ \
EXC_XFER_LITE(0x0400, do_page_fault)
prepare_transfer_to_handler; \
bl do_page_fault; \
b interrupt_return

#define ALIGNMENT_EXCEPTION \
START_EXCEPTION(Alignment) \
Expand All @@ -503,15 +502,19 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
NORMAL_EXCEPTION_PROLOG(0x900, DECREMENTER); \
lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \
mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \
EXC_XFER_LITE(0x0900, timer_interrupt)
prepare_transfer_to_handler; \
bl timer_interrupt; \
b interrupt_return

#define FP_UNAVAILABLE_EXCEPTION \
START_EXCEPTION(FloatingPointUnavailable) \
NORMAL_EXCEPTION_PROLOG(0x800, FP_UNAVAIL); \
beq 1f; \
bl load_up_fpu; /* if from user, just load it up */ \
b fast_exception_return; \
1: EXC_XFER_STD(0x800, kernel_fp_unavailable_exception)
1: prepare_transfer_to_handler; \
bl kernel_fp_unavailable_exception; \
b interrupt_return

#else /* __ASSEMBLY__ */
struct exception_regs {
Expand Down
Loading

0 comments on commit 4c0104a

Please sign in to comment.