mirror of https://gitee.com/openkylin/linux.git
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 8b64a9dfb0
("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
This commit is contained in:
parent
82d86de25b
commit
9d378dfac8
|
@ -46,9 +46,8 @@
|
||||||
#define EX_CR (1 * 8)
|
#define EX_CR (1 * 8)
|
||||||
#define EX_R10 (2 * 8)
|
#define EX_R10 (2 * 8)
|
||||||
#define EX_R11 (3 * 8)
|
#define EX_R11 (3 * 8)
|
||||||
#define EX_R13 (4 * 8)
|
#define EX_R14 (4 * 8)
|
||||||
#define EX_R14 (5 * 8)
|
#define EX_R15 (5 * 8)
|
||||||
#define EX_R15 (6 * 8)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The TLB miss exception uses different slots.
|
* The TLB miss exception uses different slots.
|
||||||
|
|
|
@ -36,19 +36,12 @@
|
||||||
* *(r8 + GPR11) = saved r11
|
* *(r8 + GPR11) = saved r11
|
||||||
*
|
*
|
||||||
* 64-bit host
|
* 64-bit host
|
||||||
* Expected inputs (GEN/GDBELL/DBG/MC exception types):
|
* Expected inputs (GEN/GDBELL/DBG/CRIT/MC exception types):
|
||||||
* r10 = saved CR
|
* r10 = saved CR
|
||||||
* r13 = PACA_POINTER
|
* r13 = PACA_POINTER
|
||||||
* *(r13 + PACA_EX##type + EX_R10) = saved r10
|
* *(r13 + PACA_EX##type + EX_R10) = saved r10
|
||||||
* *(r13 + PACA_EX##type + EX_R11) = saved r11
|
* *(r13 + PACA_EX##type + EX_R11) = saved r11
|
||||||
* SPRN_SPRG_##type##_SCRATCH = saved r13
|
* SPRN_SPRG_##type##_SCRATCH = saved r13
|
||||||
*
|
|
||||||
* Expected inputs (CRIT exception type):
|
|
||||||
* r10 = saved CR
|
|
||||||
* r13 = PACA_POINTER
|
|
||||||
* *(r13 + PACA_EX##type + EX_R10) = saved r10
|
|
||||||
* *(r13 + PACA_EX##type + EX_R11) = saved r11
|
|
||||||
* *(r13 + PACA_EX##type + EX_R13) = saved r13
|
|
||||||
*
|
*
|
||||||
* Expected inputs (TLB exception type):
|
* Expected inputs (TLB exception type):
|
||||||
* r10 = saved CR
|
* r10 = saved CR
|
||||||
|
|
|
@ -146,7 +146,7 @@ struct paca_struct {
|
||||||
u8 io_sync; /* writel() needs spin_unlock sync */
|
u8 io_sync; /* writel() needs spin_unlock sync */
|
||||||
u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
|
u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
|
||||||
u8 nap_state_lost; /* NV GPR values lost in power7_idle */
|
u8 nap_state_lost; /* NV GPR values lost in power7_idle */
|
||||||
u64 sprg3; /* Saved user-visible sprg */
|
u64 sprg_vdso; /* Saved user-visible sprg */
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
u64 tm_scratch; /* TM scratch area for reclaim */
|
u64 tm_scratch; /* TM scratch area for reclaim */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -577,9 +577,13 @@
|
||||||
#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
|
#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
|
||||||
#define SPRN_USPRG3 0x103 /* SPRG3 userspace read */
|
#define SPRN_USPRG3 0x103 /* SPRG3 userspace read */
|
||||||
#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
|
#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
|
||||||
|
#define SPRN_USPRG4 0x104 /* SPRG4 userspace read */
|
||||||
#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
|
#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
|
||||||
|
#define SPRN_USPRG5 0x105 /* SPRG5 userspace read */
|
||||||
#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
|
#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
|
||||||
|
#define SPRN_USPRG6 0x106 /* SPRG6 userspace read */
|
||||||
#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
|
#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
|
||||||
|
#define SPRN_USPRG7 0x107 /* SPRG7 userspace read */
|
||||||
#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
|
#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
|
||||||
#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
|
#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
|
||||||
#define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */
|
#define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */
|
||||||
|
@ -879,11 +883,10 @@
|
||||||
* 64-bit embedded
|
* 64-bit embedded
|
||||||
* - SPRG0 generic exception scratch
|
* - SPRG0 generic exception scratch
|
||||||
* - SPRG2 TLB exception stack
|
* - SPRG2 TLB exception stack
|
||||||
* - SPRG3 critical exception scratch and
|
* - SPRG3 critical exception scratch (user visible, sorry!)
|
||||||
* CPU and NUMA node for VDSO getcpu (user visible)
|
|
||||||
* - SPRG4 unused (user visible)
|
* - SPRG4 unused (user visible)
|
||||||
* - SPRG6 TLB miss scratch (user visible, sorry !)
|
* - SPRG6 TLB miss scratch (user visible, sorry !)
|
||||||
* - SPRG7 critical exception scratch
|
* - SPRG7 CPU and NUMA node for VDSO getcpu (user visible)
|
||||||
* - SPRG8 machine check exception scratch
|
* - SPRG8 machine check exception scratch
|
||||||
* - SPRG9 debug exception scratch
|
* - SPRG9 debug exception scratch
|
||||||
*
|
*
|
||||||
|
@ -940,6 +943,8 @@
|
||||||
#define SPRN_SPRG_SCRATCH0 SPRN_SPRG2
|
#define SPRN_SPRG_SCRATCH0 SPRN_SPRG2
|
||||||
#define SPRN_SPRG_HPACA SPRN_HSPRG0
|
#define SPRN_SPRG_HPACA SPRN_HSPRG0
|
||||||
#define SPRN_SPRG_HSCRATCH0 SPRN_HSPRG1
|
#define SPRN_SPRG_HSCRATCH0 SPRN_HSPRG1
|
||||||
|
#define SPRN_SPRG_VDSO_READ SPRN_USPRG3
|
||||||
|
#define SPRN_SPRG_VDSO_WRITE SPRN_SPRG3
|
||||||
|
|
||||||
#define GET_PACA(rX) \
|
#define GET_PACA(rX) \
|
||||||
BEGIN_FTR_SECTION_NESTED(66); \
|
BEGIN_FTR_SECTION_NESTED(66); \
|
||||||
|
@ -983,6 +988,8 @@
|
||||||
#define SPRN_SPRG_TLB_SCRATCH SPRN_SPRG6
|
#define SPRN_SPRG_TLB_SCRATCH SPRN_SPRG6
|
||||||
#define SPRN_SPRG_GEN_SCRATCH SPRN_SPRG0
|
#define SPRN_SPRG_GEN_SCRATCH SPRN_SPRG0
|
||||||
#define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
|
#define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
|
||||||
|
#define SPRN_SPRG_VDSO_READ SPRN_USPRG7
|
||||||
|
#define SPRN_SPRG_VDSO_WRITE SPRN_SPRG7
|
||||||
|
|
||||||
#define SET_PACA(rX) mtspr SPRN_SPRG_PACA,rX
|
#define SET_PACA(rX) mtspr SPRN_SPRG_PACA,rX
|
||||||
#define GET_PACA(rX) mfspr rX,SPRN_SPRG_PACA
|
#define GET_PACA(rX) mfspr rX,SPRN_SPRG_PACA
|
||||||
|
|
|
@ -253,7 +253,7 @@ int main(void)
|
||||||
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
||||||
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
|
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
|
||||||
DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
|
DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
|
||||||
DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3));
|
DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso));
|
||||||
#endif /* CONFIG_PPC64 */
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
/* RTAS */
|
/* RTAS */
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
|
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
|
||||||
std r10,PACA_EX##type+EX_R10(r13); \
|
std r10,PACA_EX##type+EX_R10(r13); \
|
||||||
std r11,PACA_EX##type+EX_R11(r13); \
|
std r11,PACA_EX##type+EX_R11(r13); \
|
||||||
PROLOG_STORE_RESTORE_SCRATCH_##type; \
|
|
||||||
mfcr r10; /* save CR */ \
|
mfcr r10; /* save CR */ \
|
||||||
mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \
|
mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \
|
||||||
DO_KVM intnum,SPRN_##type##_SRR1; /* KVM hook */ \
|
DO_KVM intnum,SPRN_##type##_SRR1; /* KVM hook */ \
|
||||||
|
@ -116,20 +115,6 @@
|
||||||
#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition) \
|
#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition) \
|
||||||
EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
|
EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
|
||||||
|
|
||||||
/*
|
|
||||||
* Store user-visible scratch in PACA exception slots and restore proper value
|
|
||||||
*/
|
|
||||||
#define PROLOG_STORE_RESTORE_SCRATCH_GEN
|
|
||||||
#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
|
|
||||||
#define PROLOG_STORE_RESTORE_SCRATCH_DBG
|
|
||||||
#define PROLOG_STORE_RESTORE_SCRATCH_MC
|
|
||||||
|
|
||||||
#define PROLOG_STORE_RESTORE_SCRATCH_CRIT \
|
|
||||||
mfspr r10,SPRN_SPRG_CRIT_SCRATCH; /* get r13 */ \
|
|
||||||
std r10,PACA_EXCRIT+EX_R13(r13); \
|
|
||||||
ld r11,PACA_SPRG3(r13); \
|
|
||||||
mtspr SPRN_SPRG_CRIT_SCRATCH,r11;
|
|
||||||
|
|
||||||
/* Variants of the "addition" argument for the prolog
|
/* Variants of the "addition" argument for the prolog
|
||||||
*/
|
*/
|
||||||
#define PROLOG_ADDITION_NONE_GEN(n)
|
#define PROLOG_ADDITION_NONE_GEN(n)
|
||||||
|
@ -529,7 +514,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||||
mtcr r10
|
mtcr r10
|
||||||
ld r10,PACA_EXCRIT+EX_R10(r13) /* restore registers */
|
ld r10,PACA_EXCRIT+EX_R10(r13) /* restore registers */
|
||||||
ld r11,PACA_EXCRIT+EX_R11(r13)
|
ld r11,PACA_EXCRIT+EX_R11(r13)
|
||||||
ld r13,PACA_EXCRIT+EX_R13(r13)
|
mfspr r13,SPRN_SPRG_CRIT_SCRATCH
|
||||||
rfci
|
rfci
|
||||||
|
|
||||||
/* Normal debug exception */
|
/* Normal debug exception */
|
||||||
|
@ -542,7 +527,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||||
/* Now we mash up things to make it look like we are coming on a
|
/* Now we mash up things to make it look like we are coming on a
|
||||||
* normal exception
|
* normal exception
|
||||||
*/
|
*/
|
||||||
ld r15,PACA_EXCRIT+EX_R13(r13)
|
mfspr r15,SPRN_SPRG_CRIT_SCRATCH
|
||||||
mtspr SPRN_SPRG_GEN_SCRATCH,r15
|
mtspr SPRN_SPRG_GEN_SCRATCH,r15
|
||||||
mfspr r14,SPRN_DBSR
|
mfspr r14,SPRN_DBSR
|
||||||
EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
|
EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
|
||||||
|
|
|
@ -715,8 +715,8 @@ int vdso_getcpu_init(void)
|
||||||
unsigned long cpu, node, val;
|
unsigned long cpu, node, val;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in
|
* SPRG_VDSO contains the CPU in the bottom 16 bits and the NUMA node
|
||||||
* the next 16 bits. The VDSO uses this to implement getcpu().
|
* in the next 16 bits. The VDSO uses this to implement getcpu().
|
||||||
*/
|
*/
|
||||||
cpu = get_cpu();
|
cpu = get_cpu();
|
||||||
WARN_ON_ONCE(cpu > 0xffff);
|
WARN_ON_ONCE(cpu > 0xffff);
|
||||||
|
@ -725,8 +725,8 @@ int vdso_getcpu_init(void)
|
||||||
WARN_ON_ONCE(node > 0xffff);
|
WARN_ON_ONCE(node > 0xffff);
|
||||||
|
|
||||||
val = (cpu & 0xfff) | ((node & 0xffff) << 16);
|
val = (cpu & 0xfff) | ((node & 0xffff) << 16);
|
||||||
mtspr(SPRN_SPRG3, val);
|
mtspr(SPRN_SPRG_VDSO_WRITE, val);
|
||||||
get_paca()->sprg3 = val;
|
get_paca()->sprg_vdso = val;
|
||||||
|
|
||||||
put_cpu();
|
put_cpu();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
V_FUNCTION_BEGIN(__kernel_getcpu)
|
V_FUNCTION_BEGIN(__kernel_getcpu)
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
mfspr r5,SPRN_USPRG3
|
mfspr r5,SPRN_SPRG_VDSO_READ
|
||||||
cmpdi cr0,r3,0
|
cmpdi cr0,r3,0
|
||||||
cmpdi cr1,r4,0
|
cmpdi cr1,r4,0
|
||||||
clrlwi r6,r5,16
|
clrlwi r6,r5,16
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
V_FUNCTION_BEGIN(__kernel_getcpu)
|
V_FUNCTION_BEGIN(__kernel_getcpu)
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
mfspr r5,SPRN_USPRG3
|
mfspr r5,SPRN_SPRG_VDSO_READ
|
||||||
cmpdi cr0,r3,0
|
cmpdi cr0,r3,0
|
||||||
cmpdi cr1,r4,0
|
cmpdi cr1,r4,0
|
||||||
clrlwi r6,r5,16
|
clrlwi r6,r5,16
|
||||||
|
|
|
@ -75,8 +75,8 @@ BEGIN_FTR_SECTION
|
||||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
||||||
|
|
||||||
/* Restore SPRG3 */
|
/* Restore SPRG3 */
|
||||||
ld r3,PACA_SPRG3(r13)
|
ld r3,PACA_SPRG_VDSO(r13)
|
||||||
mtspr SPRN_SPRG3,r3
|
mtspr SPRN_SPRG_VDSO_WRITE,r3
|
||||||
|
|
||||||
/* Reload the host's PMU registers */
|
/* Reload the host's PMU registers */
|
||||||
ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */
|
ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */
|
||||||
|
|
|
@ -153,8 +153,8 @@ kvm_start_lightweight:
|
||||||
* Reload kernel SPRG3 value.
|
* Reload kernel SPRG3 value.
|
||||||
* No need to save guest value as usermode can't modify SPRG3.
|
* No need to save guest value as usermode can't modify SPRG3.
|
||||||
*/
|
*/
|
||||||
ld r3, PACA_SPRG3(r13)
|
ld r3, PACA_SPRG_VDSO(r13)
|
||||||
mtspr SPRN_SPRG3, r3
|
mtspr SPRN_SPRG_VDSO_WRITE, r3
|
||||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||||
|
|
||||||
/* R7 = vcpu */
|
/* R7 = vcpu */
|
||||||
|
|
|
@ -229,11 +229,7 @@
|
||||||
stw r10, VCPU_CR(r4)
|
stw r10, VCPU_CR(r4)
|
||||||
PPC_STL r11, VCPU_GPR(R4)(r4)
|
PPC_STL r11, VCPU_GPR(R4)(r4)
|
||||||
PPC_STL r5, VCPU_GPR(R5)(r4)
|
PPC_STL r5, VCPU_GPR(R5)(r4)
|
||||||
.if \type == EX_CRIT
|
|
||||||
PPC_LL r5, (\paca_ex + EX_R13)(r13)
|
|
||||||
.else
|
|
||||||
mfspr r5, \scratch
|
mfspr r5, \scratch
|
||||||
.endif
|
|
||||||
PPC_STL r6, VCPU_GPR(R6)(r4)
|
PPC_STL r6, VCPU_GPR(R6)(r4)
|
||||||
PPC_STL r8, VCPU_GPR(R8)(r4)
|
PPC_STL r8, VCPU_GPR(R8)(r4)
|
||||||
PPC_STL r9, VCPU_GPR(R9)(r4)
|
PPC_STL r9, VCPU_GPR(R9)(r4)
|
||||||
|
@ -435,10 +431,16 @@ _GLOBAL(kvmppc_resume_host)
|
||||||
PPC_STL r5, VCPU_LR(r4)
|
PPC_STL r5, VCPU_LR(r4)
|
||||||
mfspr r7, SPRN_SPRG5
|
mfspr r7, SPRN_SPRG5
|
||||||
stw r3, VCPU_VRSAVE(r4)
|
stw r3, VCPU_VRSAVE(r4)
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
PPC_LL r3, PACA_SPRG_VDSO(r13)
|
||||||
|
#endif
|
||||||
PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
|
PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
|
||||||
mfspr r8, SPRN_SPRG6
|
mfspr r8, SPRN_SPRG6
|
||||||
PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
|
PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
|
||||||
mfspr r9, SPRN_SPRG7
|
mfspr r9, SPRN_SPRG7
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
mtspr SPRN_SPRG_VDSO_WRITE, r3
|
||||||
|
#endif
|
||||||
PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
|
PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
|
||||||
mfxer r3
|
mfxer r3
|
||||||
PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
|
PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
|
||||||
|
|
Loading…
Reference in New Issue