Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/booke64: Use SPRG7 for VDSO

Previously SPRG3 was marked for use by both VDSO and critical
interrupts (though critical interrupts were not fully implemented).

In commit 8b64a9dfb091f1eca8b7e58da82f1e7d1d5fe0ad ("powerpc/booke64:
Use SPRG0/3 scratch for bolted TLB miss & crit int"), Mihai Caraman
made an attempt to resolve this conflict by restoring the VDSO value
early in the critical interrupt, but this has some issues:

- It's incompatible with EXCEPTION_COMMON which restores r13 from the
by-then-overwritten scratch (this cost me some debugging time).
- It forces critical exceptions to be a special case handled
differently from even machine check and debug level exceptions.
- It didn't occur to me that it was possible to make this work at all
(by doing a final "ld r13, PACA_EXCRIT+EX_R13(r13)") until after
I made (most of) this patch. :-)

It might be worth investigating using a load rather than SPRG on return
from all exceptions (except TLB misses where the scratch never leaves
the SPRG) -- it could save a few cycles. Until then, let's stick with
SPRG for all exceptions.

Since we cannot use SPRG4-7 for scratch without corrupting the state of
a KVM guest, move VDSO to SPRG7 on book3e. Since neither SPRG4-7 nor
critical interrupts exist on book3s, SPRG3 is still used for VDSO
there.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: kvm-ppc@vger.kernel.org

+33 -47
+2 -3
arch/powerpc/include/asm/exception-64e.h
··· 46 46 #define EX_CR (1 * 8) 47 47 #define EX_R10 (2 * 8) 48 48 #define EX_R11 (3 * 8) 49 - #define EX_R13 (4 * 8) 50 - #define EX_R14 (5 * 8) 51 - #define EX_R15 (6 * 8) 49 + #define EX_R14 (4 * 8) 50 + #define EX_R15 (5 * 8) 52 51 53 52 /* 54 53 * The TLB miss exception uses different slots.
+1 -8
arch/powerpc/include/asm/kvm_booke_hv_asm.h
··· 36 36 * *(r8 + GPR11) = saved r11 37 37 * 38 38 * 64-bit host 39 - * Expected inputs (GEN/GDBELL/DBG/MC exception types): 39 + * Expected inputs (GEN/GDBELL/DBG/CRIT/MC exception types): 40 40 * r10 = saved CR 41 41 * r13 = PACA_POINTER 42 42 * *(r13 + PACA_EX##type + EX_R10) = saved r10 43 43 * *(r13 + PACA_EX##type + EX_R11) = saved r11 44 44 * SPRN_SPRG_##type##_SCRATCH = saved r13 45 - * 46 - * Expected inputs (CRIT exception type): 47 - * r10 = saved CR 48 - * r13 = PACA_POINTER 49 - * *(r13 + PACA_EX##type + EX_R10) = saved r10 50 - * *(r13 + PACA_EX##type + EX_R11) = saved r11 51 - * *(r13 + PACA_EX##type + EX_R13) = saved r13 52 45 * 53 46 * Expected inputs (TLB exception type): 54 47 * r10 = saved CR
+1 -1
arch/powerpc/include/asm/paca.h
··· 146 146 u8 io_sync; /* writel() needs spin_unlock sync */ 147 147 u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ 148 148 u8 nap_state_lost; /* NV GPR values lost in power7_idle */ 149 - u64 sprg3; /* Saved user-visible sprg */ 149 + u64 sprg_vdso; /* Saved user-visible sprg */ 150 150 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM 151 151 u64 tm_scratch; /* TM scratch area for reclaim */ 152 152 #endif
+10 -3
arch/powerpc/include/asm/reg.h
··· 577 577 #define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */ 578 578 #define SPRN_USPRG3 0x103 /* SPRG3 userspace read */ 579 579 #define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */ 580 + #define SPRN_USPRG4 0x104 /* SPRG4 userspace read */ 580 581 #define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */ 582 + #define SPRN_USPRG5 0x105 /* SPRG5 userspace read */ 581 583 #define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */ 584 + #define SPRN_USPRG6 0x106 /* SPRG6 userspace read */ 582 585 #define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */ 586 + #define SPRN_USPRG7 0x107 /* SPRG7 userspace read */ 583 587 #define SPRN_SRR0 0x01A /* Save/Restore Register 0 */ 584 588 #define SPRN_SRR1 0x01B /* Save/Restore Register 1 */ 585 589 #define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */ ··· 883 879 * 64-bit embedded 884 880 * - SPRG0 generic exception scratch 885 881 * - SPRG2 TLB exception stack 886 - * - SPRG3 critical exception scratch and 887 - * CPU and NUMA node for VDSO getcpu (user visible) 882 + * - SPRG3 critical exception scratch (user visible, sorry!) 888 883 * - SPRG4 unused (user visible) 889 884 * - SPRG6 TLB miss scratch (user visible, sorry !) 890 - * - SPRG7 critical exception scratch 885 + * - SPRG7 CPU and NUMA node for VDSO getcpu (user visible) 891 886 * - SPRG8 machine check exception scratch 892 887 * - SPRG9 debug exception scratch 893 888 * ··· 943 940 #define SPRN_SPRG_SCRATCH0 SPRN_SPRG2 944 941 #define SPRN_SPRG_HPACA SPRN_HSPRG0 945 942 #define SPRN_SPRG_HSCRATCH0 SPRN_HSPRG1 943 + #define SPRN_SPRG_VDSO_READ SPRN_USPRG3 944 + #define SPRN_SPRG_VDSO_WRITE SPRN_SPRG3 946 945 947 946 #define GET_PACA(rX) \ 948 947 BEGIN_FTR_SECTION_NESTED(66); \ ··· 988 983 #define SPRN_SPRG_TLB_SCRATCH SPRN_SPRG6 989 984 #define SPRN_SPRG_GEN_SCRATCH SPRN_SPRG0 990 985 #define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH 986 + #define SPRN_SPRG_VDSO_READ SPRN_USPRG7 987 + #define SPRN_SPRG_VDSO_WRITE SPRN_SPRG7 991 988 992 989 #define SET_PACA(rX) mtspr SPRN_SPRG_PACA,rX 993 990 #define GET_PACA(rX) mfspr rX,SPRN_SPRG_PACA
+1 -1
arch/powerpc/kernel/asm-offsets.c
··· 253 253 DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); 254 254 DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); 255 255 DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost)); 256 - DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3)); 256 + DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso)); 257 257 #endif /* CONFIG_PPC64 */ 258 258 259 259 /* RTAS */
+2 -17
arch/powerpc/kernel/exceptions-64e.S
··· 55 55 mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \ 56 56 std r10,PACA_EX##type+EX_R10(r13); \ 57 57 std r11,PACA_EX##type+EX_R11(r13); \ 58 - PROLOG_STORE_RESTORE_SCRATCH_##type; \ 59 58 mfcr r10; /* save CR */ \ 60 59 mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \ 61 60 DO_KVM intnum,SPRN_##type##_SRR1; /* KVM hook */ \ ··· 114 115 115 116 #define GDBELL_EXCEPTION_PROLOG(n, intnum, addition) \ 116 117 EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n)) 117 - 118 - /* 119 - * Store user-visible scratch in PACA exception slots and restore proper value 120 - */ 121 - #define PROLOG_STORE_RESTORE_SCRATCH_GEN 122 - #define PROLOG_STORE_RESTORE_SCRATCH_GDBELL 123 - #define PROLOG_STORE_RESTORE_SCRATCH_DBG 124 - #define PROLOG_STORE_RESTORE_SCRATCH_MC 125 - 126 - #define PROLOG_STORE_RESTORE_SCRATCH_CRIT \ 127 - mfspr r10,SPRN_SPRG_CRIT_SCRATCH; /* get r13 */ \ 128 - std r10,PACA_EXCRIT+EX_R13(r13); \ 129 - ld r11,PACA_SPRG3(r13); \ 130 - mtspr SPRN_SPRG_CRIT_SCRATCH,r11; 131 118 132 119 /* Variants of the "addition" argument for the prolog 133 120 */ ··· 514 529 mtcr r10 515 530 ld r10,PACA_EXCRIT+EX_R10(r13) /* restore registers */ 516 531 ld r11,PACA_EXCRIT+EX_R11(r13) 517 - ld r13,PACA_EXCRIT+EX_R13(r13) 532 + mfspr r13,SPRN_SPRG_CRIT_SCRATCH 518 533 rfci 519 534 520 535 /* Normal debug exception */ ··· 527 542 /* Now we mash up things to make it look like we are coming on a 528 543 * normal exception 529 544 */ 530 - ld r15,PACA_EXCRIT+EX_R13(r13) 545 + mfspr r15,SPRN_SPRG_CRIT_SCRATCH 531 546 mtspr SPRN_SPRG_GEN_SCRATCH,r15 532 547 mfspr r14,SPRN_DBSR 533 548 EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
+4 -4
arch/powerpc/kernel/vdso.c
··· 715 715 unsigned long cpu, node, val; 716 716 717 717 /* 718 - * SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in 719 - * the next 16 bits. The VDSO uses this to implement getcpu(). 718 + * SPRG_VDSO contains the CPU in the bottom 16 bits and the NUMA node 719 + * in the next 16 bits. The VDSO uses this to implement getcpu(). 720 720 */ 721 721 cpu = get_cpu(); 722 722 WARN_ON_ONCE(cpu > 0xffff); ··· 725 725 WARN_ON_ONCE(node > 0xffff); 726 726 727 727 val = (cpu & 0xfff) | ((node & 0xffff) << 16); 728 - mtspr(SPRN_SPRG3, val); 729 - get_paca()->sprg3 = val; 728 + mtspr(SPRN_SPRG_VDSO_WRITE, val); 729 + get_paca()->sprg_vdso = val; 730 730 731 731 put_cpu(); 732 732
+1 -1
arch/powerpc/kernel/vdso32/getcpu.S
··· 29 29 */ 30 30 V_FUNCTION_BEGIN(__kernel_getcpu) 31 31 .cfi_startproc 32 - mfspr r5,SPRN_USPRG3 32 + mfspr r5,SPRN_SPRG_VDSO_READ 33 33 cmpdi cr0,r3,0 34 34 cmpdi cr1,r4,0 35 35 clrlwi r6,r5,16
+1 -1
arch/powerpc/kernel/vdso64/getcpu.S
··· 29 29 */ 30 30 V_FUNCTION_BEGIN(__kernel_getcpu) 31 31 .cfi_startproc 32 - mfspr r5,SPRN_USPRG3 32 + mfspr r5,SPRN_SPRG_VDSO_READ 33 33 cmpdi cr0,r3,0 34 34 cmpdi cr1,r4,0 35 35 clrlwi r6,r5,16
+2 -2
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 75 75 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) 76 76 77 77 /* Restore SPRG3 */ 78 - ld r3,PACA_SPRG3(r13) 79 - mtspr SPRN_SPRG3,r3 78 + ld r3,PACA_SPRG_VDSO(r13) 79 + mtspr SPRN_SPRG_VDSO_WRITE,r3 80 80 81 81 /* Reload the host's PMU registers */ 82 82 ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */
+2 -2
arch/powerpc/kvm/book3s_interrupts.S
··· 153 153 * Reload kernel SPRG3 value. 154 154 * No need to save guest value as usermode can't modify SPRG3. 155 155 */ 156 - ld r3, PACA_SPRG3(r13) 157 - mtspr SPRN_SPRG3, r3 156 + ld r3, PACA_SPRG_VDSO(r13) 157 + mtspr SPRN_SPRG_VDSO_WRITE, r3 158 158 #endif /* CONFIG_PPC_BOOK3S_64 */ 159 159 160 160 /* R7 = vcpu */
+6 -4
arch/powerpc/kvm/bookehv_interrupts.S
··· 229 229 stw r10, VCPU_CR(r4) 230 230 PPC_STL r11, VCPU_GPR(R4)(r4) 231 231 PPC_STL r5, VCPU_GPR(R5)(r4) 232 - .if \type == EX_CRIT 233 - PPC_LL r5, (\paca_ex + EX_R13)(r13) 234 - .else 235 232 mfspr r5, \scratch 236 - .endif 237 233 PPC_STL r6, VCPU_GPR(R6)(r4) 238 234 PPC_STL r8, VCPU_GPR(R8)(r4) 239 235 PPC_STL r9, VCPU_GPR(R9)(r4) ··· 431 435 PPC_STL r5, VCPU_LR(r4) 432 436 mfspr r7, SPRN_SPRG5 433 437 stw r3, VCPU_VRSAVE(r4) 438 + #ifdef CONFIG_64BIT 439 + PPC_LL r3, PACA_SPRG_VDSO(r13) 440 + #endif 434 441 PPC_STD(r6, VCPU_SHARED_SPRG4, r11) 435 442 mfspr r8, SPRN_SPRG6 436 443 PPC_STD(r7, VCPU_SHARED_SPRG5, r11) 437 444 mfspr r9, SPRN_SPRG7 445 + #ifdef CONFIG_64BIT 446 + mtspr SPRN_SPRG_VDSO_WRITE, r3 447 + #endif 438 448 PPC_STD(r8, VCPU_SHARED_SPRG6, r11) 439 449 mfxer r3 440 450 PPC_STD(r9, VCPU_SHARED_SPRG7, r11)