powerpc: interrupt wrappers
Subsystems (4)
Nicholas Piggin
reviewerv7 cover powerpc: interrupt wrappers
This adds interrupt handler wrapper functions, similar to the generic / x86 code, and moves several common operations into them from either asm or open coded in the individual handlers.
This series is based on powerpc fixes-test tree, there's another unrelated pending fix in patch 1 of the series which clashes a bit.
This includes more changes and fixes suggested by Christophe, a few minor bug fixes and compile fix noticed by kbuild, and some NMI changes Athira asked about -- PMI interrupts don't block tracing when they are soft-NMI.
Since v1:
- Fixed a couple of compile issues
- Fixed perf weirdness (sometimes NMI, sometimes not)
- Also move irq_enter/exit into wrappers
Since v2:
- Rebased upstream
- Took code in patch 3 from Christophe
- Fixed some compile errors from 0day
Since v3:
- Rebased
- Split Christophe's 32s DABR patch into its own patch
- Fixed missing asm from 32s on patch 3 noticed by Christophe.
- Moved changes around, split out one more patch (patch 9) to make changes more logical and atomic.
- Add comments explaining _RAW handlers (SLB, HPTE) interrupts better
Since v4:
- Rebased (on top of scv fallback flush fix)
- Rearranged a few changes into different patches from Christophe, e.g., the ___do_page_fault change from patch 2 to 10. I didn't do everything (e.g., splitting to update __hash_page to drop the msr argument before the bulk of patch 2 seemed like churn without much improvement), and also other things like removing the new ___do_page_fault variant if we can change hash fault context tracking I didn't get time to completely investigate and implement. I think this shouldn't be a showstopper though we can make more improvements as we go.
Since v5:
- Lots of good review suggestions from Christophe, see v5 email threads.
- Major change being do_break is left in asm and selected early as an alternate interrupt handler now, which is a smaller step and matches other subarchs better.
- Rearranged patches, split, moved things, bug fixes, etc.
- Converted a few more missed exception handlers for debug and ras
Since v6:
- Move related interrupt handler de-argify patches together [Christophe]
- Split do_bad_page_fault patch [Christophe]
- Change do_page_fault cleanup patch [Christophe]
- entry_32.S can't avoid saving r4/r5 until later in the series [Christophe]
- Soft-NMI decrementer and perf don't block ftrace [Athira]
- Rebased on some fixes
- Fixed mismerge / duplicate line in patch 40
- Fix kbuild hash missing declaration bug
Christophe Leroy (1):
powerpc/32s: move DABR match out of handle_page_fault
Nicholas Piggin (41):
powerpc/64s: interrupt exit improve bounding of interrupt recursion
KVM: PPC: Book3S HV: Context tracking exit guest context before
enabling irqs
powerpc/64s: move DABR match out of handle_page_fault powerpc/64s: move the hash fault handling logic to C
powerpc: remove arguments from fault handler functions powerpc/fsl_booke/32: CacheLockingException remove args
powerpc: do_break get registers from regs
powerpc: DebugException remove args
powerpc/32: transfer can avoid saving r4/r5 over trace call
powerpc: bad_page_fault get registers from regs powerpc/64s: add do_bad_page_fault_segv handler
powerpc: rearrange do_page_fault error case to be inside
exception_enter
powerpc/64s: move bad_page_fault handling to C powerpc/64s: split do_hash_fault
powerpc/mm: Remove stale do_page_fault comment referring to SLB faults powerpc/64s: slb comment update
powerpc/traps: add NOKPROBE_SYMBOL for sreset and mce powerpc/perf: move perf irq/nmi handling details into traps.c powerpc/time: move timer_broadcast_interrupt prototype to asm/time.h
powerpc: add and use unknown_async_exception
powerpc/cell: tidy up pervasive declarations
powerpc: introduce die_mce
powerpc/mce: ensure machine check handler always tests RI
powerpc: improve handling of unrecoverable system reset
powerpc: interrupt handler wrapper functions
powerpc: add interrupt wrapper entry / exit stub functions
powerpc: convert interrupt handlers to use wrappers
powerpc: add interrupt_cond_local_irq_enable helper powerpc/64: context tracking remove _TIF_NOHZ powerpc/64s/hash: improve context tracking of hash faults powerpc/64: context tracking move to interrupt wrappers powerpc/64: add context tracking to asynchronous interrupts
powerpc: handle irq_enter/irq_exit in interrupt handler wrappers powerpc/64s: move context tracking exit to interrupt exit path powerpc/64s: reconcile interrupts in C
powerpc/64: move account_stolen_time into its own function powerpc/64: entry cpu time accounting in C
powerpc: move NMI entry/exit code into wrapper powerpc/64s: move NMI soft-mask handling to C
powerpc/64s: runlatch interrupt handling in C
powerpc/64s: power4 nap fixup in C
arch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/asm-prototypes.h | 29 -- arch/powerpc/include/asm/bug.h | 9 +- arch/powerpc/include/asm/cputime.h | 14 + arch/powerpc/include/asm/debug.h | 4 - arch/powerpc/include/asm/hw_irq.h | 9 - arch/powerpc/include/asm/interrupt.h | 437 +++++++++++++++++++++ arch/powerpc/include/asm/ppc_asm.h | 24 -- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 10 +- arch/powerpc/include/asm/time.h | 2 + arch/powerpc/kernel/dbell.c | 9 +- arch/powerpc/kernel/entry_32.S | 25 +- arch/powerpc/kernel/exceptions-64e.S | 8 +- arch/powerpc/kernel/exceptions-64s.S | 310 ++------------- arch/powerpc/kernel/head_40x.S | 11 +- arch/powerpc/kernel/head_8xx.S | 11 +- arch/powerpc/kernel/head_book3s_32.S | 14 +- arch/powerpc/kernel/head_booke.h | 6 +- arch/powerpc/kernel/head_fsl_booke.S | 6 +- arch/powerpc/kernel/idle_book3s.S | 4 + arch/powerpc/kernel/irq.c | 7 +- arch/powerpc/kernel/mce.c | 16 +- arch/powerpc/kernel/process.c | 8 +- arch/powerpc/kernel/ptrace/ptrace.c | 4 - arch/powerpc/kernel/signal.c | 4 - arch/powerpc/kernel/syscall_64.c | 90 +++-- arch/powerpc/kernel/tau_6xx.c | 5 +- arch/powerpc/kernel/time.c | 7 +- arch/powerpc/kernel/traps.c | 265 ++++++------- arch/powerpc/kernel/watchdog.c | 15 +- arch/powerpc/kvm/book3s_hv.c | 7 +- arch/powerpc/kvm/book3s_hv_builtin.c | 1 + arch/powerpc/kvm/booke.c | 1 + arch/powerpc/mm/book3s64/hash_utils.c | 97 +++-- arch/powerpc/mm/book3s64/slb.c | 40 +- arch/powerpc/mm/fault.c | 76 ++-- arch/powerpc/perf/core-book3s.c | 35 +- arch/powerpc/perf/core-fsl-emb.c | 25 -- arch/powerpc/platforms/8xx/machine_check.c | 2 +- arch/powerpc/platforms/cell/pervasive.c | 1 + arch/powerpc/platforms/cell/pervasive.h | 3 - arch/powerpc/platforms/cell/ras.c | 6 +- arch/powerpc/platforms/cell/ras.h | 9 +- arch/powerpc/platforms/powernv/idle.c | 1 + arch/powerpc/platforms/powernv/opal.c | 2 +- arch/powerpc/platforms/pseries/ras.c | 2 +- 47 files changed, 914 insertions(+), 759 deletions(-) create mode 100644 arch/powerpc/include/asm/interrupt.h
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 1/42 powerpc/64s: interrupt exit improve bounding of interrupt recursion
When replaying pending soft-masked interrupts when an interrupt returns to an irqs-enabled context, there is a special case required if this was an asynchronous interrupt to avoid unbounded interrupt recursion.
This case was not tested for in the case the asynchronous interrupt hit in user context, because a subsequent nested interrupt would by definition hit in kernel mode, which then exits via the kernel path which does test this case.
There is no reason to allow this for such interrupts. While recursion is bounded at the next level, it's simpler and uses less stack to apply the replay logic consistently.
This also expands the comment which was really pretty poor and didn't explain the problem (I can say that because I wrote it).
--- arch/powerpc/kernel/syscall_64.c | 55 +++++++++++++++++++------------- 1 file changed, 33 insertions(+), 22 deletions(-)
arch/powerpc/kernel/syscall_64.c +33 -22
@@ -138,8 +138,12 @@ notrace long system_call_exception(long r3, long r4, long r5,/* * local irqs must be disabled. Returns false if the caller must re-enable * them, check for new work, and try again. +* +* This should be called with local irqs disabled, but if they were previously +* enabled when the interrupt handler returns (indicating a process-context / +* synchronous interrupt) then irqs_enabled should be true. */ -static notrace inline bool prep_irq_for_enabled_exit(bool clear_ri) +static notrace inline bool prep_irq_for_enabled_exit(bool clear_ri, bool irqs_enabled) {/* This must be done with RI=1 because tracing may touch vmaps */ trace_hardirqs_on ();
@@ -156,6 +160,29 @@ static notrace inline bool prep_irq_for_enabled_exit(bool clear_ri)trace_hardirqs_off (); local_paca->irq_happened |=PACA_IRQ_HARD_DIS ; +/* +* Must replay pending soft-masked interrupts now. Don't just +* local_irq_enabe(); local_irq_disable(); because if we are +* returning from an asynchronous interrupt here, another one +* might hit after irqs are enabled, and it would exit via this +* same path allowing another to fire, and so on unbounded. +* +* If interrupts were enabled when this interrupt exited, +* indicating a process context (synchronous) interrupt, +* local_irq_enable/disable can be used, which will enable +* interrupts rather than keeping them masked (unclear how +* much benefit this is over just replaying for all cases, +* because we immediately disable again, so all we're really +* doing is allowing hard interrupts to execute directly for +* a very small time, rather than being masked and replayed). +*/ +if (irqs_enabled) { +local_irq_enable (); +local_irq_disable (); + }else { +replay_soft_interrupts (); + } +return false; } local_paca->irq_happened =0 ;
@@ -212,8 +239,9 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, ret |= _TIF_RESTOREALL; } -again:local_irq_disable (); + +again: ti_flags =READ_ONCE (*ti_flagsp);while (unlikely (ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {local_irq_enable ();
@@ -258,10 +286,8 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, }/* scv need not set RI=0 because SRRs are not used */ -if (unlikely (!prep_irq_for_enabled_exit (!scv))) { -local_irq_enable (); +if (unlikely (!prep_irq_for_enabled_exit (!scv, true))) goto again; - }#ifdef CONFIG_PPC_TRANSACTIONAL_MEM local_paca->tm_scratch = regs->msr;
@@ -336,11 +362,8 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned } } -if (unlikely (!prep_irq_for_enabled_exit (true))) { -local_irq_enable (); -local_irq_disable (); +if (unlikely (!prep_irq_for_enabled_exit (true, !irqs_disabled_flags (flags)))) goto again; - }#ifdef CONFIG_PPC_BOOK3E if (unlikely (ts->debug.dbcr0 &DBCR0_IDM )) {
@@ -403,20 +426,8 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign } } -if (unlikely (!prep_irq_for_enabled_exit (true))) { -/* -* Can't local_irq_restore to replay if we were in -* interrupt context. Must replay directly. -*/ -if (irqs_disabled_flags (flags)) { -replay_soft_interrupts (); - }else { -local_irq_restore (flags); -local_irq_save (flags); - } -/* Took an interrupt, may have more exit work to do. */ +if (unlikely (!prep_irq_for_enabled_exit (true, !irqs_disabled_flags (flags)))) goto again; - } }else {/* Returning to a kernel context with local irqs disabled. */ __hard_EE_RI_disable ();
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 2/42 KVM: PPC: Book3S HV: Context tracking exit guest context before enabling irqs
In reply to Nicholas PigginInterrupts that occur in kernel mode expect that context tracking is set to kernel. Enabling local irqs before context tracking switches from guest to host means interrupts can come in and trigger warnings about wrong context, and possibly worse.
--- arch/powerpc/kvm/book3s_hv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/kvm/book3s_hv.c +4 -2
@@ -3407,8 +3407,9 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)kvmppc_set_host_core (pcpu); +guest_exit_irqoff (); +local_irq_enable (); -guest_exit ();/* Let secondaries go back to the offline loop */ for (i =0 ; i < controlled_threads; ++i) {
@@ -4217,8 +4218,9 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,kvmppc_set_host_core (pcpu); +guest_exit_irqoff (); +local_irq_enable (); -guest_exit ();cpumask_clear_cpu (pcpu, &kvm->arch.cpu_in_guest);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 3/42 powerpc/32s: move DABR match out of handle_page_fault
In reply to Nicholas PigginFrom: Christophe Leroy <[email protected]>
handle_page_fault() has some code dedicated to book3s/32 to call do_break() when the DSI is a DABR match.
On other platforms, do_break() is handled separately.
Do the same for book3s/32, do it earlier in the process of DSI.
This change also avoid doing the test on ISI.
--- arch/powerpc/kernel/entry_32.S | 15 --------------- arch/powerpc/kernel/head_book3s_32.S | 3 +++ 2 files changed, 3 insertions(+), 15 deletions(-)
arch/powerpc/kernel/entry_32.S +0 -15
@@ -670,10 +670,6 @@ ppc_swapcontext: .globl handle_page_fault handle_page_fault: addi r3,r1,STACK_FRAME_OVERHEAD -#ifdef CONFIG_PPC_BOOK3S_32 - andis. r0,r5,DSISR_DABRMATCH@h - bne- handle_dabr_fault -#endif bl do_page_fault cmpwi r3,0 beq+ ret_from_except
@@ -687,17 +683,6 @@ handle_page_fault: bl __bad_page_fault b ret_from_except_full -#ifdef CONFIG_PPC_BOOK3S_32 - /* We have a data breakpoint exception - handle it */ -handle_dabr_fault: - SAVE_NVGPRS(r1) - lwz r0,_TRAP(r1) - clrrwi r0,r0,1 - stw r0,_TRAP(r1) - bl do_break - b ret_from_except_full -#endif - /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state
arch/powerpc/kernel/head_book3s_32.S +3 -0
@@ -689,7 +689,10 @@ handle_page_fault_tramp_1: lwz r5, _DSISR(r11) /* fall through */ handle_page_fault_tramp_2: + andis. r0, r5, DSISR_DABRMATCH@h + bne- 1f EXC_XFER_LITE(0x300, handle_page_fault) +1: EXC_XFER_STD(0x300, do_break) #ifdef CONFIG_VMAP_STACK .macro save_regs_thread thread
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 4/42 powerpc/64s: move DABR match out of handle_page_fault
In reply to Nicholas PigginSimilar to the 32/s change, move the test and call to the do_break handler to the DSI.
--- arch/powerpc/kernel/exceptions-64s.S | 34 +++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-)
arch/powerpc/kernel/exceptions-64s.S +16 -18
@@ -1439,6 +1439,8 @@ EXC_COMMON_BEGIN(data_access_common) GEN_COMMON data_access ld r4,_DAR(r1) ld r5,_DSISR(r1) + andis. r0,r5,DSISR_DABRMATCH@h + bne- 1f BEGIN_MMU_FTR_SECTION ld r6,_MSR(r1) li r3,0x300
@@ -1447,6 +1449,18 @@ MMU_FTR_SECTION_ELSE b handle_page_fault ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) +1: /* We have a data breakpoint exception - handle it */ + ld r4,_DAR(r1) + ld r5,_DSISR(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_break + /* + * do_break() may have changed the NV GPRS while handling a breakpoint. + * If so, we need to restore them with their updated values. + */ + REST_NVGPRS(r1) + b interrupt_return + GEN_KVM data_access
@@ -3228,7 +3242,7 @@ disable_machine_check: .balign IFETCH_ALIGN_BYTES do_hash_page: #ifdef CONFIG_PPC_BOOK3S_64 - lis r0,(DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)@h + lis r0,(DSISR_BAD_FAULT_64S | DSISR_KEYFAULT)@h ori r0,r0,DSISR_BAD_FAULT_64S@l and. r0,r5,r0 /* weird error? */ bne- handle_page_fault /* if not, try to insert a HPTE */
@@ -3262,15 +3276,13 @@ do_hash_page: /* Error */ blt- 13f - /* Reload DAR/DSISR into r4/r5 for the DABR check below */ + /* Reload DAR/DSISR into r4/r5 for handle_page_fault */ ld r4,_DAR(r1) ld r5,_DSISR(r1) #endif /* CONFIG_PPC_BOOK3S_64 */ /* Here we have a page fault that hash_page can't handle. */ handle_page_fault: -11: andis. r0,r5,DSISR_DABRMATCH@h - bne- handle_dabr_fault addi r3,r1,STACK_FRAME_OVERHEAD bl do_page_fault cmpdi r3,0
@@ -3281,20 +3293,6 @@ handle_page_fault: bl __bad_page_fault b interrupt_return -/* We have a data breakpoint exception - handle it */ -handle_dabr_fault: - ld r4,_DAR(r1) - ld r5,_DSISR(r1) - addi r3,r1,STACK_FRAME_OVERHEAD - bl do_break - /* - * do_break() may have changed the NV GPRS while handling a breakpoint. - * If so, we need to restore them with their updated values. - */ - REST_NVGPRS(r1) - b interrupt_return - - #ifdef CONFIG_PPC_BOOK3S_64 /* We have a page fault that hash_page could handle but HV refused * the PTE insertion
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 5/42 powerpc/64s: move the hash fault handling logic to C
In reply to Nicholas PigginThe fault handling still has some complex logic particularly around hash table handling, in asm. Implement most of this in C.
--- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 1 + arch/powerpc/kernel/exceptions-64s.S | 127 ++++-------------- arch/powerpc/mm/book3s64/hash_utils.c | 77 +++++++---- 3 files changed, 78 insertions(+), 127 deletions(-)
arch/powerpc/include/asm/book3s/64/mmu-hash.h +1 -0
@@ -454,6 +454,7 @@ static inline unsigned long hpt_hash(unsigned long vpn,#define HPTE_NOHPTE_UPDATE 0x2#define HPTE_USE_KERNEL_KEY 0x4 +int do_hash_fault (struct pt_regs *regs,unsigned long ea,unsigned long dsisr);extern int __hash_page_4K (unsigned long ea,unsigned long access,unsigned long vsid,pte_t *ptep,unsigned long trap,unsigned long flags,int ssize,int subpage_prot);
arch/powerpc/kernel/exceptions-64s.S +28 -99
165 lines not on this page · raw message
arch/powerpc/mm/book3s64/hash_utils.c +49 -28
105 lines not on this page · raw message
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 6/42 powerpc: remove arguments from fault handler functions
In reply to Nicholas PigginMake mm fault handlers all just take the pt_regs * argument and load DAR/DSISR from that. Make those that return a value return long.
This is done to make the function signatures match other handlers, which will help with a future patch to add wrappers. Explicit arguments could be added for performance but that would require more wrapper macro variants.
--- arch/powerpc/include/asm/asm-prototypes.h | 4 ++-- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 2 +- arch/powerpc/include/asm/bug.h | 2 +- arch/powerpc/kernel/exceptions-64e.S | 2 -- arch/powerpc/kernel/exceptions-64s.S | 17 ++++------------- arch/powerpc/kernel/head_40x.S | 10 +++++----- arch/powerpc/kernel/head_8xx.S | 6 +++--- arch/powerpc/kernel/head_book3s_32.S | 5 ++--- arch/powerpc/kernel/head_booke.h | 4 +--- arch/powerpc/mm/book3s64/hash_utils.c | 8 +++++--- arch/powerpc/mm/book3s64/slb.c | 11 +++++++---- arch/powerpc/mm/fault.c | 5 ++--- 12 files changed, 33 insertions(+), 43 deletions(-)
arch/powerpc/include/asm/asm-prototypes.h +2 -2
@@ -82,8 +82,8 @@ void kernel_bad_stack(struct pt_regs *regs);void system_reset_exception (struct pt_regs *regs);void machine_check_exception (struct pt_regs *regs);void emulation_assist_interrupt (struct pt_regs *regs); -long do_slb_fault (struct pt_regs *regs,unsigned long ea); -void do_bad_slb_fault (struct pt_regs *regs,unsigned long ea,long err); +long do_slb_fault (struct pt_regs *regs); +void do_bad_slb_fault (struct pt_regs *regs);/* signals, syscalls and interrupts */ long sys_swapcontext(struct ucontext __user *old_ctx,
arch/powerpc/include/asm/book3s/64/mmu-hash.h +1 -1
@@ -454,7 +454,7 @@ static inline unsigned long hpt_hash(unsigned long vpn,#define HPTE_NOHPTE_UPDATE 0x2#define HPTE_USE_KERNEL_KEY 0x4 -int do_hash_fault (struct pt_regs *regs,unsigned long ea,unsigned long dsisr); +long do_hash_fault (struct pt_regs *regs);extern int __hash_page_4K (unsigned long ea,unsigned long access,unsigned long vsid,pte_t *ptep,unsigned long trap,unsigned long flags,int ssize,int subpage_prot);
arch/powerpc/include/asm/bug.h +1 -1
@@ -111,7 +111,7 @@#ifndef __ASSEMBLY__struct pt_regs ; -extern int do_page_fault (struct pt_regs *,unsigned long ,unsigned long ); +long do_page_fault (struct pt_regs *);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 );
arch/powerpc/kernel/exceptions-64e.S +0 -2
@@ -1011,8 +1011,6 @@ storage_fault_common: std r14,_DAR(r1) std r15,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD - mr r4,r14 - mr r5,r15 ld r14,PACA_EXGEN+EX_R14(r13) ld r15,PACA_EXGEN+EX_R15(r13) bl do_page_fault
arch/powerpc/kernel/exceptions-64s.S +4 -13
@@ -1438,10 +1438,9 @@ EXC_VIRT_BEGIN(data_access, 0x4300, 0x80) EXC_VIRT_END(data_access, 0x4300, 0x80) EXC_COMMON_BEGIN(data_access_common) GEN_COMMON data_access - ld r4,_DAR(r1) - ld r5,_DSISR(r1) + ld r4,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD - andis. r0,r5,DSISR_DABRMATCH@h + andis. r0,r4,DSISR_DABRMATCH@h bne- 1f BEGIN_MMU_FTR_SECTION bl do_hash_fault
@@ -1504,10 +1503,9 @@ EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) EXC_VIRT_END(data_access_slb, 0x4380, 0x80) EXC_COMMON_BEGIN(data_access_slb_common) GEN_COMMON data_access_slb - ld r4,_DAR(r1) - addi r3,r1,STACK_FRAME_OVERHEAD BEGIN_MMU_FTR_SECTION /* HPT case, do SLB fault */ + addi r3,r1,STACK_FRAME_OVERHEAD bl do_slb_fault cmpdi r3,0 bne- 1f
@@ -1519,8 +1517,6 @@ MMU_FTR_SECTION_ELSE ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) std r3,RESULT(r1) RECONCILE_IRQ_STATE(r10, r11) - ld r4,_DAR(r1) - ld r5,RESULT(r1) addi r3,r1,STACK_FRAME_OVERHEAD bl do_bad_slb_fault b interrupt_return
@@ -1555,8 +1551,6 @@ EXC_VIRT_BEGIN(instruction_access, 0x4400, 0x80) EXC_VIRT_END(instruction_access, 0x4400, 0x80) EXC_COMMON_BEGIN(instruction_access_common) GEN_COMMON instruction_access - ld r4,_DAR(r1) - ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD BEGIN_MMU_FTR_SECTION bl do_hash_fault
@@ -1602,10 +1596,9 @@ EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80) EXC_COMMON_BEGIN(instruction_access_slb_common) GEN_COMMON instruction_access_slb - ld r4,_DAR(r1) - addi r3,r1,STACK_FRAME_OVERHEAD BEGIN_MMU_FTR_SECTION /* HPT case, do SLB fault */ + addi r3,r1,STACK_FRAME_OVERHEAD bl do_slb_fault cmpdi r3,0 bne- 1f
@@ -1617,8 +1610,6 @@ MMU_FTR_SECTION_ELSE ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) std r3,RESULT(r1) RECONCILE_IRQ_STATE(r10, r11) - ld r4,_DAR(r1) - ld r5,RESULT(r1) addi r3,r1,STACK_FRAME_OVERHEAD bl do_bad_slb_fault b interrupt_return
arch/powerpc/kernel/head_40x.S +5 -5
@@ -179,9 +179,9 @@ _ENTRY(saved_ksp_limit) */ START_EXCEPTION(0x0300, DataStorage) EXCEPTION_PROLOG - mfspr r5, SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + mfspr r5, SPRN_ESR /* Grab the ESR, save it */ stw r5, _ESR(r11) - mfspr r4, SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ + mfspr r4, SPRN_DEAR /* Grab the DEAR, save it */ stw r4, _DEAR(r11) EXC_XFER_LITE(0x300, handle_page_fault)
@@ -191,9 +191,9 @@ _ENTRY(saved_ksp_limit) */ START_EXCEPTION(0x0400, InstructionAccess) EXCEPTION_PROLOG - mr r4,r12 /* Pass SRR0 as arg2 */ - stw r4, _DEAR(r11) - li r5,0 /* Pass zero as arg3 */ + li r5,0 + stw r5, _ESR(r11) /* Zero ESR */ + stw r12, _DEAR(r11) /* SRR0 as DEAR */ EXC_XFER_LITE(0x400, handle_page_fault) /* 0x0500 - External Interrupt Exception */
arch/powerpc/kernel/head_8xx.S +3 -3
@@ -312,14 +312,14 @@ DataStoreTLBMiss: . = 0x1300 InstructionTLBError: EXCEPTION_PROLOG - mr r4,r12 andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */ andis. r10,r9,SRR1_ISI_NOPT@h beq+ .Litlbie - tlbie r4 + tlbie r12 /* 0x400 is InstructionAccess exception, needed by bad_page_fault() */ .Litlbie: - stw r4, _DAR(r11) + stw r12, _DAR(r11) + stw r5, _DSISR(r11) EXC_XFER_LITE(0x400, handle_page_fault) /* This is the data TLB error on the MPC8xx. This could be due to
arch/powerpc/kernel/head_book3s_32.S +2 -3
@@ -361,9 +361,9 @@ BEGIN_MMU_FTR_SECTION bl hash_page END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE) #endif /* CONFIG_VMAP_STACK */ -1: mr r4,r12 andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */ - stw r4, _DAR(r11) + stw r5, _DSISR(r11) + stw r12, _DAR(r11) EXC_XFER_LITE(0x400, handle_page_fault) /* External interrupt */
@@ -685,7 +685,6 @@ handle_page_fault_tramp_1: #ifdef CONFIG_VMAP_STACK EXCEPTION_PROLOG_2 handle_dar_dsisr=1 #endif - lwz r4, _DAR(r11) lwz r5, _DSISR(r11) /* fall through */ handle_page_fault_tramp_2:
arch/powerpc/kernel/head_booke.h +1 -3
@@ -476,9 +476,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)NORMAL_EXCEPTION_PROLOG (INST_STORAGE ); \mfspr r5,SPRN_ESR ;/* Grab the ESR and save it */ \stw r5,_ESR (r11 ); \ -mr r4,r12;/* Pass SRR0 as arg2 */ \ -stw r4,_DEAR (r11 ); \ - li r5,0; /* Pass zero as arg3 */ \ +stw r12,_DEAR (r11 );/* Pass SRR0 as arg2 */ \ EXC_XFER_LITE(0x0400, handle_page_fault)#define ALIGNMENT_EXCEPTION \
arch/powerpc/mm/book3s64/hash_utils.c +5 -3
@@ -1512,13 +1512,15 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap, }EXPORT_SYMBOL_GPL (hash_page); -int do_hash_fault (struct pt_regs *regs,unsigned long ea,unsigned long dsisr) +long do_hash_fault (struct pt_regs *regs) { +unsigned long ea = regs->dar; +unsigned long dsisr = regs->dsisr;unsigned long access = _PAGE_PRESENT | _PAGE_READ;unsigned long flags =0 ;struct mm_struct *mm;unsigned int region_id; -int err; +long err;if (unlikely (dsisr & (DSISR_BAD_FAULT_64S |DSISR_KEYFAULT ))) goto page_fault;
@@ -1582,7 +1584,7 @@ int do_hash_fault(struct pt_regs *regs, unsigned long ea, unsigned long dsisr) }else if (err) { page_fault: - err =do_page_fault (regs, ea, dsisr); + err =do_page_fault (regs); }return err;
arch/powerpc/mm/book3s64/slb.c +7 -4
@@ -813,8 +813,9 @@ static long slb_allocate_user(struct mm_struct *mm, unsigned long ea)return slb_insert_entry (ea, context, flags, ssize, false); } -long do_slb_fault (struct pt_regs *regs,unsigned long ea) +long do_slb_fault (struct pt_regs *regs) { +unsigned long ea = regs->dar;unsigned long id =get_region_id (ea);/* IRQs are not reconciled here, so can't check irqs_disabled */
@@ -865,13 +866,15 @@ long do_slb_fault(struct pt_regs *regs, unsigned long ea) } } -void do_bad_slb_fault (struct pt_regs *regs,unsigned long ea,long err) +void do_bad_slb_fault (struct pt_regs *regs) { +int err = regs->result; +if (err == -EFAULT ) {if (user_mode (regs)) -_exception (SIGSEGV , regs,SEGV_BNDERR , ea); +_exception (SIGSEGV , regs,SEGV_BNDERR , regs->dar);else -bad_page_fault (regs, ea,SIGSEGV ); +bad_page_fault (regs, regs->dar,SIGSEGV ); }else if (err == -EINVAL ) {unrecoverable_exception (regs); }else {
arch/powerpc/mm/fault.c +2 -3
@@ -542,12 +542,11 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, }NOKPROBE_SYMBOL (__do_page_fault); -int do_page_fault (struct pt_regs *regs,unsigned long address, -unsigned long error_code) +long do_page_fault (struct pt_regs *regs) {const struct exception_table_entry *entry;enum ctx_state prev_state =exception_enter (); -int rc =__do_page_fault (regs, address, error_code); +int rc =__do_page_fault (regs, regs->dar, regs->dsisr);exception_exit (prev_state);if (likely (!rc))return 0 ;
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 7/42 powerpc/fsl_booke/32: CacheLockingException remove args
In reply to Nicholas PigginLike other interrupt handler conversions, switch to getting registers from the pt_regs argument.
--- arch/powerpc/kernel/head_fsl_booke.S | 6 +++--- arch/powerpc/kernel/traps.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-)
arch/powerpc/kernel/head_fsl_booke.S +3 -3
@@ -364,12 +364,12 @@ interrupt_base: /* Data Storage Interrupt */ START_EXCEPTION(DataStorage) NORMAL_EXCEPTION_PROLOG(DATA_STORAGE) - mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + mfspr r5,SPRN_ESR /* Grab the ESR, save it3 */ stw r5,_ESR(r11) - mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ + mfspr r4,SPRN_DEAR /* Grab the DEAR, save it */ + stw r4, _DEAR(r11) andis. r10,r5,(ESR_ILK|ESR_DLK)@h bne 1f - stw r4, _DEAR(r11) EXC_XFER_LITE(0x0300, handle_page_fault) 1: addi r3,r1,STACK_FRAME_OVERHEAD
arch/powerpc/kernel/traps.c +3 -2
@@ -2062,9 +2062,10 @@ void altivec_assist_exception(struct pt_regs *regs)#endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_FSL_BOOKE -void CacheLockingException (struct pt_regs *regs,unsigned long address, -unsigned long error_code) +void CacheLockingException (struct pt_regs *regs) { +unsigned long error_code = regs->dsisr; +/* We treat cache locking instructions from the user * as priv ops, in the future we could try to do * something smarter
Signature · 1 line
2.23.0
Re: [PATCH v7 07/42] powerpc/fsl_booke/32: CacheLockingException remove args
Quoted 14 lines · Nicholas Piggin
Like other interrupt handler conversions, switch to getting registers from the
pt_regsargument.Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/kernel/head_fsl_booke.S | 6 +++--- arch/powerpc/kernel/traps.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-)arch/powerpc/kernel/head_fsl_booke.S +0
-0
arch/powerpc/kernel/head_fsl_booke.S interrupt_base: · line 367
Quoted 5 lines
arch/powerpc/kernel/head_fsl_booke.S +1
-1@@ -364,12 +364,12 @@ interrupt_base: /* Data Storage Interrupt */ START_EXCEPTION(DataStorage) NORMAL_EXCEPTION_PROLOG(DATA_STORAGE) - mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + mfspr r5,SPRN_ESR /* Grab the ESR, save it3 */
^^^^^^^^^^
Sorry for the nitpick.. Should be "/* Grab the ESR, save it */"
Quoted 30 lines
arch/powerpc/kernel/head_fsl_booke.S +2
-2stw r5,_ESR(r11) - mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ + mfspr r4,SPRN_DEAR /* Grab the DEAR, save it */ + stw r4, _DEAR(r11) andis. r10,r5,(ESR_ILK|ESR_DLK)@h bne 1f - stw r4, _DEAR(r11) EXC_XFER_LITE(0x0300, handle_page_fault) 1: addi r3,r1,STACK_FRAME_OVERHEADarch/powerpc/kernel/traps.c +3
-2@@ -2062,9 +2062,10 @@ void altivec_assist_exception(struct pt_regs *regs)#endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_FSL_BOOKE -void CacheLockingException (struct pt_regs *regs,unsigned long address, -unsigned long error_code) +void CacheLockingException (struct pt_regs *regs) { +unsigned long error_code = regs->dsisr; +/* We treat cache locking instructions from the user * as priv ops, in the future we could try to do * something smarter Signature · 1 line
2.23.0
Michael Ellerman
reviewerRe: [PATCH v7 07/42] powerpc/fsl_booke/32: CacheLockingException remove args
Quoted 21 lines · Gautham R Shenoy
Quoted 14 lines · Nicholas Piggin
Like other interrupt handler conversions, switch to getting registers from the
pt_regsargument.Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/kernel/head_fsl_booke.S | 6 +++--- arch/powerpc/kernel/traps.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-)arch/powerpc/kernel/head_fsl_booke.S +0
-0arch/powerpc/kernel/head_fsl_booke.S interrupt_base: · line 367
Quoted 5 lines
arch/powerpc/kernel/head_fsl_booke.S +1
-1@@ -364,12 +364,12 @@ interrupt_base: /* Data Storage Interrupt */ START_EXCEPTION(DataStorage) NORMAL_EXCEPTION_PROLOG(DATA_STORAGE) - mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + mfspr r5,SPRN_ESR /* Grab the ESR, save it3 */^^^^^^^^^^
Quoted 1 line
Sorry for the nitpick.. Should be "/* Grab the ESR, save it */"
Thanks, I fixed it up.
cheers
Nicholas Piggin
reviewerPATCH v7 8/42 powerpc: do_break get registers from regs
In reply to Nicholas PigginSimilar to the previous patch this makes interrupt handler function types more regular so they can be wrapped with the next patch.
--- arch/powerpc/include/asm/debug.h | 3 +-- arch/powerpc/kernel/head_8xx.S | 5 ++--- arch/powerpc/kernel/process.c | 7 +++---- 3 files changed, 6 insertions(+), 9 deletions(-)
arch/powerpc/include/asm/debug.h +1 -2
@@ -52,8 +52,7 @@ extern void do_send_trap(struct pt_regs *regs, unsigned long address, unsigned long error_code, int brkpt);#else -extern void do_break (struct pt_regs *regs,unsigned long address, -unsigned long error_code); +void do_break (struct pt_regs *regs);#endif #endif /* _ASM_POWERPC_DEBUG_H */
arch/powerpc/kernel/head_8xx.S +2 -3
@@ -364,10 +364,9 @@ do_databreakpoint: addi r3,r1,STACK_FRAME_OVERHEAD mfspr r4,SPRN_BAR stw r4,_DAR(r11) -#ifdef CONFIG_VMAP_STACK - lwz r5,_DSISR(r11) -#else +#ifndef CONFIG_VMAP_STACK mfspr r5,SPRN_DSISR + stw r5,_DSISR(r11) #endif EXC_XFER_STD(0x1c00, do_break)
arch/powerpc/kernel/process.c +3 -4
@@ -659,11 +659,10 @@ static void do_break_handler(struct pt_regs *regs) } } -void do_break (struct pt_regs *regs,unsigned long address, -unsigned long error_code) +void do_break (struct pt_regs *regs) { current->thread.trap_nr =TRAP_HWBKPT ; -if (notify_die (DIE_DABR_MATCH ,"dabr_match" , regs, error_code, +if (notify_die (DIE_DABR_MATCH ,"dabr_match" , regs, regs->dsisr,11 ,SIGSEGV ) ==NOTIFY_STOP )return ;
@@ -681,7 +680,7 @@ void do_break (struct pt_regs *regs, unsigned long address,do_break_handler (regs);/* Deliver the signal to userspace */ - force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)address); + force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)regs->dar); }#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 9/42 powerpc: DebugException remove args
In reply to Nicholas PigginLike other interrupt handler conversions, switch to getting registers from the pt_regs argument.
--- arch/powerpc/kernel/exceptions-64e.S | 2 -- arch/powerpc/kernel/head_40x.S | 1 + arch/powerpc/kernel/head_booke.h | 2 ++ arch/powerpc/kernel/traps.c | 4 +++- 4 files changed, 6 insertions(+), 3 deletions(-)
arch/powerpc/kernel/exceptions-64e.S +0 -2
@@ -791,7 +791,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) EXCEPTION_COMMON_CRIT(0xd00) std r14,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD - mr r4,r14 ld r14,PACA_EXCRIT+EX_R14(r13) ld r15,PACA_EXCRIT+EX_R15(r13) bl save_nvgprs
@@ -864,7 +863,6 @@ kernel_dbg_exc: INTS_DISABLE std r14,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD - mr r4,r14 ld r14,PACA_EXDBG+EX_R14(r13) ld r15,PACA_EXDBG+EX_R15(r13) bl save_nvgprs
arch/powerpc/kernel/head_40x.S +1 -0
@@ -476,6 +476,7 @@ _ENTRY(saved_ksp_limit) /* continue normal handling for a critical exception... */ 2: mfspr r4,SPRN_DBSR + stw r4,_ESR(r11) /* DebugException takes DBSR in _ESR */ addi r3,r1,STACK_FRAME_OVERHEAD EXC_XFER_TEMPLATE(DebugException, 0x2002, \ (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
arch/powerpc/kernel/head_booke.h +2 -0
@@ -406,6 +406,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) \/* continue normal handling for a debug exception... */ \ 2: mfspr r4,SPRN_DBSR; \ +stw r4,_ESR (r11 );/* DebugException takes DBSR in _ESR */ \addi r3,r1,STACK_FRAME_OVERHEAD ; \EXC_XFER_TEMPLATE (DebugException,0x2008 , (MSR_KERNEL & ~(MSR_ME |MSR_DE |MSR_CE )), debug_transfer_to_handler, ret_from_debug_exc)
@@ -459,6 +460,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV) \/* continue normal handling for a critical exception... */ \ 2: mfspr r4,SPRN_DBSR; \ +stw r4,_ESR (r11 );/* DebugException takes DBSR in _ESR */ \addi r3,r1,STACK_FRAME_OVERHEAD ; \EXC_XFER_TEMPLATE (DebugException,0x2002 , (MSR_KERNEL & ~(MSR_ME |MSR_DE |MSR_CE )), crit_transfer_to_handler, ret_from_crit_exc)
arch/powerpc/kernel/traps.c +3 -1
@@ -1957,8 +1957,10 @@ static void handle_debug(struct pt_regs *regs, unsigned long debug_status)mtspr (SPRN_DBCR0 , current->thread.debug.dbcr0); } -void DebugException (struct pt_regs *regs,unsigned long debug_status) +void DebugException (struct pt_regs *regs) { +unsigned long debug_status = regs->dsisr; + current->thread.debug.dbsr = debug_status;/* Hack alert: On BookE, Branch Taken stops on the branch itself, while
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 10/42 powerpc/32: transfer can avoid saving r4/r5 over trace call
In reply to Nicholas PigginNow that handlers get all registers from pt_regs, r4 and r5 are no longer live here and may be clobbered.
--- arch/powerpc/kernel/entry_32.S | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
arch/powerpc/kernel/entry_32.S +1 -6
@@ -276,8 +276,7 @@ reenable_mmu: * We save a bunch of GPRs, * r3 can be different from GPR3(r1) at this point, r9 and r11 * contains the old MSR and handler address respectively, - * r4 & r5 can contain page fault arguments that need to be passed - * along as well. r0, r6-r8, r12, CCR, CTR, XER etc... are left + * r0, r4-r8, r12, CCR, CTR, XER etc... are left * clobbered as they aren't useful past this point. */
@@ -285,15 +284,11 @@ reenable_mmu: stw r9,8(r1) stw r11,12(r1) stw r3,16(r1) - stw r4,20(r1) - stw r5,24(r1) /* If we are disabling interrupts (normal case), simply log it with * lockdep */ 1: bl trace_hardirqs_off - lwz r5,24(r1) - lwz r4,20(r1) lwz r3,16(r1) lwz r11,12(r1) lwz r9,8(r1)
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 11/42 powerpc: bad_page_fault get registers from regs
In reply to Nicholas PigginSimilar to the previous patch this makes interrupt handler function types more regular so they can be wrapped with the next patch.
--- arch/powerpc/include/asm/bug.h | 4 ++-- arch/powerpc/kernel/entry_32.S | 3 +-- arch/powerpc/kernel/exceptions-64e.S | 3 +-- arch/powerpc/kernel/traps.c | 2 +- arch/powerpc/mm/book3s64/hash_utils.c | 4 ++-- arch/powerpc/mm/book3s64/slb.c | 2 +- arch/powerpc/mm/fault.c | 6 +++--- arch/powerpc/platforms/8xx/machine_check.c | 2 +- 8 files changed, 12 insertions(+), 14 deletions(-)
arch/powerpc/include/asm/bug.h +2 -2
@@ -112,8 +112,8 @@struct pt_regs ;long do_page_fault (struct pt_regs *); -extern void bad_page_fault (struct pt_regs *,unsigned long ,int ); -void __bad_page_fault (struct pt_regs *regs,unsigned long address,int sig); +void bad_page_fault (struct pt_regs *,int ); +void __bad_page_fault (struct pt_regs *regs,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 );
arch/powerpc/kernel/entry_32.S +1 -2
@@ -672,9 +672,8 @@ handle_page_fault: lwz r0,_TRAP(r1) clrrwi r0,r0,1 stw r0,_TRAP(r1) - mr r5,r3 + mr r4,r3 /* err arg for bad_page_fault */ addi r3,r1,STACK_FRAME_OVERHEAD - lwz r4,_DAR(r1) bl __bad_page_fault b ret_from_except_full
arch/powerpc/kernel/exceptions-64e.S +1 -2
@@ -1016,9 +1016,8 @@ storage_fault_common: bne- 1f b ret_from_except_lite 1: bl save_nvgprs - mr r5,r3 + mr r4,r3 addi r3,r1,STACK_FRAME_OVERHEAD - ld r4,_DAR(r1) bl __bad_page_fault b ret_from_except
arch/powerpc/kernel/traps.c +1 -1
@@ -1612,7 +1612,7 @@ void alignment_exception(struct pt_regs *regs)if (user_mode (regs))_exception (sig, regs, code, regs->dar);else -bad_page_fault (regs, regs->dar, sig); +bad_page_fault (regs, sig); bail:exception_exit (prev_state);
arch/powerpc/mm/book3s64/hash_utils.c +2 -2
@@ -1539,7 +1539,7 @@ long do_hash_fault(struct pt_regs *regs)* the access, or panic if there isn't a handler. */ if (unlikely (in_nmi ())) { -bad_page_fault (regs, ea,SIGSEGV ); +bad_page_fault (regs,SIGSEGV );return 0 ; }
@@ -1578,7 +1578,7 @@ long do_hash_fault(struct pt_regs *regs)else _exception (SIGBUS , regs,BUS_ADRERR , ea); }else { -bad_page_fault (regs, ea,SIGBUS ); +bad_page_fault (regs,SIGBUS ); } err =0 ;
arch/powerpc/mm/book3s64/slb.c +1 -1
@@ -874,7 +874,7 @@ void do_bad_slb_fault(struct pt_regs *regs)if (user_mode (regs))_exception (SIGSEGV , regs,SEGV_BNDERR , regs->dar);else -bad_page_fault (regs, regs->dar,SIGSEGV ); +bad_page_fault (regs,SIGSEGV ); }else if (err == -EINVAL ) {unrecoverable_exception (regs); }else {
arch/powerpc/mm/fault.c +3 -3
@@ -566,7 +566,7 @@ 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,int sig) {int is_write =page_fault_is_write (regs->dsisr);
@@ -604,7 +604,7 @@ 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) +void bad_page_fault (struct pt_regs *regs,int sig) {const struct exception_table_entry *entry;
@@ -613,5 +613,5 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)if (entry)instruction_pointer_set (regs,extable_fixup (entry));else -__bad_page_fault (regs, address, sig); +__bad_page_fault (regs, sig); }
arch/powerpc/platforms/8xx/machine_check.c +1 -1
@@ -26,7 +26,7 @@ int machine_check_8xx(struct pt_regs *regs)* to deal with that than having a wart in the mcheck handler. * -- BenH */ -bad_page_fault (regs, regs->dar,SIGBUS ); +bad_page_fault (regs,SIGBUS );return 1 ;#else return 0 ;
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 12/42 powerpc/64s: add do_bad_page_fault_segv handler
In reply to Nicholas PigginThis function acts like an interrupt handler so it needs to follow the standard interrupt handler function signature which will be introduced in a future change.
--- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/kernel/exceptions-64s.S | 4 +--- arch/powerpc/mm/fault.c | 7 +++++++ 3 files changed, 9 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/bug.h +1 -0
@@ -114,6 +114,7 @@ struct pt_regs;long do_page_fault (struct pt_regs *);void bad_page_fault (struct pt_regs *,int );void __bad_page_fault (struct pt_regs *regs,int sig); +void do_bad_page_fault_segv (struct pt_regs *regs);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 );
arch/powerpc/kernel/exceptions-64s.S +1 -3
@@ -2151,9 +2151,7 @@ EXC_COMMON_BEGIN(h_data_storage_common) GEN_COMMON h_data_storage addi r3,r1,STACK_FRAME_OVERHEAD BEGIN_MMU_FTR_SECTION - ld r4,_DAR(r1) - li r5,SIGSEGV - bl bad_page_fault + bl do_bad_page_fault_segv MMU_FTR_SECTION_ELSE bl unknown_exception ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_TYPE_RADIX)
arch/powerpc/mm/fault.c +7 -0
@@ -615,3 +615,10 @@ void bad_page_fault(struct pt_regs *regs, int sig)else __bad_page_fault (regs, sig); } + +#ifdef CONFIG_PPC_BOOK3S_64 +void do_bad_page_fault_segv (struct pt_regs *regs) +{ +bad_page_fault (regs,SIGSEGV ); +} +#endif
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 13/42 powerpc: rearrange do_page_fault error case to be inside exception_enter
In reply to Nicholas PigginThis keeps the context tracking over the entire interrupt handler which helps later with moving context tracking into interrupt wrappers.
--- arch/powerpc/mm/fault.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
arch/powerpc/mm/fault.c +14 -9
@@ -545,19 +545,24 @@ NOKPROBE_SYMBOL(__do_page_fault);long do_page_fault (struct pt_regs *regs) {const struct exception_table_entry *entry; -enum ctx_state prev_state =exception_enter (); -int rc =__do_page_fault (regs, regs->dar, regs->dsisr); -exception_exit (prev_state); -if (likely (!rc)) -return 0 ; +enum ctx_state prev_state; +long err; + + prev_state =exception_enter (); + err =__do_page_fault (regs, regs->dar, regs->dsisr); +if (likely (!err)) + goto out; entry =search_exception_tables (regs->nip); -if (unlikely (!entry)) -return rc; +if (likely (entry)) { +instruction_pointer_set (regs,extable_fixup (entry)); + err =0 ; + } -instruction_pointer_set (regs,extable_fixup (entry)); +out: +exception_exit (prev_state); -return 0 ; +return err; }NOKPROBE_SYMBOL (do_page_fault);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 14/42 powerpc/64s: move bad_page_fault handling to C
In reply to Nicholas PigginThis simplifies code, and it is also useful when introducing interrupt handler wrappers when introducing wrapper functionality that doesn't cope with asm entry code calling into more than one handler function.
32-bit and 64e still have some such cases, which limits some ways they can use interrupt wrappers.
--- arch/powerpc/kernel/exceptions-64s.S | 12 ------------ arch/powerpc/mm/fault.c | 4 ++++ 2 files changed, 4 insertions(+), 12 deletions(-)
arch/powerpc/kernel/exceptions-64s.S +0 -12
@@ -1447,12 +1447,6 @@ BEGIN_MMU_FTR_SECTION MMU_FTR_SECTION_ELSE bl do_page_fault ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) - cmpdi r3,0 - beq+ interrupt_return - mr r5,r3 - addi r3,r1,STACK_FRAME_OVERHEAD - ld r4,_DAR(r1) - bl __bad_page_fault b interrupt_return 1: bl do_break
@@ -1557,12 +1551,6 @@ BEGIN_MMU_FTR_SECTION MMU_FTR_SECTION_ELSE bl do_page_fault ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) - cmpdi r3,0 - beq+ interrupt_return - mr r5,r3 - addi r3,r1,STACK_FRAME_OVERHEAD - ld r4,_DAR(r1) - bl __bad_page_fault b interrupt_return GEN_KVM instruction_access
arch/powerpc/mm/fault.c +4 -0
@@ -557,6 +557,10 @@ long do_page_fault(struct pt_regs *regs)if (likely (entry)) {instruction_pointer_set (regs,extable_fixup (entry)); err =0 ; + }else if (IS_ENABLED (CONFIG_PPC_BOOK3S_64 )) { +/* 32 and 64e handle this in asm */ +__bad_page_fault (regs, err); + err =0 ; } out:
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 15/42 powerpc/64s: split do_hash_fault
In reply to Nicholas PigginThis is required for subsequent interrupt wrapper implementation.
--- arch/powerpc/mm/book3s64/hash_utils.c | 56 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 23 deletions(-)
arch/powerpc/mm/book3s64/hash_utils.c +33 -23
@@ -1512,7 +1512,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap, }EXPORT_SYMBOL_GPL (hash_page); -long do_hash_fault (struct pt_regs *regs) +static long __do_hash_fault (struct pt_regs *regs) {unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;
@@ -1522,27 +1522,6 @@ long do_hash_fault(struct pt_regs *regs)unsigned int region_id;long err; -if (unlikely (dsisr & (DSISR_BAD_FAULT_64S |DSISR_KEYFAULT ))) - goto page_fault; - -/* -* If we are in an "NMI" (e.g., an interrupt when soft-disabled), then -* don't call hash_page, just fail the fault. This is required to -* prevent re-entrancy problems in the hash code, namely perf -* interrupts hitting while something holds H_PAGE_BUSY, and taking a -* hash fault. See the comment in hash_preload(). -* -* We come here as a result of a DSI at a point where we don't want -* to call hash_page, such as when we are accessing memory (possibly -* user memory) inside a PMU interrupt that occurred while interrupts -* were soft-disabled. We want to invoke the exception handler for -* the access, or panic if there isn't a handler. -*/ -if (unlikely (in_nmi ())) { -bad_page_fault (regs,SIGSEGV ); -return 0 ; - } - region_id =get_region_id (ea);if ((region_id ==VMALLOC_REGION_ID ) || (region_id ==IO_REGION_ID )) mm = &init_mm;
@@ -1581,8 +1560,39 @@ long do_hash_fault(struct pt_regs *regs)bad_page_fault (regs,SIGBUS ); } err =0 ; + } + +return err; +} + +long do_hash_fault (struct pt_regs *regs) +{ +unsigned long dsisr = regs->dsisr; +long err; + +if (unlikely (dsisr & (DSISR_BAD_FAULT_64S |DSISR_KEYFAULT ))) + goto page_fault; + +/* +* If we are in an "NMI" (e.g., an interrupt when soft-disabled), then +* don't call hash_page, just fail the fault. This is required to +* prevent re-entrancy problems in the hash code, namely perf +* interrupts hitting while something holds H_PAGE_BUSY, and taking a +* hash fault. See the comment in hash_preload(). +* +* We come here as a result of a DSI at a point where we don't want +* to call hash_page, such as when we are accessing memory (possibly +* user memory) inside a PMU interrupt that occurred while interrupts +* were soft-disabled. We want to invoke the exception handler for +* the access, or panic if there isn't a handler. +*/ +if (unlikely (in_nmi ())) { +bad_page_fault (regs,SIGSEGV ); +return 0 ; + } - }else if (err) { + err =__do_hash_fault (regs); +if (err) { page_fault: err =do_page_fault (regs); }
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 16/42 powerpc/mm: Remove stale do_page_fault comment referring to SLB faults
In reply to Nicholas PigginSLB faults no longer call do_page_fault, this was removed somewhere between 2.6.0 and 2.6.12.
--- arch/powerpc/mm/fault.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
arch/powerpc/mm/fault.c +5 -7
@@ -377,13 +377,11 @@ static void sanity_check_fault(bool is_write, bool is_user,/* * For 600- and 800-family processors, the error_code parameter is DSISR -* for a data fault, SRR1 for an instruction fault. For 400-family processors -* the error_code parameter is ESR for a data fault, 0 for an instruction -* fault. -* For 64-bit processors, the error_code parameter is -* - DSISR for a non-SLB data access fault, -* - SRR1 & 0x08000000 for a non-SLB instruction access fault -* - 0 any SLB fault. +* for a data fault, SRR1 for an instruction fault. +* For 400-family processors the error_code parameter is ESR for a data fault, +* 0 for an instruction fault. +* For 64-bit processors, the error_code parameter is DSISR for a data access +* fault, SRR1 & 0x08000000 for an instruction access fault. * * The return value is 0 if the fault was handled, or the signal * number if this is a kernel fault that can't be handled here.
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 17/42 powerpc/64s: slb comment update
In reply to Nicholas PigginThis makes a small improvement to the description of the SLB interrupt environment. Move the memory access restrictions into one paragraph, and the interrupt restrictions into the next rather than mix them.
--- arch/powerpc/mm/book3s64/slb.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
arch/powerpc/mm/book3s64/slb.c +15 -13
@@ -825,19 +825,21 @@ long do_slb_fault(struct pt_regs *regs)return -EINVAL ;/* -* SLB kernel faults must be very careful not to touch anything -* that is not bolted. E.g., PACA and global variables are okay, -* mm->context stuff is not. -* -* SLB user faults can access all of kernel memory, but must be -* careful not to touch things like IRQ state because it is not -* "reconciled" here. The difficulty is that we must use -* fast_exception_return to return from kernel SLB faults without -* looking at possible non-bolted memory. We could test user vs -* kernel faults in the interrupt handler asm and do a full fault, -* reconcile, ret_from_except for user faults which would make them -* first class kernel code. But for performance it's probably nicer -* if they go via fast_exception_return too. +* SLB kernel faults must be very careful not to touch anything that is +* not bolted. E.g., PACA and global variables are okay, mm->context +* stuff is not. SLB user faults may access all of memory (and induce +* one recursive SLB kernel fault), so the kernel fault must not +* trample on the user fault state at those points. +*/ + +/* +* The interrupt state is not reconciled, for performance, so that +* fast_interrupt_return can be used. The handler must not touch local +* irq state, or schedule. We could test for usermode and upgrade to a +* normal process context (synchronous) interrupt for those, which +* would make them first-class kernel code and able to be traced and +* instrumented, although performance would suffer a bit, it would +* probably be a good tradeoff. */ if (id >=LINEAR_MAP_REGION_ID ) {long err;
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 18/42 powerpc/traps: add NOKPROBE_SYMBOL for sreset and mce
In reply to Nicholas PigginThese NMIs could fire any time including inside kprobe code, so exclude them from kprobes.
--- arch/powerpc/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/kernel/traps.c +2 -0
@@ -517,6 +517,7 @@ void system_reset_exception(struct pt_regs *regs)/* What should we do here? We could issue a shutdown or hard reset. */ } +NOKPROBE_SYMBOL (system_reset_exception);/* * I/O accesses can cause machine checks on powermacs.
@@ -843,6 +844,7 @@ void machine_check_exception(struct pt_regs *regs) bail:if (nmi)nmi_exit (); } +NOKPROBE_SYMBOL (machine_check_exception);void SMIException (struct pt_regs *regs) {
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 19/42 powerpc/perf: move perf irq/nmi handling details into traps.c
In reply to Nicholas PigginThis is required in order to allow more significant differences between NMI type interrupt handlers and regular asynchronous handlers.
--- arch/powerpc/kernel/traps.c | 31 +++++++++++++++++++++++++++- arch/powerpc/perf/core-book3s.c | 35 ++------------------------------ arch/powerpc/perf/core-fsl-emb.c | 25 ----------------------- 3 files changed, 32 insertions(+), 59 deletions(-)
arch/powerpc/kernel/traps.c +30 -1
@@ -1892,11 +1892,40 @@ void vsx_unavailable_tm(struct pt_regs *regs) }#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ -void performance_monitor_exception (struct pt_regs *regs) +static void performance_monitor_exception_nmi (struct pt_regs *regs) +{ +nmi_enter (); + +__this_cpu_inc (irq_stat.pmu_irqs); + +perf_irq (regs); + +nmi_exit (); +} + +static void performance_monitor_exception_async (struct pt_regs *regs) { +irq_enter (); +__this_cpu_inc (irq_stat.pmu_irqs);perf_irq (regs); + +irq_exit (); +} + +void performance_monitor_exception (struct pt_regs *regs) +{ +/* +* On 64-bit, if perf interrupts hit in a local_irq_disable +* (soft-masked) region, we consider them as NMIs. This is required to +* prevent hash faults on user addresses when reading callchains (and +* looks better from an irq tracing perspective). +*/ +if (IS_ENABLED (CONFIG_PPC64 ) &&unlikely (arch_irq_disabled_regs (regs))) +performance_monitor_exception_nmi (regs); +else +performance_monitor_exception_async (regs); }#ifdef CONFIG_PPC_ADV_DEBUG_REGS
arch/powerpc/perf/core-book3s.c +2 -33
@@ -110,10 +110,6 @@ static inline void perf_read_regs(struct pt_regs *regs) { regs->result =0 ; } -static inline int perf_intr_is_nmi (struct pt_regs *regs) -{ -return 0 ; -}static inline int siar_valid (struct pt_regs *regs) {
@@ -353,15 +349,6 @@ static inline void perf_read_regs(struct pt_regs *regs) regs->result = use_siar; } -/* -* If interrupts were soft-disabled when a PMU interrupt occurs, treat -* it as an NMI. -*/ -static inline int perf_intr_is_nmi (struct pt_regs *regs) -{ -return (regs->softe &IRQS_DISABLED ); -} -/* * On processors like P7+ that have the SIAR-Valid bit, marked instructions * must be sampled only if the SIAR-valid bit is set.
@@ -2279,7 +2266,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)struct perf_event *event;unsigned long val[8 ];int found, active; -int nmi;if (cpuhw->n_limited) freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5),
@@ -2287,18 +2273,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)perf_read_regs (regs); -/* -* If perf interrupts hit in a local_irq_disable (soft-masked) region, -* we consider them as NMIs. This is required to prevent hash faults on -* user addresses when reading callchains. See the NMI test in -* do_hash_page. -*/ - nmi =perf_intr_is_nmi (regs); -if (nmi) -nmi_enter (); -else -irq_enter (); -/* Read all the PMCs since we'll need them a bunch of times */ for (i =0 ; i < ppmu->n_counter; ++i) val[i] =read_pmc (i +1 );
@@ -2344,8 +2318,8 @@ static void __perf_event_interrupt(struct pt_regs *regs) } } } -if (!found && !nmi &&printk_ratelimit ()) -printk (KERN_WARNING "Can't find PMC that caused IRQ\n" ); +if (unlikely (!found) && !arch_irq_disabled_regs (regs)) +printk_ratelimited (KERN_WARNING "Can't find PMC that caused IRQ\n" );/* * Reset MMCR0 to its normal value. This will set PMXE and
@@ -2355,11 +2329,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)* we get back out of this interrupt. */ write_mmcr0 (cpuhw, cpuhw->mmcr.mmcr0); - -if (nmi) -nmi_exit (); -else -irq_exit (); }static void perf_event_interrupt (struct pt_regs *regs)
arch/powerpc/perf/core-fsl-emb.c +0 -25
@@ -31,19 +31,6 @@ static atomic_t num_events;/* Used to avoid races in calling reserve/release_pmc_hardware */ static DEFINE_MUTEX (pmc_reserve_mutex); -/* -* If interrupts were soft-disabled when a PMU interrupt occurs, treat -* it as an NMI. -*/ -static inline int perf_intr_is_nmi (struct pt_regs *regs) -{ -#ifdef __powerpc64__ -return (regs->softe &IRQS_DISABLED ); -#else -return 0 ; -#endif -} -static void perf_event_interrupt (struct pt_regs *regs);/*
@@ -659,13 +646,6 @@ static void perf_event_interrupt(struct pt_regs *regs)struct perf_event *event;unsigned long val;int found =0 ; -int nmi; - - nmi =perf_intr_is_nmi (regs); -if (nmi) -nmi_enter (); -else -irq_enter ();for (i =0 ; i < ppmu->n_counter; ++i) { event = cpuhw->event[i];
@@ -690,11 +670,6 @@ static void perf_event_interrupt(struct pt_regs *regs)mtmsr (mfmsr () |MSR_PMM );mtpmr (PMRN_PMGC0 ,PMGC0_PMIE |PMGC0_FCECE );isync (); - -if (nmi) -nmi_exit (); -else -irq_exit (); }void hw_perf_event_setup (int cpu)
Signature · 1 line
2.23.0
Re: [PATCH v7 19/42] powerpc/perf: move perf irq/nmi handling details into traps.c
On 30-Jan-2021, at 6:38 PM, Nicholas Piggin <[email protected]> wrote:
This is required in order to allow more significant differences between NMI type interrupt handlers and regular asynchronous handlers.
---arch/powerpc/kernel/traps.c | 31 +++++++++++++++++++++++++++- arch/powerpc/perf/core-book3s.c | 35 ++------------------------------ arch/powerpc/perf/core-fsl-emb.c | 25 -----------------------
3 files changed, 32 insertions(+), 59 deletions(-)
arch/powerpc/kernel/traps.c +0 -0
@@ -1892,11 +1892,40 @@ void vsx_unavailable_tm(struct pt_regs *regs)
}
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
-void performance_monitor_exception(struct pt_regs *regs) +static void performance_monitor_exception_nmi(struct pt_regs *regs) +{
+nmi_enter();
+
+__this_cpu_inc(irq_stat.pmu_irqs);
+
+perf_irq(regs);
+
+nmi_exit();
+}
+
+static void performance_monitor_exception_async(struct pt_regs *regs) {
+irq_enter();
+__this_cpu_inc(irq_stat.pmu_irqs);
perf_irq(regs);
+
+irq_exit();
+}
+
+void performance_monitor_exception(struct pt_regs *regs)
+{
+ /*
+* On 64-bit, if perf interrupts hit in a local_irq_disable +* (soft-masked) region, we consider them as NMIs. This is required to +* prevent hash faults on user addresses when reading callchains (and +* looks better from an irq tracing perspective).
+ */
+if (IS_ENABLED(CONFIG_PPC64) && unlikely(arch_irq_disabled_regs(regs))) +performance_monitor_exception_nmi(regs);
+ else
+performance_monitor_exception_async(regs);
}
Hi Nick,
Thanks for the change in tracing of PMI interrupts.
I tested with this patch that moves perf irq/nmi handling details into traps.c and verified the patch works fine for NMI and asynchronous cases.
Test scenario1: My test kernel module tries to create one of performance monitor counter overflow between local_irq_save/local_irq_restore which should be delivered as an NMI.
Verified it calls NMI exception handler from my ftrace logs below
<<>>dummy_perf <-performance_monitor_exception_nmi
<<>>
Test scenario2: My test kernel module tries to create one of performance monitor counter overflow between powerpc_local_irq_pmu_save/restore which should be delivered as an asynchronous interrupt ( replayed PMI ).
Verified it calls correct handler from my ftrace logs:
<<>>replay_soft_interrupts <-arch_local_irq_restore irq_enter <-performance_monitor_exception_async irq_enter_rcu <-performance_monitor_exception_async dummy_perf <-performance_monitor_exception_async irq_exit <-performance_monitor_exception_async <<>>
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
arch/powerpc/perf/core-book3s.c +0 -0
@@ -110,10 +110,6 @@ static inline void perf_read_regs(struct pt_regs *regs)
{regs->result = 0;
}
-static inline int perf_intr_is_nmi(struct pt_regs *regs) -{
-return 0;
-}
static inline int siar_valid(struct pt_regs *regs)
{
@@ -353,15 +349,6 @@ static inline void perf_read_regs(struct pt_regs *regs) regs->result = use_siar;
}
-/*
- * If interrupts were soft-disabled when a PMU interrupt occurs, treat
- * it as an NMI.
- */
-static inline int perf_intr_is_nmi(struct pt_regs *regs)
-{
-return (regs->softe & IRQS_DISABLED);
-}
-
/*
* On processors like P7+ that have the SIAR-Valid bit, marked instructions
* must be sampled only if the SIAR-valid bit is set.
@@ -2279,7 +2266,6 @@ static void __perf_event_interrupt(struct pt_regs *regs) struct perf_event *event;
unsigned long val[8];
int found, active;
-int nmi;
if (cpuhw->n_limited)
freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5),
@@ -2287,18 +2273,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)
perf_read_regs(regs);
- /*
-* If perf interrupts hit in a local_irq_disable (soft-masked) region, -* we consider them as NMIs. This is required to prevent hash faults on -* user addresses when reading callchains. See the NMI test in
-* do_hash_page.
- */
-nmi = perf_intr_is_nmi(regs);
-if (nmi)
-nmi_enter();
- else
-irq_enter();
-
/* Read all the PMCs since we'll need them a bunch of times */ for (i = 0; i < ppmu->n_counter; ++i)
val[i] = read_pmc(i + 1);
@@ -2344,8 +2318,8 @@ static void __perf_event_interrupt(struct pt_regs *regs)
}
}
}
-if (!found && !nmi && printk_ratelimit())
-printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
+if (unlikely(!found) && !arch_irq_disabled_regs(regs)) +printk_ratelimited(KERN_WARNING "Can't find PMC that caused IRQ\n");
/*
* Reset MMCR0 to its normal value. This will set PMXE and
@@ -2355,11 +2329,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)
* we get back out of this interrupt.
*/write_mmcr0(cpuhw, cpuhw->mmcr.mmcr0);
-
-if (nmi)
-nmi_exit();
- else
-irq_exit();
}
static void perf_event_interrupt(struct pt_regs *regs)
arch/powerpc/perf/core-fsl-emb.c +0 -0
@@ -31,19 +31,6 @@ static atomic_t num_events;
/* Used to avoid races in calling reserve/release_pmc_hardware */ static DEFINE_MUTEX(pmc_reserve_mutex);
-/*
- * If interrupts were soft-disabled when a PMU interrupt occurs, treat
- * it as an NMI.
- */
-static inline int perf_intr_is_nmi(struct pt_regs *regs)
-{
-#ifdef __powerpc64__
-return (regs->softe & IRQS_DISABLED);
-#else
-return 0;
-#endif
-}
-
static void perf_event_interrupt(struct pt_regs *regs);
/*
@@ -659,13 +646,6 @@ static void perf_event_interrupt(struct pt_regs *regs) struct perf_event *event;
unsigned long val;
int found = 0;
-int nmi;
-
-nmi = perf_intr_is_nmi(regs);
-if (nmi)
-nmi_enter();
- else
-irq_enter();
for (i = 0; i < ppmu->n_counter; ++i) {
event = cpuhw->event[i];
@@ -690,11 +670,6 @@ static void perf_event_interrupt(struct pt_regs *regs) mtmsr(mfmsr() | MSR_PMM);mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);isync();
-
-if (nmi)
-nmi_exit();
- else
-irq_exit();
}
void hw_perf_event_setup(int cpu)
--
2.23.0
Nicholas Piggin
reviewerPATCH v7 20/42 powerpc/time: move timer_broadcast_interrupt prototype to asm/time.h
In reply to Nicholas PigginInterrupt handler prototypes are going to be rearranged in a future patch, so tidy this out of the way first.
--- arch/powerpc/include/asm/hw_irq.h | 1 - arch/powerpc/include/asm/time.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/hw_irq.h +0 -1
@@ -54,7 +54,6 @@ extern void replay_system_reset(void);extern void replay_soft_interrupts (void );extern void timer_interrupt (struct pt_regs *); -extern void timer_broadcast_interrupt (void );extern void performance_monitor_exception (struct pt_regs *regs);extern void WatchdogException (struct pt_regs *regs);extern void unknown_exception (struct pt_regs *regs);
arch/powerpc/include/asm/time.h +2 -0
@@ -102,6 +102,8 @@ DECLARE_PER_CPU(u64, decrementers_next_tb);/* Convert timebase ticks to nanoseconds */ unsigned long long tb_to_ns (unsigned long long tb_ticks); +void timer_broadcast_interrupt (void ); +/* SPLPAR */ void accumulate_stolen_time (void );
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 21/42 powerpc: add and use unknown_async_exception
In reply to Nicholas PigginThis is currently the same as unknown_exception, but it will diverge after interrupt wrappers are added and code moved out of asm into the wrappers (e.g., async handlers will check FINISH_NAP).
--- arch/powerpc/include/asm/hw_irq.h | 1 + arch/powerpc/kernel/exceptions-64s.S | 4 ++-- arch/powerpc/kernel/head_book3s_32.S | 6 +++--- arch/powerpc/kernel/traps.c | 12 ++++++++++++ 4 files changed, 18 insertions(+), 5 deletions(-)
arch/powerpc/include/asm/hw_irq.h +1 -0
@@ -57,6 +57,7 @@ extern void timer_interrupt(struct pt_regs *);extern void performance_monitor_exception (struct pt_regs *regs);extern void WatchdogException (struct pt_regs *regs);extern void unknown_exception (struct pt_regs *regs); +void unknown_async_exception (struct pt_regs *regs);#ifdef CONFIG_PPC64 #include <asm/paca.h>
arch/powerpc/kernel/exceptions-64s.S +2 -2
@@ -1926,7 +1926,7 @@ EXC_COMMON_BEGIN(doorbell_super_common) #ifdef CONFIG_PPC_DOORBELL bl doorbell_exception #else - bl unknown_exception + bl unknown_async_exception #endif b interrupt_return
@@ -2312,7 +2312,7 @@ EXC_COMMON_BEGIN(h_doorbell_common) #ifdef CONFIG_PPC_DOORBELL bl doorbell_exception #else - bl unknown_exception + bl unknown_async_exception #endif b interrupt_return
arch/powerpc/kernel/head_book3s_32.S +3 -3
@@ -238,8 +238,8 @@ __secondary_hold_acknowledge: /* System reset */ /* core99 pmac starts the seconary here by changing the vector, and - putting it back to what it was (unknown_exception) when done. */ - EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD) + putting it back to what it was (unknown_async_exception) when done. */ + EXCEPTION(0x100, Reset, unknown_async_exception, EXC_XFER_STD) /* Machine check */ /*
@@ -640,7 +640,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) #endif #ifndef CONFIG_TAU_INT -#define TAUException unknown_exception +#define TAUException unknown_async_exception #endif EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_STD)
arch/powerpc/kernel/traps.c +12 -0
@@ -1073,6 +1073,18 @@ void unknown_exception(struct pt_regs *regs)exception_exit (prev_state); } +void unknown_async_exception (struct pt_regs *regs) +{ +enum ctx_state prev_state =exception_enter (); + +printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , + regs->nip, regs->msr, regs->trap); + +_exception (SIGTRAP , regs,TRAP_UNK ,0 ); + +exception_exit (prev_state); +} +void instruction_breakpoint_exception (struct pt_regs *regs) {enum ctx_state prev_state =exception_enter ();
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 22/42 powerpc/cell: tidy up pervasive declarations
In reply to Nicholas PigginThese are declared in ras.h and defined in ras.c so remove them from pervasive.h
--- arch/powerpc/platforms/cell/pervasive.c | 1 + arch/powerpc/platforms/cell/pervasive.h | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-)
arch/powerpc/platforms/cell/pervasive.c +1 -0
@@ -25,6 +25,7 @@#include <asm/cpu_has_feature.h> #include "pervasive.h" +#include "ras.h" static void cbe_power_save (void ) {
arch/powerpc/platforms/cell/pervasive.h +0 -3
@@ -13,9 +13,6 @@#define PERVASIVE_H extern void cbe_pervasive_init (void ); -extern void cbe_system_error_exception (struct pt_regs *regs); -extern void cbe_maintenance_exception (struct pt_regs *regs); -extern void cbe_thermal_exception (struct pt_regs *regs);#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON extern int cbe_sysreset_hack (void );
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 23/42 powerpc: introduce die_mce
In reply to Nicholas PigginAs explained by commit daf00ae71dad ("powerpc/traps: restore recoverability of machine_check interrupts"), die() can't be called from within nmi_enter to nicely kill a process context that was interrupted. nmi_exit must be called first.
This adds a function die_mce which takes care of this for machine check handlers.
--- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/kernel/traps.c | 21 +++++++++++++++------ arch/powerpc/platforms/powernv/opal.c | 2 +- arch/powerpc/platforms/pseries/ras.c | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-)
arch/powerpc/include/asm/bug.h +1 -0
@@ -118,6 +118,7 @@ void do_bad_page_fault_segv(struct pt_regs *regs);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 ); +void die_mce (const char *str,struct pt_regs *regs,long err);extern bool die_will_crash (void );extern void panic_flush_kmsg_start (void );extern void panic_flush_kmsg_end (void );
arch/powerpc/kernel/traps.c +15 -6
@@ -789,6 +789,19 @@ int machine_check_generic(struct pt_regs *regs) }#endif /* everything else */ +void die_mce (const char *str,struct pt_regs *regs,long err) +{ +/* +* The machine check wants to kill the interrupted context, but +* do_exit() checks for in_interrupt() and panics in that case, so +* exit the irq/nmi before calling die. +*/ +if (!IS_ENABLED (CONFIG_PPC_BOOK3S_64 )) +nmi_exit (); +die (str, regs, err); +} +NOKPROBE_SYMBOL (die_mce); +void machine_check_exception (struct pt_regs *regs) {int recover =0 ;
@@ -831,15 +844,11 @@ void machine_check_exception(struct pt_regs *regs)if (check_io_access (regs)) goto bail; -if (nmi)nmi_exit (); - -die ("Machine check" , regs,SIGBUS ); +die_mce ("Machine check" , regs,SIGBUS );/* Must die if the interrupt is not recoverable */ if (!(regs->msr &MSR_RI )) -die ("Unrecoverable Machine check" , regs,SIGBUS ); - -return ; +die_mce ("Unrecoverable Machine check" , regs,SIGBUS ); bail:if (nmi)nmi_exit ();
arch/powerpc/platforms/powernv/opal.c +1 -1
@@ -624,7 +624,7 @@ static int opal_recover_mce(struct pt_regs *regs,*/ recovered =0 ; }else { -die ("Machine check" , regs,SIGBUS ); +die_mce ("Machine check" , regs,SIGBUS ); recovered =1 ; } }
arch/powerpc/platforms/pseries/ras.c +1 -1
@@ -813,7 +813,7 @@ static int recover_mce(struct pt_regs *regs, struct machine_check_event *evt)*/ recovered =0 ; }else { -die ("Machine check" , regs,SIGBUS ); +die_mce ("Machine check" , regs,SIGBUS ); recovered =1 ; } }
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 24/42 powerpc/mce: ensure machine check handler always tests RI
In reply to Nicholas PigginA machine check that is handled must still check MSR[RI] for recoverability of the interrupted context. Without this patch it's possible for a handled machine check to return to a context where it has clobbered live registers.
--- arch/powerpc/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/traps.c +1 -1
@@ -846,11 +846,11 @@ void machine_check_exception(struct pt_regs *regs)die_mce ("Machine check" , regs,SIGBUS ); +bail:/* Must die if the interrupt is not recoverable */ if (!(regs->msr &MSR_RI ))die_mce ("Unrecoverable Machine check" , regs,SIGBUS ); -bail:if (nmi)nmi_exit (); }NOKPROBE_SYMBOL (machine_check_exception);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 25/42 powerpc: improve handling of unrecoverable system reset
In reply to Nicholas PigginIf an unrecoverable system reset hits in process context, the system does not have to panic. Similar to machine check, call nmi_exit() before die().
--- arch/powerpc/kernel/traps.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/powerpc/kernel/traps.c +4 -1
@@ -503,8 +503,11 @@ void system_reset_exception(struct pt_regs *regs)die ("Unrecoverable nested System Reset" , regs,SIGABRT );#endif /* Must die if the interrupt is not recoverable */ -if (!(regs->msr &MSR_RI )) +if (!(regs->msr &MSR_RI )) { +/* For the reason explained in die_mce, nmi_exit before die */ +nmi_exit ();die ("Unrecoverable System Reset" , regs,SIGABRT ); + }if (saved_hsrrs) {mtspr (SPRN_HSRR0 , hsrr0);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 26/42 powerpc: interrupt handler wrapper functions
In reply to Nicholas PigginAdd wrapper functions (derived from x86 macros) for interrupt handler functions. This allows interrupt entry code to be written in C.
--- arch/powerpc/include/asm/interrupt.h | 169 +++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 arch/powerpc/include/asm/interrupt.h
arch/powerpc/include/asm/interrupt.h new file +169 -0
@@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _ASM_POWERPC_INTERRUPT_H +#define _ASM_POWERPC_INTERRUPT_H + +#include <linux/context_tracking.h> +#include <asm/ftrace.h> + +/** +* DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +*/ +#define DECLARE_INTERRUPT_HANDLER_RAW (func) \ + __visible long func(struct pt_regs *regs) + +/** +* DEFINE_INTERRUPT_HANDLER_RAW - Define raw interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +* +* @func is called from ASM entry code. +* +* This is a plain function which does no tracing, reconciling, etc. +* The macro is written so it acts as function definition. Append the +* body with a pair of curly brackets. +* +* raw interrupt handlers must not enable or disable interrupts, or +* schedule, tracing and instrumentation (ftrace, lockdep, etc) would +* not be advisable either, although may be possible in a pinch, the +* trace will look odd at least. +* +* A raw handler may call one of the other interrupt handler functions +* to be converted into that interrupt context without these restrictions. +* +* On PPC64, _RAW handlers may return with fast_interrupt_return. +* +* Specific handlers may have additional restrictions. +*/ +#define DEFINE_INTERRUPT_HANDLER_RAW (func) \ +static __always_inline long ____##func(struct pt_regs *regs); \ + \ +__visible noinstr long func(struct pt_regs *regs) \ +{ \ + long ret; \ + \ + ret = ____##func (regs); \ + \ + return ret; \ +} \ + \ +static __always_inline long ____##func(struct pt_regs *regs) + +/** +* DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function +* @func: Function name of the entry point +*/ +#define DECLARE_INTERRUPT_HANDLER (func) \ + __visible void func(struct pt_regs *regs) + +/** +* DEFINE_INTERRUPT_HANDLER - Define synchronous interrupt handler function +* @func: Function name of the entry point +* +* @func is called from ASM entry code. +* +* The macro is written so it acts as function definition. Append the +* body with a pair of curly brackets. +*/ +#define DEFINE_INTERRUPT_HANDLER (func) \ +static __always_inline void ____##func(struct pt_regs *regs); \ + \ +__visible noinstr void func(struct pt_regs *regs) \ +{ \ + ____##func (regs); \ +} \ + \ +static __always_inline void ____##func(struct pt_regs *regs) + +/** +* DECLARE_INTERRUPT_HANDLER_RET - Declare synchronous interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +*/ +#define DECLARE_INTERRUPT_HANDLER_RET (func) \ + __visible long func(struct pt_regs *regs) + +/** +* DEFINE_INTERRUPT_HANDLER_RET - Define synchronous interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +* +* @func is called from ASM entry code. +* +* The macro is written so it acts as function definition. Append the +* body with a pair of curly brackets. +*/ +#define DEFINE_INTERRUPT_HANDLER_RET (func) \ +static __always_inline long ____##func(struct pt_regs *regs); \ + \ +__visible noinstr long func(struct pt_regs *regs) \ +{ \ + long ret; \ + \ + ret = ____##func (regs); \ + \ + return ret; \ +} \ + \ +static __always_inline long ____##func(struct pt_regs *regs) + +/** +* DECLARE_INTERRUPT_HANDLER_ASYNC - Declare asynchronous interrupt handler function +* @func: Function name of the entry point +*/ +#define DECLARE_INTERRUPT_HANDLER_ASYNC (func) \ + __visible void func(struct pt_regs *regs) + +/** +* DEFINE_INTERRUPT_HANDLER_ASYNC - Define asynchronous interrupt handler function +* @func: Function name of the entry point +* +* @func is called from ASM entry code. +* +* The macro is written so it acts as function definition. Append the +* body with a pair of curly brackets. +*/ +#define DEFINE_INTERRUPT_HANDLER_ASYNC (func) \ +static __always_inline void ____##func(struct pt_regs *regs); \ + \ +__visible noinstr void func(struct pt_regs *regs) \ +{ \ + ____##func (regs); \ +} \ + \ +static __always_inline void ____##func(struct pt_regs *regs) + +/** +* DECLARE_INTERRUPT_HANDLER_NMI - Declare NMI interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +*/ +#define DECLARE_INTERRUPT_HANDLER_NMI (func) \ + __visible long func(struct pt_regs *regs) + +/** +* DEFINE_INTERRUPT_HANDLER_NMI - Define NMI interrupt handler function +* @func: Function name of the entry point +* @returns: Returns a value back to asm caller +* +* @func is called from ASM entry code. +* +* The macro is written so it acts as function definition. Append the +* body with a pair of curly brackets. +*/ +#define DEFINE_INTERRUPT_HANDLER_NMI (func) \ +static __always_inline long ____##func(struct pt_regs *regs); \ + \ +__visible noinstr long func(struct pt_regs *regs) \ +{ \ + long ret; \ + \ + ret = ____##func (regs); \ + \ + return ret; \ +} \ + \ +static __always_inline long ____##func(struct pt_regs *regs) + +#endif /* _ASM_POWERPC_INTERRUPT_H */
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 27/42 powerpc: add interrupt wrapper entry / exit stub functions
In reply to Nicholas PigginThese will be used by subsequent patches.
--- arch/powerpc/include/asm/interrupt.h | 66 ++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
arch/powerpc/include/asm/interrupt.h +66 -0
@@ -5,6 +5,50 @@#include <linux/context_tracking.h> #include <asm/ftrace.h> +struct interrupt_state { +}; + +static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) +{ +} + +/* +* Care should be taken to note that interrupt_exit_prepare and +* interrupt_async_exit_prepare do not necessarily return immediately to +* regs context (e.g., if regs is usermode, we don't necessarily return to +* user mode). Other interrupts might be taken between here and return, +* context switch / preemption may occur in the exit path after this, or a +* signal may be delivered, etc. +* +* The real interrupt exit code is platform specific, e.g., +* interrupt_exit_user_prepare / interrupt_exit_kernel_prepare for 64s. +* +* However interrupt_nmi_exit_prepare does return directly to regs, because +* NMIs do not do "exit work" or replay soft-masked interrupts. +*/ +static inline void interrupt_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) +{ +} + +static inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) +{ +} + +static inline void interrupt_async_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) +{ +} + +struct interrupt_nmi_state { +}; + +static inline void interrupt_nmi_enter_prepare (struct pt_regs *regs,struct interrupt_nmi_state *state) +{ +} + +static inline void interrupt_nmi_exit_prepare (struct pt_regs *regs,struct interrupt_nmi_state *state) +{ +} +/** * DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function * @func: Function name of the entry point
@@ -71,7 +115,13 @@ static __always_inline void ____##func(struct pt_regs *regs); \ \ __visible noinstr void func(struct pt_regs *regs) \ { \ +struct interrupt_state state; \ + \ +interrupt_enter_prepare (regs, &state); \ + \ ____##func (regs); \ + \ + interrupt_exit_prepare(regs, &state); \ } \ \ static __always_inline void ____##func(struct pt_regs *regs)
@@ -99,10 +149,15 @@ static __always_inline long ____##func(struct pt_regs *regs); \ \ __visible noinstr long func(struct pt_regs *regs) \ { \ +struct interrupt_state state; \long ret; \ \ +interrupt_enter_prepare (regs, &state); \ + \ ret = ____##func (regs); \ \ +interrupt_exit_prepare (regs, &state); \ + \return ret; \ } \ \
@@ -129,7 +184,13 @@ static __always_inline void ____##func(struct pt_regs *regs); \ \ __visible noinstr void func(struct pt_regs *regs) \ { \ +struct interrupt_state state; \ + \ +interrupt_async_enter_prepare (regs, &state); \ + \ ____##func (regs); \ + \ + interrupt_async_exit_prepare(regs, &state); \ } \ \ static __always_inline void ____##func(struct pt_regs *regs)
@@ -157,10 +218,15 @@ static __always_inline long ____##func(struct pt_regs *regs); \ \ __visible noinstr long func(struct pt_regs *regs) \ { \ +struct interrupt_nmi_state state; \long ret; \ \ +interrupt_nmi_enter_prepare (regs, &state); \ + \ ret = ____##func (regs); \ \ +interrupt_nmi_exit_prepare (regs, &state); \ + \return ret; \ } \ \
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 28/42 powerpc: convert interrupt handlers to use wrappers
In reply to Nicholas Piggin--- arch/powerpc/include/asm/asm-prototypes.h | 29 ------- arch/powerpc/include/asm/book3s/64/mmu-hash.h | 1 - arch/powerpc/include/asm/debug.h | 3 - arch/powerpc/include/asm/hw_irq.h | 9 -- arch/powerpc/include/asm/interrupt.h | 66 ++++++++++++++ arch/powerpc/kernel/dbell.c | 6 +- arch/powerpc/kernel/irq.c | 3 +- arch/powerpc/kernel/mce.c | 5 +- arch/powerpc/kernel/process.c | 3 +- arch/powerpc/kernel/syscall_64.c | 1 + arch/powerpc/kernel/tau_6xx.c | 2 +- arch/powerpc/kernel/time.c | 3 +- arch/powerpc/kernel/traps.c | 86 ++++++++++++------- arch/powerpc/kernel/watchdog.c | 7 +- arch/powerpc/kvm/book3s_hv.c | 1 + arch/powerpc/kvm/book3s_hv_builtin.c | 1 + arch/powerpc/kvm/booke.c | 1 + arch/powerpc/mm/book3s64/hash_utils.c | 12 ++- arch/powerpc/mm/book3s64/slb.c | 7 +- arch/powerpc/mm/fault.c | 5 +- arch/powerpc/platforms/cell/ras.c | 6 +- arch/powerpc/platforms/cell/ras.h | 9 +- arch/powerpc/platforms/powernv/idle.c | 1 + 23 files changed, 167 insertions(+), 100 deletions(-)
arch/powerpc/include/asm/asm-prototypes.h +0 -29
@@ -56,35 +56,6 @@ int exit_vmx_usercopy(void);int enter_vmx_ops (void );void *exit_vmx_ops (void *dest); -/* Traps */ -long machine_check_early (struct pt_regs *regs); -long hmi_exception_realmode (struct pt_regs *regs); -void SMIException (struct pt_regs *regs); -void handle_hmi_exception (struct pt_regs *regs); -void instruction_breakpoint_exception (struct pt_regs *regs); -void RunModeException (struct pt_regs *regs); -void single_step_exception (struct pt_regs *regs); -void program_check_exception (struct pt_regs *regs); -void alignment_exception (struct pt_regs *regs); -void StackOverflow (struct pt_regs *regs); -void stack_overflow_exception (struct pt_regs *regs); -void kernel_fp_unavailable_exception (struct pt_regs *regs); -void altivec_unavailable_exception (struct pt_regs *regs); -void vsx_unavailable_exception (struct pt_regs *regs); -void fp_unavailable_tm (struct pt_regs *regs); -void altivec_unavailable_tm (struct pt_regs *regs); -void vsx_unavailable_tm (struct pt_regs *regs); -void facility_unavailable_exception (struct pt_regs *regs); -void TAUException (struct pt_regs *regs); -void altivec_assist_exception (struct pt_regs *regs); -void unrecoverable_exception (struct pt_regs *regs); -void kernel_bad_stack (struct pt_regs *regs); -void system_reset_exception (struct pt_regs *regs); -void machine_check_exception (struct pt_regs *regs); -void emulation_assist_interrupt (struct pt_regs *regs); -long do_slb_fault (struct pt_regs *regs); -void do_bad_slb_fault (struct pt_regs *regs); -/* signals, syscalls and interrupts */ long sys_swapcontext(struct ucontext __user *old_ctx, struct ucontext __user *new_ctx,
arch/powerpc/include/asm/book3s/64/mmu-hash.h +0 -1
@@ -454,7 +454,6 @@ static inline unsigned long hpt_hash(unsigned long vpn,#define HPTE_NOHPTE_UPDATE 0x2#define HPTE_USE_KERNEL_KEY 0x4 -long do_hash_fault (struct pt_regs *regs);extern int __hash_page_4K (unsigned long ea,unsigned long access,unsigned long vsid,pte_t *ptep,unsigned long trap,unsigned long flags,int ssize,int subpage_prot);
arch/powerpc/include/asm/debug.h +0 -3
@@ -50,9 +50,6 @@ bool ppc_breakpoint_available(void);#ifdef CONFIG_PPC_ADV_DEBUG_REGS extern void do_send_trap (struct pt_regs *regs,unsigned long address,unsigned long error_code,int brkpt); -#else - -void do_break (struct pt_regs *regs);#endif #endif /* _ASM_POWERPC_DEBUG_H */
arch/powerpc/include/asm/hw_irq.h +0 -9
@@ -50,15 +50,6 @@#ifndef __ASSEMBLY__ -extern void replay_system_reset (void ); -extern void replay_soft_interrupts (void ); - -extern void timer_interrupt (struct pt_regs *); -extern void performance_monitor_exception (struct pt_regs *regs); -extern void WatchdogException (struct pt_regs *regs); -extern void unknown_exception (struct pt_regs *regs); -void unknown_async_exception (struct pt_regs *regs); -#ifdef CONFIG_PPC64 #include <asm/paca.h>
arch/powerpc/include/asm/interrupt.h +66 -0
70 lines not on this page · raw message
arch/powerpc/kernel/dbell.c +3 -3
@@ -12,13 +12,14 @@#include <linux/hardirq.h> #include <asm/dbell.h> +#include <asm/interrupt.h> #include <asm/irq_regs.h> #include <asm/kvm_ppc.h> #include <asm/trace.h> #ifdef CONFIG_SMP -void doorbell_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_ASYNC (doorbell_exception) {struct pt_regs *old_regs =set_irq_regs (regs);
@@ -39,9 +40,8 @@ void doorbell_exception(struct pt_regs *regs) set_irq_regs(old_regs); }#else /* CONFIG_SMP */ -void doorbell_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_ASYNC (doorbell_exception) {printk (KERN_WARNING "Received doorbell on non-smp system\n" ); }#endif /* CONFIG_SMP */ -
arch/powerpc/kernel/irq.c +2 -1
@@ -54,6 +54,7 @@#include <linux/pgtable.h> #include <linux/uaccess.h> +#include <asm/interrupt.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/cache.h>
@@ -669,7 +670,7 @@ void __do_irq(struct pt_regs *regs)irq_exit (); } -void do_IRQ (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_ASYNC (do_IRQ) {struct pt_regs *old_regs =set_irq_regs (regs);void *cursp, *irqsp, *sirqsp;
arch/powerpc/kernel/mce.c +3 -2
@@ -18,6 +18,7 @@#include <linux/extable.h> #include <linux/ftrace.h> +#include <asm/interrupt.h> #include <asm/machdep.h> #include <asm/mce.h> #include <asm/nmi.h>
@@ -588,7 +589,7 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);* * regs->nip and regs->msr contains srr0 and ssr1. */ -long notrace machine_check_early (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_NMI (machine_check_early) {long handled =0 ;u8 ftrace_enabled =this_cpu_get_ftrace_enabled ();
@@ -722,7 +723,7 @@ long hmi_handle_debugtrig(struct pt_regs *regs)/* * Return values: */ -long hmi_exception_realmode (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_NMI (hmi_exception_realmode) {int ret;
arch/powerpc/kernel/process.c +2 -1
@@ -41,6 +41,7 @@#include <linux/pkeys.h> #include <linux/seq_buf.h> +#include <asm/interrupt.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/mmu.h>
@@ -659,7 +660,7 @@ static void do_break_handler(struct pt_regs *regs) } } -void do_break (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (do_break) { current->thread.trap_nr =TRAP_HWBKPT ; if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, regs->dsisr,
arch/powerpc/kernel/syscall_64.c +1 -0
@@ -5,6 +5,7 @@#include <asm/kup.h> #include <asm/cputime.h> #include <asm/hw_irq.h> +#include <asm/interrupt.h> #include <asm/kprobes.h> #include <asm/paca.h> #include <asm/ptrace.h>
arch/powerpc/kernel/tau_6xx.c +1 -1
@@ -100,7 +100,7 @@ static void TAUupdate(int cpu)* with interrupts disabled */ -void TAUException (struct pt_regs * regs) +DEFINE_INTERRUPT_HANDLER_ASYNC (TAUException) {int cpu =smp_processor_id ();
arch/powerpc/kernel/time.c +2 -1
@@ -56,6 +56,7 @@#include <linux/processor.h> #include <asm/trace.h> +#include <asm/interrupt.h> #include <asm/io.h> #include <asm/nvram.h> #include <asm/cache.h>
@@ -570,7 +571,7 @@ void arch_irq_work_raise(void)* timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. */ -void timer_interrupt (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_ASYNC (timer_interrupt) {struct clock_event_device *evt =this_cpu_ptr (&decrementers);u64 *next_tb =this_cpu_ptr (&decrementers_next_tb);
arch/powerpc/kernel/traps.c +53 -33
299 lines not on this page · raw message
arch/powerpc/kernel/watchdog.c +5 -2
@@ -26,6 +26,7 @@#include <linux/delay.h> #include <linux/smp.h> +#include <asm/interrupt.h> #include <asm/paca.h> /*
@@ -247,14 +248,14 @@ static void watchdog_timer_interrupt(int cpu)watchdog_smp_panic (cpu, tb); } -void soft_nmi_interrupt (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_NMI (soft_nmi_interrupt) {unsigned long flags;int cpu =raw_smp_processor_id ();u64 tb;if (!cpumask_test_cpu (cpu, &wd_cpus_enabled)) -return ; +return 0 ;nmi_enter ();
@@ -291,6 +292,8 @@ void soft_nmi_interrupt(struct pt_regs *regs) out:nmi_exit (); + +return 0 ; }static enum hrtimer_restart watchdog_timer_fn (struct hrtimer *hrtimer)
arch/powerpc/kvm/book3s_hv.c +1 -0
@@ -53,6 +53,7 @@#include <asm/cputable.h> #include <asm/cacheflush.h> #include <linux/uaccess.h> +#include <asm/interrupt.h> #include <asm/io.h> #include <asm/kvm_ppc.h> #include <asm/kvm_book3s.h>
arch/powerpc/kvm/book3s_hv_builtin.c +1 -0
@@ -17,6 +17,7 @@#include <asm/asm-prototypes.h> #include <asm/cputable.h> +#include <asm/interrupt.h> #include <asm/kvm_ppc.h> #include <asm/kvm_book3s.h> #include <asm/archrandom.h>
arch/powerpc/kvm/booke.c +1 -0
@@ -20,6 +20,7 @@#include <asm/cputable.h> #include <linux/uaccess.h> +#include <asm/interrupt.h> #include <asm/kvm_ppc.h> #include <asm/cacheflush.h> #include <asm/dbell.h>
arch/powerpc/mm/book3s64/hash_utils.c +9 -3
@@ -38,6 +38,7 @@#include <linux/pgtable.h> #include <asm/debugfs.h> +#include <asm/interrupt.h> #include <asm/processor.h> #include <asm/mmu.h> #include <asm/mmu_context.h>
@@ -1512,7 +1513,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap, }EXPORT_SYMBOL_GPL (hash_page); -static long __do_hash_fault (struct pt_regs *regs) +DECLARE_INTERRUPT_HANDLER_RET (__do_hash_fault); +DEFINE_INTERRUPT_HANDLER_RET (__do_hash_fault) {unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;
@@ -1565,7 +1567,11 @@ static long __do_hash_fault(struct pt_regs *regs)return err; } -long do_hash_fault (struct pt_regs *regs) +/* +* The _RAW interrupt entry checks for the in_nmi() case before +* running the full handler. +*/ +DEFINE_INTERRUPT_HANDLER_RAW (do_hash_fault) {unsigned long dsisr = regs->dsisr;long err;
@@ -1587,7 +1593,7 @@ long do_hash_fault(struct pt_regs *regs)* the access, or panic if there isn't a handler. */ if (unlikely (in_nmi ())) { -bad_page_fault (regs,SIGSEGV ); +do_bad_page_fault_segv (regs);return 0 ; }
arch/powerpc/mm/book3s64/slb.c +4 -3
@@ -10,6 +10,7 @@*/ #include <asm/asm-prototypes.h> +#include <asm/interrupt.h> #include <asm/mmu.h> #include <asm/mmu_context.h> #include <asm/paca.h>
@@ -813,7 +814,7 @@ static long slb_allocate_user(struct mm_struct *mm, unsigned long ea)return slb_insert_entry (ea, context, flags, ssize, false); } -long do_slb_fault (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_RAW (do_slb_fault) {unsigned long ea = regs->dar;unsigned long id =get_region_id (ea);
@@ -833,7 +834,7 @@ long do_slb_fault(struct pt_regs *regs)*/ /* -* The interrupt state is not reconciled, for performance, so that +* This is a raw interrupt handler, for performance, so that * fast_interrupt_return can be used. The handler must not touch local * irq state, or schedule. We could test for usermode and upgrade to a * normal process context (synchronous) interrupt for those, which
@@ -868,7 +869,7 @@ long do_slb_fault(struct pt_regs *regs) } } -void do_bad_slb_fault (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (do_bad_slb_fault) {int err = regs->result;
arch/powerpc/mm/fault.c +3 -2
@@ -34,6 +34,7 @@#include <linux/uaccess.h> #include <asm/firmware.h> +#include <asm/interrupt.h> #include <asm/page.h> #include <asm/mmu.h> #include <asm/mmu_context.h>
@@ -540,7 +541,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, }NOKPROBE_SYMBOL (__do_page_fault); -long do_page_fault (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) {const struct exception_table_entry *entry;enum ctx_state prev_state;
@@ -624,7 +625,7 @@ void bad_page_fault(struct pt_regs *regs, int sig) }#ifdef CONFIG_PPC_BOOK3S_64 -void do_bad_page_fault_segv (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (do_bad_page_fault_segv) {bad_page_fault (regs,SIGSEGV ); }
arch/powerpc/platforms/cell/ras.c +3 -3
@@ -49,7 +49,7 @@ static void dump_fir(int cpu) } -void cbe_system_error_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (cbe_system_error_exception) {int cpu =smp_processor_id ();
@@ -58,7 +58,7 @@ void cbe_system_error_exception(struct pt_regs *regs)dump_stack (); } -void cbe_maintenance_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (cbe_maintenance_exception) {int cpu =smp_processor_id ();
@@ -70,7 +70,7 @@ void cbe_maintenance_exception(struct pt_regs *regs)dump_stack (); } -void cbe_thermal_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (cbe_thermal_exception) {int cpu =smp_processor_id ();
arch/powerpc/platforms/cell/ras.h +6 -3
@@ -2,9 +2,12 @@#ifndef RAS_H #define RAS_H -extern void cbe_system_error_exception (struct pt_regs *regs); -extern void cbe_maintenance_exception (struct pt_regs *regs); -extern void cbe_thermal_exception (struct pt_regs *regs); +#include <asm/interrupt.h> + +DECLARE_INTERRUPT_HANDLER (cbe_system_error_exception); +DECLARE_INTERRUPT_HANDLER (cbe_maintenance_exception); +DECLARE_INTERRUPT_HANDLER (cbe_thermal_exception); +extern void cbe_ras_init (void );#endif /* RAS_H */
arch/powerpc/platforms/powernv/idle.c +1 -0
@@ -14,6 +14,7 @@#include <asm/asm-prototypes.h> #include <asm/firmware.h> +#include <asm/interrupt.h> #include <asm/machdep.h> #include <asm/opal.h> #include <asm/cputhreads.h>
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerRe: [PATCH v7 28/42] powerpc: convert interrupt handlers to use wrappers
Excerpts from Nicholas Piggin's message of January 30, 2021 11:08 pm:
Quoted 1 line
Signed-off-by Nicholas Piggin <[email protected]>
powerpc: fix tau6xxx compile error in convert interrupt handlers to use wrappers
This should fix the missing declaration compile error although it doesn't show up with my toolchain.
--- arch/powerpc/kernel/tau_6xx.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/kernel/tau_6xx.c +1 -0
@@ -22,6 +22,7 @@#include <linux/delay.h> #include <linux/workqueue.h> +#include <asm/interrupt.h> #include <asm/io.h> #include <asm/reg.h> #include <asm/nvram.h>
Signature · 1 line
2.23.0
Re: [PATCH v7 28/42] powerpc: convert interrupt handlers to use wrappers
In reply to Nicholas PigginLe 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 18 lines
Signed-off-by Nicholas Piggin <[email protected]>---
arch/powerpc/kernel/traps.c +1
-1@@ -1462,7 +1474,7 @@ static int emulate_math(struct pt_regs *regs)static inline int emulate_math (struct pt_regs *regs) {return -1 ; }#endif -void program_check_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (program_check_exception) {enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);
arch/powerpc/kernel/traps.c NOKPROBE_SYMBOL(program_check_exception); · line 1605
Quoted 8 lines
arch/powerpc/kernel/traps.c +1
-1@@ -1587,14 +1599,14 @@ NOKPROBE_SYMBOL(program_check_exception);* This occurs when running in hypervisor mode on POWER6 or later * and an illegal instruction is encountered. */ -void emulation_assist_interrupt (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (emulation_assist_interrupt) { regs->msr |=REASON_ILLEGAL ;program_check_exception (regs);
Is it correct that an INTERRUPT_HANDLER calls another INTERRUPT_HANDLER ?
Quoted 3 lines
arch/powerpc/kernel/traps.c +0
-0}NOKPROBE_SYMBOL (emulation_assist_interrupt);
Nicholas Piggin
reviewerRe: [PATCH v7 28/42] powerpc: convert interrupt handlers to use wrappers
Excerpts from Christophe Leroy's message of February 5, 2021 6:09 pm:
Quoted 15 lines
Le 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 12 lines
Signed-off-by Nicholas Piggin <[email protected]>---
arch/powerpc/kernel/traps.c +0
-0@@ -1462,7 +1474,7 @@ static int emulate_math(struct pt_regs *regs)static inline int emulate_math (struct pt_regs *regs) {return -1 ; }#endif
Quoted 16 lines
Quoted 6 lines
arch/powerpc/kernel/traps.c +1
-1-void program_check_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (program_check_exception) {enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);arch/powerpc/kernel/traps.c NOKPROBE_SYMBOL(program_check_exception); · line 1605
Quoted 8 lines
arch/powerpc/kernel/traps.c +1
-1@@ -1587,14 +1599,14 @@ NOKPROBE_SYMBOL(program_check_exception);* This occurs when running in hypervisor mode on POWER6 or later * and an illegal instruction is encountered. */ -void emulation_assist_interrupt (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (emulation_assist_interrupt) { regs->msr |=REASON_ILLEGAL ;program_check_exception (regs);Is it correct that an
INTERRUPT_HANDLERcalls anotherINTERRUPT_HANDLER?
No you're right, I'll have to send a patch.
Thanks,
Nick
Nicholas Piggin
reviewerRe: [PATCH v7 28/42] powerpc: convert interrupt handlers to use wrappers
In reply to Christophe LeroyExcerpts from Christophe Leroy's message of February 5, 2021 6:09 pm:
Quoted 15 lines
Le 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 12 lines
Signed-off-by Nicholas Piggin <[email protected]>---
arch/powerpc/kernel/traps.c +0
-0@@ -1462,7 +1474,7 @@ static int emulate_math(struct pt_regs *regs)static inline int emulate_math (struct pt_regs *regs) {return -1 ; }#endif
Quoted 16 lines
Quoted 6 lines
arch/powerpc/kernel/traps.c +1
-1-void program_check_exception (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (program_check_exception) {enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);arch/powerpc/kernel/traps.c NOKPROBE_SYMBOL(program_check_exception); · line 1605
Quoted 8 lines
arch/powerpc/kernel/traps.c +1
-1@@ -1587,14 +1599,14 @@ NOKPROBE_SYMBOL(program_check_exception);* This occurs when running in hypervisor mode on POWER6 or later * and an illegal instruction is encountered. */ -void emulation_assist_interrupt (struct pt_regs *regs) +DEFINE_INTERRUPT_HANDLER (emulation_assist_interrupt) { regs->msr |=REASON_ILLEGAL ;program_check_exception (regs);Is it correct that an
INTERRUPT_HANDLERcalls anotherINTERRUPT_HANDLER?
No, here is a patch for it, should go any time before the interrupt wrappers are introduced. It causes some conflicts later but are not too complex. I can resend the series if necessary.
Thanks,
Nick
---
powerpc/traps: factor common code from program check and emulation assist
Move the program check handling into a function called by both, rather than have the emulation assist handler call the program check handler.
This allows each of these handlers to be implemented with "interrupt wrappers" in a later change.
--- arch/powerpc/kernel/traps.c | 38 +++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-)
arch/powerpc/kernel/traps.c +24 -14
@@ -1462,9 +1462,8 @@ static int emulate_math(struct pt_regs *regs)static inline int emulate_math (struct pt_regs *regs) {return -1 ; }#endif -void program_check_exception (struct pt_regs *regs) +static void do_program_check (struct pt_regs *regs) { -enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);/* We can now get here via a FP Unavailable exception if the core
@@ -1473,22 +1472,22 @@ void program_check_exception(struct pt_regs *regs)if (reason &REASON_FP ) {/* IEEE FP exception */ parse_fpe (regs); - goto bail; +return ; }if (reason &REASON_TRAP ) {unsigned long bugaddr;/* Debugger is first in line to stop recursive faults in * rcu_lock, notify_die, or atomic_notifier_call_chain */ if (debugger_bpt (regs)) - goto bail; +return ;if (kprobe_handler (regs)) - goto bail; +return ;/* trap exception */ if (notify_die (DIE_BPT ,"breakpoint" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ; bugaddr = regs->nip;/*
@@ -1500,10 +1499,10 @@ void program_check_exception(struct pt_regs *regs)if (!(regs->msr &MSR_PR ) &&/* not user-mode */ report_bug (bugaddr, regs) ==BUG_TRAP_TYPE_WARN ) { regs->nip +=4 ; - goto bail; +return ; }_exception (SIGTRAP , regs,TRAP_BRKPT , regs->nip); - goto bail; +return ; }#ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (reason &REASON_TM ) {
@@ -1524,7 +1523,7 @@ void program_check_exception(struct pt_regs *regs)*/ if (user_mode (regs)) {_exception (SIGILL , regs,ILL_ILLOPN , regs->nip); - goto bail; +return ; }else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " "at %lx (msr 0x%lx) tm_scratch=%llx\n",
@@ -1557,7 +1556,7 @@ void program_check_exception(struct pt_regs *regs)* pattern to occurrences etc. -dgibson 31/Mar/2003 */ if (!emulate_math (regs)) - goto bail; +return ;/* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL |REASON_PRIVILEGED )) {
@@ -1565,10 +1564,10 @@ void program_check_exception(struct pt_regs *regs)case 0 : regs->nip +=4 ;emulate_single_step (regs); - goto bail; +return ;case -EFAULT :_exception (SIGSEGV , regs,SEGV_MAPERR , regs->nip); - goto bail; +return ; } }
@@ -1578,7 +1577,14 @@ void program_check_exception(struct pt_regs *regs)else _exception (SIGILL , regs,ILL_ILLOPC , regs->nip); -bail: +} + +void program_check_exception (struct pt_regs *regs) +{ +enum ctx_state prev_state =exception_enter (); + +do_program_check (regs); +exception_exit (prev_state); }NOKPROBE_SYMBOL (program_check_exception);
@@ -1589,8 +1595,12 @@ NOKPROBE_SYMBOL(program_check_exception);*/ void emulation_assist_interrupt (struct pt_regs *regs) { +enum ctx_state prev_state =exception_enter (); + regs->msr |=REASON_ILLEGAL ; -program_check_exception (regs); +do_program_check (regs); + +exception_exit (prev_state); }NOKPROBE_SYMBOL (emulation_assist_interrupt);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 29/42 powerpc: add interrupt_cond_local_irq_enable helper
In reply to Nicholas PigginSimple helper for synchronous interrupt handlers (i.e., process-context) to enable interrupts if it was taken in an interrupts-enabled context.
--- arch/powerpc/include/asm/interrupt.h | 7 +++++++ arch/powerpc/kernel/traps.c | 24 +++++++----------------- arch/powerpc/mm/fault.c | 4 +--- 3 files changed, 15 insertions(+), 20 deletions(-)
arch/powerpc/include/asm/interrupt.h +7 -0
@@ -3,6 +3,7 @@#define _ASM_POWERPC_INTERRUPT_H#include <linux/context_tracking.h> +#include <linux/hardirq.h> #include <asm/ftrace.h> struct interrupt_state {
@@ -298,4 +299,10 @@ DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);void replay_system_reset (void );void replay_soft_interrupts (void ); +static inline void interrupt_cond_local_irq_enable (struct pt_regs *regs) +{ +if (!arch_irq_disabled_regs (regs)) +local_irq_enable (); +} +#endif /* _ASM_POWERPC_INTERRUPT_H */
arch/powerpc/kernel/traps.c +7 -17
@@ -343,8 +343,8 @@ static bool exception_common(int signr, struct pt_regs *regs, int code,show_signal_msg (signr, regs, code, addr); -if (arch_irqs_disabled () && !arch_irq_disabled_regs (regs)) -local_irq_enable (); +if (arch_irqs_disabled ()) +interrupt_cond_local_irq_enable (regs); current->thread.trap_nr = code;
@@ -1556,9 +1556,7 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)if (!user_mode (regs)) goto sigill; -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs);/* (reason & REASON_ILLEGAL) would be the obvious thing here, * but there seems to be a hardware bug on the 405GP (RevD)
@@ -1612,9 +1610,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)int sig, code, fixed =0 ;unsigned long reason; -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs); reason =get_reason (regs);
@@ -1775,9 +1771,7 @@ DEFINE_INTERRUPT_HANDLER(facility_unavailable_exception)die ("Unexpected facility unavailable exception" , regs,SIGABRT ); } -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs);if (status ==FSCR_DSCR_LG ) {/*
@@ -2162,9 +2156,7 @@ DEFINE_INTERRUPT_HANDLER(SPEFloatingPointException)int code =FPE_FLTUNK ;int err; -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs);flush_spe_to_thread (current);
@@ -2211,9 +2203,7 @@ DEFINE_INTERRUPT_HANDLER(SPEFloatingPointRoundException)extern int speround_handler (struct pt_regs *regs);int err; -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs);preempt_disable ();if (regs->msr &MSR_SPE )
arch/powerpc/mm/fault.c +1 -3
@@ -434,9 +434,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,return bad_area_nosemaphore (regs, address); } -/* We restore the interrupt state now */ -if (!arch_irq_disabled_regs (regs)) -local_irq_enable (); +interrupt_cond_local_irq_enable (regs);perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS ,1 , regs, address);
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 30/42 powerpc/64: context tracking remove _TIF_NOHZ
In reply to Nicholas PigginAdd context tracking to the system call handler explicitly, and remove _TIF_NOHZ.
This improves system call performance when nohz_full is enabled. On a POWER9, gettid scv system call cost on a nohz_full CPU improves from 1129 cycles to 1004 cycles and on a housekeeping CPU from 550 cycles to 430 cycles.
--- arch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/thread_info.h | 4 +- arch/powerpc/kernel/ptrace/ptrace.c | 4 -- arch/powerpc/kernel/signal.c | 4 -- arch/powerpc/kernel/syscall_64.c | 72 ++++++++++++++++---------- 5 files changed, 47 insertions(+), 38 deletions(-)
arch/powerpc/Kconfig +0 -1
@@ -196,7 +196,6 @@ config PPC select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13) select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) select HAVE_CONTEXT_TRACKING if PPC64 - select HAVE_TIF_NOHZ if PPC64 select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_STACKOVERFLOW select HAVE_DYNAMIC_FTRACE
arch/powerpc/include/asm/thread_info.h +1 -3
@@ -94,7 +94,6 @@ void arch_setup_new_exec(void);#define TIF_PATCH_PENDING 6/* pending live patching update */ #define TIF_SYSCALL_AUDIT 7/* syscall auditing active */ #define TIF_SINGLESTEP 8/* singlestepping active */ -#define TIF_NOHZ 9/* in adaptive nohz mode */ #define TIF_SECCOMP 10/* secure computing */ #define TIF_RESTOREALL 11/* Restore all regs (implies NOERROR) */ #define TIF_NOERROR 12/* Force successful syscall return */
@@ -128,11 +127,10 @@ void arch_setup_new_exec(void);#define _TIF_UPROBE (1<<TIF_UPROBE)#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)#define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) -#define _TIF_NOHZ (1<<TIF_NOHZ)#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)#define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ | _TIF_SYSCALL_EMU) + _TIF_SYSCALL_EMU)#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
arch/powerpc/kernel/ptrace/ptrace.c +0 -4
@@ -262,8 +262,6 @@ long do_syscall_trace_enter(struct pt_regs *regs) {u32 flags; -user_exit (); - flags =READ_ONCE (current_thread_info ()->flags) & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
@@ -340,8 +338,6 @@ void do_syscall_trace_leave(struct pt_regs *regs) step =test_thread_flag (TIF_SINGLESTEP );if (step ||test_thread_flag (TIF_SYSCALL_TRACE ))tracehook_report_syscall_exit (regs, step); - -user_enter (); }void __init pt_regs_check (void );
arch/powerpc/kernel/signal.c +0 -4
@@ -282,8 +282,6 @@ static void do_signal(struct task_struct *tsk)void do_notify_resume (struct pt_regs *regs,unsigned long thread_info_flags) { -user_exit (); -if (thread_info_flags & _TIF_UPROBE)uprobe_notify_resume (regs);
@@ -299,8 +297,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)tracehook_notify_resume (regs);rseq_handle_notify_resume (NULL , regs); } - -user_enter (); }static unsigned long get_tm_stackpointer (struct task_struct *tsk)
arch/powerpc/kernel/syscall_64.c +46 -26
127 lines not on this page · raw message
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 31/42 powerpc/64s/hash: improve context tracking of hash faults
In reply to Nicholas PigginThis moves the 64s/hash context tracking from hash_page_mm() to __do_hash_fault(), so it's no longer called by OCXL / SPU accelerators, which was certainly the wrong thing to be doing, because those callers are not low level interrupt handlers, so should have entered a kernel context tracking already.
Then remain in kernel context for the duration of the fault, rather than enter/exit for the hash fault then enter/exit for the page fault, which is pointless.
Even still, calling exception_enter/exit in __do_hash_fault seems questionable because that's touching per-cpu variables, tracing, etc., which might have been interrupted by this hash fault or themselves cause hash faults. But maybe I miss something because hash_page_mm very deliberately calls trace_hash_fault too, for example. So for now go with it, it's no worse than before, in this regard.
--- arch/powerpc/include/asm/bug.h | 1 + arch/powerpc/mm/book3s64/hash_utils.c | 7 ++--- arch/powerpc/mm/fault.c | 39 +++++++++++++++++++-------- 3 files changed, 33 insertions(+), 14 deletions(-)
arch/powerpc/include/asm/bug.h +1 -0
@@ -112,6 +112,7 @@struct pt_regs ;long do_page_fault (struct pt_regs *); +long hash__do_page_fault (struct pt_regs *);void bad_page_fault (struct pt_regs *,int );void __bad_page_fault (struct pt_regs *regs,int sig);void do_bad_page_fault_segv (struct pt_regs *regs);
arch/powerpc/mm/book3s64/hash_utils.c +4 -3
@@ -1289,7 +1289,6 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long flags) {bool is_thp; -enum ctx_state prev_state =exception_enter ();pgd_t *pgdir;unsigned long vsid;pte_t *ptep;
@@ -1491,7 +1490,6 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,DBG_LOW (" -> rc=%d\n" , rc); bail: -exception_exit (prev_state);return rc; }EXPORT_SYMBOL_GPL (hash_page_mm);
@@ -1516,6 +1514,7 @@ EXPORT_SYMBOL_GPL(hash_page);DECLARE_INTERRUPT_HANDLER_RET (__do_hash_fault);DEFINE_INTERRUPT_HANDLER_RET (__do_hash_fault) { +enum ctx_state prev_state =exception_enter ();unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;unsigned long access = _PAGE_PRESENT | _PAGE_READ;
@@ -1564,6 +1563,8 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault) err =0 ; } +exception_exit (prev_state); +return err; }
@@ -1600,7 +1601,7 @@ DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault) err =__do_hash_fault (regs);if (err) { page_fault: - err =do_page_fault (regs); + err =hash__do_page_fault (regs); }return err;
arch/powerpc/mm/fault.c +28 -11
@@ -387,7 +387,7 @@ static void sanity_check_fault(bool is_write, bool is_user,* The return value is 0 if the fault was handled, or the signal * number if this is a kernel fault that can't be handled here. */ -static int __do_page_fault (struct pt_regs *regs,unsigned long address, +static int ___do_page_fault (struct pt_regs *regs,unsigned long address,unsigned long error_code) {struct vm_area_struct * vma;
@@ -537,36 +537,53 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,return 0 ; } -NOKPROBE_SYMBOL (__do_page_fault); +NOKPROBE_SYMBOL (___do_page_fault); -DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) +static long __do_page_fault (struct pt_regs *regs) {const struct exception_table_entry *entry; -enum ctx_state prev_state;long err; - prev_state =exception_enter (); - err =__do_page_fault (regs, regs->dar, regs->dsisr); + err =___do_page_fault (regs, regs->dar, regs->dsisr);if (likely (!err)) - goto out; +return err; entry =search_exception_tables (regs->nip);if (likely (entry)) {instruction_pointer_set (regs,extable_fixup (entry)); - err =0 ; +return 0 ; }else if (IS_ENABLED (CONFIG_PPC_BOOK3S_64 )) { -/* 32 and 64e handle this in asm */ __bad_page_fault (regs, err); - err =0 ; +return 0 ; + }else { +/* 32 and 64e handle the bad page fault in asm */ +return err; } +} +NOKPROBE_SYMBOL (__do_page_fault); + +DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) +{ +enum ctx_state prev_state =exception_enter (); +long err; + + err =__do_page_fault (regs); -out:exception_exit (prev_state);return err; }NOKPROBE_SYMBOL (do_page_fault); +#ifdef CONFIG_PPC_BOOK3S_64 +/* Same as do_page_fault but interrupt entry has already run in do_hash_fault */ +long hash__do_page_fault (struct pt_regs *regs) +{ +return __do_page_fault (regs); +} +NOKPROBE_SYMBOL (hash__do_page_fault); +#endif +/* * bad_page_fault is called when we have a bad access from the kernel. * It is called from the DSI and ISI handlers in head.S and from some
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 32/42 powerpc/64: context tracking move to interrupt wrappers
In reply to Nicholas PigginThis moves exception_enter/exit calls to wrapper functions for synchronous interrupts. More interrupt handlers are covered by this than previously.
--- arch/powerpc/include/asm/interrupt.h | 9 ++++ arch/powerpc/kernel/traps.c | 74 ++++++--------------------- arch/powerpc/mm/book3s64/hash_utils.c | 3 -- arch/powerpc/mm/fault.c | 9 +--- 4 files changed, 27 insertions(+), 68 deletions(-)
arch/powerpc/include/asm/interrupt.h +9 -0
@@ -7,10 +7,16 @@#include <asm/ftrace.h> struct interrupt_state { +#ifdef CONFIG_PPC64 +enum ctx_state ctx_state; +#endif };static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 + state->ctx_state =exception_enter (); +#endif }/*
@@ -29,6 +35,9 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup*/ static inline void interrupt_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 +exception_exit (state->ctx_state); +#endif }static inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state)
arch/powerpc/kernel/traps.c +17 -57
230 lines not on this page · raw message
arch/powerpc/mm/book3s64/hash_utils.c +0 -3
@@ -1514,7 +1514,6 @@ EXPORT_SYMBOL_GPL(hash_page);DECLARE_INTERRUPT_HANDLER_RET (__do_hash_fault);DEFINE_INTERRUPT_HANDLER_RET (__do_hash_fault) { -enum ctx_state prev_state =exception_enter ();unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;unsigned long access = _PAGE_PRESENT | _PAGE_READ;
@@ -1563,8 +1562,6 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault) err =0 ; } -exception_exit (prev_state); -return err; }
arch/powerpc/mm/fault.c +1 -8
@@ -564,14 +564,7 @@ NOKPROBE_SYMBOL(__do_page_fault);DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) { -enum ctx_state prev_state =exception_enter (); -long err; - - err =__do_page_fault (regs); - -exception_exit (prev_state); - -return err; +return __do_page_fault (regs); }NOKPROBE_SYMBOL (do_page_fault);
Signature · 1 line
2.23.0
Re: [PATCH v7 32/42] powerpc/64: context tracking move to interrupt wrappers
Le 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 3 lines
This moves exception_enter/exit calls to wrapper functions for synchronous interrupts. More interrupt handlers are covered by this than previously.
Why did you enclose everything in #ifdef CONFIG_PPC64 ? As far as I understand, before this patch exception_enter() and exception_exit() are called also on PPC32.
Christophe
Quoted 331 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 9 ++++ arch/powerpc/kernel/traps.c | 74 ++++++--------------------- arch/powerpc/mm/book3s64/hash_utils.c | 3 -- arch/powerpc/mm/fault.c | 9 +--- 4 files changed, 27 insertions(+), 68 deletions(-)arch/powerpc/include/asm/interrupt.h +9
-0@@ -7,10 +7,16 @@#include <asm/ftrace.h> struct interrupt_state { +#ifdef CONFIG_PPC64 +enum ctx_state ctx_state; +#endif };static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 + state->ctx_state =exception_enter (); +#endif }/* @@ -29,6 +35,9 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup*/ static inline void interrupt_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 +exception_exit (state->ctx_state); +#endif }static inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state)arch/powerpc/kernel/traps.c +17
-57@@ -1087,41 +1087,28 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(handle_hmi_exception)DEFINE_INTERRUPT_HANDLER (unknown_exception) { -enum ctx_state prev_state =exception_enter (); -printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , regs->nip, regs->msr, regs->trap);_exception (SIGTRAP , regs,TRAP_UNK ,0 ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER_ASYNC (unknown_async_exception) { -enum ctx_state prev_state =exception_enter (); -printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , regs->nip, regs->msr, regs->trap);_exception (SIGTRAP , regs,TRAP_UNK ,0 ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (instruction_breakpoint_exception) { -enum ctx_state prev_state =exception_enter (); -if (notify_die (DIE_IABR_MATCH ,"iabr_match" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ;if (debugger_iabr_match (regs)) - goto bail; +return ;_exception (SIGTRAP , regs,TRAP_BRKPT , regs->nip); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (RunModeException)@@ -1131,8 +1118,6 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)DEFINE_INTERRUPT_HANDLER (single_step_exception) { -enum ctx_state prev_state =exception_enter (); -clear_single_step (regs);clear_br_trace (regs);@@ -1141,14 +1126,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)if (notify_die (DIE_SSTEP ,"single_step" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ;if (debugger_sstep (regs)) - goto bail; +return ;_exception (SIGTRAP , regs,TRAP_TRACE , regs->nip); - -bail: -exception_exit (prev_state); }NOKPROBE_SYMBOL (single_step_exception);@@ -1476,7 +1458,6 @@ static inline int emulate_math(struct pt_regs *regs) { return -1; }DEFINE_INTERRUPT_HANDLER (program_check_exception) { -enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);/* We can now get here via a FP Unavailable exception if the core @@ -1485,22 +1466,22 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)if (reason &REASON_FP ) {/* IEEE FP exception */ parse_fpe (regs); - goto bail; +return ; }if (reason &REASON_TRAP ) {unsigned long bugaddr;/* Debugger is first in line to stop recursive faults in * rcu_lock, notify_die, or atomic_notifier_call_chain */ if (debugger_bpt (regs)) - goto bail; +return ;if (kprobe_handler (regs)) - goto bail; +return ;/* trap exception */ if (notify_die (DIE_BPT ,"breakpoint" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ; bugaddr = regs->nip;/* @@ -1512,10 +1493,10 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)if (!(regs->msr &MSR_PR ) &&/* not user-mode */ report_bug (bugaddr, regs) ==BUG_TRAP_TYPE_WARN ) { regs->nip +=4 ; - goto bail; +return ; }_exception (SIGTRAP , regs,TRAP_BRKPT , regs->nip); - goto bail; +return ; }#ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (reason &REASON_TM ) {@@ -1536,7 +1517,7 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)*/ if (user_mode (regs)) {_exception (SIGILL , regs,ILL_ILLOPN , regs->nip); - goto bail; +return ; }else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " "at %lx (msr 0x%lx) tm_scratch=%llx\n",@@ -1567,7 +1548,7 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)* pattern to occurrences etc. -dgibson 31/Mar/2003 */ if (!emulate_math (regs)) - goto bail; +return ;/* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL |REASON_PRIVILEGED )) {@@ -1575,10 +1556,10 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)case 0 : regs->nip +=4 ;emulate_single_step (regs); - goto bail; +return ;case -EFAULT :_exception (SIGSEGV , regs,SEGV_MAPERR , regs->nip); - goto bail; +return ; } }@@ -1587,9 +1568,6 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)_exception (SIGILL , regs,ILL_PRVOPC , regs->nip); else _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); - -bail: -exception_exit (prev_state); }NOKPROBE_SYMBOL (program_check_exception);@@ -1606,14 +1584,12 @@ NOKPROBE_SYMBOL(emulation_assist_interrupt);DEFINE_INTERRUPT_HANDLER (alignment_exception) { -enum ctx_state prev_state =exception_enter ();int sig, code, fixed =0 ;unsigned long reason;interrupt_cond_local_irq_enable (regs); reason =get_reason (regs); -if (reason &REASON_BOUNDARY ) { sig =SIGBUS ; code =BUS_ADRALN ;@@ -1621,7 +1597,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception) }if (tm_abort_check (regs,TM_CAUSE_ALIGNMENT |TM_CAUSE_PERSISTENT )) - goto bail; +return ;/* we don't implement logging of alignment exceptions */ if (!(current->thread.align_ctl &PR_UNALIGN_SIGBUS ))@@ -1631,7 +1607,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)/* skip over emulated instruction */ regs->nip +=inst_length (reason);emulate_single_step (regs); - goto bail; +return ; }/* Operand address was bad */ @@ -1647,9 +1623,6 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)_exception (sig, regs, code, regs->dar); elsebad_page_fault (regs ,sig ); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (StackOverflow)@@ -1663,41 +1636,28 @@ DEFINE_INTERRUPT_HANDLER(StackOverflow)DEFINE_INTERRUPT_HANDLER (stack_overflow_exception) { -enum ctx_state prev_state =exception_enter (); -die ("Kernel stack overflow" , regs,SIGSEGV ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (kernel_fp_unavailable_exception) { -enum ctx_state prev_state =exception_enter (); -printk (KERN_EMERG "Unrecoverable FP Unavailable Exception " "%lx at %lx\n" , regs->trap, regs->nip);die ("Unrecoverable FP Unavailable Exception" , regs,SIGABRT ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (altivec_unavailable_exception) { -enum ctx_state prev_state =exception_enter (); -if (user_mode (regs)) {/* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception (SIGILL , regs,ILL_ILLOPC , regs->nip); - goto bail; +return ; }printk (KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n" , regs->trap, regs->nip);die ("Unrecoverable VMX/Altivec Unavailable Exception" , regs,SIGABRT ); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (vsx_unavailable_exception)arch/powerpc/mm/book3s64/hash_utils.c +0
-3@@ -1514,7 +1514,6 @@ EXPORT_SYMBOL_GPL(hash_page);DECLARE_INTERRUPT_HANDLER_RET (__do_hash_fault);DEFINE_INTERRUPT_HANDLER_RET (__do_hash_fault) { -enum ctx_state prev_state =exception_enter ();unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;unsigned long access = _PAGE_PRESENT | _PAGE_READ;@@ -1563,8 +1562,6 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault) err =0 ; } -exception_exit (prev_state); -return err; }arch/powerpc/mm/fault.c +1
-8@@ -564,14 +564,7 @@ NOKPROBE_SYMBOL(__do_page_fault);DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) { -enum ctx_state prev_state =exception_enter (); -long err; - - err =__do_page_fault (regs); - -exception_exit (prev_state); - -return err; +return __do_page_fault (regs); }NOKPROBE_SYMBOL (do_page_fault);
Nicholas Piggin
reviewerRe: [PATCH v7 32/42] powerpc/64: context tracking move to interrupt wrappers
Excerpts from Christophe Leroy's message of February 9, 2021 3:49 pm:
Quoted 9 lines
Le 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 3 lines
This moves exception_enter/exit calls to wrapper functions for synchronous interrupts. More interrupt handlers are covered by this than previously.
Why did you enclose everything in #ifdef
CONFIG_PPC64? As far as I understand, before this patchexception_enter()andexception_exit()are called also on PPC32.
PPC32 never selects CONTEXT_TRACKING AFAIKS, but I'm not sure. I worried ctx_state would not be no-oped, but if it's all inlined into the same function then maybe the compiler will eliminate it.
On the other hand I may move some of the wrapper into its own function if that helps code size, but we can do something about it then...
Hmm, end result is it shouldn't matter for PPC32 at the moment.
Thanks,
Nick
Quoted 336 lines
Christophe
Quoted 331 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 9 ++++ arch/powerpc/kernel/traps.c | 74 ++++++--------------------- arch/powerpc/mm/book3s64/hash_utils.c | 3 -- arch/powerpc/mm/fault.c | 9 +--- 4 files changed, 27 insertions(+), 68 deletions(-)arch/powerpc/include/asm/interrupt.h +9
-0@@ -7,10 +7,16 @@#include <asm/ftrace.h> struct interrupt_state { +#ifdef CONFIG_PPC64 +enum ctx_state ctx_state; +#endif };static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 + state->ctx_state =exception_enter (); +#endif }/* @@ -29,6 +35,9 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup*/ static inline void interrupt_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC64 +exception_exit (state->ctx_state); +#endif }static inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state)arch/powerpc/kernel/traps.c +17
-57@@ -1087,41 +1087,28 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(handle_hmi_exception)DEFINE_INTERRUPT_HANDLER (unknown_exception) { -enum ctx_state prev_state =exception_enter (); -printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , regs->nip, regs->msr, regs->trap);_exception (SIGTRAP , regs,TRAP_UNK ,0 ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER_ASYNC (unknown_async_exception) { -enum ctx_state prev_state =exception_enter (); -printk ("Bad trap at PC: %lx, SR: %lx, vector=%lx\n" , regs->nip, regs->msr, regs->trap);_exception (SIGTRAP , regs,TRAP_UNK ,0 ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (instruction_breakpoint_exception) { -enum ctx_state prev_state =exception_enter (); -if (notify_die (DIE_IABR_MATCH ,"iabr_match" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ;if (debugger_iabr_match (regs)) - goto bail; +return ;_exception (SIGTRAP , regs,TRAP_BRKPT , regs->nip); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (RunModeException)@@ -1131,8 +1118,6 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)DEFINE_INTERRUPT_HANDLER (single_step_exception) { -enum ctx_state prev_state =exception_enter (); -clear_single_step (regs);clear_br_trace (regs);@@ -1141,14 +1126,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)if (notify_die (DIE_SSTEP ,"single_step" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ;if (debugger_sstep (regs)) - goto bail; +return ;_exception (SIGTRAP , regs,TRAP_TRACE , regs->nip); - -bail: -exception_exit (prev_state); }NOKPROBE_SYMBOL (single_step_exception);@@ -1476,7 +1458,6 @@ static inline int emulate_math(struct pt_regs *regs) { return -1; }DEFINE_INTERRUPT_HANDLER (program_check_exception) { -enum ctx_state prev_state =exception_enter ();unsigned int reason =get_reason (regs);/* We can now get here via a FP Unavailable exception if the core @@ -1485,22 +1466,22 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)if (reason &REASON_FP ) {/* IEEE FP exception */ parse_fpe (regs); - goto bail; +return ; }if (reason &REASON_TRAP ) {unsigned long bugaddr;/* Debugger is first in line to stop recursive faults in * rcu_lock, notify_die, or atomic_notifier_call_chain */ if (debugger_bpt (regs)) - goto bail; +return ;if (kprobe_handler (regs)) - goto bail; +return ;/* trap exception */ if (notify_die (DIE_BPT ,"breakpoint" , regs,5 ,5 ,SIGTRAP ) ==NOTIFY_STOP ) - goto bail; +return ; bugaddr = regs->nip;/* @@ -1512,10 +1493,10 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)if (!(regs->msr &MSR_PR ) &&/* not user-mode */ report_bug (bugaddr, regs) ==BUG_TRAP_TYPE_WARN ) { regs->nip +=4 ; - goto bail; +return ; }_exception (SIGTRAP , regs,TRAP_BRKPT , regs->nip); - goto bail; +return ; }#ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (reason &REASON_TM ) {@@ -1536,7 +1517,7 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)*/ if (user_mode (regs)) {_exception (SIGILL , regs,ILL_ILLOPN , regs->nip); - goto bail; +return ; }else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " "at %lx (msr 0x%lx) tm_scratch=%llx\n",@@ -1567,7 +1548,7 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)* pattern to occurrences etc. -dgibson 31/Mar/2003 */ if (!emulate_math (regs)) - goto bail; +return ;/* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL |REASON_PRIVILEGED )) {@@ -1575,10 +1556,10 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)case 0 : regs->nip +=4 ;emulate_single_step (regs); - goto bail; +return ;case -EFAULT :_exception (SIGSEGV , regs,SEGV_MAPERR , regs->nip); - goto bail; +return ; } }@@ -1587,9 +1568,6 @@ DEFINE_INTERRUPT_HANDLER(program_check_exception)_exception (SIGILL , regs,ILL_PRVOPC , regs->nip); else _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); - -bail: -exception_exit (prev_state); }NOKPROBE_SYMBOL (program_check_exception);@@ -1606,14 +1584,12 @@ NOKPROBE_SYMBOL(emulation_assist_interrupt);DEFINE_INTERRUPT_HANDLER (alignment_exception) { -enum ctx_state prev_state =exception_enter ();int sig, code, fixed =0 ;unsigned long reason;interrupt_cond_local_irq_enable (regs); reason =get_reason (regs); -if (reason &REASON_BOUNDARY ) { sig =SIGBUS ; code =BUS_ADRALN ;@@ -1621,7 +1597,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception) }if (tm_abort_check (regs,TM_CAUSE_ALIGNMENT |TM_CAUSE_PERSISTENT )) - goto bail; +return ;/* we don't implement logging of alignment exceptions */ if (!(current->thread.align_ctl &PR_UNALIGN_SIGBUS ))@@ -1631,7 +1607,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)/* skip over emulated instruction */ regs->nip +=inst_length (reason);emulate_single_step (regs); - goto bail; +return ; }/* Operand address was bad */ @@ -1647,9 +1623,6 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)_exception (sig, regs, code, regs->dar); elsebad_page_fault (regs ,sig ); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (StackOverflow)@@ -1663,41 +1636,28 @@ DEFINE_INTERRUPT_HANDLER(StackOverflow)DEFINE_INTERRUPT_HANDLER (stack_overflow_exception) { -enum ctx_state prev_state =exception_enter (); -die ("Kernel stack overflow" , regs,SIGSEGV ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (kernel_fp_unavailable_exception) { -enum ctx_state prev_state =exception_enter (); -printk (KERN_EMERG "Unrecoverable FP Unavailable Exception " "%lx at %lx\n" , regs->trap, regs->nip);die ("Unrecoverable FP Unavailable Exception" , regs,SIGABRT ); - -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (altivec_unavailable_exception) { -enum ctx_state prev_state =exception_enter (); -if (user_mode (regs)) {/* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception (SIGILL , regs,ILL_ILLOPC , regs->nip); - goto bail; +return ; }printk (KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n" , regs->trap, regs->nip);die ("Unrecoverable VMX/Altivec Unavailable Exception" , regs,SIGABRT ); - -bail: -exception_exit (prev_state); }DEFINE_INTERRUPT_HANDLER (vsx_unavailable_exception)arch/powerpc/mm/book3s64/hash_utils.c +0
-3@@ -1514,7 +1514,6 @@ EXPORT_SYMBOL_GPL(hash_page);DECLARE_INTERRUPT_HANDLER_RET (__do_hash_fault);DEFINE_INTERRUPT_HANDLER_RET (__do_hash_fault) { -enum ctx_state prev_state =exception_enter ();unsigned long ea = regs->dar;unsigned long dsisr = regs->dsisr;unsigned long access = _PAGE_PRESENT | _PAGE_READ;@@ -1563,8 +1562,6 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault) err =0 ; } -exception_exit (prev_state); -return err; }arch/powerpc/mm/fault.c +1
-8@@ -564,14 +564,7 @@ NOKPROBE_SYMBOL(__do_page_fault);DEFINE_INTERRUPT_HANDLER_RET (do_page_fault) { -enum ctx_state prev_state =exception_enter (); -long err; - - err =__do_page_fault (regs); - -exception_exit (prev_state); - -return err; +return __do_page_fault (regs); }NOKPROBE_SYMBOL (do_page_fault);
Nicholas Piggin
reviewerPATCH v7 33/42 powerpc/64: add context tracking to asynchronous interrupts
In reply to Nicholas PigginPreviously context tracking was not done for asynchronous interrupts, (those that run in interrupt context), and if those would cause a reschedule when they exit, then scheduling functions (schedule_user, preempt_schedule_irq) call exception_enter/exit to fix this up and exit user context.
This is a hack we would like to get away from, so do context tracking for asynchronous interrupts too.
--- arch/powerpc/include/asm/interrupt.h | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/include/asm/interrupt.h +2 -0
@@ -42,10 +42,12 @@ static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interruptstatic inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { +interrupt_enter_prepare (regs, state); }static inline void interrupt_async_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { +interrupt_exit_prepare (regs, state); }struct interrupt_nmi_state {
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 34/42 powerpc: handle irq_enter/irq_exit in interrupt handler wrappers
In reply to Nicholas PigginMove irq_enter/irq_exit into asynchronous interrupt handler wrappers.
--- arch/powerpc/include/asm/interrupt.h | 2 ++ arch/powerpc/kernel/dbell.c | 3 +-- arch/powerpc/kernel/irq.c | 4 ---- arch/powerpc/kernel/tau_6xx.c | 3 --- arch/powerpc/kernel/time.c | 4 ++-- arch/powerpc/kernel/traps.c | 10 +++------- 6 files changed, 8 insertions(+), 18 deletions(-)
arch/powerpc/include/asm/interrupt.h +2 -0
@@ -43,10 +43,12 @@ static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interruptstatic inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) {interrupt_enter_prepare (regs, state); +irq_enter (); }static inline void interrupt_async_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { +irq_exit ();interrupt_exit_prepare (regs, state); }
arch/powerpc/kernel/dbell.c +1 -2
@@ -23,7 +23,6 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(doorbell_exception) {struct pt_regs *old_regs =set_irq_regs (regs); -irq_enter ();trace_doorbell_entry (regs);ppc_msgsync ();
@@ -36,7 +35,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(doorbell_exception)smp_ipi_demux_relaxed ();/* already performed the barrier */ trace_doorbell_exit (regs); -irq_exit (); + set_irq_regs(old_regs); }#else /* CONFIG_SMP */
arch/powerpc/kernel/irq.c +0 -4
@@ -645,8 +645,6 @@ void __do_irq(struct pt_regs *regs) {unsigned int irq; -irq_enter (); -trace_irq_entry (regs);/*
@@ -666,8 +664,6 @@ void __do_irq(struct pt_regs *regs)generic_handle_irq (irq);trace_irq_exit (regs); - -irq_exit (); }DEFINE_INTERRUPT_HANDLER_ASYNC (do_IRQ)
arch/powerpc/kernel/tau_6xx.c +0 -3
@@ -104,12 +104,9 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(TAUException) {int cpu =smp_processor_id (); -irq_enter (); tau[cpu].interrupts++;TAUupdate (cpu); - -irq_exit (); }#endif /* CONFIG_TAU_INT */
arch/powerpc/kernel/time.c +2 -2
@@ -610,7 +610,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)#endif old_regs =set_irq_regs (regs); -irq_enter (); +trace_timer_interrupt_entry (regs);if (test_irq_work_pending ()) {
@@ -635,7 +635,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt) }trace_timer_interrupt_exit (regs); -irq_exit (); +set_irq_regs (old_regs); }EXPORT_SYMBOL (timer_interrupt);
arch/powerpc/kernel/traps.c +3 -7
@@ -801,7 +801,9 @@ void die_mce(const char *str, struct pt_regs *regs, long err)* do_exit() checks for in_interrupt() and panics in that case, so * exit the irq/nmi before calling die. */ -if (!IS_ENABLED (CONFIG_PPC_BOOK3S_64 )) +if (IS_ENABLED (CONFIG_PPC_BOOK3S_64 )) +irq_exit (); +else nmi_exit ();die (str, regs, err); }
@@ -1061,7 +1063,6 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(handle_hmi_exception)struct pt_regs *old_regs; old_regs =set_irq_regs (regs); -irq_enter ();#ifdef CONFIG_VSX /* Real mode flagged P9 special emu is needed */
@@ -1081,7 +1082,6 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(handle_hmi_exception)if (ppc_md.handle_hmi_exception) ppc_md.handle_hmi_exception (regs); -irq_exit ();set_irq_regs (old_regs); }
@@ -1901,13 +1901,9 @@ DEFINE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi)DECLARE_INTERRUPT_HANDLER_ASYNC (performance_monitor_exception_async);DEFINE_INTERRUPT_HANDLER_ASYNC (performance_monitor_exception_async) { -irq_enter (); -__this_cpu_inc (irq_stat.pmu_irqs);perf_irq (regs); - -irq_exit (); }DEFINE_INTERRUPT_HANDLER_RAW (performance_monitor_exception)
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 35/42 powerpc/64s: move context tracking exit to interrupt exit path
In reply to Nicholas PigginThe interrupt handler wrapper functions are not the ideal place to maintain context tracking because after they return, the low level exit code must then determine if there are interrupts to replay, or if the task should be preempted, etc. Those paths (e.g., schedule_user) include their own exception_enter/exit pairs to fix this up but it's a bit hacky (see schedule_user() comments).
Ideally context tracking will go to user mode only when there are no more interrupts or context switches or other exit processing work to handle.
64e can not do this because it does not use the C interrupt exit code.
--- arch/powerpc/include/asm/interrupt.h | 34 +++++++++++++++++++++++++--- arch/powerpc/kernel/syscall_64.c | 18 +++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-)
arch/powerpc/include/asm/interrupt.h +31 -3
@@ -7,16 +7,30 @@#include <asm/ftrace.h> struct interrupt_state { -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3E_64 enum ctx_state ctx_state;#endif };static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3E_64 state->ctx_state =exception_enter ();#endif + +#ifdef CONFIG_PPC_BOOK3S_64 +if (user_mode (regs)) { +CT_WARN_ON (ct_state () !=CONTEXT_USER ); +user_exit_irqoff (); + }else { +/* +* CT_WARN_ON comes here via program_check_exception, +* so avoid recursion. +*/ +if (TRAP (regs) !=0x700 ) +CT_WARN_ON (ct_state () !=CONTEXT_KERNEL ); + } +#endif }/*
@@ -35,9 +49,23 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup*/ static inline void interrupt_exit_prepare (struct pt_regs *regs,struct interrupt_state *state) { -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3E_64 exception_exit (state->ctx_state);#endif + +/* +* Book3S exits to user via interrupt_exit_user_prepare(), which does +* context tracking, which is a cleaner way to handle PREEMPT=y +* and avoid context entry/exit in e.g., preempt_schedule_irq()), +* which is likely to be where the core code wants to end up. +* +* The above comment explains why we can't do the +* +* if (user_mode(regs)) +* user_exit_irqoff(); +* +* sequence here. +*/ }static inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state)
arch/powerpc/kernel/syscall_64.c +16 -2
@@ -255,9 +255,9 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, ret |= _TIF_RESTOREALL; } -again:local_irq_disable (); +again: ti_flags =READ_ONCE (*ti_flagsp);while (unlikely (ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {local_irq_enable ();
@@ -307,6 +307,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,if (unlikely (!__prep_irq_for_enabled_exit (!scv))) {user_exit_irqoff ();local_irq_enable (); +local_irq_disable (); goto again; }
@@ -341,6 +342,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsignedBUG_ON (!(regs->msr &MSR_PR ));BUG_ON (!FULL_REGS (regs));BUG_ON (regs->softe !=IRQS_ENABLED ); +CT_WARN_ON (ct_state () ==CONTEXT_USER );/* * We don't need to restore AMR on the way back to userspace for KUAP.
@@ -383,8 +385,14 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs, unsigned } } -if (unlikely (!prep_irq_for_enabled_exit (true, !irqs_disabled_flags (flags)))) +user_enter_irqoff (); + +if (unlikely (!__prep_irq_for_enabled_exit (true))) { +user_exit_irqoff (); +local_irq_enable (); +local_irq_disable (); goto again; + }#ifdef CONFIG_PPC_BOOK3E if (unlikely (ts->debug.dbcr0 &DBCR0_IDM )) {
@@ -425,6 +433,12 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsignunrecoverable_exception (regs);BUG_ON (regs->msr &MSR_PR );BUG_ON (!FULL_REGS (regs)); +/* +* CT_WARN_ON comes here via program_check_exception, +* so avoid recursion. +*/ +if (TRAP (regs) !=0x700 ) +CT_WARN_ON (ct_state () ==CONTEXT_USER ); amr =kuap_get_and_check_amr ();
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 36/42 powerpc/64s: reconcile interrupts in C
In reply to Nicholas PigginThere is no need for this to be in asm, use the new intrrupt entry wrapper.
--- arch/powerpc/include/asm/interrupt.h | 15 +++++++++++---- arch/powerpc/kernel/exceptions-64s.S | 26 -------------------------- 2 files changed, 11 insertions(+), 30 deletions(-)
arch/powerpc/include/asm/interrupt.h +11 -4
@@ -14,11 +14,14 @@ struct interrupt_state {static inline void interrupt_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { -#ifdef CONFIG_PPC_BOOK3E_64 - state->ctx_state =exception_enter (); -#endif - +/* +* Book3E reconciles irq soft mask in asm +*/ #ifdef CONFIG_PPC_BOOK3S_64 +if (irq_soft_mask_set_return (IRQS_ALL_DISABLED ) ==IRQS_ENABLED ) +trace_hardirqs_off (); + local_paca->irq_happened |=PACA_IRQ_HARD_DIS ; +if (user_mode (regs)) {CT_WARN_ON (ct_state () !=CONTEXT_USER );user_exit_irqoff ();
@@ -31,6 +34,10 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup CT_WARN_ON(ct_state() != CONTEXT_KERNEL); }#endif + +#ifdef CONFIG_PPC_BOOK3E_64 + state->ctx_state =exception_enter (); +#endif }/*
arch/powerpc/kernel/exceptions-64s.S +0 -26
@@ -139,7 +139,6 @@ name: #define IKVM_VIRT .L_IKVM_VIRT_\name\() /* Virt entry tests KVM */ #define ISTACK .L_ISTACK_\name\() /* Set regular kernel stack */ #define __ISTACK(name) .L_ISTACK_ ## name -#define IRECONCILE .L_IRECONCILE_\name\() /* Do RECONCILE_IRQ_STATE */ #define IKUAP .L_IKUAP_\name\() /* Do KUAP lock */ #define INT_DEFINE_BEGIN(n) \
@@ -203,9 +202,6 @@ do_define_int n .ifndef ISTACK ISTACK=1 .endif - .ifndef IRECONCILE - IRECONCILE=1 - .endif .ifndef IKUAP IKUAP=1 .endif
@@ -653,10 +649,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) .if ISTACK ACCOUNT_STOLEN_TIME .endif - - .if IRECONCILE - RECONCILE_IRQ_STATE(r10, r11) - .endif .endm /*
@@ -935,7 +927,6 @@ INT_DEFINE_BEGIN(system_reset) */ ISET_RI=0 ISTACK=0 - IRECONCILE=0 IKVM_REAL=1 INT_DEFINE_END(system_reset)
@@ -1123,7 +1114,6 @@ INT_DEFINE_BEGIN(machine_check_early) ISTACK=0 IDAR=1 IDSISR=1 - IRECONCILE=0 IKUAP=0 /* We don't touch AMR here, we never go to virtual mode */ INT_DEFINE_END(machine_check_early)
@@ -1483,7 +1473,6 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) INT_DEFINE_BEGIN(data_access_slb) IVEC=0x380 IAREA=PACA_EXSLB - IRECONCILE=0 IDAR=1 IKVM_SKIP=1 IKVM_REAL=1
@@ -1510,7 +1499,6 @@ MMU_FTR_SECTION_ELSE li r3,-EFAULT ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) std r3,RESULT(r1) - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl do_bad_slb_fault b interrupt_return
@@ -1568,7 +1556,6 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) INT_DEFINE_BEGIN(instruction_access_slb) IVEC=0x480 IAREA=PACA_EXSLB - IRECONCILE=0 IISIDE=1 IDAR=1 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
@@ -1597,7 +1584,6 @@ MMU_FTR_SECTION_ELSE li r3,-EFAULT ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) std r3,RESULT(r1) - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl do_bad_slb_fault b interrupt_return
@@ -1757,7 +1743,6 @@ EXC_COMMON_BEGIN(program_check_common) */ INT_DEFINE_BEGIN(fp_unavailable) IVEC=0x800 - IRECONCILE=0 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_REAL=1 #endif
@@ -1772,7 +1757,6 @@ EXC_VIRT_END(fp_unavailable, 0x4800, 0x100) EXC_COMMON_BEGIN(fp_unavailable_common) GEN_COMMON fp_unavailable bne 1f /* if from user, just load it up */ - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl kernel_fp_unavailable_exception 0: trap
@@ -1791,7 +1775,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) b fast_interrupt_return #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2: /* User process was in a transaction */ - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl fp_unavailable_tm b interrupt_return
@@ -1856,7 +1839,6 @@ INT_DEFINE_BEGIN(hdecrementer) IVEC=0x980 IHSRR=1 ISTACK=0 - IRECONCILE=0 IKVM_REAL=1 IKVM_VIRT=1 INT_DEFINE_END(hdecrementer)
@@ -2230,7 +2212,6 @@ INT_DEFINE_BEGIN(hmi_exception_early) IHSRR=1 IREALMODE_COMMON=1 ISTACK=0 - IRECONCILE=0 IKUAP=0 /* We don't touch AMR here, we never go to virtual mode */ IKVM_REAL=1 INT_DEFINE_END(hmi_exception_early)
@@ -2404,7 +2385,6 @@ EXC_COMMON_BEGIN(performance_monitor_common) */ INT_DEFINE_BEGIN(altivec_unavailable) IVEC=0xf20 - IRECONCILE=0 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_REAL=1 #endif
@@ -2434,7 +2414,6 @@ BEGIN_FTR_SECTION b fast_interrupt_return #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2: /* User process was in a transaction */ - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl altivec_unavailable_tm b interrupt_return
@@ -2442,7 +2421,6 @@ BEGIN_FTR_SECTION 1: END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl altivec_unavailable_exception b interrupt_return
@@ -2458,7 +2436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) */ INT_DEFINE_BEGIN(vsx_unavailable) IVEC=0xf40 - IRECONCILE=0 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_REAL=1 #endif
@@ -2487,7 +2464,6 @@ BEGIN_FTR_SECTION b load_up_vsx #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2: /* User process was in a transaction */ - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl vsx_unavailable_tm b interrupt_return
@@ -2495,7 +2471,6 @@ BEGIN_FTR_SECTION 1: END_FTR_SECTION_IFSET(CPU_FTR_VSX) #endif - RECONCILE_IRQ_STATE(r10, r11) addi r3,r1,STACK_FRAME_OVERHEAD bl vsx_unavailable_exception b interrupt_return
@@ -2830,7 +2805,6 @@ EXC_VIRT_NONE(0x5800, 0x100) INT_DEFINE_BEGIN(soft_nmi) IVEC=0x900 ISTACK=0 - IRECONCILE=0 /* Soft-NMI may fire under local_irq_disable */ INT_DEFINE_END(soft_nmi) /*
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 37/42 powerpc/64: move account_stolen_time into its own function
In reply to Nicholas PigginThis will be used by interrupt entry as well.
--- arch/powerpc/include/asm/cputime.h | 14 ++++++++++++++ arch/powerpc/kernel/syscall_64.c | 10 +--------- 2 files changed, 15 insertions(+), 9 deletions(-)
arch/powerpc/include/asm/cputime.h +14 -0
@@ -87,6 +87,17 @@ static notrace inline void account_cpu_user_exit(void) acct->starttime_user = tb; } +static notrace inline void account_stolen_time(void) +{ +#ifdef CONFIG_PPC_SPLPAR +if (firmware_has_feature (FW_FEATURE_SPLPAR )) { +struct lppaca *lp = local_paca->lppaca_ptr; + +if (unlikely (local_paca->dtl_ridx !=be64_to_cpu (lp->dtl_idx))) +accumulate_stolen_time (); + } +#endif +}#endif /* __KERNEL__ */ #else /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
@@ -96,5 +107,8 @@ static inline void account_cpu_user_entry(void)static inline void account_cpu_user_exit (void ) { } +static notrace inline void account_stolen_time(void) +{ +}#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ #endif /* __POWERPC_CPUTIME_H */
arch/powerpc/kernel/syscall_64.c +1 -9
@@ -69,15 +69,7 @@ notrace long system_call_exception(long r3, long r4, long r5,account_cpu_user_entry (); -#ifdef CONFIG_PPC_SPLPAR -if (IS_ENABLED (CONFIG_VIRT_CPU_ACCOUNTING_NATIVE ) && -firmware_has_feature (FW_FEATURE_SPLPAR )) { -struct lppaca *lp = local_paca->lppaca_ptr; - -if (unlikely (local_paca->dtl_ridx !=be64_to_cpu (lp->dtl_idx))) -accumulate_stolen_time (); - } -#endif +account_stolen_time ();/* * This is not required for the syscall exit path, but makes the
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 38/42 powerpc/64: entry cpu time accounting in C
In reply to Nicholas PigginThere is no need for this to be in asm, use the new interrupt entry wrapper.
--- arch/powerpc/include/asm/interrupt.h | 6 ++++++ arch/powerpc/include/asm/ppc_asm.h | 24 ------------------------ arch/powerpc/kernel/exceptions-64e.S | 1 - arch/powerpc/kernel/exceptions-64s.S | 5 ----- 4 files changed, 6 insertions(+), 30 deletions(-)
arch/powerpc/include/asm/interrupt.h +6 -0
@@ -4,6 +4,7 @@#include <linux/context_tracking.h> #include <linux/hardirq.h> +#include <asm/cputime.h> #include <asm/ftrace.h> struct interrupt_state {
@@ -25,6 +26,9 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupif (user_mode (regs)) {CT_WARN_ON (ct_state () !=CONTEXT_USER );user_exit_irqoff (); + +account_cpu_user_entry (); +account_stolen_time (); }else {/* * CT_WARN_ON comes here via program_check_exception,
@@ -37,6 +41,8 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup#ifdef CONFIG_PPC_BOOK3E_64 state->ctx_state =exception_enter (); +if (user_mode (regs)) +account_cpu_user_entry ();#endif }
arch/powerpc/include/asm/ppc_asm.h +0 -24
@@ -25,7 +25,6 @@#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE #define ACCOUNT_CPU_USER_ENTRY (ptr, ra, rb)#define ACCOUNT_CPU_USER_EXIT (ptr, ra, rb) -#define ACCOUNT_STOLEN_TIME #else #define ACCOUNT_CPU_USER_ENTRY (ptr, ra, rb) \ MFTB(ra);/* get timebase */ \
@@ -44,29 +43,6 @@PPC_LL ra,ACCOUNT_SYSTEM_TIME (ptr ); \add ra,ra,rb;/* add on to system time */ \ PPC_STL ra, ACCOUNT_SYSTEM_TIME(ptr) - -#ifdef CONFIG_PPC_SPLPAR -#define ACCOUNT_STOLEN_TIME \ -BEGIN_FW_FTR_SECTION; \ - beq 33f; \ -/* from user - see if there are any DTL entries to process */ \ -ld r10,PACALPPACAPTR (r13 );/* get ptr to VPA */ \ -ld r11,PACA_DTL_RIDX (r13 );/* get log read index */ \ -addi r10,r10,LPPACA_DTLIDX ; \ - LDX_BE r10,0,r10; /* get log write index */ \ -cmpd cr1,r11,r10; \ - beq+ cr1,33f ; \ -bl accumulate_stolen_time; \ -ld r12,_MSR (r1 ); \ - andi. r10,r12,MSR_PR ;/* Restore cr0 (coming from user) */ \ -33: \ -END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) - -#else /* CONFIG_PPC_SPLPAR */ -#define ACCOUNT_STOLEN_TIME - -#endif /* CONFIG_PPC_SPLPAR */ -#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ /*
arch/powerpc/kernel/exceptions-64e.S +0 -1
@@ -398,7 +398,6 @@ exc_##n##_common: \ std r10,_NIP(r1); /* save SRR0 to stackframe */ \ std r11,_MSR(r1); /* save SRR1 to stackframe */ \ beq 2f; /* if from kernel mode */ \ - ACCOUNT_CPU_USER_ENTRY(r13,r10,r11);/* accounting (uses cr0+eq) */ \ 2: ld r3,excf+EX_R10(r13); /* get back r10 */ \ ld r4,excf+EX_R11(r13); /* get back r11 */ \ mfspr r5,scratch; /* get back r13 */ \
arch/powerpc/kernel/exceptions-64s.S +0 -5
@@ -577,7 +577,6 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real) kuap_save_amr_and_lock r9, r10, cr1, cr0 .endif beq 101f /* if from kernel mode */ - ACCOUNT_CPU_USER_ENTRY(r13, r9, r10) BEGIN_FTR_SECTION ld r9,IAREA+EX_PPR(r13) /* Read PPR from paca */ std r9,_PPR(r1)
@@ -645,10 +644,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) ld r11,exception_marker@toc(r2) std r10,RESULT(r1) /* clear regs->result */ std r11,STACK_FRAME_OVERHEAD-16(r1) /* mark the frame */ - - .if ISTACK - ACCOUNT_STOLEN_TIME - .endif .endm /*
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 39/42 powerpc: move NMI entry/exit code into wrapper
In reply to Nicholas PigginThis moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)
arch/powerpc/include/asm/interrupt.h +28 -0
@@ -94,14 +94,42 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int }struct interrupt_nmi_state { +#ifdef CONFIG_PPC64 +u8 ftrace_enabled; +#endif };static inline void interrupt_nmi_enter_prepare (struct pt_regs *regs,struct interrupt_nmi_state *state) { +#ifdef CONFIG_PPC64 +/* Allow DEC and PMI to be traced when they are soft-NMI */ +if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 ) { + state->ftrace_enabled =this_cpu_get_ftrace_enabled (); +this_cpu_set_ftrace_enabled (0 ); + } +#endif + +/* +* Do not use nmi_enter() for pseries hash guest taking a real-mode +* NMI because not everything it touches is within the RMA limit. +*/ +if (!IS_ENABLED (CONFIG_PPC_BOOK3S_64 ) || + !firmware_has_feature (FW_FEATURE_LPAR ) || +radix_enabled () || (mfmsr () &MSR_DR )) +nmi_enter (); }static inline void interrupt_nmi_exit_prepare (struct pt_regs *regs,struct interrupt_nmi_state *state) { +if (!IS_ENABLED (CONFIG_PPC_BOOK3S_64 ) || + !firmware_has_feature (FW_FEATURE_LPAR ) || +radix_enabled () || (mfmsr () &MSR_DR )) +nmi_exit (); + +#ifdef CONFIG_PPC64 +if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 ) +this_cpu_set_ftrace_enabled (state->ftrace_enabled); +#endif }/**
arch/powerpc/kernel/mce.c +0 -11
@@ -592,12 +592,6 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);DEFINE_INTERRUPT_HANDLER_NMI (machine_check_early) {long handled =0 ; -u8 ftrace_enabled =this_cpu_get_ftrace_enabled (); - -this_cpu_set_ftrace_enabled (0 ); -/* Do not use nmi_enter/exit for pseries hpte guest */ -if (radix_enabled () || !firmware_has_feature (FW_FEATURE_LPAR )) -nmi_enter ();hv_nmi_check_nonrecoverable (regs);
@@ -607,11 +601,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_early)if (ppc_md.machine_check_early) handled = ppc_md.machine_check_early (regs); -if (radix_enabled () || !firmware_has_feature (FW_FEATURE_LPAR )) -nmi_exit (); - -this_cpu_set_ftrace_enabled (ftrace_enabled); -return handled; }
arch/powerpc/kernel/traps.c +6 -29
@@ -435,11 +435,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception) {unsigned long hsrr0, hsrr1;bool saved_hsrrs = false; -u8 ftrace_enabled =this_cpu_get_ftrace_enabled (); - -this_cpu_set_ftrace_enabled (0 ); - -nmi_enter ();/* * System reset can interrupt code where HSRRs are live and MSR[RI]=1.
@@ -514,10 +509,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception)mtspr (SPRN_HSRR1 , hsrr1); } -nmi_exit (); - -this_cpu_set_ftrace_enabled (ftrace_enabled); -/* What should we do here? We could issue a shutdown or hard reset. */ return 0 ;
@@ -809,6 +800,12 @@ void die_mce(const char *str, struct pt_regs *regs, long err) }NOKPROBE_SYMBOL (die_mce); +/* +* BOOK3S_64 does not call this handler as a non-maskable interrupt +* (it uses its own early real-mode handler to handle the MCE proper +* and then raises irq_work to call this handler when interrupts are +* enabled). +*/ #ifdef CONFIG_PPC_BOOK3S_64 DEFINE_INTERRUPT_HANDLER_ASYNC (machine_check_exception) #else
@@ -817,20 +814,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception) {int recover =0 ; -/* -* BOOK3S_64 does not call this handler as a non-maskable interrupt -* (it uses its own early real-mode handler to handle the MCE proper -* and then raises irq_work to call this handler when interrupts are -* enabled). -* -* This is silly. The BOOK3S_64 should just call a different function -* rather than expecting semantics to magically change. Something -* like 'non_nmi_machine_check_exception()', perhaps? -*/ -const bool nmi = !IS_ENABLED (CONFIG_PPC_BOOK3S_64 ); - -if (nmi)nmi_enter (); -__this_cpu_inc (irq_stat.mce_exceptions);add_taint (TAINT_MACHINE_CHECK ,LOCKDEP_NOW_UNRELIABLE );
@@ -862,8 +845,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception)if (!(regs->msr &MSR_RI ))die_mce ("Unrecoverable Machine check" , regs,SIGBUS ); -if (nmi)nmi_exit (); -#ifdef CONFIG_PPC_BOOK3S_64 return ;#else
@@ -1886,14 +1867,10 @@ DEFINE_INTERRUPT_HANDLER(vsx_unavailable_tm)DECLARE_INTERRUPT_HANDLER_NMI (performance_monitor_exception_nmi);DEFINE_INTERRUPT_HANDLER_NMI (performance_monitor_exception_nmi) { -nmi_enter (); -__this_cpu_inc (irq_stat.pmu_irqs);perf_irq (regs); -nmi_exit (); -return 0 ; }#endif
arch/powerpc/kernel/watchdog.c +4 -6
@@ -254,11 +254,12 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)int cpu =raw_smp_processor_id ();u64 tb; +/* should only arrive from kernel, with irqs disabled */ +WARN_ON_ONCE (!arch_irq_disabled_regs (regs)); +if (!cpumask_test_cpu (cpu, &wd_cpus_enabled))return 0 ; -nmi_enter (); -__this_cpu_inc (irq_stat.soft_nmi_irqs); tb =get_tb ();
@@ -266,7 +267,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)wd_smp_lock (&flags);if (cpumask_test_cpu (cpu, &wd_smp_cpus_stuck)) {wd_smp_unlock (&flags); - goto out; +return 0 ; }set_cpu_stuck (cpu, tb);
@@ -290,9 +291,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)if (wd_panic_timeout_tb <0x7fffffff )mtspr (SPRN_DEC , wd_panic_timeout_tb); -out: -nmi_exit (); -return 0 ; }
Signature · 1 line
2.23.0
Michael Ellerman
reviewerRe: [PATCH v7 39/42] powerpc: move NMI entry/exit code into wrapper
Quoted 7 lines · Nicholas Piggin
This moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
Quoted 7 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)
This is unhappy when injecting SLB multi-hits:
root@p86-2:~# echo PPC_SLB_MULTIHIT > /sys/kernel/debug/provoke-crash/DIRECT [ 312.496026][ T1344] kernel BUG at arch/powerpc/include/asm/interrupt.h:152! [ 312.496037][ T1344] Oops: Exception in kernel mode, sig: 5 [#1] [ 312.496045][ T1344] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries [ 312.496053][ T1344] Modules linked in: squashfs dm_multipath scsi_dh_rdac scsi_dh_alua pseries_rng rng_core vmx_crypto gf128mul crc32c_vpmsum ip_tables x_tables autofs4 [ 312.496085][ T1344] CPU: 19 PID: 1344 Comm: bash Not tainted 5.11.0-rc2-gcc-8.2.0-00123-g3fadced17474-dirty #638 [ 312.496096][ T1344] NIP: c000000000ef1618 LR: c000000000ef1600 CTR: 0000000000000000 [ 312.496104][ T1344] REGS: c00000001eb4ba00 TRAP: 0700 Not tainted (5.11.0-rc2-gcc-8.2.0-00123-g3fadced17474-dirty) [ 312.496113][ T1344] MSR: 8000000000021033 <SF,ME,IR,DR,RI,LE> CR: 48428284 XER: 00000000 [ 312.496132][ T1344] CFAR: c000000000ef28b8 IRQMASK: 3 [ 312.496132][ T1344] GPR00: c000000000ef15e4 c00000001eb4bca0 c000000001a53900 0000000000000001 [ 312.496132][ T1344] GPR04: c0000000017e7230 4000000000000000 3ffffffffffffffe 0000000000006d66 [ 312.496132][ T1344] GPR08: c00000001ec6fe80 0000000000000001 c00000000e72d380 0000000000001001 [ 312.496132][ T1344] GPR12: 0000000000000010 c00000001ec6fe80 00000100235ad1d0 000000013c2fb738 [ 312.496132][ T1344] GPR16: 000000013c210ae0 0000000000000000 0000000022000000 00000100235af740 [ 312.496132][ T1344] GPR20: 0000000000000000 0000000000000001 000000013c2a3ca0 c000000033c50040 [ 312.496132][ T1344] GPR24: c0000000100fbd80 0000000000000000 c000000001a7dc78 0000000000000001 [ 312.496132][ T1344] GPR28: c00000001eb4bd60 0000000000000001 0000000000000000 0000000000000001 [ 312.496229][ T1344] NIP [c000000000ef1618] machine_check_early+0x138/0x1f0 [ 312.496241][ T1344] LR [c000000000ef1600] machine_check_early+0x120/0x1f0 [ 312.496249][ T1344] Call Trace: [ 312.496254][ T1344] [c00000001eb4bca0] [c000000000ef15e4] machine_check_early+0x104/0x1f0 (unreliable) [ 312.496267][ T1344] [c00000001eb4bcf0] [c000000000008394] machine_check_early_common+0x134/0x1f0 [ 312.496279][ T1344] --- interrupt: 200 at lkdtm_PPC_SLB_MULTIHIT+0x128/0x138 [ 312.496290][ T1344] NIP: c0000000009cfea8 LR: c0000000009cfea0 CTR: 0000000000000000 [ 312.496298][ T1344] REGS: c00000001eb4bd60 TRAP: 0200 Not tainted (5.11.0-rc2-gcc-8.2.0-00123-g3fadced17474-dirty) [ 312.496307][ T1344] MSR: 8000000000209033 <SF,EE,ME,IR,DR,RI,LE> CR: 24428284 XER: 00000000 [ 312.496326][ T1344] CFAR: 000000000000021c DAR: c008000003880000 DSISR: 00000080 IRQMASK: 0 [ 312.496326][ T1344] GPR00: c0000000009cfea0 c0000000100fbb80 c000000001a53900 c008000003880000 [ 312.496326][ T1344] GPR04: 00000000000000b0 c000000401023440 8e01c533000000c0 0000000000bf50d9 [ 312.496326][ T1344] GPR08: 000000000fffffff 0000000000000021 000000000000001c c008000004880000 [ 312.496326][ T1344] GPR12: 0000000048428222 c00000001ec6fe80 00000100235ad1d0 000000013c2fb738 [ 312.496326][ T1344] GPR16: 000000013c210ae0 0000000000000000 0000000022000000 00000100235af740 [ 312.496326][ T1344] GPR20: 0000000000000000 0000000000000001 000000013c2a3ca0 c000000033c50040 [ 312.496326][ T1344] GPR24: c0000000100fbd80 0000000000000000 0000000000000011 c000000001a2ffb8 [ 312.496326][ T1344] GPR28: 00000000000004b0 c000000033c50000 c000000001105298 c008000003880000 [ 312.496427][ T1344] NIP [c0000000009cfea8] lkdtm_PPC_SLB_MULTIHIT+0x128/0x138 [ 312.496437][ T1344] LR [c0000000009cfea0] lkdtm_PPC_SLB_MULTIHIT+0x120/0x138 [ 312.496446][ T1344] --- interrupt: 200 [ 312.496451][ T1344] [c0000000100fbbf0] [c0000000009cb530] lkdtm_do_action+0x40/0x80 [ 312.496462][ T1344] [c0000000100fbc10] [c0000000009cbdfc] direct_entry+0x16c/0x350 [ 312.496473][ T1344] [c0000000100fbcc0] [c0000000007a7590] full_proxy_write+0x90/0xe0 [ 312.496484][ T1344] [c0000000100fbd10] [c00000000046b090] vfs_write+0xf0/0x310 [ 312.496496][ T1344] [c0000000100fbd60] [c00000000046b48c] ksys_write+0x7c/0x140 [ 312.496507][ T1344] [c0000000100fbdb0] [c000000000036340] system_call_exception+0x1a0/0x2e0 [ 312.496518][ T1344] [c0000000100fbe10] [c00000000000d360] system_call_common+0xf0/0x27c [ 312.496528][ T1344] Instruction dump: [ 312.496534][ T1344] 7c7b1b78 e93a0000 75290040 41820008 480000a8 4800125d 60000000 e94d0968 [ 312.496552][ T1344] 812a0000 55290216 7d290034 5529d97e <0b090000> 812a0000 3d29ffef 912a0000 [ 312.496571][ T1344] ---[ end trace 1cd2275de93cc3c3 ]--- [ 312.500581][ T1344] [ 312.500705][ C19] RTAS: event: 1, Type: Unknown (0), Severity: 3 [ 312.501068][ T0] ------------[ cut here ]------------ [ 312.501081][ T0] WARNING: CPU: 19 PID: 0 at kernel/rcu/tree.c:632 rcu_eqs_enter.isra.59+0x140/0x160 [ 312.501103][ T0] Modules linked in: squashfs dm_multipath scsi_dh_rdac scsi_dh_alua pseries_rng rng_core vmx_crypto gf128mul crc32c_vpmsum ip_tables x_tables autofs4 [ 312.501152][ T0] CPU: 19 PID: 0 Comm: swapper/19 Tainted: G D 5.11.0-rc2-gcc-8.2.0-00123-g3fadced17474-dirty #638 [ 312.501173][ T0] NIP: c000000000ef2830 LR: c000000000c287c0 CTR: 0000000000000000 [ 312.501187][ T0] REGS: c000000008d5fa50 TRAP: 0700 Tainted: G D (5.11.0-rc2-gcc-8.2.0-00123-g3fadced17474-dirty) [ 312.501203][ T0] MSR: 800000000282b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 28000248 XER: 20000009 [ 312.501248][ T0] CFAR: c000000000ef2728 IRQMASK: 1 [ 312.501248][ T0] GPR00: c000000000c287c0 c000000008d5fcf0 c000000001a53900 00000048c283bf7e [ 312.501248][ T0] GPR04: c00000000199fae0 0000000000000001 0000000000000800 4000000000000000 [ 312.501248][ T0] GPR08: c00000001ec6fe80 c0000003fdb93980 3ffffffffffffffe 000000000098967f [ 312.501248][ T0] GPR12: 00000000ffffffff c00000001ec6fe80 0000000000000000 000000001ef2fa60 [ 312.501248][ T0] GPR16: 0000000000000000 0000000000000000 c0000007fffebff8 c000000000051ca0 [ 312.501248][ T0] GPR20: c0000007fffec628 c00000000199fae0 0000000000000001 c0000003fdb917c8 [ 312.501248][ T0] GPR24: 0000000000000001 00000048c283bf7e 0000000000000000 0000000000000001 [ 312.501248][ T0] GPR28: c0000003fdb917c8 c00000000199fae0 0000000000000001 c0000000013d3980 [ 312.501428][ T0] NIP [c000000000ef2830] rcu_eqs_enter.isra.59+0x140/0x160 [ 312.501445][ T0] LR [c000000000c287c0] cpuidle_enter_state+0x2f0/0x540 [ 312.501469][ T0] Call Trace: [ 312.501481][ T0] [c000000008d5fcf0] [c000000008d5fd40] 0xc000000008d5fd40 (unreliable) [ 312.501508][ T0] [c000000008d5fd20] [c0000003fdb917c8] 0xc0000003fdb917c8 [ 312.501524][ T0] [c000000008d5fd80] [c000000000c28ab0] cpuidle_enter+0x50/0x70 [ 312.501544][ T0] [c000000008d5fdc0] [c00000000019000c] call_cpuidle+0x4c/0x80 [ 312.501564][ T0] [c000000008d5fde0] [c0000000001906a0] do_idle+0x390/0x3e0 [ 312.501581][ T0] [c000000008d5fe70] [c00000000019096c] cpu_startup_entry+0x3c/0x40 [ 312.501602][ T0] [c000000008d5fea0] [c000000000054838] start_secondary+0x5b8/0x9b0 [ 312.501619][ T0] [c000000008d5ff90] [c00000000000c654] start_secondary_prolog+0x10/0x14 [ 312.501642][ T0] Instruction dump: [ 312.501657][ T0] 60000000 e8010040 7c0803a6 e94d0030 39200000 38210030 7fff5214 f93f00f0 [ 312.501692][ T0] ebe1fff8 4bfffd14 60000000 60000000 <0fe00000> 4bfffef8 60000000 60000000 [ 312.501721][ T0] ---[ end trace 1cd2275de93cc3c4 ]---
147 static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state) 148 {
149 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
150 !firmware_has_feature(FW_FEATURE_LPAR) ||
151 radix_enabled() || (mfmsr() & MSR_DR))
152 nmi_exit();
So presumably it's:
#define __nmi_exit() \
do { \
BUG_ON(!in_nmi()); \cheers
Nicholas Piggin
reviewerRe: [PATCH v7 39/42] powerpc: move NMI entry/exit code into wrapper
Excerpts from Michael Ellerman's message of February 4, 2021 8:15 pm:
Quoted 16 lines
Quoted 7 lines · Nicholas Piggin
This moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
Quoted 7 lines
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)
Quoted 6 lines
This is unhappy when injecting SLB multi-hits:
root@p86-2:~# echo PPC_SLB_MULTIHIT > /sys/kernel/debug/provoke-crash/DIRECT [ 312.496026][ T1344] kernel BUG at arch/powerpc/include/asm/interrupt.h:152! [ 312.496037][ T1344] Oops: Exception in kernel mode, sig: 5 [#1] [ 312.496045][ T1344] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
pseries hash. Blast!
Quoted 8 lines
147 static inline void
interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)148 {
149 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
150 !firmware_has_feature(FW_FEATURE_LPAR) ||
151radix_enabled()|| (mfmsr()&MSR_DR))
152nmi_exit();
Quoted 5 lines
So presumably it's:
#define __nmi_exit() \ do { \ BUG_ON(!in_nmi()); \
Yes that would be it, pseries machine check enables MMU half way through so only one side of this triggers.
The MSR_DR check is supposed to catch the other NMIs that run with MMU on (perf, watchdog, etc). Suppose it could test TRAP(regs) explicitly although I wonder if we should also do this to keep things balanced
arch/powerpc/platforms/pseries/ras.c +5 -1
@@ -719,6 +719,7 @@ static int mce_handle_err_virtmode(struct pt_regs *regs,static int mce_handle_error (struct pt_regs *regs,struct rtas_error_log *errp) { +unsigned long msr;struct pseries_errorlog *pseries_log;struct pseries_mc_errorlog *mce_log =NULL ;int disposition =rtas_error_disposition (errp);
@@ -747,9 +748,12 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)* SLB multihit is done by now. */ out: -mtmsr (mfmsr () |MSR_IR |MSR_DR ); + msr =mfmsr (); +mtmsr (msr |MSR_IR |MSR_DR ); disposition =mce_handle_err_virtmode (regs, errp, mce_log, disposition); +mtmsr (msr); +return disposition; }
Michael Ellerman
reviewerRe: [PATCH v7 39/42] powerpc: move NMI entry/exit code into wrapper
Quoted 17 lines · Nicholas Piggin
Excerpts from Michael Ellerman's message of February 4, 2021 8:15 pm:
Quoted 16 lines
Quoted 14 lines · Nicholas Piggin
This moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)
Quoted 8 lines
Quoted 6 lines
This is unhappy when injecting SLB multi-hits:
root@p86-2:~# echo PPC_SLB_MULTIHIT > /sys/kernel/debug/provoke-crash/DIRECT [ 312.496026][ T1344] kernel BUG at arch/powerpc/include/asm/interrupt.h:152! [ 312.496037][ T1344] Oops: Exception in kernel mode, sig: 5 [#1] [ 312.496045][ T1344] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeriespseries hash. Blast!
The worst kind.
Quoted 14 lines
Quoted 8 lines
147 static inline void
interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)148 {
149 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
150 !firmware_has_feature(FW_FEATURE_LPAR) ||
151radix_enabled()|| (mfmsr()&MSR_DR))
152nmi_exit();Quoted 5 lines
So presumably it's:
#define __nmi_exit() \ do { \ BUG_ON(!in_nmi()); \
Quoted 6 lines
Yes that would be it, pseries machine check enables MMU half way through so only one side of this triggers.
The
MSR_DRcheck is supposed to catch the other NMIs that run with MMU on (perf, watchdog, etc). Suppose it could test TRAP(regs) explicitly although I wonder if we should also do this to keep things balanced
Yeah I think I like that. I'll give it a test.
cheers
Quoted 26 lines
arch/powerpc/platforms/pseries/ras.c +5
-1@@ -719,6 +719,7 @@ static int mce_handle_err_virtmode(struct pt_regs *regs,static int mce_handle_error (struct pt_regs *regs,struct rtas_error_log *errp) { +unsigned long msr;struct pseries_errorlog *pseries_log;struct pseries_mc_errorlog *mce_log =NULL ;int disposition =rtas_error_disposition (errp);@@ -747,9 +748,12 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)* SLB multihit is done by now. */ out: -mtmsr (mfmsr () |MSR_IR |MSR_DR ); + msr =mfmsr (); +mtmsr (msr |MSR_IR |MSR_DR ); disposition =mce_handle_err_virtmode (regs, errp, mce_log, disposition); +mtmsr (msr); +return disposition; }
Nicholas Piggin
reviewerRe: [PATCH v7 39/42] powerpc: move NMI entry/exit code into wrapper
Excerpts from Michael Ellerman's message of February 6, 2021 9:38 am:
Quoted 43 lines
Quoted 17 lines · Nicholas Piggin
Excerpts from Michael Ellerman's message of February 4, 2021 8:15 pm:
Quoted 16 lines
Quoted 14 lines · Nicholas Piggin
This moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)Quoted 8 lines
Quoted 6 lines
This is unhappy when injecting SLB multi-hits:
root@p86-2:~# echo PPC_SLB_MULTIHIT > /sys/kernel/debug/provoke-crash/DIRECT [ 312.496026][ T1344] kernel BUG at arch/powerpc/include/asm/interrupt.h:152! [ 312.496037][ T1344] Oops: Exception in kernel mode, sig: 5 [#1] [ 312.496045][ T1344] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeriespseries hash. Blast!
The worst kind.
Quoted 14 lines
Quoted 13 lines
147 static inline void
interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)148 {
149 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
150 !firmware_has_feature(FW_FEATURE_LPAR) ||
151radix_enabled()|| (mfmsr()&MSR_DR))
152nmi_exit();So presumably it's:
#define __nmi_exit() \ do { \ BUG_ON(!in_nmi()); \
Quoted 8 lines
Quoted 6 lines
Yes that would be it, pseries machine check enables MMU half way through so only one side of this triggers.
The
MSR_DRcheck is supposed to catch the other NMIs that run with MMU on (perf, watchdog, etc). Suppose it could test TRAP(regs) explicitly although I wonder if we should also do this to keep things balancedYeah I think I like that. I'll give it a test.
The msr restore? Looking closer, pseries_machine_check_realmode may have expected mce_handle_error to enable the MMU, because irq_work_queue uses some per-cpu variables I think.
So the code might have to be rearranged a bit more than the patch below.
Thanks,
Nick
Quoted 31 lines
cheers
Quoted 26 lines
arch/powerpc/platforms/pseries/ras.c +5
-1@@ -719,6 +719,7 @@ static int mce_handle_err_virtmode(struct pt_regs *regs,static int mce_handle_error (struct pt_regs *regs,struct rtas_error_log *errp) { +unsigned long msr;struct pseries_errorlog *pseries_log;struct pseries_mc_errorlog *mce_log =NULL ;int disposition =rtas_error_disposition (errp);@@ -747,9 +748,12 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)* SLB multihit is done by now. */ out: -mtmsr (mfmsr () |MSR_IR |MSR_DR ); + msr =mfmsr (); +mtmsr (msr |MSR_IR |MSR_DR ); disposition =mce_handle_err_virtmode (regs, errp, mce_log, disposition); +mtmsr (msr); +return disposition; }
Nicholas Piggin
reviewerRe: [PATCH v7 39/42] powerpc: move NMI entry/exit code into wrapper
Excerpts from Nicholas Piggin's message of February 6, 2021 12:46 pm:
Quoted 51 lines
Excerpts from Michael Ellerman's message of February 6, 2021 9:38 am:
Quoted 50 lines
Quoted 17 lines · Nicholas Piggin
Excerpts from Michael Ellerman's message of February 4, 2021 8:15 pm:
Quoted 16 lines
Quoted 14 lines · Nicholas Piggin
This moves the common NMI entry and exit code into the interrupt handler wrappers.
This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 28 ++++++++++++++++++++++ arch/powerpc/kernel/mce.c | 11 --------- arch/powerpc/kernel/traps.c | 35 +++++----------------------- arch/powerpc/kernel/watchdog.c | 10 ++++---- 4 files changed, 38 insertions(+), 46 deletions(-)Quoted 8 lines
Quoted 6 lines
This is unhappy when injecting SLB multi-hits:
root@p86-2:~# echo PPC_SLB_MULTIHIT > /sys/kernel/debug/provoke-crash/DIRECT [ 312.496026][ T1344] kernel BUG at arch/powerpc/include/asm/interrupt.h:152! [ 312.496037][ T1344] Oops: Exception in kernel mode, sig: 5 [#1] [ 312.496045][ T1344] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeriespseries hash. Blast!
The worst kind.
Quoted 20 lines
Quoted 8 lines
147 static inline void
interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)148 {
149 if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
150 !firmware_has_feature(FW_FEATURE_LPAR) ||
151radix_enabled()|| (mfmsr()&MSR_DR))
152nmi_exit();Quoted 5 lines
So presumably it's:
#define __nmi_exit() \ do { \ BUG_ON(!in_nmi()); \Yes that would be it, pseries machine check enables MMU half way through so only one side of this triggers.
The
MSR_DRcheck is supposed to catch the other NMIs that run with MMU on (perf, watchdog, etc). Suppose it could test TRAP(regs) explicitly although I wonder if we should also do this to keep things balanced
Quoted 7 lines
Quoted 1 line
Yeah I think I like that. I'll give it a test.
The msr restore? Looking closer,
pseries_machine_check_realmodemay have expectedmce_handle_errorto enable the MMU, becauseirq_work_queueuses some per-cpu variables I think.So the code might have to be rearranged a bit more than the patch below.
Here is a patch, it should go anywhere before this patch. Seems to work with some test MCE injection on pseries hash.
Thanks,
Nick
--
powerpc/pseries/mce: restore msr before returning from handler
The pseries real-mode machine check handler can enable the MMU, and return from the handler with the MMU still enabled.
This works, but real-mode handler wrapper exit handlers want to rely on the MMU being in real-mode. So change the pseries handler to restore the MSR after it has finished virtual mode tasks.
--- arch/powerpc/platforms/pseries/ras.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
arch/powerpc/platforms/pseries/ras.c +15 -4
@@ -722,6 +722,7 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)struct pseries_errorlog *pseries_log;struct pseries_mc_errorlog *mce_log =NULL ;int disposition =rtas_error_disposition (errp); +unsigned long msr;u8 error_type;if (!rtas_error_extended (errp))
@@ -747,9 +748,21 @@ static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)* SLB multihit is done by now. */ out: -mtmsr (mfmsr () |MSR_IR |MSR_DR ); + msr =mfmsr (); +mtmsr (msr |MSR_IR |MSR_DR ); + disposition =mce_handle_err_virtmode (regs, errp, mce_log, disposition); + +/* +* Queue irq work to log this rtas event later. +* irq_work_queue uses per-cpu variables, so do this in virt +* mode as well. +*/ +irq_work_queue (&mce_errlog_process_work); + +mtmsr (msr); +return disposition; }
@@ -865,10 +878,8 @@ long pseries_machine_check_realmode(struct pt_regs *regs)* virtual mode. */ disposition =mce_handle_error (regs, errp); -fwnmi_release_errinfo (); -/* Queue irq work to log this rtas event later. */ -irq_work_queue (&mce_errlog_process_work); +fwnmi_release_errinfo ();if (disposition ==RTAS_DISP_FULLY_RECOVERED )return 1 ;
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 40/42 powerpc/64s: move NMI soft-mask handling to C
In reply to Nicholas PigginSaving and restoring soft-mask state can now be done in C using the interrupt handler wrapper functions.
--- arch/powerpc/include/asm/interrupt.h | 25 ++++++++++++ arch/powerpc/kernel/exceptions-64s.S | 60 ---------------------------- 2 files changed, 25 insertions(+), 60 deletions(-)
arch/powerpc/include/asm/interrupt.h +25 -0
@@ -95,6 +95,10 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct intstruct interrupt_nmi_state {#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S_64 +u8 irq_soft_mask; +u8 irq_happened; +#endif u8 ftrace_enabled;#endif };
@@ -102,6 +106,20 @@ struct interrupt_nmi_state {static inline void interrupt_nmi_enter_prepare (struct pt_regs *regs,struct interrupt_nmi_state *state) {#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S_64 + state->irq_soft_mask = local_paca->irq_soft_mask; + state->irq_happened = local_paca->irq_happened; + +/* +* Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does +* the right thing, and set IRQ_HARD_DIS. We do not want to reconcile +* because that goes through irq tracing which we don't want in NMI. +*/ + local_paca->irq_soft_mask =IRQS_ALL_DISABLED ; + local_paca->irq_happened |=PACA_IRQ_HARD_DIS ; + +/* Don't do any per-CPU operations until interrupt state is fixed */ +#endif /* Allow DEC and PMI to be traced when they are soft-NMI */ if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 ) { state->ftrace_enabled =this_cpu_get_ftrace_enabled ();
@@ -129,6 +147,13 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter#ifdef CONFIG_PPC64 if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 )this_cpu_set_ftrace_enabled (state->ftrace_enabled); + +#ifdef CONFIG_PPC_BOOK3S_64 +/* Check we didn't change the pending interrupt mask. */ +WARN_ON_ONCE ((state->irq_happened |PACA_IRQ_HARD_DIS ) != local_paca->irq_happened); + local_paca->irq_happened = state->irq_happened; + local_paca->irq_soft_mask = state->irq_soft_mask; +#endif #endif }
arch/powerpc/kernel/exceptions-64s.S +0 -60
95 lines not on this page · raw message
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 41/42 powerpc/64s: runlatch interrupt handling in C
In reply to Nicholas PigginThere is no need for this to be in asm, use the new intrrupt entry wrapper.
--- arch/powerpc/include/asm/interrupt.h | 7 +++++++ arch/powerpc/kernel/exceptions-64s.S | 18 ------------------ 2 files changed, 7 insertions(+), 18 deletions(-)
arch/powerpc/include/asm/interrupt.h +7 -0
@@ -6,6 +6,7 @@#include <linux/hardirq.h> #include <asm/cputime.h> #include <asm/ftrace.h> +#include <asm/runlatch.h> struct interrupt_state {#ifdef CONFIG_PPC_BOOK3E_64
@@ -83,6 +84,12 @@ static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interruptstatic inline void interrupt_async_enter_prepare (struct pt_regs *regs,struct interrupt_state *state) { +#ifdef CONFIG_PPC_BOOK3S_64 +if (cpu_has_feature (CPU_FTR_CTRL ) && + !test_thread_local_flags (_TLF_RUNLATCH)) +__ppc64_runlatch_on (); +#endif +interrupt_enter_prepare (regs, state);irq_enter (); }
arch/powerpc/kernel/exceptions-64s.S +0 -18
@@ -692,14 +692,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) ld r1,GPR1(r1) .endm -#define RUNLATCH_ON \ -BEGIN_FTR_SECTION \ - ld r3, PACA_THREAD_INFO(r13); \ - ld r4,TI_LOCAL_FLAGS(r3); \ - andi. r0,r4,_TLF_RUNLATCH; \ - beql ppc64_runlatch_on_trampoline; \ -END_FTR_SECTION_IFSET(CPU_FTR_CTRL) - /* * When the idle code in power4_idle puts the CPU into NAP mode, * it has to do so in a loop, and relies on the external interrupt
@@ -1585,7 +1577,6 @@ EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100) EXC_COMMON_BEGIN(hardware_interrupt_common) GEN_COMMON hardware_interrupt FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD bl do_IRQ b interrupt_return
@@ -1771,7 +1762,6 @@ EXC_VIRT_END(decrementer, 0x4900, 0x80) EXC_COMMON_BEGIN(decrementer_common) GEN_COMMON decrementer FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD bl timer_interrupt b interrupt_return
@@ -1857,7 +1847,6 @@ EXC_VIRT_END(doorbell_super, 0x4a00, 0x100) EXC_COMMON_BEGIN(doorbell_super_common) GEN_COMMON doorbell_super FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD #ifdef CONFIG_PPC_DOORBELL bl doorbell_exception
@@ -2212,7 +2201,6 @@ EXC_COMMON_BEGIN(hmi_exception_early_common) EXC_COMMON_BEGIN(hmi_exception_common) GEN_COMMON hmi_exception FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD bl handle_hmi_exception b interrupt_return
@@ -2242,7 +2230,6 @@ EXC_VIRT_END(h_doorbell, 0x4e80, 0x20) EXC_COMMON_BEGIN(h_doorbell_common) GEN_COMMON h_doorbell FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD #ifdef CONFIG_PPC_DOORBELL bl doorbell_exception
@@ -2276,7 +2263,6 @@ EXC_VIRT_END(h_virt_irq, 0x4ea0, 0x20) EXC_COMMON_BEGIN(h_virt_irq_common) GEN_COMMON h_virt_irq FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD bl do_IRQ b interrupt_return
@@ -2323,7 +2309,6 @@ EXC_VIRT_END(performance_monitor, 0x4f00, 0x20) EXC_COMMON_BEGIN(performance_monitor_common) GEN_COMMON performance_monitor FINISH_NAP - RUNLATCH_ON addi r3,r1,STACK_FRAME_OVERHEAD bl performance_monitor_exception b interrupt_return
@@ -3057,9 +3042,6 @@ kvmppc_skip_Hinterrupt: * come here. */ -EXC_COMMON_BEGIN(ppc64_runlatch_on_trampoline) - b __ppc64_runlatch_on - USE_FIXED_SECTION(virt_trampolines) /* * All code below __end_interrupts is treated as soft-masked. If
Signature · 1 line
2.23.0
Nicholas Piggin
reviewerPATCH v7 42/42 powerpc/64s: power4 nap fixup in C
In reply to Nicholas PigginThere is no need for this to be in asm, use the new intrrupt entry wrapper.
--- arch/powerpc/include/asm/interrupt.h | 15 +++++++++ arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 6 ++++ arch/powerpc/kernel/exceptions-64s.S | 45 -------------------------- arch/powerpc/kernel/idle_book3s.S | 4 +++ 5 files changed, 26 insertions(+), 45 deletions(-)
arch/powerpc/include/asm/interrupt.h +15 -0
@@ -8,6 +8,16 @@#include <asm/ftrace.h> #include <asm/runlatch.h> +static inline void nap_adjust_return (struct pt_regs *regs) +{ +#ifdef CONFIG_PPC_970_NAP +if (unlikely (test_thread_local_flags (_TLF_NAPPING))) { +clear_thread_local_flags (_TLF_NAPPING); + regs->nip = (unsigned long )power4_idle_nap_return; + } +#endif +} +struct interrupt_state {#ifdef CONFIG_PPC_BOOK3E_64 enum ctx_state ctx_state;
@@ -98,6 +108,9 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int {irq_exit ();interrupt_exit_prepare (regs, state); + +/* Adjust at exit so the main handler sees the true NIA */ +nap_adjust_return (regs); }struct interrupt_nmi_state {
@@ -151,6 +164,8 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter radix_enabled() || (mfmsr() & MSR_DR))nmi_exit (); +nap_adjust_return (regs); +#ifdef CONFIG_PPC64 if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 )this_cpu_set_ftrace_enabled (state->ftrace_enabled);
arch/powerpc/include/asm/processor.h +1 -0
@@ -393,6 +393,7 @@ extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val);extern unsigned long isa206_idle_insn_mayloss (unsigned long type);#ifdef CONFIG_PPC_970_NAP extern void power4_idle_nap (void ); +void power4_idle_nap_return (void );#endif extern unsigned long cpuidle_disable;
arch/powerpc/include/asm/thread_info.h +6 -0
@@ -152,6 +152,12 @@ void arch_setup_new_exec(void);#ifndef __ASSEMBLY__ +static inline void clear_thread_local_flags (unsigned int flags) +{ +struct thread_info *ti =current_thread_info (); + ti->local_flags &= ~flags; +} +static inline bool test_thread_local_flags (unsigned int flags) {struct thread_info *ti =current_thread_info ();
arch/powerpc/kernel/exceptions-64s.S +0 -45
105 lines not on this page · raw message
arch/powerpc/kernel/idle_book3s.S +4 -0
@@ -201,4 +201,8 @@ _GLOBAL(power4_idle_nap) mtmsrd r7 isync b 1b + + .globl power4_idle_nap_return +power4_idle_nap_return: + blr #endif
Signature · 1 line
2.23.0
Michael Ellerman
reviewerRe: [PATCH v7 42/42] powerpc/64s: power4 nap fixup in C
Quoted 10 lines · Nicholas Piggin
There is no need for this to be in asm, use the new intrrupt entry wrapper.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 15 +++++++++ arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 6 ++++ arch/powerpc/kernel/exceptions-64s.S | 45 -------------------------- arch/powerpc/kernel/idle_book3s.S | 4 +++ 5 files changed, 26 insertions(+), 45 deletions(-)
Something in here is making my G5 not boot.
I don't know what the problem is because that machine is in the office, and I am not, and it has no serial console.
I tried turning on pstore but it doesn't record anything :/
cheers
Nicholas Piggin
reviewerRe: [PATCH v7 42/42] powerpc/64s: power4 nap fixup in C
Excerpts from Michael Ellerman's message of February 2, 2021 8:31 pm:
Quoted 12 lines
Quoted 10 lines · Nicholas Piggin
There is no need for this to be in asm, use the new intrrupt entry wrapper.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 15 +++++++++ arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 6 ++++ arch/powerpc/kernel/exceptions-64s.S | 45 -------------------------- arch/powerpc/kernel/idle_book3s.S | 4 +++ 5 files changed, 26 insertions(+), 45 deletions(-)
Quoted 4 lines
Something in here is making my G5 not boot.
I don't know what the problem is because that machine is in the office, and I am not, and it has no serial console.
I'll try it in qemu again, haven't tested that for a few rebases. You can just drop this for now.
Thanks,
Nick
Nicholas Piggin
reviewerRe: [PATCH v7 42/42] powerpc/64s: power4 nap fixup in C
In reply to Michael EllermanExcerpts from Michael Ellerman's message of February 2, 2021 8:31 pm:
Quoted 12 lines
Quoted 10 lines · Nicholas Piggin
There is no need for this to be in asm, use the new intrrupt entry wrapper.
Signed-off-by Nicholas Piggin <[email protected]>--- arch/powerpc/include/asm/interrupt.h | 15 +++++++++ arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 6 ++++ arch/powerpc/kernel/exceptions-64s.S | 45 -------------------------- arch/powerpc/kernel/idle_book3s.S | 4 +++ 5 files changed, 26 insertions(+), 45 deletions(-)
Quoted 6 lines
Something in here is making my G5 not boot.
I don't know what the problem is because that machine is in the office, and I am not, and it has no serial console.
I tried turning on pstore but it doesn't record anything :/
Here is an incremental patch (hopefully) should fix it. Should be folded with this one.
Thanks,
Nick
---
powerpc/64s: nap_adjust_return fix
This is a fix for patch "powerpc/64s: power4 nap fixup in C".
Non-maskable interrupts should not create any exit work, so there should be no reason to come out of idle. So take the nap fixup out of NMIs.
The problem with having them here is that an interrupt can come in and then get interrupted by an NMI, the NMI will then set its return to the idle wakeup and never complete the regular interrupt handling.
Before the "powerpc/64s: power4 nap fixup in C" patch, this wouldn't occur because the true NMIs didn't call FIXUP_NAP, and the other interrupts would call it before running their handler, so they would not have a chance to call may_hard_irq_enable and allow soft-NMIs (watchdog, perf) to come through.
--- arch/powerpc/include/asm/interrupt.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/powerpc/include/asm/interrupt.h +5 -1
@@ -12,6 +12,7 @@ static inline void nap_adjust_return(struct pt_regs *regs) {#ifdef CONFIG_PPC_970_NAP if (unlikely (test_thread_local_flags (_TLF_NAPPING))) { +/* Can avoid a test-and-clear because NMIs do not call this */ clear_thread_local_flags (_TLF_NAPPING); regs->nip = (unsigned long )power4_idle_nap_return; }
@@ -164,7 +165,10 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter radix_enabled() || (mfmsr() & MSR_DR))nmi_exit (); -nap_adjust_return (regs); +/* +* nmi does not call nap_adjust_return because nmi should not create +* new work to do (must use irq_work for that). +*/ #ifdef CONFIG_PPC64 if (TRAP (regs) !=0x900 &&TRAP (regs) !=0xf00 &&TRAP (regs) !=0x260 )
Signature · 1 line
2.23.0
Le 30/01/2021 à 14:08, Nicholas Piggin a écrit :
Quoted 7 lines
This adds interrupt handler wrapper functions, similar to the generic / x86 code, and moves several common operations into them from either asm or open coded in the individual handlers.
This series is based on powerpc fixes-test tree, there's another unrelated pending fix in patch 1 of the series which clashes a bit.
This series trivialy conflicts with https://github.com/linuxppc/linux/commit/11f9c1d2fb497f69f83d4fab6fb7fc8a6884eded on powerpc next tree.
Quoted 152 lines
This includes more changes and fixes suggested by Christophe, a few minor bug fixes and compile fix noticed by kbuild, and some NMI changes Athira asked about -- PMI interrupts don't block tracing when they are soft-NMI.
Since v1:
- Fixed a couple of compile issues
- Fixed perf weirdness (sometimes NMI, sometimes not)
- Also move irq_enter/exit into wrappersSince v2:
- Rebased upstream
- Took code in patch 3 from Christophe
- Fixed some compile errors from 0daySince v3:
- Rebased
- Split Christophe's 32s DABR patch into its own patch
- Fixed missing asm from 32s on patch 3 noticed by Christophe.
- Moved changes around, split out one more patch (patch 9) to make changes more logical and atomic.
- Add comments explaining_RAWhandlers (SLB, HPTE) interrupts betterSince v4:
- Rebased (on top of scv fallback flush fix)
- Rearranged a few changes into different patches from Christophe, e.g., the___do_page_faultchange from patch 2 to 10. I didn't do everything (e.g., splitting to update__hash_pageto drop the msr argument before the bulk of patch 2 seemed like churn without much improvement), and also other things like removing the new___do_page_faultvariant if we can change hash fault context tracking I didn't get time to completely investigate and implement. I think this shouldn't be a showstopper though we can make more improvements as we go.Since v5:
- Lots of good review suggestions from Christophe, see v5 email threads.
- Major change beingdo_breakis left in asm and selected early as an alternate interrupt handler now, which is a smaller step and matches other subarchs better.
- Rearranged patches, split, moved things, bug fixes, etc.
- Converted a few more missed exception handlers for debug and rasSince v6:
- Move related interrupt handler de-argify patches together [Christophe]
- Splitdo_bad_page_faultpatch [Christophe]
- Changedo_page_faultcleanup patch [Christophe]
-entry_32.Scan't avoid saving r4/r5 until later in the series [Christophe]
- Soft-NMI decrementer and perf don't block ftrace [Athira]
- Rebased on some fixes
- Fixed mismerge / duplicate line in patch 40
- Fix kbuild hash missing declaration bugChristophe Leroy (1):
powerpc/32s: move DABR match out ofhandle_page_faultNicholas Piggin (41):
powerpc/64s: interrupt exit improve bounding of interrupt recursion
KVM: PPC: Book3S HV: Context tracking exit guest context before
enabling irqs
powerpc/64s: move DABR match out ofhandle_page_faultpowerpc/64s: move the hash fault handling logic to C
powerpc: remove arguments from fault handler functions powerpc/fsl_booke/32: CacheLockingException remove args
powerpc:do_breakget registers from regs
powerpc: DebugException remove args
powerpc/32: transfer can avoid saving r4/r5 over trace call
powerpc:bad_page_faultget registers from regs powerpc/64s: adddo_bad_page_fault_segvhandler
powerpc: rearrangedo_page_faulterror case to be inside
exception_enter
powerpc/64s: movebad_page_faulthandling to C powerpc/64s: splitdo_hash_fault
powerpc/mm: Remove staledo_page_faultcomment referring to SLB faults powerpc/64s: slb comment update
powerpc/traps: addNOKPROBE_SYMBOLfor sreset and mce powerpc/perf: move perf irq/nmi handling details intotraps.cpowerpc/time: movetimer_broadcast_interruptprototype toasm/time.h
powerpc: add and useunknown_async_exception
powerpc/cell: tidy up pervasive declarations
powerpc: introducedie_mce
powerpc/mce: ensure machine check handler always tests RI
powerpc: improve handling of unrecoverable system reset
powerpc: interrupt handler wrapper functions
powerpc: add interrupt wrapper entry / exit stub functions
powerpc: convert interrupt handlers to use wrappers
powerpc: addinterrupt_cond_local_irq_enablehelper powerpc/64: context tracking remove_TIF_NOHZpowerpc/64s/hash: improve context tracking of hash faults powerpc/64: context tracking move to interrupt wrappers powerpc/64: add context tracking to asynchronous interrupts
powerpc: handle irq_enter/irq_exit in interrupt handler wrappers powerpc/64s: move context tracking exit to interrupt exit path powerpc/64s: reconcile interrupts in C
powerpc/64: moveaccount_stolen_timeinto its own function powerpc/64: entry cpu time accounting in C
powerpc: move NMI entry/exit code into wrapper powerpc/64s: move NMI soft-mask handling to C
powerpc/64s: runlatch interrupt handling in C
powerpc/64s: power4 nap fixup in Carch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/asm-prototypes.h | 29 -- arch/powerpc/include/asm/bug.h | 9 +- arch/powerpc/include/asm/cputime.h | 14 + arch/powerpc/include/asm/debug.h | 4 - arch/powerpc/include/asm/hw_irq.h | 9 - arch/powerpc/include/asm/interrupt.h | 437 +++++++++++++++++++++ arch/powerpc/include/asm/ppc_asm.h | 24 -- arch/powerpc/include/asm/processor.h | 1 + arch/powerpc/include/asm/thread_info.h | 10 +- arch/powerpc/include/asm/time.h | 2 + arch/powerpc/kernel/dbell.c | 9 +- arch/powerpc/kernel/entry_32.S | 25 +- arch/powerpc/kernel/exceptions-64e.S | 8 +- arch/powerpc/kernel/exceptions-64s.S | 310 ++------------- arch/powerpc/kernel/head_40x.S | 11 +- arch/powerpc/kernel/head_8xx.S | 11 +- arch/powerpc/kernel/head_book3s_32.S | 14 +- arch/powerpc/kernel/head_booke.h | 6 +- arch/powerpc/kernel/head_fsl_booke.S | 6 +- arch/powerpc/kernel/idle_book3s.S | 4 + arch/powerpc/kernel/irq.c | 7 +- arch/powerpc/kernel/mce.c | 16 +- arch/powerpc/kernel/process.c | 8 +- arch/powerpc/kernel/ptrace/ptrace.c | 4 - arch/powerpc/kernel/signal.c | 4 - arch/powerpc/kernel/syscall_64.c | 90 +++-- arch/powerpc/kernel/tau_6xx.c | 5 +- arch/powerpc/kernel/time.c | 7 +- arch/powerpc/kernel/traps.c | 265 ++++++------- arch/powerpc/kernel/watchdog.c | 15 +- arch/powerpc/kvm/book3s_hv.c | 7 +- arch/powerpc/kvm/book3s_hv_builtin.c | 1 + arch/powerpc/kvm/booke.c | 1 + arch/powerpc/mm/book3s64/hash_utils.c | 97 +++-- arch/powerpc/mm/book3s64/slb.c | 40 +- arch/powerpc/mm/fault.c | 76 ++-- arch/powerpc/perf/core-book3s.c | 35 +- arch/powerpc/perf/core-fsl-emb.c | 25 -- arch/powerpc/platforms/8xx/machine_check.c | 2 +- arch/powerpc/platforms/cell/pervasive.c | 1 + arch/powerpc/platforms/cell/pervasive.h | 3 - arch/powerpc/platforms/cell/ras.c | 6 +- arch/powerpc/platforms/cell/ras.h | 9 +- arch/powerpc/platforms/powernv/idle.c | 1 + arch/powerpc/platforms/powernv/opal.c | 2 +- arch/powerpc/platforms/pseries/ras.c | 2 +- 47 files changed, 914 insertions(+), 759 deletions(-)create mode 100644
arch/powerpc/include/asm/interrupt.h
Quoted 9 lines · Nicholas Piggin
This adds interrupt handler wrapper functions, similar to the generic / x86 code, and moves several common operations into them from either asm or open coded in the individual handlers.
This series is based on powerpc fixes-test tree, there's another unrelated pending fix in patch 1 of the series which clashes a bit.
[...]
Patches 1-41 applied to powerpc/next.
[01/42] powerpc/64s: interrupt exit improve bounding of interrupt recursion
https://git.kernel.org/powerpc/c/c0ef717305f51e29b5ce0c78a6bfe566b3283415 [02/42] KVM: PPC: Book3S HV: Context tracking exit guest context before enabling irqs https://git.kernel.org/powerpc/c/112665286d08c87e66d699e7cba43c1497ad165f [03/42] powerpc/32s: move DABR match out of handle_page_fault https://git.kernel.org/powerpc/c/7a24ae2e172f770df07f8e48ed3ed2f3a6b17e37 [04/42] powerpc/64s: move DABR match out of handle_page_fault https://git.kernel.org/powerpc/c/36f0114140eef53e931592b65bdf8bb61ffac1f8 [05/42] powerpc/64s: move the hash fault handling logic to C https://git.kernel.org/powerpc/c/a4922f5442e7e6ce85da304e224d940edec2f1fb [06/42] powerpc: remove arguments from fault handler functions https://git.kernel.org/powerpc/c/a01a3f2ddbcda83e8572787c0ec1dcbeba86915a [07/42] powerpc/fsl_booke/32: CacheLockingException remove args https://git.kernel.org/powerpc/c/b4ced8031000b832d845dd17994e0fa1b8310496 [08/42] powerpc: do_break get registers from regs https://git.kernel.org/powerpc/c/18722ecf9efdc6a7ca933a3e5a83cc9dba375847 [09/42] powerpc: DebugException remove args https://git.kernel.org/powerpc/c/755d664174463791489dddf34c33308b61de68c3 [10/42] powerpc/32: transfer can avoid saving r4/r5 over trace call https://git.kernel.org/powerpc/c/73d7a97914f23397b012e851f6a1fe4061923a82 [11/42] powerpc: bad_page_fault get registers from regs https://git.kernel.org/powerpc/c/8458c628a53ba4311b2df12370be1a6f1870ff37 [12/42] powerpc/64s: add do_bad_page_fault_segv handler https://git.kernel.org/powerpc/c/71f47976fafc4375674bd0714153be10f878040a [13/42] powerpc: rearrange do_page_fault error case to be inside exception_enter https://git.kernel.org/powerpc/c/4cb8428465148bcca0b6b8593d51f805818a70e0 [14/42] powerpc/64s: move bad_page_fault handling to C https://git.kernel.org/powerpc/c/f4c03b0e520c5f56e569a8da3fce5ddbd0696742 [15/42] powerpc/64s: split do_hash_fault https://git.kernel.org/powerpc/c/bf0e2374aa7b4f8b01fd59fcb0746a9b6b05326a [16/42] powerpc/mm: Remove stale do_page_fault comment referring to SLB faults https://git.kernel.org/powerpc/c/31d6490ccb2868530300381d8079026cd4a9f7ad [17/42] powerpc/64s: slb comment update https://git.kernel.org/powerpc/c/e44370abb2e99299678ec6b209f8aad574fa5f36 [18/42] powerpc/traps: add NOKPROBE_SYMBOL for sreset and mce https://git.kernel.org/powerpc/c/3a3138836bc35966d59742512b597997755878f7 [19/42] powerpc/perf: move perf irq/nmi handling details into traps.c https://git.kernel.org/powerpc/c/156b5371a9c2482a9ad23ec82d1a4f89a3ab430d [20/42] powerpc/time: move timer_broadcast_interrupt prototype to asm/time.h https://git.kernel.org/powerpc/c/0440b8a22cc48922f7c6ae894abd221cf7cc4b64 [21/42] powerpc: add and use unknown_async_exception https://git.kernel.org/powerpc/c/6c6aee009ec34cb7f5ef76f910c1b9417c81efd8 [22/42] powerpc/cell: tidy up pervasive declarations https://git.kernel.org/powerpc/c/dcdb4f12963f3f4200e24e1dad78564a98736f67 [23/42] powerpc: introduce die_mce https://git.kernel.org/powerpc/c/209e9d500e25eada096b2c09a34093bc458166f3 [24/42] powerpc/mce: ensure machine check handler always tests RI https://git.kernel.org/powerpc/c/c538938fa2cfdc806c6304888e3876729e6939e0 [25/42] powerpc: improve handling of unrecoverable system reset https://git.kernel.org/powerpc/c/11cb0a25f71818ca7ab4856548ecfd83c169aa4d [26/42] powerpc: interrupt handler wrapper functions https://git.kernel.org/powerpc/c/8d41fc618ab804657acd2df8e761ce1001f41513 [27/42] powerpc: add interrupt wrapper entry / exit stub functions https://git.kernel.org/powerpc/c/25b7e6bb743ca5a375bb89522a2c2bec840d5fc3 [28/42] powerpc: convert interrupt handlers to use wrappers https://git.kernel.org/powerpc/c/3a96570ffceb15c6ed9cc6f990f172dcdc8ac279 [29/42] powerpc: add interrupt_cond_local_irq_enable helper https://git.kernel.org/powerpc/c/e6f8a6c86ce7b2108c03c1cc014fdae278573df1 [30/42] powerpc/64: context tracking remove _TIF_NOHZ https://git.kernel.org/powerpc/c/2a06bf3e95cd93e3640d431960181b8e47415f33 [31/42] powerpc/64s/hash: improve context tracking of hash faults https://git.kernel.org/powerpc/c/a008f8f9fd67ffb13d906ef4ea6235a3d62dfdb6 [32/42] powerpc/64: context tracking move to interrupt wrappers https://git.kernel.org/powerpc/c/540d4d34bef4ec58aba12b159030492616d6f54e [33/42] powerpc/64: add context tracking to asynchronous interrupts https://git.kernel.org/powerpc/c/6fdb0f410bb026ade092039a6c2655a53323c996 [34/42] powerpc: handle irq_enter/irq_exit in interrupt handler wrappers https://git.kernel.org/powerpc/c/1b1b6a6f4cc0ecc27745fa578cbaf912d76dbdda [35/42] powerpc/64s: move context tracking exit to interrupt exit path https://git.kernel.org/powerpc/c/f821bc97dee4f3ee92c3668d495af49dfd720fe0 [36/42] powerpc/64s: reconcile interrupts in C https://git.kernel.org/powerpc/c/75b96950fddab6f1c59a10160b6bf38948bdb0e3 [37/42] powerpc/64: move account_stolen_time into its own function https://git.kernel.org/powerpc/c/2994e1babfc477a3101ec6841b9dc5b770c1ec18 [38/42] powerpc/64: entry cpu time accounting in C https://git.kernel.org/powerpc/c/56acfdd8bf9f75e83a1b2957bd415368f39b67b6 [39/42] powerpc: move NMI entry/exit code into wrapper https://git.kernel.org/powerpc/c/118178e62e2e0da39b394e812fef7179c8bdb3bc [40/42] powerpc/64s: move NMI soft-mask handling to C https://git.kernel.org/powerpc/c/6ecbb582b6947f041832fff07c2f38791ae19287 [41/42] powerpc/64s: runlatch interrupt handling in C https://git.kernel.org/powerpc/c/86dbb39416493add2bdf5b7ad39a1276f2107b83
cheers