use r14 for a per-cpu kernel register
Subsystems (6)
Nicholas Piggin
reviewercover use r14 for a per-cpu kernel register
This makes r14 a fixed register and used to store per-cpu stuff in the kernel, including read-write fields that are retained over interrupts. It ends up being most useful for speeding up per-cpu pointer dereferencing and soft-irq masking and testing. But it can also reduce the number of loads and stores in the interrupt entry paths by moving several bits of interest into r14 (another bit I'm looking at is adding a bit for HSTATE_IN_GUEST to speed up kvmtest).
The series goes on top of Maddy's softi-irq patches, it works on 64s, but KVM and 64e are probably broken at the moment. So it's not intended to merge yet, but if people like the result then maybe the first patch can be merged to stop using r14 in preparation.
Nicholas Piggin (8):
powerpc/64s: stop using r14 register
powerpc/64s: poison r14 register while in kernel powerpc/64s: put the per-cpu data_offset in r14 powerpc/64s: put io_sync bit into r14
powerpc/64s: put work_pending bit into r14 powerpc/64s: put irq_soft_mask bits into r14 powerpc/64s: put irq_soft_mask and irq_happened bits into r14 powerpc/64s: inline local_irq_enable/restore
arch/powerpc/Makefile | 1 + arch/powerpc/crypto/md5-asm.S | 40 +++---- arch/powerpc/crypto/sha1-powerpc-asm.S | 10 +- arch/powerpc/include/asm/exception-64s.h | 127 +++++++++++---------- arch/powerpc/include/asm/hw_irq.h | 130 ++++++++++----------- arch/powerpc/include/asm/io.h | 11 +- arch/powerpc/include/asm/irqflags.h | 24 ++-- arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +- arch/powerpc/include/asm/kvm_ppc.h | 6 +- arch/powerpc/include/asm/paca.h | 73 +++++++++++- arch/powerpc/include/asm/percpu.h | 2 +- arch/powerpc/include/asm/ppc_asm.h | 21 +++- arch/powerpc/include/asm/spinlock.h | 21 ++-- arch/powerpc/kernel/asm-offsets.c | 23 +++- arch/powerpc/kernel/entry_32.S | 4 +- arch/powerpc/kernel/entry_64.S | 95 ++++++++++------ arch/powerpc/kernel/exceptions-64s.S | 52 ++++----- arch/powerpc/kernel/head_64.S | 25 ++-- arch/powerpc/kernel/idle_book3s.S | 86 +++++++------- arch/powerpc/kernel/irq.c | 92 ++++++--------- arch/powerpc/kernel/kgdb.c | 8 +- arch/powerpc/kernel/optprobes_head.S | 3 +- arch/powerpc/kernel/paca.c | 1 - arch/powerpc/kernel/process.c | 6 +- arch/powerpc/kernel/setup_64.c | 19 +++- arch/powerpc/kernel/time.c | 15 +-- arch/powerpc/kernel/tm.S | 40 ++++--- arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 10 +- arch/powerpc/kvm/book3s_hv.c | 6 +- arch/powerpc/kvm/book3s_hv_interrupts.S | 5 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +- arch/powerpc/kvm/book3s_interrupts.S | 93 +++++++++++---- arch/powerpc/kvm/book3s_pr.c | 6 + arch/powerpc/lib/checksum_64.S | 66 +++++------ arch/powerpc/lib/copypage_power7.S | 32 +++--- arch/powerpc/lib/copyuser_power7.S | 152 ++++++++++++------------- arch/powerpc/lib/crtsavres.S | 3 + arch/powerpc/lib/memcpy_power7.S | 80 ++++++------- arch/powerpc/lib/sstep.c | 1 + arch/powerpc/xmon/xmon.c | 7 +- 40 files changed, 764 insertions(+), 637 deletions(-)
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 1/8 powerpc/64s: stop using r14 register
--- arch/powerpc/Makefile | 1 + arch/powerpc/crypto/md5-asm.S | 40 +++---- arch/powerpc/crypto/sha1-powerpc-asm.S | 10 +- arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +- arch/powerpc/include/asm/ppc_asm.h | 21 +++- arch/powerpc/kernel/asm-offsets.c | 4 +- arch/powerpc/kernel/entry_32.S | 4 +- arch/powerpc/kernel/entry_64.S | 45 ++++---- arch/powerpc/kernel/exceptions-64s.S | 3 +- arch/powerpc/kernel/head_64.S | 8 +- arch/powerpc/kernel/idle_book3s.S | 79 +++++++------ arch/powerpc/kernel/kgdb.c | 8 +- arch/powerpc/kernel/process.c | 4 +- arch/powerpc/kernel/tm.S | 40 ++++--- arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 10 +- arch/powerpc/kvm/book3s_hv_interrupts.S | 5 +- arch/powerpc/kvm/book3s_interrupts.S | 93 +++++++++++---- arch/powerpc/kvm/book3s_pr.c | 6 + arch/powerpc/lib/checksum_64.S | 66 +++++------ arch/powerpc/lib/copypage_power7.S | 32 +++--- arch/powerpc/lib/copyuser_power7.S | 152 ++++++++++++------------- arch/powerpc/lib/crtsavres.S | 3 + arch/powerpc/lib/memcpy_power7.S | 80 ++++++------- 23 files changed, 396 insertions(+), 320 deletions(-)
arch/powerpc/Makefile +1 -0
@@ -140,6 +140,7 @@ AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv1) endif CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,$(call cc-option,-mminimal-toc)) CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions) +CFLAGS-$(CONFIG_PPC64) += -ffixed-r13 -ffixed-r14 CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 $(MULTIPLEWORD) ifeq ($(CONFIG_PPC_BOOK3S_64),y)
arch/powerpc/crypto/md5-asm.S +20 -20
@@ -25,31 +25,31 @@ #define rW02 r10 #define rW03 r11 #define rW04 r12 -#define rW05 r14 -#define rW06 r15 -#define rW07 r16 -#define rW08 r17 -#define rW09 r18 -#define rW10 r19 -#define rW11 r20 -#define rW12 r21 -#define rW13 r22 -#define rW14 r23 -#define rW15 r24 - -#define rT0 r25 -#define rT1 r26 +#define rW05 r15 +#define rW06 r16 +#define rW07 r17 +#define rW08 r18 +#define rW09 r19 +#define rW10 r20 +#define rW11 r21 +#define rW12 r22 +#define rW13 r23 +#define rW14 r24 +#define rW15 r25 + +#define rT0 r26 +#define rT1 r27 #define INITIALIZE \ PPC_STLU r1,-INT_FRAME_SIZE(r1); \ - SAVE_8GPRS(14, r1); /* push registers onto stack */ \ - SAVE_4GPRS(22, r1); \ - SAVE_GPR(26, r1) + SAVE_8GPRS(15, r1); /* push registers onto stack */ \ + SAVE_4GPRS(23, r1); \ + SAVE_GPR(27, r1) #define FINALIZE \ - REST_8GPRS(14, r1); /* pop registers from stack */ \ - REST_4GPRS(22, r1); \ - REST_GPR(26, r1); \ + REST_8GPRS(15, r1); /* pop registers from stack */ \ + REST_4GPRS(23, r1); \ + REST_GPR(27, r1); \ addi r1,r1,INT_FRAME_SIZE; #ifdef __BIG_ENDIAN__
arch/powerpc/crypto/sha1-powerpc-asm.S +4 -6
@@ -42,10 +42,10 @@ or r6,r6,r0; \ add r0,RE(t),r15; \ add RT(t),RT(t),r6; \ - add r14,r0,W(t); \ + add r6,r0,W(t); \ LWZ(W((t)+4),((t)+4)*4,r4); \ rotlwi RB(t),RB(t),30; \ - add RT(t),RT(t),r14 + add RT(t),RT(t),r6 #define STEPD0_UPDATE(t) \ and r6,RB(t),RC(t); \
@@ -124,8 +124,7 @@ _GLOBAL(powerpc_sha_transform) PPC_STLU r1,-INT_FRAME_SIZE(r1) - SAVE_8GPRS(14, r1) - SAVE_10GPRS(22, r1) + SAVE_NVGPRS(r1) /* Load up A - E */ lwz RA(0),0(r3) /* A */
@@ -183,7 +182,6 @@ _GLOBAL(powerpc_sha_transform) stw RD(0),12(r3) stw RE(0),16(r3) - REST_8GPRS(14, r1) - REST_10GPRS(22, r1) + REST_NVGPRS(r1) addi r1,r1,INT_FRAME_SIZE blr
arch/powerpc/include/asm/kvm_book3s_asm.h +1 -1
@@ -143,7 +143,7 @@ struct kvmppc_host_state {struct kvmppc_book3s_shadow_vcpu {bool in_use; -ulong gpr[14 ]; +ulong gpr[15 ];u32 cr;ulong xer;ulong ctr;
arch/powerpc/include/asm/ppc_asm.h +18 -3
@@ -10,6 +10,16 @@#include <asm/ppc-opcode.h> #include <asm/firmware.h> +#ifdef __powerpc64__ +#ifdef CONFIG_PPC_BOOK3S +#define FIRST_NVGPR 15 +#else +#define FIRST_NVGPR 14 +#endif +#else +#define FIRST_NVGPR 13 +#endif +#ifdef __ASSEMBLY__#define SZL (BITS_PER_LONG/8)
@@ -75,16 +85,21 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)#ifdef __powerpc64__#define SAVE_GPR (n, base) std n,GPR0+8*(n)(base)#define REST_GPR (n, base) ld n,GPR0+8*(n)(base) +#ifdef CONFIG_PPC_BOOK3S +#define SAVE_NVGPRS (base) SAVE_GPR(15, base); SAVE_2GPRS(16, base); SAVE_4GPRS(18, base); SAVE_10GPRS(22, base) +#define REST_NVGPRS (base) REST_GPR(15, base); REST_2GPRS(16, base); REST_4GPRS(18, base); REST_10GPRS(22, base) +#else /* CONFIG_PPC_BOOK3S */ #define SAVE_NVGPRS (base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base)#define REST_NVGPRS (base) REST_8GPRS(14, base); REST_10GPRS(22, base) -#else +#endif /* CONFIG_PPC_BOOK3S */ +#else /* __powerpc64__ */ #define SAVE_GPR (n, base) stw n,GPR0+4*(n)(base)#define REST_GPR (n, base) lwz n,GPR0+4*(n)(base)#define SAVE_NVGPRS (base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \ SAVE_10GPRS(22, base)#define REST_NVGPRS (base) REST_GPR(13, base); REST_8GPRS(14, base); \ REST_10GPRS(22, base) -#endif +#endif /* __powerpc64__ */ #define SAVE_2GPRS (n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)#define SAVE_4GPRS (n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
@@ -184,7 +199,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)#ifdef CONFIG_PPC64 #define STACKFRAMESIZE 256 -#define __STK_REG (i) (112 + ((i)-14)*8) +#define __STK_REG (i) (112 + ((i)-15)*8)#define STK_REG (i) __STK_REG(__REG_##i)#ifdef PPC64_ELF_ABI_v2
arch/powerpc/kernel/asm-offsets.c +2 -2
@@ -283,9 +283,9 @@ int main(void)STACK_PT_REGS_OFFSET (GPR11 , gpr[11 ]);STACK_PT_REGS_OFFSET (GPR12 , gpr[12 ]);STACK_PT_REGS_OFFSET (GPR13 , gpr[13 ]); -#ifndef CONFIG_PPC64 +#ifndef CONFIG_PPC_BOOK3E_64 STACK_PT_REGS_OFFSET (GPR14 , gpr[14 ]); -#endif /* CONFIG_PPC64 */ +#endif /* * Note: these symbols include _ because they overlap with special * register names
arch/powerpc/kernel/entry_32.S +2 -2
@@ -458,8 +458,8 @@ ret_from_fork: ret_from_kernel_thread: REST_NVGPRS(r1) bl schedule_tail - mtlr r14 - mr r3,r15 + mtlr FIRST_NVGPR + mr r3,FIRST_NVGPR+1 PPC440EP_ERR42 blrl li r3,0
arch/powerpc/kernel/entry_64.S +25 -20
100 lines not on this page · raw message
arch/powerpc/kernel/exceptions-64s.S +1 -2
@@ -1656,8 +1656,7 @@ BEGIN_FTR_SECTION ld r10,EX_CFAR(r3) std r10,ORIG_GPR3(r1) END_FTR_SECTION_IFSET(CPU_FTR_CFAR) - SAVE_8GPRS(14,r1) - SAVE_10GPRS(22,r1) + SAVE_NVGPRS(r1) lhz r12,PACA_TRAP_SAVE(r13) std r12,_TRAP(r1) addi r11,r1,INT_FRAME_SIZE
arch/powerpc/kernel/head_64.S +4 -4
@@ -802,9 +802,9 @@ __secondary_start: /* Initialize the kernel stack */ LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ - ldx r14,r3,r28 - addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD - std r14,PACAKSAVE(r13) + ldx r15,r3,r28 + addi r15,r15,THREAD_SIZE-STACK_FRAME_OVERHEAD + std r15,PACAKSAVE(r13) /* Do early setup for that CPU (SLB and hash table pointer) */ bl early_setup_secondary
@@ -813,7 +813,7 @@ __secondary_start: * setup the new stack pointer, but *don't* use this until * translation is on. */ - mr r1, r14 + mr r1, r15 /* Clear backchain so we get nice backtraces */ li r7,0
arch/powerpc/kernel/idle_book3s.S +39 -40
184 lines not on this page · raw message
arch/powerpc/kernel/kgdb.c +4 -4
@@ -230,11 +230,11 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)for (reg =0 ; reg <3 ; reg++)PACK64 (ptr, regs->gpr[reg]); -/* Regs GPR3-13 are caller saved, not in regs->gpr[] */ - ptr +=11 ; +/* Regs GPR3-13/14 are caller saved, not in regs->gpr[] */ + ptr +=FIRST_NVGPR -2 ; -/* Regs GPR14-31 */ -for (reg =14 ; reg <32 ; reg++) +/* Regs GPR14/15-31 */ +for (reg =FIRST_NVGPR ; reg <32 ; reg++)PACK64 (ptr, regs->gpr[reg]);#ifdef CONFIG_FSL_BOOKE
arch/powerpc/kernel/process.c +2 -2
@@ -1672,12 +1672,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->gpr[1 ] = sp +sizeof (struct pt_regs );/* function */ if (usp) - childregs->gpr[14 ] =ppc_function_entry ((void *)usp); + childregs->gpr[FIRST_NVGPR ] =ppc_function_entry ((void *)usp);#ifdef CONFIG_PPC64 clear_tsk_thread_flag (p,TIF_32BIT ); childregs->softe =IRQ_SOFT_MASK_NONE ;#endif - childregs->gpr[15 ] = kthread_arg; + childregs->gpr[FIRST_NVGPR +1 ] = kthread_arg; p->thread.regs =NULL ;/* no user register state */ ti->flags |= _TIF_RESTOREALL; f = ret_from_kernel_thread;
arch/powerpc/kernel/tm.S +23 -17
@@ -106,27 +106,28 @@ _GLOBAL(tm_reclaim) /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ std r3, STK_PARAM(R3)(r1) + SAVE_GPR(14, r1) SAVE_NVGPRS(r1) /* We need to setup MSR for VSX register save instructions. */ - mfmsr r14 - mr r15, r14 - ori r15, r15, MSR_FP - li r16, 0 - ori r16, r16, MSR_EE /* IRQs hard off */ - andc r15, r15, r16 - oris r15, r15, MSR_VEC@h + mfmsr r15 + mr r16, r15 + ori r16, r16, MSR_FP + li r17, 0 + ori r17, r17, MSR_EE /* IRQs hard off */ + andc r16, r16, r17 + oris r16, r16, MSR_VEC@h #ifdef CONFIG_VSX BEGIN_FTR_SECTION - oris r15,r15, MSR_VSX@h + oris r16,r16, MSR_VSX@h END_FTR_SECTION_IFSET(CPU_FTR_VSX) #endif - mtmsrd r15 - std r14, TM_FRAME_L0(r1) + mtmsrd r16 + std r15, TM_FRAME_L0(r1) /* Do sanity check on MSR to make sure we are suspended */ li r7, (MSR_TS_S)@higher - srdi r6, r14, 32 + srdi r6, r15, 32 and r6, r6, r7 1: tdeqi r6, 0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
@@ -205,7 +206,8 @@ _GLOBAL(tm_reclaim) std r6, GPR12(r7) std r8, GPR13(r7) - SAVE_NVGPRS(r7) /* user r14-r31 */ + SAVE_GPR(14, r7) /* user r14 */ + SAVE_NVGPRS(r7) /* user r15-r31 */ /* ******************** NIP ******************** */ mfspr r3, SPRN_TFHAR
@@ -278,12 +280,13 @@ _GLOBAL(tm_reclaim) /* AMR is checkpointed too, but is unsupported by Linux. */ /* Restore original MSR/IRQ state & clear TM mode */ - ld r14, TM_FRAME_L0(r1) /* Orig MSR */ + ld r15, TM_FRAME_L0(r1) /* Orig MSR */ - li r15, 0 - rldimi r14, r15, MSR_TS_LG, (63-MSR_TS_LG)-1 - mtmsrd r14 + li r16, 0 + rldimi r15, r16, MSR_TS_LG, (63-MSR_TS_LG)-1 + mtmsrd r15 + REST_GPR(14, r1) REST_NVGPRS(r1) addi r1, r1, TM_FRAME_SIZE
@@ -319,6 +322,7 @@ _GLOBAL(__tm_recheckpoint) /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. * This is used for backing up the NVGPRs: */ + SAVE_GPR(14, r1) SAVE_NVGPRS(r1) /* Load complete register state from ts_ckpt* registers */
@@ -391,8 +395,9 @@ restore_gprs: REST_GPR(4, r7) /* GPR4 */ REST_4GPRS(8, r7) /* GPR8-11 */ REST_2GPRS(12, r7) /* GPR12-13 */ + REST_GPR(14, r7) /* GPR14 */ - REST_NVGPRS(r7) /* GPR14-31 */ + REST_NVGPRS(r7) /* GPR15-31 */ /* Load up PPR and DSCR here so we don't run with user values for long */
@@ -471,6 +476,7 @@ restore_gprs: li r4, MSR_RI mtmsrd r4, 1 + REST_GPR(14, r1) REST_NVGPRS(r1) addi r1, r1, TM_FRAME_SIZE
arch/powerpc/kernel/trace/ftrace_64_mprofile.S +5 -5
@@ -76,7 +76,7 @@ _GLOBAL(ftrace_caller) ld r5,0(r3) #ifdef CONFIG_LIVEPATCH - mr r14,r7 /* remember old NIP */ + mr r15,r7 /* remember old NIP */ #endif /* Calculate ip from nip-4 into r3 for call below */ subi r3, r7, MCOUNT_INSN_SIZE
@@ -100,10 +100,10 @@ ftrace_call: nop /* Load the possibly modified NIP */ - ld r15, _NIP(r1) + ld r16, _NIP(r1) #ifdef CONFIG_LIVEPATCH - cmpd r14, r15 /* has NIP been altered? */ + cmpd r15, r16 /* has NIP been altered? */ #endif #if defined(CONFIG_LIVEPATCH) && defined(CONFIG_KPROBES_ON_FTRACE)
@@ -111,7 +111,7 @@ ftrace_call: beq 1f /* Check if there is an active jprobe on us */ - subi r3, r14, 4 + subi r3, r15, 4 bl __is_active_jprobe nop
@@ -130,7 +130,7 @@ ftrace_call: #endif /* Load CTR with the possibly modified NIP */ - mtctr r15 + mtctr r16 /* Restore gprs */ REST_GPR(0,r1)
arch/powerpc/kvm/book3s_hv_interrupts.S +3 -2
@@ -46,7 +46,7 @@ _GLOBAL(__kvmppc_vcore_entry) /* Save host state to the stack */ stdu r1, -SWITCH_FRAME_SIZE(r1) - /* Save non-volatile registers (r14 - r31) and CR */ + /* Save non-volatile registers (r15 - r31) and CR */ SAVE_NVGPRS(r1) mfcr r3 std r3, _CCR(r1)
@@ -149,9 +149,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) * R3 = trap number on this thread * R12 = exit handler id * R13 = PACA + * R14 = ? XXX */ - /* Restore non-volatile host registers (r14 - r31) and CR */ + /* Restore non-volatile host registers (r15 - r31) and CR */ REST_NVGPRS(r1) ld r4, _CCR(r1) mtcr r4
arch/powerpc/kvm/book3s_interrupts.S +68 -25
127 lines not on this page · raw message
arch/powerpc/kvm/book3s_pr.c +6 -0
@@ -159,6 +159,9 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, svcpu->gpr[11 ] = vcpu->arch.gpr[11 ]; svcpu->gpr[12 ] = vcpu->arch.gpr[12 ]; svcpu->gpr[13 ] = vcpu->arch.gpr[13 ]; +#ifdef CONFIG_PPC_BOOK3S_64 + svcpu->gpr[14 ] = vcpu->arch.gpr[14 ]; +#endif svcpu->cr = vcpu->arch.cr; svcpu->xer = vcpu->arch.xer; svcpu->ctr = vcpu->arch.ctr;
@@ -209,6 +212,9 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, vcpu->arch.gpr[11 ] = svcpu->gpr[11 ]; vcpu->arch.gpr[12 ] = svcpu->gpr[12 ]; vcpu->arch.gpr[13 ] = svcpu->gpr[13 ]; +#ifdef CONFIG_PPC_BOOK3S_64 + vcpu->arch.gpr[14 ] = svcpu->gpr[14 ]; +#endif vcpu->arch.cr = svcpu->cr; vcpu->arch.xer = svcpu->xer; vcpu->arch.ctr = svcpu->ctr;
arch/powerpc/lib/checksum_64.S +33 -33
175 lines not on this page · raw message
arch/powerpc/lib/copypage_power7.S +16 -16
@@ -113,13 +113,13 @@ _GLOBAL(copypage_power7) #endif .Lnonvmx_copy: - std r14,STK_REG(R14)(r1) std r15,STK_REG(R15)(r1) std r16,STK_REG(R16)(r1) std r17,STK_REG(R17)(r1) std r18,STK_REG(R18)(r1) std r19,STK_REG(R19)(r1) std r20,STK_REG(R20)(r1) + std r21,STK_REG(R21)(r1) 1: ld r0,0(r4) ld r5,8(r4)
@@ -130,13 +130,13 @@ _GLOBAL(copypage_power7) ld r10,48(r4) ld r11,56(r4) ld r12,64(r4) - ld r14,72(r4) - ld r15,80(r4) - ld r16,88(r4) - ld r17,96(r4) - ld r18,104(r4) - ld r19,112(r4) - ld r20,120(r4) + ld r15,72(r4) + ld r16,80(r4) + ld r17,88(r4) + ld r18,96(r4) + ld r19,104(r4) + ld r20,112(r4) + ld r21,120(r4) addi r4,r4,128 std r0,0(r3) std r5,8(r3)
@@ -147,22 +147,22 @@ _GLOBAL(copypage_power7) std r10,48(r3) std r11,56(r3) std r12,64(r3) - std r14,72(r3) - std r15,80(r3) - std r16,88(r3) - std r17,96(r3) - std r18,104(r3) - std r19,112(r3) - std r20,120(r3) + std r15,72(r3) + std r16,80(r3) + std r17,88(r3) + std r18,96(r3) + std r19,104(r3) + std r20,112(r3) + std r21,120(r3) addi r3,r3,128 bdnz 1b - ld r14,STK_REG(R14)(r1) ld r15,STK_REG(R15)(r1) ld r16,STK_REG(R16)(r1) ld r17,STK_REG(R17)(r1) ld r18,STK_REG(R18)(r1) ld r19,STK_REG(R19)(r1) ld r20,STK_REG(R20)(r1) + ld r21,STK_REG(R21)(r1) addi r1,r1,STACKFRAMESIZE blr
arch/powerpc/lib/copyuser_power7.S +76 -76
235 lines not on this page · raw message
arch/powerpc/lib/crtsavres.S +3 -0
@@ -314,9 +314,12 @@ _GLOBAL(_restvr_31) #else /* CONFIG_PPC64 */ +/* 64-bit has -ffixed-r13, Book3S also has -ffixed-r14 */ +#ifdef CONFIG_PPC_BOOK3E .globl _savegpr0_14 _savegpr0_14: std r14,-144(r1) +#endif .globl _savegpr0_15 _savegpr0_15: std r15,-136(r1)
arch/powerpc/lib/memcpy_power7.S +40 -40
171 lines not on this page · raw message
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 2/8 powerpc/64s: poison r14 register while in kernel
In reply to Nicholas PigginPoison r14 register with the PIR SPR, an a magic number. This means it must be treated like r13, saving and restoring the register on kernel entry/exit, but not restoring it when returning back to kernel
However r14 will not be a constant like r13, but may be modified by the kernel, which means it must not be loaded on exception entry if the exception is coming from the kernel.
This requires loading SRR1 earlier, before the exception mask/kvm test. That's okay because SRR1 almost always gets loaded anyway.
--- arch/powerpc/include/asm/exception-64s.h | 121 ++++++++++++++++--------------- arch/powerpc/include/asm/paca.h | 5 +- arch/powerpc/kernel/asm-offsets.c | 3 +- arch/powerpc/kernel/entry_64.S | 23 ++++++ arch/powerpc/kernel/exceptions-64s.S | 45 ++++++------ arch/powerpc/kernel/head_64.S | 5 ++ arch/powerpc/kernel/idle_book3s.S | 4 + arch/powerpc/kernel/paca.c | 1 - arch/powerpc/kernel/setup_64.c | 3 + arch/powerpc/lib/sstep.c | 1 + 10 files changed, 128 insertions(+), 83 deletions(-)
arch/powerpc/include/asm/exception-64s.h +63 -58
@@ -42,16 +42,18 @@#define EX_R11 16#define EX_R12 24#define EX_R13 32 -#define EX_DAR 40 -#define EX_DSISR 48 -#define EX_CCR 52 -#define EX_CFAR 56 -#define EX_PPR 64 +#define EX_R14 40 +#define EX_DAR 48 +#define EX_DSISR 56 +#define EX_CCR 60 +#define EX_CFAR 64 +#define EX_PPR 72 +#if defined(CONFIG_RELOCATABLE ) -#define EX_CTR 72 -#define EX_SIZE 10/* size in u64 units */ +#define EX_CTR 80 +#define EX_SIZE 11/* size in u64 units */ #else -#define EX_SIZE 9/* size in u64 units */ +#define EX_SIZE 10/* size in u64 units */ #endif /*
@@ -77,9 +79,8 @@#ifdef CONFIG_RELOCATABLE #define __EXCEPTION_RELON_PROLOG_PSERIES_1 (label, h) \ mfspr r11,SPRN_##h##SRR0;/* save SRR0 */ \ -LOAD_HANDLER (r12,label); \ -mtctr r12; \ - mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ +LOAD_HANDLER (r10,label); \ +mtctr r10; \li r10,MSR_RI ; \ mtmsrd r10,1; /* Set RI (EE=0) */ \ bctr;
@@ -87,7 +88,6 @@/* If not relocatable, we can jump directly -- and save messing with LR */ #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ - mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ li r10,MSR_RI; \ mtmsrd r10,1;/* Set RI (EE=0) */ \b label;
@@ -102,7 +102,7 @@*/ #define EXCEPTION_RELON_PROLOG_PSERIES (area, label, h, extra, vec) \ EXCEPTION_PROLOG_0(area); \ - EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_1(area, h, extra, vec); \ EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)/*
@@ -198,17 +198,21 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) std r10,area+EX_R10(r13); /* save r10 - r12 */ \ OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR) -#define __EXCEPTION_PROLOG_1_PRE (area) \ +#define __EXCEPTION_PROLOG_1 (area, h) \ + std r11,area+EX_R11(r13); \ + std r12,area+EX_R12(r13); \ + mfspr r12,SPRN_##h##SRR1;/* and SRR1 */ \ +GET_SCRATCH0 (r11); \OPT_SAVE_REG_TO_PACA (area+EX_PPR , r9,CPU_FTR_HAS_PPR ); \OPT_SAVE_REG_TO_PACA (area+EX_CFAR , r10,CPU_FTR_CFAR ); \SAVE_CTR (r10, area); \ - mfcr r9; - -#define __EXCEPTION_PROLOG_1_POST (area) \ - std r11,area+EX_R11(r13); \ - std r12,area+EX_R12(r13); \ - GET_SCRATCH0(r10); \ - std r10,area+EX_R13(r13) +mfcr r9; \ + std r11,area+EX_R13(r13); \ + std r14,area+EX_R14(r13); \ + andi. r10,r12,MSR_PR ; \ + beq 1f; \ +ld r14,PACA_R14 (r13 ); \ +1:/* * This version of the EXCEPTION_PROLOG_1 will carry
@@ -216,30 +220,27 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)* checking of the interrupt maskable level in the SOFTEN_TEST. * Intended to be used in MASKABLE_EXCPETION_* macros. */ -#define MASKABLE_EXCEPTION_PROLOG_1 (area, extra, vec, bitmask) \ - __EXCEPTION_PROLOG_1_PRE(area); \ - extra(vec, bitmask); \ - __EXCEPTION_PROLOG_1_POST(area); +#define MASKABLE_EXCEPTION_PROLOG_1 (area, h, extra, vec, bitmask) \ + __EXCEPTION_PROLOG_1(area, h); \ + extra(vec, bitmask);/* * This version of the EXCEPTION_PROLOG_1 is intended * to be used in STD_EXCEPTION* macros */ -#define _EXCEPTION_PROLOG_1 (area, extra, vec) \ - __EXCEPTION_PROLOG_1_PRE(area); \ - extra(vec); \ - __EXCEPTION_PROLOG_1_POST(area); +#define _EXCEPTION_PROLOG_1 (area, h, extra, vec) \ + __EXCEPTION_PROLOG_1(area, h); \ + extra(vec); -#define EXCEPTION_PROLOG_1 (area, extra, vec) \ - _EXCEPTION_PROLOG_1(area, extra, vec) +#define EXCEPTION_PROLOG_1 (area, h, extra, vec) \ + _EXCEPTION_PROLOG_1(area, h, extra, vec)#define __EXCEPTION_PROLOG_PSERIES_1 (label, h) \ - ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ mfspr r11,SPRN_##h##SRR0;/* save SRR0 */ \ - LOAD_HANDLER(r12,label) \ - mtspr SPRN_##h##SRR0,r12; \ - mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ +ld r10,PACAKMSR (r13 );/* get MSR value for kernel */ \ mtspr SPRN_##h##SRR1,r10; \ + LOAD_HANDLER(r10,label) \ + mtspr SPRN_##h##SRR0,r10; \ h##rfid; \ b ./* prevent speculative execution */ #define EXCEPTION_PROLOG_PSERIES_1 (label, h) \
@@ -247,13 +248,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)/* _NORI variant keeps MSR_RI clear */ #define __EXCEPTION_PROLOG_PSERIES_1_NORI (label, h) \ + mfspr r11,SPRN_##h##SRR0;/* save SRR0 */ \ld r10,PACAKMSR (r13 );/* get MSR value for kernel */ \xori r10,r10,MSR_RI ;/* Clear MSR_RI */ \ - mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ - LOAD_HANDLER(r12,label) \ - mtspr SPRN_##h##SRR0,r12; \ - mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ mtspr SPRN_##h##SRR1,r10; \ + LOAD_HANDLER(r10,label) \ + mtspr SPRN_##h##SRR0,r10; \ h##rfid; \ b ./* prevent speculative execution */
@@ -262,7 +262,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)#define EXCEPTION_PROLOG_PSERIES (area, label, h, extra, vec) \ EXCEPTION_PROLOG_0(area); \ - EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_1(area, h, extra, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, h);#define __KVMTEST (h, n) \
@@ -336,7 +336,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)/* Do not enable RI */ #define EXCEPTION_PROLOG_PSERIES_NORI (area, label, h, extra, vec) \ EXCEPTION_PROLOG_0(area); \ - EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_1(area, h, extra, vec); \ EXCEPTION_PROLOG_PSERIES_1_NORI(label, h);
@@ -349,8 +349,9 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) ld r10,area+EX_PPR(r13); \std r10,HSTATE_PPR (r13 ); \END_FTR_SECTION_NESTED (CPU_FTR_HAS_PPR ,CPU_FTR_HAS_PPR ,948 ); \ + ld r10,area+EX_R12(r13); \ +std r10,HSTATE_SCRATCH0 (r13 ); \ ld r10,area+EX_R10(r13); \ -std r12,HSTATE_SCRATCH0 (r13 ); \ sldi r12,r9,32; \ori r12,r12,(n); \/* This reloads r9 before branching to kvmppc_interrupt */ \
@@ -363,8 +364,9 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) ld r10,area+EX_PPR(r13); \std r10,HSTATE_PPR (r13 ); \END_FTR_SECTION_NESTED (CPU_FTR_HAS_PPR ,CPU_FTR_HAS_PPR ,948 ); \ + ld r10,area+EX_R12(r13); \ +std r10,HSTATE_SCRATCH0 (r13 ); \ ld r10,area+EX_R10(r13); \ -std r12,HSTATE_SCRATCH0 (r13 ); \ sldi r12,r9,32; \ori r12,r12,(n); \/* This reloads r9 before branching to kvmppc_interrupt */ \
@@ -372,6 +374,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) 89: mtocrf 0x80,r9; \ ld r9,area+EX_R9(r13); \ ld r10,area+EX_R10(r13); \ + ld r12,area+EX_R12(r13); \ b kvmppc_skip_##h##interrupt#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
@@ -393,7 +396,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)std r12,_MSR (r1 );/* save SRR1 in stackframe */ \ std r10,0(r1); /* make stack chain pointer */ \std r0,GPR0 (r1 );/* save r0 in stackframe */ \ -std r10,GPR1 (r1 );/* save r1 in stackframe */ \ +std r10,GPR1 (r1 )/* save r1 in stackframe */ /*
@@ -430,16 +433,18 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)/* Save original regs values from save area to stack frame. */ #define EXCEPTION_PROLOG_COMMON_2(area) \ - ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ + ld r9,area+EX_R9(r13); /* move r9-r14 to stackframe */ \ ld r10,area+EX_R10(r13); \ std r9,GPR9(r1); \ std r10,GPR10(r1); \ - ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ + ld r9,area+EX_R11(r13); \ ld r10,area+EX_R12(r13); \ - ld r11,area+EX_R13(r13); \ std r9,GPR11(r1); \ std r10,GPR12(r1); \ - std r11,GPR13(r1); \ + ld r9,area+EX_R13(r13); \ + ld r10,area+EX_R14(r13); \ + std r9,GPR13(r1); \ + std r10,GPR14(r1); \ BEGIN_FTR_SECTION_NESTED(66); \ ld r10,area+EX_CFAR(r13); \ std r10,ORIG_GPR3(r1); \
@@ -480,7 +485,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)b hdlr;#define STD_EXCEPTION_PSERIES_OOL (vec, label) \ - EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ + EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD, KVMTEST_PR, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, EXC_STD)#define STD_EXCEPTION_HV (loc, vec, label) \
@@ -489,7 +494,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_HV, KVMTEST_HV, vec);#define STD_EXCEPTION_HV_OOL (vec, label) \ - EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec); \ + EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_HV, KVMTEST_HV, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, EXC_HV)#define STD_RELON_EXCEPTION_PSERIES (loc, vec, label) \
@@ -498,7 +503,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)EXCEPTION_RELON_PROLOG_PSERIES (PACA_EXGEN , label,EXC_STD ,NOTEST , vec);#define STD_RELON_EXCEPTION_PSERIES_OOL (vec, label) \ - EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec); \ + EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD, NOTEST, vec); \ EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_STD)#define STD_RELON_EXCEPTION_HV (loc, vec, label) \
@@ -507,7 +512,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_HV, KVMTEST_HV, vec);#define STD_RELON_EXCEPTION_HV_OOL (vec, label) \ - EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec); \ + EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_HV, KVMTEST_HV, vec); \ EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)/* This associate vector numbers with bits in paca->irq_happened */
@@ -548,7 +553,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)#define __MASKABLE_EXCEPTION_PSERIES (vec, label, h, extra, bitmask) \ SET_SCRATCH0(r13);/* save r13 */ \EXCEPTION_PROLOG_0 (PACA_EXGEN ); \ -MASKABLE_EXCEPTION_PROLOG_1 (PACA_EXGEN , extra, vec, bitmask); \ +MASKABLE_EXCEPTION_PROLOG_1 (PACA_EXGEN , h, extra, vec, bitmask);\EXCEPTION_PROLOG_PSERIES_1 (label, h);#define _MASKABLE_EXCEPTION_PSERIES (vec, label, h, extra, bitmask) \
@@ -559,7 +564,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_STD, SOFTEN_TEST_PR, bitmask)#define MASKABLE_EXCEPTION_PSERIES_OOL (vec, label, bitmask) \ - MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_PR, vec, bitmask);\ + MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD, SOFTEN_TEST_PR, vec, bitmask);\ EXCEPTION_PROLOG_PSERIES_1(label, EXC_STD)#define MASKABLE_EXCEPTION_HV (loc, vec, label, bitmask) \
@@ -567,13 +572,13 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_HV, SOFTEN_TEST_HV, bitmask)#define MASKABLE_EXCEPTION_HV_OOL (vec, label, bitmask) \ - MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec, bitmask);\ + MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_HV, SOFTEN_TEST_HV, vec, bitmask);\ EXCEPTION_PROLOG_PSERIES_1(label, EXC_HV)#define __MASKABLE_RELON_EXCEPTION_PSERIES (vec, label, h, extra, bitmask) \ SET_SCRATCH0(r13);/* save r13 */ \EXCEPTION_PROLOG_0 (PACA_EXGEN ); \ -MASKABLE_EXCEPTION_PROLOG_1 (PACA_EXGEN , extra, vec, bitmask); \ +MASKABLE_EXCEPTION_PROLOG_1 (PACA_EXGEN , h, extra, vec, bitmask);\ EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)#define _MASKABLE_RELON_EXCEPTION_PSERIES (vec, label, h, extra, bitmask)\
@@ -584,7 +589,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_STD, SOFTEN_NOTEST_PR, bitmask)#define MASKABLE_RELON_EXCEPTION_PSERIES_OOL (vec, label, bitmask) \ - MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_PR, vec, bitmask);\ + MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_STD, SOFTEN_NOTEST_PR, vec, bitmask);\ EXCEPTION_PROLOG_PSERIES_1(label, EXC_STD);#define MASKABLE_RELON_EXCEPTION_HV (loc, vec, label, bitmask) \
@@ -592,7 +597,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) EXC_HV, SOFTEN_TEST_HV, bitmask)#define MASKABLE_RELON_EXCEPTION_HV_OOL (vec, label, bitmask) \ - MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec, bitmask);\ + MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, EXC_HV, SOFTEN_NOTEST_HV, vec, bitmask);\ EXCEPTION_RELON_PROLOG_PSERIES_1(label, EXC_HV)/*
arch/powerpc/include/asm/paca.h +4 -1
@@ -34,6 +34,9 @@#include <asm/cpuidle.h> registerstruct paca_struct *local_paca asm("r13" ); +#ifdef CONFIG_PPC_BOOK3S +registeru64 local_r14 asm("r14" ); +#endif #if defined(CONFIG_DEBUG_PREEMPT ) && defined(CONFIG_SMP )extern unsigned int debug_smp_processor_id (void );/* from linux/smp.h */
@@ -65,7 +68,6 @@ struct paca_struct {* read-only (after boot) fields in the first cacheline to * avoid cacheline bouncing. */ -struct lppaca *lppaca_ptr;/* Pointer to LpPaca for PLIC */ #endif /* CONFIG_PPC_BOOK3S */ /*
@@ -104,6 +106,7 @@ struct paca_struct {*/ /* used for most interrupts/exceptions */ u64 exgen[EX_SIZE] __attribute__((aligned(0x80))); +u64 r14;u64 exslb[EX_SIZE ];/* used for SLB/segment table misses * on the linear mapping */ /* SLB related definitions */
arch/powerpc/kernel/asm-offsets.c +2 -1
@@ -218,8 +218,9 @@ int main(void)OFFSET (PACACONTEXTSLLP , paca_struct, mm_ctx_sllp);#endif /* CONFIG_PPC_MM_SLICES */ OFFSET (PACA_EXGEN , paca_struct, exgen); -OFFSET (PACA_EXMC , paca_struct, exmc); +OFFSET (PACA_R14 , paca_struct, r14);OFFSET (PACA_EXSLB , paca_struct, exslb); +OFFSET (PACA_EXMC , paca_struct, exmc);OFFSET (PACA_EXNMI , paca_struct, exnmi);OFFSET (PACALPPACAPTR , paca_struct, lppaca_ptr);OFFSET (PACA_SLBSHADOWPTR , paca_struct, slb_shadow_ptr);
arch/powerpc/kernel/entry_64.S +23 -0
@@ -37,6 +37,11 @@ #include <asm/tm.h> #include <asm/ppc-opcode.h> #include <asm/export.h> +#ifdef CONFIG_PPC_BOOK3S +#include <asm/exception-64s.h> +#else +#include <asm/exception-64e.h> +#endif /* * System calls.
@@ -65,11 +70,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) addi r1,r1,-INT_FRAME_SIZE beq- 1f ld r1,PACAKSAVE(r13) +#ifdef CONFIG_PPC_BOOK3S + ld r14,PACA_R14(r13) +#endif 1: std r10,0(r1) std r11,_NIP(r1) std r12,_MSR(r1) std r0,GPR0(r1) std r10,GPR1(r1) +#ifdef CONFIG_PPC_BOOK3S + ld r10,PACA_EXGEN+EX_R14(r13) + std r10,GPR14(r1) +#endif beq 2f /* if from kernel mode */ ACCOUNT_CPU_USER_ENTRY(r13, r10, r11) 2: std r2,GPR2(r1)
@@ -250,6 +262,11 @@ system_call_exit: BEGIN_FTR_SECTION stdcx. r0,0,r1 /* to clear the reservation */ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) + LOAD_REG_IMMEDIATE(r10, 0xdeadbeefULL << 32) + mfspr r11,SPRN_PIR + or r10,r10,r11 + tdne r10,r14 + andi. r6,r8,MSR_PR ld r4,_LINK(r1)
@@ -261,6 +278,9 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ +#ifdef CONFIG_PPC_BOOK3S + ld r14,GPR14(r1) /* only restore r14 if returning to usermode */ +#endif 1: ld r2,GPR2(r1) ld r1,GPR1(r1) mtlr r4
@@ -874,6 +894,9 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) ACCOUNT_CPU_USER_EXIT(r13, r2, r4) REST_GPR(13, r1) +#ifdef CONFIG_PPC_BOOK3S + REST_GPR(14, r1) +#endif 1: mtspr SPRN_SRR1,r3
arch/powerpc/kernel/exceptions-64s.S +23 -22
175 lines not on this page · raw message
arch/powerpc/kernel/head_64.S +5 -0
@@ -413,6 +413,11 @@ generic_secondary_common_init: b kexec_wait /* next kernel might do better */ 2: SET_PACA(r13) + LOAD_REG_IMMEDIATE(r14, 0xdeadbeef << 32) + mfspr r3,SPRN_PIR + or r14,r14,r3 + std r14,PACA_R14(r13) + #ifdef CONFIG_PPC_BOOK3E addi r12,r13,PACA_EXTLB /* and TLB exc frame in another */ mtspr SPRN_SPRG_TLB_EXFRAME,r12
arch/powerpc/kernel/idle_book3s.S +4 -0
@@ -195,6 +195,7 @@ pnv_powersave_common: /* Continue saving state */ SAVE_GPR(2, r1) + SAVE_GPR(14, r1) /* XXX: check if we need to save/restore or can rely on PACA_R14 reload */ SAVE_NVGPRS(r1) mfcr r5 std r5,_CCR(r1)
@@ -464,6 +465,7 @@ power9_dd1_recover_paca: /* Load paca->thread_sibling_pacas[i] into r13 */ ldx r13, r4, r5 SET_PACA(r13) + /* R14 will be restored */ /* * Indicate that we have lost NVGPR state * which needs to be restored from the stack.
@@ -926,6 +928,7 @@ fastsleep_workaround_at_exit: .global pnv_wakeup_loss pnv_wakeup_loss: ld r1,PACAR1(r13) + REST_GPR(14, r1) BEGIN_FTR_SECTION CHECK_HMI_INTERRUPT END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
@@ -950,6 +953,7 @@ pnv_wakeup_noloss: cmpwi r0,0 bne pnv_wakeup_loss ld r1,PACAR1(r13) + REST_GPR(14, r1) BEGIN_FTR_SECTION CHECK_HMI_INTERRUPT END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
arch/powerpc/kernel/paca.c +0 -1
@@ -198,7 +198,6 @@ void setup_paca(struct paca_struct *new_paca)mtspr (SPRN_SPRG_HPACA , local_paca);#endif mtspr (SPRN_SPRG_PACA , local_paca); - }static int __initdata paca_size;
arch/powerpc/kernel/setup_64.c +3 -0
@@ -192,6 +192,9 @@ static void __init fixup_boot_paca(void)get_paca ()->data_offset =0 ;/* Mark interrupts disabled in PACA */ irq_soft_mask_set (IRQ_SOFT_MASK_STD ); +/* Set r14 and paca_r14 to debug value */ +get_paca ()->r14 = (0xdeadbeefULL <<32 ) |mfspr (SPRN_PIR ); + local_r14 =get_paca ()->r14; }static void __init configure_exceptions (void )
arch/powerpc/lib/sstep.c +1 -0
@@ -3073,6 +3073,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr) regs->gpr[11 ] = regs->nip +4 ; regs->gpr[12 ] = regs->msr &MSR_MASK ; regs->gpr[13 ] = (unsigned long )get_paca (); + regs->gpr[14 ] = local_r14; regs->nip = (unsigned long ) &system_call_common; regs->msr =MSR_KERNEL ;return 1 ;
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 3/8 powerpc/64s: put the per-cpu data_offset in r14
In reply to Nicholas PigginShifted left by 16 bits, so the low 16 bits of r14 remain available. This allows per-cpu pointers to be dereferenced with a single extra shift whereas previously it was a load and add.
--- arch/powerpc/include/asm/paca.h | 5 +++++ arch/powerpc/include/asm/percpu.h | 2 +- arch/powerpc/kernel/entry_64.S | 5 ----- arch/powerpc/kernel/head_64.S | 5 +---- arch/powerpc/kernel/setup_64.c | 11 +++++++++-- 5 files changed, 16 insertions(+), 12 deletions(-)
arch/powerpc/include/asm/paca.h +5 -0
@@ -35,6 +35,11 @@ registerstruct paca_struct *local_paca asm("r13" );#ifdef CONFIG_PPC_BOOK3S +/* +* The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT. +* The per-cpu could be moved completely to vmalloc space if we had large +* vmalloc page mapping? (no, must access it in real mode). +*/ registeru64 local_r14 asm("r14" );#endif
arch/powerpc/include/asm/percpu.h +1 -1
@@ -12,7 +12,7 @@#include <asm/paca.h> -#define __my_cpu_offset local_paca->data_offset +#define __my_cpu_offset (local_r14 >> 16)#endif /* CONFIG_SMP */ #endif /* __powerpc64__ */
arch/powerpc/kernel/entry_64.S +0 -5
@@ -262,11 +262,6 @@ system_call_exit: BEGIN_FTR_SECTION stdcx. r0,0,r1 /* to clear the reservation */ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) - LOAD_REG_IMMEDIATE(r10, 0xdeadbeefULL << 32) - mfspr r11,SPRN_PIR - or r10,r10,r11 - tdne r10,r14 - andi. r6,r8,MSR_PR ld r4,_LINK(r1)
arch/powerpc/kernel/head_64.S +1 -4
@@ -413,10 +413,7 @@ generic_secondary_common_init: b kexec_wait /* next kernel might do better */ 2: SET_PACA(r13) - LOAD_REG_IMMEDIATE(r14, 0xdeadbeef << 32) - mfspr r3,SPRN_PIR - or r14,r14,r3 - std r14,PACA_R14(r13) + ld r14,PACA_R14(r13) #ifdef CONFIG_PPC_BOOK3E addi r12,r13,PACA_EXTLB /* and TLB exc frame in another */
arch/powerpc/kernel/setup_64.c +9 -2
@@ -192,8 +192,8 @@ static void __init fixup_boot_paca(void)get_paca ()->data_offset =0 ;/* Mark interrupts disabled in PACA */ irq_soft_mask_set (IRQ_SOFT_MASK_STD ); -/* Set r14 and paca_r14 to debug value */ -get_paca ()->r14 = (0xdeadbeefULL <<32 ) |mfspr (SPRN_PIR ); +/* Set r14 and paca_r14 to zero */ +get_paca ()->r14 =0 ; local_r14 =get_paca ()->r14; }
@@ -761,7 +761,14 @@ void __init setup_per_cpu_areas(void)for_each_possible_cpu (cpu) { __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; paca[cpu].data_offset = __per_cpu_offset[cpu]; + +BUG_ON (paca[cpu].data_offset & (PAGE_SIZE -1 )); +BUG_ON (paca[cpu].data_offset >= (1UL << (64 -16 ))); + +/* The top 48 bits are used for per-cpu data */ + paca[cpu].r14 |= paca[cpu].data_offset <<16 ; } + local_r14 = paca[smp_processor_id()].r14; }#endif
Signature · 1 line
2.15.0
Re: [RFC PATCH 3/8] powerpc/64s: put the per-cpu data_offset in r14
Quoted 16 lines · Nicholas Piggin
Shifted left by 16 bits, so the low 16 bits of r14 remain available. This allows per-cpu pointers to be dereferenced with a single extra shift whereas previously it was a load and add.
--- arch/powerpc/include/asm/paca.h | 5 +++++ arch/powerpc/include/asm/percpu.h | 2 +- arch/powerpc/kernel/entry_64.S | 5 ----- arch/powerpc/kernel/head_64.S | 5 +---- arch/powerpc/kernel/setup_64.c | 11 +++++++++-- 5 files changed, 16 insertions(+), 12 deletions(-)arch/powerpc/include/asm/paca.h +0
-0
arch/powerpc/include/asm/paca.h line 39
Quoted 5 lines
arch/powerpc/include/asm/paca.h +2
-0@@ -35,6 +35,11 @@ registerstruct paca_struct *local_paca asm("r13" );#ifdef CONFIG_PPC_BOOK3S +/* +* The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.
Top 32, really? It's 48 in later comments.
Gabriel
Quoted 83 lines
arch/powerpc/include/asm/paca.h +3
-0+* The per-cpu could be moved completely to vmalloc space if we had large +* vmalloc page mapping? (no, must access it in real mode). +*/ registeru64 local_r14 asm("r14" );#endif arch/powerpc/include/asm/percpu.h +1
-1@@ -12,7 +12,7 @@#include <asm/paca.h> -#define __my_cpu_offset local_paca->data_offset +#define __my_cpu_offset (local_r14 >> 16)#endif /* CONFIG_SMP */ #endif /* __powerpc64__ */ arch/powerpc/kernel/entry_64.S +0
-5@@ -262,11 +262,6 @@ system_call_exit: BEGIN_FTR_SECTION stdcx. r0,0,r1 /* to clear the reservation */ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) - LOAD_REG_IMMEDIATE(r10, 0xdeadbeefULL << 32) - mfspr r11,SPRN_PIR - or r10,r10,r11 - tdne r10,r14 - andi. r6,r8,MSR_PR ld r4,_LINK(r1)arch/powerpc/kernel/head_64.S +1
-4@@ -413,10 +413,7 @@ generic_secondary_common_init: b kexec_wait /* next kernel might do better */ 2: SET_PACA(r13) - LOAD_REG_IMMEDIATE(r14, 0xdeadbeef << 32) - mfspr r3,SPRN_PIR - or r14,r14,r3 - std r14,PACA_R14(r13) + ld r14,PACA_R14(r13) #ifdef CONFIG_PPC_BOOK3E addi r12,r13,PACA_EXTLB /* and TLB exc frame in another */arch/powerpc/kernel/setup_64.c +9
-2@@ -192,8 +192,8 @@ static void __init fixup_boot_paca(void)get_paca ()->data_offset =0 ;/* Mark interrupts disabled in PACA */ irq_soft_mask_set (IRQ_SOFT_MASK_STD ); -/* Set r14 and paca_r14 to debug value */ -get_paca ()->r14 = (0xdeadbeefULL <<32 ) |mfspr (SPRN_PIR ); +/* Set r14 and paca_r14 to zero */ +get_paca ()->r14 =0 ; local_r14 =get_paca ()->r14; }@@ -761,7 +761,14 @@ void __init setup_per_cpu_areas(void)for_each_possible_cpu (cpu) { __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; paca[cpu].data_offset = __per_cpu_offset[cpu]; + +BUG_ON (paca[cpu].data_offset & (PAGE_SIZE -1 )); +BUG_ON (paca[cpu].data_offset >= (1UL << (64 -16 ))); + +/* The top 48 bits are used for per-cpu data */ + paca[cpu].r14 |= paca[cpu].data_offset <<16 ; } + local_r14 = paca[smp_processor_id()].r14; }#endif Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRe: [RFC PATCH 3/8] powerpc/64s: put the per-cpu data_offset in r14
Quoted 18 lines · On Wed, 20 Dec 2017 18:53:24 +0100 Gabriel Paubert <[email protected]> wrote:
Quoted 17 lines · Nicholas Piggin
Shifted left by 16 bits, so the low 16 bits of r14 remain available. This allows per-cpu pointers to be dereferenced with a single extra shift whereas previously it was a load and add.
--- arch/powerpc/include/asm/paca.h | 5 +++++ arch/powerpc/include/asm/percpu.h | 2 +- arch/powerpc/kernel/entry_64.S | 5 ----- arch/powerpc/kernel/head_64.S | 5 +---- arch/powerpc/kernel/setup_64.c | 11 +++++++++-- 5 files changed, 16 insertions(+), 12 deletions(-)arch/powerpc/include/asm/paca.h +0
-0@@ -35,6 +35,11 @@
Quoted 6 lines
arch/powerpc/include/asm/paca.h line 39
Quoted 4 lines
arch/powerpc/include/asm/paca.h +2
-0registerstruct paca_struct *local_paca asm("r13" );#ifdef CONFIG_PPC_BOOK3S +/* +* The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT. Top 32, really? It's 48 in later comments.
Yep, I used 32 to start with but it wasn't enough. Will fix.
Thanks,
Nick
Nicholas Piggin
reviewerRFC PATCH 4/8 powerpc/64s: put io_sync bit into r14
In reply to Nicholas PigginThis simplifies spin unlock code and mmio primitives. This may not be the best use of an r14 bit, but it was a simple first proof of concept after the per-cpu data_offset, and so it can stay until we get low on bits.
--- arch/powerpc/include/asm/io.h | 11 ++++------ arch/powerpc/include/asm/paca.h | 44 ++++++++++++++++++++++++++++++++++++- arch/powerpc/include/asm/spinlock.h | 21 ++++++++++-------- arch/powerpc/xmon/xmon.c | 1 - 4 files changed, 59 insertions(+), 18 deletions(-)
arch/powerpc/include/asm/io.h +4 -7
@@ -104,8 +104,8 @@ extern bool isa_io_special;* */ -#ifdef CONFIG_PPC64 -#define IO_SET_SYNC_FLAG () do { local_paca->io_sync = 1; } while(0) +#if defined(CONFIG_PPC64 ) && defined(CONFIG_SMP ) +#define IO_SET_SYNC_FLAG () do { r14_set_bits(R14_BIT_IO_SYNC); } while(0)#else #define IO_SET_SYNC_FLAG ()#endif
@@ -673,11 +673,8 @@ static inline void name at \*/ static inline void mmiowb (void ) { -unsigned long tmp; - - __asm__ __volatile__("sync; li %0,0; stb %0,%1(13)" - :"=&r" (tmp) :"i" (offsetof(struct paca_struct , io_sync)) - :"memory" ); + __asm__ __volatile__("sync" : : :"memory" ); +r14_clear_bits (R14_BIT_IO_SYNC ); }#endif /* !CONFIG_PPC32 */
arch/powerpc/include/asm/paca.h +43 -1
62 lines not on this page · raw message
arch/powerpc/include/asm/spinlock.h +12 -9
@@ -40,16 +40,9 @@#endif #if defined(CONFIG_PPC64 ) && defined(CONFIG_SMP ) -#define CLEAR_IO_SYNC (get_paca()->io_sync = 0) -#define SYNC_IO do { \ - if (unlikely(get_paca()->io_sync)) { \ - mb(); \ - get_paca()->io_sync = 0; \ - } \ - } while (0) +#define CLEAR_IO_SYNC do { r14_clear_bits(R14_BIT_IO_SYNC); } while(0)#else #define CLEAR_IO_SYNC -#define SYNC_IO #endif #ifdef CONFIG_PPC_PSERIES
@@ -165,9 +158,19 @@ void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)static inline void arch_spin_unlock (arch_spinlock_t *lock) { -SYNC_IO ; +#if defined(CONFIG_PPC64 ) && defined(CONFIG_SMP ) +bool io_sync = local_r14 &R14_BIT_IO_SYNC ; +if (unlikely (io_sync)) { +mb (); +CLEAR_IO_SYNC ; + }else { + __asm__ __volatile__("# arch_spin_unlock\n\t" +PPC_RELEASE_BARRIER : : :"memory" ); + } +#else __asm__ __volatile__("# arch_spin_unlock\n\t" PPC_RELEASE_BARRIER : : :"memory" ); +#endif lock->slock =0 ; }
arch/powerpc/xmon/xmon.c +0 -1
@@ -2393,7 +2393,6 @@ static void dump_one_paca(int cpu)DUMP (p, trap_save,"x" );DUMP (p, irq_soft_mask,"x" );DUMP (p, irq_happened,"x" ); -DUMP (p, io_sync,"x" );DUMP (p, irq_work_pending,"x" );DUMP (p, nap_state_lost,"x" );DUMP (p, sprg_vdso,"llx" );
Signature · 1 line
2.15.0
Re: [RFC PATCH 4/8] powerpc/64s: put io_sync bit into r14
Hello Nicholas,
Just a small comment about syntax. I'm afraid I can't comment much about the substance of the patch.
Quoted 6 lines · Nicholas Piggin
arch/powerpc/include/asm/spinlock.h +0
-0@@ -40,16 +40,9 @@#endif
arch/powerpc/include/asm/spinlock.h line 43
Quoted 10 lines
arch/powerpc/include/asm/spinlock.h +1
-7#if defined(CONFIG_PPC64 ) && defined(CONFIG_SMP ) -#define CLEAR_IO_SYNC (get_paca()->io_sync = 0) -#define SYNC_IO do { \ - if (unlikely(get_paca()->io_sync)) { \ - mb(); \ - get_paca()->io_sync = 0; \ - } \ - } while (0) +#define CLEAR_IO_SYNC do { r14_clear_bits(R14_BIT_IO_SYNC); } while(0)
Is there a reason for the do { } while(0) idiom here? If r14_clear_bits() is an inline function, isn't it a single statement already?
Signature · 2 lines
Thiago Jung Bauermann IBM Linux Technology Center
Nicholas Piggin
reviewerRFC PATCH 5/8 powerpc/64s: put work_pending bit into r14
In reply to Nicholas PigginSimilarly, may not be worth an r14 bit, but...
--- arch/powerpc/include/asm/paca.h | 4 ++-- arch/powerpc/kernel/time.c | 15 +++------------ arch/powerpc/xmon/xmon.c | 1 - 3 files changed, 5 insertions(+), 15 deletions(-)
arch/powerpc/include/asm/paca.h +2 -2
@@ -36,7 +36,8 @@ registerstruct paca_struct *local_paca asm("r13" );#ifdef CONFIG_PPC_BOOK3S -#define R14_BIT_IO_SYNC 0x0001 +#define R14_BIT_IO_SYNC 0x0001 +#define R14_BIT_IRQ_WORK_PENDING 0x0002/* IRQ_WORK interrupt while soft-disable */ /* * The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.
@@ -212,7 +213,6 @@ struct paca_struct {u16 trap_save;/* Used when bad stack is encountered */ u8 irq_soft_mask;/* mask for irq soft masking */ u8 irq_happened;/* irq happened while soft-disabled */ -u8 irq_work_pending;/* IRQ_WORK interrupt while soft-disable */ u8 nap_state_lost;/* NV GPR values lost in power7_idle */ u64 sprg_vdso;/* Saved user-visible sprg */ #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
arch/powerpc/kernel/time.c +3 -12
@@ -488,26 +488,17 @@ EXPORT_SYMBOL(profile_pc);#ifdef CONFIG_PPC64 static inline unsigned long test_irq_work_pending (void ) { -unsigned long x; - - asmvolatile ("lbz %0,%1(13)" - :"=r" (x) - :"i" (offsetof(struct paca_struct , irq_work_pending))); -return x; +return local_r14 &R14_BIT_IRQ_WORK_PENDING ; }static inline void set_irq_work_pending_flag (void ) { - asmvolatile ("stb %0,%1(13)" : : -"r" (1 ), -"i" (offsetof(struct paca_struct , irq_work_pending))); +r14_set_bits (R14_BIT_IRQ_WORK_PENDING ); }static inline void clear_irq_work_pending (void ) { - asmvolatile ("stb %0,%1(13)" : : -"r" (0 ), -"i" (offsetof(struct paca_struct , irq_work_pending))); +r14_clear_bits (R14_BIT_IRQ_WORK_PENDING ); }#else /* 32-bit */
arch/powerpc/xmon/xmon.c +0 -1
@@ -2393,7 +2393,6 @@ static void dump_one_paca(int cpu)DUMP (p, trap_save,"x" );DUMP (p, irq_soft_mask,"x" );DUMP (p, irq_happened,"x" ); -DUMP (p, irq_work_pending,"x" );DUMP (p, nap_state_lost,"x" );DUMP (p, sprg_vdso,"llx" );
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 6/8 powerpc/64s: put irq_soft_mask bits into r14
In reply to Nicholas PigginPut the STD and PMI interrupt mask bits into r14. This benefits IRQ disabling (enabling to a lesser extent), and soft mask check in the interrupt entry handler.
--- arch/powerpc/include/asm/exception-64s.h | 6 +- arch/powerpc/include/asm/hw_irq.h | 98 ++++++++++++-------------------- arch/powerpc/include/asm/irqflags.h | 9 +-- arch/powerpc/include/asm/kvm_ppc.h | 2 +- arch/powerpc/include/asm/paca.h | 18 +++++- arch/powerpc/kernel/asm-offsets.c | 7 ++- arch/powerpc/kernel/entry_64.S | 19 +++---- arch/powerpc/kernel/idle_book3s.S | 3 + arch/powerpc/kernel/irq.c | 12 ++-- arch/powerpc/kernel/optprobes_head.S | 3 +- arch/powerpc/kernel/process.c | 2 +- arch/powerpc/kernel/setup_64.c | 11 ++-- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +- arch/powerpc/xmon/xmon.c | 5 +- 14 files changed, 95 insertions(+), 103 deletions(-)
arch/powerpc/include/asm/exception-64s.h +2 -4
@@ -459,9 +459,8 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)mflr r9;/* Get LR, later save to stack */ \ld r2,PACATOC (r13 );/* get kernel TOC into r2 */ \std r9,_LINK (r1 ); \ -lbz r10,PACAIRQSOFTMASK (r13 ); \mfspr r11,SPRN_XER ;/* save XER in stackframe */ \ -std r10,SOFTE (r1 ); \ +std r14,SOFTE (r1 );/* full r14 not just softe XXX */ \std r11,_XER (r1 ); \ li r9,(n)+1; \std r9,_TRAP (r1 );/* set trap number */ \
@@ -526,8 +525,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)#define SOFTEN_VALUE_0xf00 PACA_IRQ_PMI#define __SOFTEN_TEST (h, vec, bitmask) \ - lbz r10,PACAIRQSOFTMASK(r13); \ - andi. r10,r10,bitmask; \ + andi. r10,r14,bitmask; \ li r10,SOFTEN_VALUE_##vec; \ bne masked_##h##interrupt
arch/powerpc/include/asm/hw_irq.h +37 -61
154 lines not on this page · raw message
arch/powerpc/include/asm/irqflags.h +3 -6
@@ -47,14 +47,12 @@* be clobbered. */ #define RECONCILE_IRQ_STATE (__rA, __rB) \ - lbz __rA,PACAIRQSOFTMASK(r13); \ lbz __rB,PACAIRQHAPPENED(r13); \ - andi. __rA,__rA,IRQ_SOFT_MASK_STD; \ - li __rA,IRQ_SOFT_MASK_STD; \ + andi. __rA,r14,IRQ_SOFT_MASK_STD; \ + ori r14,r14,IRQ_SOFT_MASK_STD; \ ori __rB,__rB,PACA_IRQ_HARD_DIS; \ stb __rB,PACAIRQHAPPENED(r13); \ bne 44f; \ - stb __rA,PACAIRQSOFTMASK(r13); \ TRACE_DISABLE_INTS; \ 44:
@@ -64,9 +62,8 @@#define RECONCILE_IRQ_STATE (__rA, __rB) \ lbz __rA,PACAIRQHAPPENED(r13); \ - li __rB,IRQ_SOFT_MASK_STD; \ + ori r14,r14,IRQ_SOFT_MASK_STD; \ ori __rA,__rA,PACA_IRQ_HARD_DIS; \ - stb __rB,PACAIRQSOFTMASK(r13); \ stb __rA,PACAIRQHAPPENED(r13)#endif #endif
arch/powerpc/include/asm/kvm_ppc.h +1 -1
@@ -873,7 +873,7 @@ static inline void kvmppc_fix_ee_before_entry(void)/* Only need to enable IRQs by hard enabling them after this */ local_paca->irq_happened =0 ; -irq_soft_mask_set (IRQ_SOFT_MASK_NONE ); +__irq_soft_mask_clear (IRQ_SOFT_MASK_ALL );#endif }
arch/powerpc/include/asm/paca.h +15 -3
@@ -36,8 +36,10 @@ registerstruct paca_struct *local_paca asm("r13" );#ifdef CONFIG_PPC_BOOK3S -#define R14_BIT_IO_SYNC 0x0001 -#define R14_BIT_IRQ_WORK_PENDING 0x0002/* IRQ_WORK interrupt while soft-disable */ +#define R14_BIT_IRQ_SOFT_MASK_SHIFT 0 +#define R14_BIT_IRQ_SOFT_MASK (0x3 << R14_BIT_IRQ_SOFT_MASK_SHIFT) +#define R14_BIT_IO_SYNC 0x0004 +#define R14_BIT_IRQ_WORK_PENDING 0x0008/* IRQ_WORK interrupt while soft-disable */ /* * The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.
@@ -79,6 +81,17 @@ static inline void r14_flip_bits(unsigned long mask) : "0" (local_r14), "r" (mask)); } +static inline void r14_insert_bits (unsigned long source,unsigned long mask) +{ +unsigned long first =ffs (mask) -1 ; +unsigned long last =fls64 (mask) -1 ; + + mask >>= first; + asmvolatile ("rldimi %0,%2,%3,%4\n" + :"=r" (local_r14) + :"0" (local_r14),"r" (source),"i" (first),"i" (63 - last)); +} +static inline void r14_clear_bits (unsigned long mask) { asm volatile("andc %0,%0,%2\n"
@@ -211,7 +224,6 @@ struct paca_struct {u64 saved_r1;/* r1 save for RTAS calls or PM */ u64 saved_msr;/* MSR saved here by enter_rtas */ u16 trap_save;/* Used when bad stack is encountered */ -u8 irq_soft_mask;/* mask for irq soft masking */ u8 irq_happened;/* irq happened while soft-disabled */ u8 nap_state_lost;/* NV GPR values lost in power7_idle */ u64 sprg_vdso;/* Saved user-visible sprg */
arch/powerpc/kernel/asm-offsets.c +6 -1
@@ -83,6 +83,12 @@ int main(void)#ifdef CONFIG_PPC64 DEFINE (SIGSEGV ,SIGSEGV );DEFINE (NMI_MASK ,NMI_MASK ); +DEFINE (R14_BIT_IRQ_SOFT_MASK_SHIFT ,R14_BIT_IRQ_SOFT_MASK_SHIFT ); +DEFINE (R14_BIT_IRQ_SOFT_MASK ,R14_BIT_IRQ_SOFT_MASK ); +DEFINE (IRQ_SOFT_MASK_STD ,IRQ_SOFT_MASK_STD ); +DEFINE (IRQ_SOFT_MASK_PMU ,IRQ_SOFT_MASK_PMU ); +DEFINE (IRQ_SOFT_MASK_ALL ,IRQ_SOFT_MASK_ALL ); +OFFSET (TASKTHREADPPR , task_struct, thread.ppr);#else OFFSET (THREAD_INFO , task_struct, stack);
@@ -178,7 +184,6 @@ int main(void)OFFSET (PACATOC , paca_struct, kernel_toc);OFFSET (PACAKBASE , paca_struct, kernelbase);OFFSET (PACAKMSR , paca_struct, kernel_msr); -OFFSET (PACAIRQSOFTMASK , paca_struct, irq_soft_mask);OFFSET (PACAIRQHAPPENED , paca_struct, irq_happened);#ifdef CONFIG_PPC_BOOK3S OFFSET (PACACONTEXTID , paca_struct, mm_ctx_id);
arch/powerpc/kernel/entry_64.S +9 -10
@@ -141,8 +141,8 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) * is correct */ #if defined(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG) && defined(CONFIG_BUG) - lbz r10,PACAIRQSOFTMASK(r13) -1: tdnei r10,IRQ_SOFT_MASK_NONE + andi. r10,r14,R14_BIT_IRQ_SOFT_MASK +1: tdnei r10,0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING #endif
@@ -158,7 +158,7 @@ system_call: /* label this so stack traces look sane */ /* We do need to set SOFTE in the stack frame or the return * from interrupt will be painful */ - li r10,IRQ_SOFT_MASK_NONE + li r10,0 std r10,SOFTE(r1) CURRENT_THREAD_INFO(r11, r1)
@@ -793,13 +793,12 @@ restore: * are about to re-enable interrupts */ ld r5,SOFTE(r1) - lbz r6,PACAIRQSOFTMASK(r13) andi. r5,r5,IRQ_SOFT_MASK_STD bne .Lrestore_irq_off /* We are enabling, were we already enabled ? Yes, just return */ - andi. r6,r6,IRQ_SOFT_MASK_STD - beq cr0,.Ldo_restore + andi. r5,r14,IRQ_SOFT_MASK_STD + beq .Ldo_restore /* * We are about to soft-enable interrupts (we are hard disabled
@@ -817,8 +816,8 @@ restore: */ .Lrestore_no_replay: TRACE_ENABLE_INTS - li r0,IRQ_SOFT_MASK_NONE - stb r0,PACAIRQSOFTMASK(r13); + li r0,R14_BIT_IRQ_SOFT_MASK + andc r14,r14,r0 /* * Final return path. BookE is handled in a different file
@@ -1056,8 +1055,8 @@ _GLOBAL(enter_rtas) /* There is no way it is acceptable to get here with interrupts enabled, * check it with the asm equivalent of WARN_ON */ - lbz r0,PACAIRQSOFTMASK(r13) -1: tdeqi r0,IRQ_SOFT_MASK_NONE + andi. r0,r14,R14_BIT_IRQ_SOFT_MASK +1: tdeqi r0,0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING #endif
arch/powerpc/kernel/idle_book3s.S +3 -0
@@ -510,12 +510,15 @@ pnv_powersave_wakeup: BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(70) bl power9_dd1_recover_paca + ld r14,PACA_R14(r13) END_FTR_SECTION_NESTED_IFSET(CPU_FTR_POWER9_DD1, 70) bl pnv_restore_hyp_resource_arch300 FTR_SECTION_ELSE bl pnv_restore_hyp_resource_arch207 ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) + ori r14,r14,PACA_IRQ_HARD_DIS + li r0,PNV_THREAD_RUNNING stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */
arch/powerpc/kernel/irq.c +8 -4
@@ -230,10 +230,13 @@ notrace void arch_local_irq_restore(unsigned long mask)unsigned int replay;/* Write the new soft-enabled value */ -irq_soft_mask_set (mask); +__irq_soft_mask_insert (mask); +/* any bits still disabled */ if (mask)return ; +barrier (); +/* * From this point onward, we can take interrupts, preempt, * etc... unless we got hard-disabled. We check if an event
@@ -261,6 +264,7 @@ notrace void arch_local_irq_restore(unsigned long mask)* then we are already hard disabled (there are other less * common cases that we'll ignore for now), so we skip the * (expensive) mtmsrd. +* XXX: why not test & IRQ_HARD_DIS? */ if (unlikely (irq_happened !=PACA_IRQ_HARD_DIS ))__hard_irq_disable ();
@@ -277,7 +281,7 @@ notrace void arch_local_irq_restore(unsigned long mask) }#endif -irq_soft_mask_set (IRQ_SOFT_MASK_ALL ); +__irq_soft_mask_set (IRQ_SOFT_MASK_ALL );trace_hardirqs_off ();/*
@@ -289,7 +293,7 @@ notrace void arch_local_irq_restore(unsigned long mask)/* We can soft-enable now */ trace_hardirqs_on (); -irq_soft_mask_set (IRQ_SOFT_MASK_NONE ); +__irq_soft_mask_clear (IRQ_SOFT_MASK_ALL );/* * And replay if we have to. This will return with interrupts
@@ -364,7 +368,7 @@ bool prep_irq_for_idle(void)* of entering the low power state. */ local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS ; -irq_soft_mask_set (IRQ_SOFT_MASK_NONE ); +__irq_soft_mask_clear (IRQ_SOFT_MASK_ALL );/* Tell the caller to enter the low power state */ return true;
arch/powerpc/kernel/optprobes_head.S +1 -2
@@ -58,8 +58,7 @@ optprobe_template_entry: std r5,_XER(r1) mfcr r5 std r5,_CCR(r1) - lbz r5,PACAIRQSOFTMASK(r13) - std r5,SOFTE(r1) + std r14,SOFTE(r1) /* * We may get here from a module, so load the kernel TOC in r2.
arch/powerpc/kernel/process.c +1 -1
@@ -1675,7 +1675,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->gpr[FIRST_NVGPR ] =ppc_function_entry ((void *)usp);#ifdef CONFIG_PPC64 clear_tsk_thread_flag (p,TIF_32BIT ); - childregs->softe =IRQ_SOFT_MASK_NONE ; + childregs->softe =0 ;#endif childregs->gpr[FIRST_NVGPR +1 ] = kthread_arg; p->thread.regs =NULL ;/* no user register state */
arch/powerpc/kernel/setup_64.c +6 -5
@@ -190,11 +190,12 @@ static void __init fixup_boot_paca(void)get_paca ()->cpu_start =1 ;/* Allow percpu accesses to work until we setup percpu data */ get_paca ()->data_offset =0 ; -/* Mark interrupts disabled in PACA */ -irq_soft_mask_set (IRQ_SOFT_MASK_STD );/* Set r14 and paca_r14 to zero */ get_paca ()->r14 =0 ; local_r14 =get_paca ()->r14; + +/* Mark interrupts disabled in PACA or r14 */ +__irq_soft_mask_set (IRQ_SOFT_MASK_STD ); }static void __init configure_exceptions (void )
@@ -356,8 +357,8 @@ void __init early_setup(unsigned long dt_ptr)#ifdef CONFIG_SMP void early_setup_secondary (void ) { -/* Mark interrupts disabled in PACA */ -irq_soft_mask_set (IRQ_SOFT_MASK_STD ); +/* Mark interrupts disabled in r14 */ +__irq_soft_mask_set (IRQ_SOFT_MASK_STD );/* Initialize the hash table or TLB handling */ early_init_mmu_secondary ();
@@ -768,7 +769,7 @@ void __init setup_per_cpu_areas(void)/* The top 48 bits are used for per-cpu data */ paca[cpu].r14 |= paca[cpu].data_offset << 16; } - local_r14 = paca[smp_processor_id ()].r14; + local_r14 |= paca[smp_processor_id ()].r14; }#endif
arch/powerpc/kvm/book3s_hv_rmhandlers.S +1 -2
@@ -3249,11 +3249,10 @@ kvmppc_bad_host_intr: mfctr r4 #endif mfxer r5 - lbz r6, PACAIRQSOFTMASK(r13) std r3, _LINK(r1) std r4, _CTR(r1) std r5, _XER(r1) - std r6, SOFTE(r1) + std r14, SOFTE(r1) ld r2, PACATOC(r13) LOAD_REG_IMMEDIATE(3, 0x7265677368657265) std r3, STACK_FRAME_OVERHEAD-16(r1)
arch/powerpc/xmon/xmon.c +2 -3
@@ -1622,8 +1622,8 @@ static void excprint(struct pt_regs *fp)printf (" current = 0x%lx\n" , current);#ifdef CONFIG_PPC64 -printf (" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n" , - local_paca, local_paca->irq_soft_mask, local_paca->irq_happened); +printf (" paca = 0x%lx\t r14: 0x%lx\t irq_happened: 0x%02x\n" , + local_paca, local_r14, local_paca->irq_happened);#endif if (current) { printf(" pid = %ld, comm = %s\n",
@@ -2391,7 +2391,6 @@ static void dump_one_paca(int cpu)DUMP (p, stab_rr,"lx" );DUMP (p, saved_r1,"lx" );DUMP (p, trap_save,"x" ); -DUMP (p, irq_soft_mask,"x" );DUMP (p, irq_happened,"x" );DUMP (p, nap_state_lost,"x" );DUMP (p, sprg_vdso,"llx" );
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 7/8 powerpc/64s: put irq_soft_mask and irq_happened bits into r14
In reply to Nicholas PigginThis should be split into two patches. irq_happened and soft_mask. It may not be worth putting all irq_happened bits into r14, just a single "an irq did happen" bit may be good enough to then load a paca variable.
--- arch/powerpc/include/asm/hw_irq.h | 23 +++++++++---- arch/powerpc/include/asm/irqflags.h | 21 +++++------- arch/powerpc/include/asm/kvm_ppc.h | 4 +-- arch/powerpc/include/asm/paca.h | 7 ++-- arch/powerpc/kernel/asm-offsets.c | 9 +++++- arch/powerpc/kernel/entry_64.S | 13 ++++---- arch/powerpc/kernel/exceptions-64s.S | 4 +-- arch/powerpc/kernel/head_64.S | 15 ++------- arch/powerpc/kernel/irq.c | 62 ++++++++++++++---------------------- arch/powerpc/kvm/book3s_hv.c | 6 ++-- arch/powerpc/xmon/xmon.c | 4 +-- 11 files changed, 76 insertions(+), 92 deletions(-)
arch/powerpc/include/asm/hw_irq.h +16 -7
@@ -22,6 +22,7 @@* and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS * is set whenever we manually hard disable. */ +#ifdef CONFIG_PPC_BOOK3E #define PACA_IRQ_HARD_DIS 0x01#define PACA_IRQ_DBELL 0x02#define PACA_IRQ_EE 0x04
@@ -30,14 +31,22 @@#define PACA_IRQ_HMI 0x20#define PACA_IRQ_PMI 0x40 +#else /* CONFIG_PPC_BOOK3E */ /* -* 64s uses r14 rather than paca for irq_soft_mask +* 64s uses r14 rather than paca for irq_soft_mask and irq_happened */ -#ifdef CONFIG_PPC_BOOK3S + +#define PACA_IRQ_HARD_DIS (0x01 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define PACA_IRQ_DBELL (0x02 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define PACA_IRQ_EE (0x04 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define PACA_IRQ_DEC (0x08 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define PACA_IRQ_HMI (0x10 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define PACA_IRQ_PMI (0x20 << R14_BIT_IRQ_HAPPENED_SHIFT) +#define IRQ_SOFT_MASK_STD (0x01 << R14_BIT_IRQ_SOFT_MASK_SHIFT)#define IRQ_SOFT_MASK_PMU (0x02 << R14_BIT_IRQ_SOFT_MASK_SHIFT)#define IRQ_SOFT_MASK_ALL (0x03 << R14_BIT_IRQ_SOFT_MASK_SHIFT) -#endif /* CONFIG_PPC_BOOK3S */ +#endif /* CONFIG_PPC_BOOK3E */ #endif /* CONFIG_PPC64 */
@@ -206,14 +215,14 @@ static inline bool arch_irqs_disabled(void)unsigned long flags; \__hard_irq_disable (); \ flags =irq_soft_mask_set_return (IRQ_SOFT_MASK_ALL ); \ - local_paca->irq_happened |=PACA_IRQ_HARD_DIS ; \ +r14_set_bits (PACA_IRQ_HARD_DIS ); \if (!arch_irqs_disabled_flags (flags)) \trace_hardirqs_off (); \ }while (0 ) static inline bool lazy_irq_pending(void) { -return !!(get_paca ()->irq_happened & ~PACA_IRQ_HARD_DIS ); +return !!(local_r14 &R14_BIT_IRQ_HAPPENED_MASK & ~PACA_IRQ_HARD_DIS ); }/*
@@ -223,8 +232,8 @@ static inline bool lazy_irq_pending(void)*/ static inline void may_hard_irq_enable (void ) { -get_paca ()->irq_happened &= ~PACA_IRQ_HARD_DIS ; -if (!(get_paca ()->irq_happened &PACA_IRQ_EE )) +r14_clear_bits (PACA_IRQ_HARD_DIS ); +if (!(local_r14 &PACA_IRQ_EE ))__hard_irq_enable (); }
arch/powerpc/include/asm/irqflags.h +8 -13
@@ -45,26 +45,21 @@* * NB: This may call C code, so the caller must be prepared for volatiles to * be clobbered. +* XXX: could make this single-register now */ -#define RECONCILE_IRQ_STATE (__rA, __rB) \ - lbz __rB,PACAIRQHAPPENED(r13); \ - andi. __rA,r14,IRQ_SOFT_MASK_STD; \ - ori r14,r14,IRQ_SOFT_MASK_STD; \ - ori __rB,__rB,PACA_IRQ_HARD_DIS; \ - stb __rB,PACAIRQHAPPENED(r13); \ - bne 44f; \ - TRACE_DISABLE_INTS; \ +#define RECONCILE_IRQ_STATE (__rA, __rB) \ + andi. __rA,r14,IRQ_SOFT_MASK_STD; \ + ori r14,r14,(PACA_IRQ_HARD_DIS | IRQ_SOFT_MASK_STD); \ + bne 44f; \ + TRACE_DISABLE_INTS; \ 44:#else #define TRACE_ENABLE_INTS #define TRACE_DISABLE_INTS -#define RECONCILE_IRQ_STATE (__rA, __rB) \ - lbz __rA,PACAIRQHAPPENED(r13); \ - ori r14,r14,IRQ_SOFT_MASK_STD; \ - ori __rA,__rA,PACA_IRQ_HARD_DIS; \ - stb __rA,PACAIRQHAPPENED(r13) +#define RECONCILE_IRQ_STATE (__rA, __rB) \ + ori r14,r14,(PACA_IRQ_HARD_DIS | IRQ_SOFT_MASK_STD)#endif #endif
arch/powerpc/include/asm/kvm_ppc.h +2 -2
@@ -869,10 +869,10 @@ static inline void kvmppc_fix_ee_before_entry(void)* To avoid races, the caller must have gone directly from having * interrupts fully-enabled to hard-disabled. */ -WARN_ON (local_paca->irq_happened !=PACA_IRQ_HARD_DIS ); +WARN_ON ((local_r14 &R14_BIT_IRQ_HAPPENED_MASK ) !=PACA_IRQ_HARD_DIS );/* Only need to enable IRQs by hard enabling them after this */ - local_paca->irq_happened =0 ; +r14_clear_bits (R14_BIT_IRQ_HAPPENED_MASK );__irq_soft_mask_clear (IRQ_SOFT_MASK_ALL );#endif }
arch/powerpc/include/asm/paca.h +4 -3
@@ -38,8 +38,10 @@ register struct paca_struct *local_paca asm("r13");#define R14_BIT_IRQ_SOFT_MASK_SHIFT 0#define R14_BIT_IRQ_SOFT_MASK (0x3 << R14_BIT_IRQ_SOFT_MASK_SHIFT) -#define R14_BIT_IO_SYNC 0x0004 -#define R14_BIT_IRQ_WORK_PENDING 0x0008/* IRQ_WORK interrupt while soft-disable */ +#define R14_BIT_IRQ_HAPPENED_SHIFT 2 +#define R14_BIT_IRQ_HAPPENED_MASK (0x3f << R14_BIT_IRQ_HAPPENED_SHIFT)/* irq happened while soft-disabled */ +#define R14_BIT_IO_SYNC 0x0100 +#define R14_BIT_IRQ_WORK_PENDING 0x0200/* IRQ_WORK interrupt while soft-disable */ /* * The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.
@@ -224,7 +226,6 @@ struct paca_struct {u64 saved_r1;/* r1 save for RTAS calls or PM */ u64 saved_msr;/* MSR saved here by enter_rtas */ u16 trap_save;/* Used when bad stack is encountered */ -u8 irq_happened;/* irq happened while soft-disabled */ u8 nap_state_lost;/* NV GPR values lost in power7_idle */ u64 sprg_vdso;/* Saved user-visible sprg */ #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
arch/powerpc/kernel/asm-offsets.c +8 -1
@@ -88,6 +88,14 @@ int main(void)DEFINE (IRQ_SOFT_MASK_STD ,IRQ_SOFT_MASK_STD );DEFINE (IRQ_SOFT_MASK_PMU ,IRQ_SOFT_MASK_PMU );DEFINE (IRQ_SOFT_MASK_ALL ,IRQ_SOFT_MASK_ALL ); +DEFINE (R14_BIT_IRQ_HAPPENED_SHIFT ,R14_BIT_IRQ_HAPPENED_SHIFT ); +DEFINE (R14_BIT_IRQ_HAPPENED_MASK ,R14_BIT_IRQ_HAPPENED_MASK ); +DEFINE (PACA_IRQ_HARD_DIS ,PACA_IRQ_HARD_DIS ); +DEFINE (PACA_IRQ_EE ,PACA_IRQ_EE ); +DEFINE (PACA_IRQ_DBELL ,PACA_IRQ_DBELL ); +DEFINE (PACA_IRQ_DEC ,PACA_IRQ_DEC ); +DEFINE (PACA_IRQ_HMI ,PACA_IRQ_HMI ); +DEFINE (PACA_IRQ_PMI ,PACA_IRQ_PMI );OFFSET (TASKTHREADPPR , task_struct, thread.ppr);#else
@@ -184,7 +192,6 @@ int main(void)OFFSET (PACATOC , paca_struct, kernel_toc);OFFSET (PACAKBASE , paca_struct, kernelbase);OFFSET (PACAKMSR , paca_struct, kernel_msr); -OFFSET (PACAIRQHAPPENED , paca_struct, irq_happened);#ifdef CONFIG_PPC_BOOK3S OFFSET (PACACONTEXTID , paca_struct, mm_ctx_id);#ifdef CONFIG_PPC_MM_SLICES
arch/powerpc/kernel/entry_64.S +6 -7
@@ -805,8 +805,7 @@ restore: * at this point). We check if there's anything that needs to * be replayed first. */ - lbz r0,PACAIRQHAPPENED(r13) - cmpwi cr0,r0,0 + andi. r0,r14,R14_BIT_IRQ_HAPPENED_MASK bne- .Lrestore_check_irq_replay /*
@@ -919,16 +918,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) */ .Lrestore_irq_off: ld r3,_MSR(r1) - lbz r7,PACAIRQHAPPENED(r13) + ori r14,r14,IRQ_SOFT_MASK_STD andi. r0,r3,MSR_EE beq 1f - rlwinm r7,r7,0,~PACA_IRQ_HARD_DIS - stb r7,PACAIRQHAPPENED(r13) + li r0,PACA_IRQ_HARD_DIS + andc r14,r14,r0 1: #if defined(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG) && defined(CONFIG_BUG) /* The interrupt should not have soft enabled. */ - lbz r7,PACAIRQSOFTMASK(r13) - tdeqi r7,IRQ_SOFT_MASK_NONE + andi. r7,r14,R14_BIT_IRQ_SOFT_MASK +1: tdeqi r7,0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING #endif b .Ldo_restore
arch/powerpc/kernel/exceptions-64s.S +1 -3
@@ -1404,9 +1404,7 @@ EXC_COMMON_BEGIN(soft_nmi_common) */ #define MASKED_INTERRUPT(_H) \ masked_##_H##interrupt: \ - lbz r11,PACAIRQHAPPENED(r13); \ - or r11,r11,r10; \ - stb r11,PACAIRQHAPPENED(r13); \ + or r14,r14,r10; \ cmpwi r10,PACA_IRQ_DEC; \ bne 1f; \ lis r10,0x7fff; \
arch/powerpc/kernel/head_64.S +3 -12
@@ -767,10 +767,7 @@ _GLOBAL(pmac_secondary_start) /* Mark interrupts soft and hard disabled (they might be enabled * in the PACA when doing hotplug) */ - li r0,IRQ_SOFT_MASK_STD - stb r0,PACAIRQSOFTMASK(r13) - li r0,PACA_IRQ_HARD_DIS - stb r0,PACAIRQHAPPENED(r13) + ori r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS) /* Create a temp kernel stack for use before relocation is on. */ ld r1,PACAEMERGSP(r13)
@@ -824,10 +821,7 @@ __secondary_start: /* Mark interrupts soft and hard disabled (they might be enabled * in the PACA when doing hotplug) */ - li r7,IRQ_SOFT_MASK_STD - stb r7,PACAIRQSOFTMASK(r13) - li r0,PACA_IRQ_HARD_DIS - stb r0,PACAIRQHAPPENED(r13) + ori r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS) /* enable MMU and jump to start_secondary */ LOAD_REG_ADDR(r3, start_secondary_prolog)
@@ -991,10 +985,7 @@ start_here_common: /* Mark interrupts soft and hard disabled (they might be enabled * in the PACA when doing hotplug) */ - li r0,IRQ_SOFT_MASK_STD - stb r0,PACAIRQSOFTMASK(r13) - li r0,PACA_IRQ_HARD_DIS - stb r0,PACAIRQHAPPENED(r13) + ori r14,r14,(IRQ_SOFT_MASK_STD | PACA_IRQ_HARD_DIS) /* Generic kernel entry */ bl start_kernel
arch/powerpc/kernel/irq.c +24 -38
148 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv.c +3 -3
@@ -2614,13 +2614,13 @@ static void set_irq_happened(int trap) {switch (trap) {case BOOK3S_INTERRUPT_EXTERNAL : - local_paca->irq_happened |=PACA_IRQ_EE ; +r14_set_bits (PACA_IRQ_EE );break ;case BOOK3S_INTERRUPT_H_DOORBELL : - local_paca->irq_happened |=PACA_IRQ_DBELL ; +r14_set_bits (PACA_IRQ_DBELL );break ;case BOOK3S_INTERRUPT_HMI : - local_paca->irq_happened |=PACA_IRQ_HMI ; +r14_set_bits (PACA_IRQ_HMI );break ;case BOOK3S_INTERRUPT_SYSTEM_RESET :replay_system_reset ();
arch/powerpc/xmon/xmon.c +1 -3
@@ -1622,8 +1622,7 @@ static void excprint(struct pt_regs *fp)printf (" current = 0x%lx\n" , current);#ifdef CONFIG_PPC64 -printf (" paca = 0x%lx\t r14: 0x%lx\t irq_happened: 0x%02x\n" , - local_paca, local_r14, local_paca->irq_happened); +printf (" paca = 0x%lx\t r14: %lx\n" , local_paca, local_r14);#endif if (current) { printf(" pid = %ld, comm = %s\n",
@@ -2391,7 +2390,6 @@ static void dump_one_paca(int cpu)DUMP (p, stab_rr,"lx" );DUMP (p, saved_r1,"lx" );DUMP (p, trap_save,"x" ); -DUMP (p, irq_happened,"x" );DUMP (p, nap_state_lost,"x" );DUMP (p, sprg_vdso,"llx" );
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerRFC PATCH 8/8 powerpc/64s: inline local_irq_enable/restore
In reply to Nicholas PigginThis does increase kernel text size by about 0.4%, but code is often improved by putting the interrupt-replay call out of line, and gcc function "shrink wrapping" can more often avoid setting up a stack frame, e.g., _raw_spin_unlock_irqrestore fastpath before:
<_raw_spin_unlock_irqrestore>: addis r2,r12,63 addi r2,r2,24688 mflr r0 andi. r9,r14,256 mr r9,r3 std r0,16(r1) stdu r1,-32(r1) bne c0000000009fd1e0 <_raw_spin_unlock_irqrestore+0x50> lwsync li r10,0 mr r3,r4 stw r10,0(r9) bl c000000000013f98 <arch_local_irq_restore+0x8> <arch_local_irq_restore>: addis r2,r12,222 addi r2,r2,-3472 rldimi r14,r3,0,62 cmpdi cr7,r3,0 bnelr cr7 andi. r9,r14,252 beqlr nop addi r1,r1,32 ld r0,16(r1) mtlr r0 blr
And after:
<_raw_spin_unlock_irqrestore>: addis r2,r12,64 addi r2,r2,-15200 andi. r9,r14,256 bne c000000000a06dd0 <_raw_spin_unlock_irqrestore+0x70> lwsync li r9,0 stw r9,0(r3) rldimi r14,r4,0,62 cmpdi cr7,r4,0 bne cr7,c000000000a06d90 <_raw_spin_unlock_irqrestore+0x30> andi. r9,r14,252 bne c000000000a06da0 <_raw_spin_unlock_irqrestore+0x40> blr
GCC can still improve code size for the slow paths by avoiding aligning branch targets too, so there is room to reduce the text size cost there.
--- arch/powerpc/include/asm/hw_irq.h | 15 +++++++++++++-- arch/powerpc/kernel/irq.c | 28 ++++++---------------------- 2 files changed, 19 insertions(+), 24 deletions(-)
arch/powerpc/include/asm/hw_irq.h +13 -2
@@ -132,11 +132,22 @@ static inline void arch_local_irq_disable(void)irq_soft_mask_set (IRQ_SOFT_MASK_STD ); } -extern void arch_local_irq_restore (unsigned long ); +extern void __arch_local_irq_enable (void );static inline void arch_local_irq_enable (void ) { -arch_local_irq_restore (0 ); +__irq_soft_mask_clear (IRQ_SOFT_MASK_ALL ); +if (unlikely (local_r14 &R14_BIT_IRQ_HAPPENED_MASK )) +__arch_local_irq_enable (); +} + +static inline void arch_local_irq_restore (unsigned long flags) +{ +__irq_soft_mask_insert (flags); +if (!flags) { +if (unlikely (local_r14 &R14_BIT_IRQ_HAPPENED_MASK )) +__arch_local_irq_enable (); + } }static inline unsigned long arch_local_irq_save (void )
arch/powerpc/kernel/irq.c +6 -22
@@ -97,11 +97,6 @@ extern int tau_interrupts(int);int distribute_irqs =1 ; -static inline notrace unsigned long get_irq_happened (void ) -{ -return local_r14 &R14_BIT_IRQ_HAPPENED_MASK ; -} - static inline notrace int decrementer_check_overflow(void) {u64 now =get_tb_or_rtc ();
@@ -210,19 +205,10 @@ notrace unsigned int __check_irq_replay(void)return 0 ; } -notrace void arch_local_irq_restore(unsigned long mask) +notrace void __arch_local_irq_enable(void) { -unsigned char irq_happened;unsigned int replay; -/* Write the new soft-enabled value */ -__irq_soft_mask_insert (mask); -/* any bits still disabled */ -if (mask) -return ; - -barrier (); -/* * From this point onward, we can take interrupts, preempt, * etc... unless we got hard-disabled. We check if an event
@@ -236,9 +222,6 @@ notrace void arch_local_irq_restore(unsigned long mask)* be hard-disabled, so there is no problem, we * cannot have preempted. */ - irq_happened =get_irq_happened (); -if (!irq_happened) -return ;/* * We need to hard disable to get a trusted value from
@@ -252,10 +235,11 @@ notrace void arch_local_irq_restore(unsigned long mask)* (expensive) mtmsrd. * XXX: why not test & IRQ_HARD_DIS? */ -if (unlikely (irq_happened !=PACA_IRQ_HARD_DIS )) +if (unlikely ((local_r14 &R14_BIT_IRQ_HAPPENED_MASK ) != +PACA_IRQ_HARD_DIS )) {__hard_irq_disable (); #ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG - else { + }else {/* * We should already be hard disabled here. We had bugs * where that wasn't the case so let's dbl check it and
@@ -264,8 +248,8 @@ notrace void arch_local_irq_restore(unsigned long mask)*/ if (WARN_ON (mfmsr () &MSR_EE ))__hard_irq_disable (); - }#endif + }__irq_soft_mask_set (IRQ_SOFT_MASK_ALL );trace_hardirqs_off ();
@@ -293,7 +277,7 @@ notrace void arch_local_irq_restore(unsigned long mask)/* Finally, let's ensure we are hard enabled */ __hard_irq_enable (); } -EXPORT_SYMBOL (arch_local_irq_restore); +EXPORT_SYMBOL (__arch_local_irq_enable);/* * This is specifically called by assembly code to re-enable interrupts
Signature · 1 line
2.15.0