KVM: PPC: Book3S HV: Add new POWER9 guest-accessible SPRs
This adds code to handle two new guest-accessible special-purpose registers on POWER9: TIDR (thread ID register) and PSSCR (processor stop status and control register). They are context-switched between host and guest, and the guest values can be read and set via the one_reg interface. The PSSCR contains some fields which are guest-accessible and some which are only accessible in hypervisor mode. We only allow the guest-accessible fields to be read or set by userspace. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
83677f551e
commit
e9cf1e0856
|
@ -2023,6 +2023,8 @@ registers, find a list below:
|
||||||
PPC | KVM_REG_PPC_WORT | 64
|
PPC | KVM_REG_PPC_WORT | 64
|
||||||
PPC | KVM_REG_PPC_SPRG9 | 64
|
PPC | KVM_REG_PPC_SPRG9 | 64
|
||||||
PPC | KVM_REG_PPC_DBSR | 32
|
PPC | KVM_REG_PPC_DBSR | 32
|
||||||
|
PPC | KVM_REG_PPC_TIDR | 64
|
||||||
|
PPC | KVM_REG_PPC_PSSCR | 64
|
||||||
PPC | KVM_REG_PPC_TM_GPR0 | 64
|
PPC | KVM_REG_PPC_TM_GPR0 | 64
|
||||||
...
|
...
|
||||||
PPC | KVM_REG_PPC_TM_GPR31 | 64
|
PPC | KVM_REG_PPC_TM_GPR31 | 64
|
||||||
|
|
|
@ -517,6 +517,8 @@ struct kvm_vcpu_arch {
|
||||||
ulong tcscr;
|
ulong tcscr;
|
||||||
ulong acop;
|
ulong acop;
|
||||||
ulong wort;
|
ulong wort;
|
||||||
|
ulong tid;
|
||||||
|
ulong psscr;
|
||||||
ulong shadow_srr1;
|
ulong shadow_srr1;
|
||||||
#endif
|
#endif
|
||||||
u32 vrsave; /* also USPRG0 */
|
u32 vrsave; /* also USPRG0 */
|
||||||
|
|
|
@ -573,6 +573,10 @@ struct kvm_get_htab_header {
|
||||||
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
|
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
|
||||||
#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
|
#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
|
||||||
|
|
||||||
|
/* POWER9 registers */
|
||||||
|
#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
|
||||||
|
#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
|
||||||
|
|
||||||
/* Transactional Memory checkpointed state:
|
/* Transactional Memory checkpointed state:
|
||||||
* This is all GPRs, all VSX regs and a subset of SPRs
|
* This is all GPRs, all VSX regs and a subset of SPRs
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -548,6 +548,8 @@ int main(void)
|
||||||
DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr));
|
DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr));
|
||||||
DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
|
DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
|
||||||
DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
|
DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
|
||||||
|
DEFINE(VCPU_TID, offsetof(struct kvm_vcpu, arch.tid));
|
||||||
|
DEFINE(VCPU_PSSCR, offsetof(struct kvm_vcpu, arch.psscr));
|
||||||
DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map));
|
DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map));
|
||||||
DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
|
DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
|
||||||
DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
|
DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
|
||||||
|
|
|
@ -1230,6 +1230,12 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||||
case KVM_REG_PPC_WORT:
|
case KVM_REG_PPC_WORT:
|
||||||
*val = get_reg_val(id, vcpu->arch.wort);
|
*val = get_reg_val(id, vcpu->arch.wort);
|
||||||
break;
|
break;
|
||||||
|
case KVM_REG_PPC_TIDR:
|
||||||
|
*val = get_reg_val(id, vcpu->arch.tid);
|
||||||
|
break;
|
||||||
|
case KVM_REG_PPC_PSSCR:
|
||||||
|
*val = get_reg_val(id, vcpu->arch.psscr);
|
||||||
|
break;
|
||||||
case KVM_REG_PPC_VPA_ADDR:
|
case KVM_REG_PPC_VPA_ADDR:
|
||||||
spin_lock(&vcpu->arch.vpa_update_lock);
|
spin_lock(&vcpu->arch.vpa_update_lock);
|
||||||
*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
|
*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
|
||||||
|
@ -1431,6 +1437,12 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
|
||||||
case KVM_REG_PPC_WORT:
|
case KVM_REG_PPC_WORT:
|
||||||
vcpu->arch.wort = set_reg_val(id, *val);
|
vcpu->arch.wort = set_reg_val(id, *val);
|
||||||
break;
|
break;
|
||||||
|
case KVM_REG_PPC_TIDR:
|
||||||
|
vcpu->arch.tid = set_reg_val(id, *val);
|
||||||
|
break;
|
||||||
|
case KVM_REG_PPC_PSSCR:
|
||||||
|
vcpu->arch.psscr = set_reg_val(id, *val) & PSSCR_GUEST_VIS;
|
||||||
|
break;
|
||||||
case KVM_REG_PPC_VPA_ADDR:
|
case KVM_REG_PPC_VPA_ADDR:
|
||||||
addr = set_reg_val(id, *val);
|
addr = set_reg_val(id, *val);
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
|
|
|
@ -523,6 +523,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||||
* *
|
* *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/* Stack frame offsets */
|
||||||
|
#define STACK_SLOT_TID (112-16)
|
||||||
|
#define STACK_SLOT_PSSCR (112-24)
|
||||||
|
|
||||||
.global kvmppc_hv_entry
|
.global kvmppc_hv_entry
|
||||||
kvmppc_hv_entry:
|
kvmppc_hv_entry:
|
||||||
|
|
||||||
|
@ -700,6 +704,14 @@ kvmppc_got_guest:
|
||||||
mtspr SPRN_PURR,r7
|
mtspr SPRN_PURR,r7
|
||||||
mtspr SPRN_SPURR,r8
|
mtspr SPRN_SPURR,r8
|
||||||
|
|
||||||
|
/* Save host values of some registers */
|
||||||
|
BEGIN_FTR_SECTION
|
||||||
|
mfspr r5, SPRN_TIDR
|
||||||
|
mfspr r6, SPRN_PSSCR
|
||||||
|
std r5, STACK_SLOT_TID(r1)
|
||||||
|
std r6, STACK_SLOT_PSSCR(r1)
|
||||||
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
||||||
|
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
/* Set partition DABR */
|
/* Set partition DABR */
|
||||||
/* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
|
/* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
|
||||||
|
@ -824,6 +836,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
||||||
mtspr SPRN_PID, r7
|
mtspr SPRN_PID, r7
|
||||||
mtspr SPRN_WORT, r8
|
mtspr SPRN_WORT, r8
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
|
/* POWER8-only registers */
|
||||||
ld r5, VCPU_TCSCR(r4)
|
ld r5, VCPU_TCSCR(r4)
|
||||||
ld r6, VCPU_ACOP(r4)
|
ld r6, VCPU_ACOP(r4)
|
||||||
ld r7, VCPU_CSIGR(r4)
|
ld r7, VCPU_CSIGR(r4)
|
||||||
|
@ -832,7 +845,14 @@ BEGIN_FTR_SECTION
|
||||||
mtspr SPRN_ACOP, r6
|
mtspr SPRN_ACOP, r6
|
||||||
mtspr SPRN_CSIGR, r7
|
mtspr SPRN_CSIGR, r7
|
||||||
mtspr SPRN_TACR, r8
|
mtspr SPRN_TACR, r8
|
||||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
|
FTR_SECTION_ELSE
|
||||||
|
/* POWER9-only registers */
|
||||||
|
ld r5, VCPU_TID(r4)
|
||||||
|
ld r6, VCPU_PSSCR(r4)
|
||||||
|
oris r6, r6, PSSCR_EC@h /* This makes stop trap to HV */
|
||||||
|
mtspr SPRN_TIDR, r5
|
||||||
|
mtspr SPRN_PSSCR, r6
|
||||||
|
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
||||||
8:
|
8:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1362,7 +1382,14 @@ BEGIN_FTR_SECTION
|
||||||
std r6, VCPU_ACOP(r9)
|
std r6, VCPU_ACOP(r9)
|
||||||
std r7, VCPU_CSIGR(r9)
|
std r7, VCPU_CSIGR(r9)
|
||||||
std r8, VCPU_TACR(r9)
|
std r8, VCPU_TACR(r9)
|
||||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
|
FTR_SECTION_ELSE
|
||||||
|
mfspr r5, SPRN_TIDR
|
||||||
|
mfspr r6, SPRN_PSSCR
|
||||||
|
std r5, VCPU_TID(r9)
|
||||||
|
rldicl r6, r6, 4, 50 /* r6 &= PSSCR_GUEST_VIS */
|
||||||
|
rotldi r6, r6, 60
|
||||||
|
std r6, VCPU_PSSCR(r9)
|
||||||
|
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
||||||
/*
|
/*
|
||||||
* Restore various registers to 0, where non-zero values
|
* Restore various registers to 0, where non-zero values
|
||||||
* set by the guest could disrupt the host.
|
* set by the guest could disrupt the host.
|
||||||
|
@ -1531,6 +1558,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||||
slbia
|
slbia
|
||||||
ptesync
|
ptesync
|
||||||
|
|
||||||
|
/* Restore host values of some registers */
|
||||||
|
BEGIN_FTR_SECTION
|
||||||
|
ld r5, STACK_SLOT_TID(r1)
|
||||||
|
ld r6, STACK_SLOT_PSSCR(r1)
|
||||||
|
mtspr SPRN_TIDR, r5
|
||||||
|
mtspr SPRN_PSSCR, r6
|
||||||
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* POWER7/POWER8 guest -> host partition switch code.
|
* POWER7/POWER8 guest -> host partition switch code.
|
||||||
* We don't have to lock against tlbies but we do
|
* We don't have to lock against tlbies but we do
|
||||||
|
|
Loading…
Reference in New Issue