diff options
author | Paul Mackerras <paulus@ozlabs.org> | 2016-11-17 21:11:42 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@ozlabs.org> | 2016-11-23 17:24:23 -0500 |
commit | e9cf1e085647b433ccd98582681b17121ecfdc21 (patch) | |
tree | 6147ebf857ac4c8ff7439c0f2d038745ea6763be | |
parent | 83677f551e0a6ad43061053e7d6208abcd2707f0 (diff) |
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>
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/uapi/asm/kvm.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 12 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 39 |
6 files changed, 59 insertions, 2 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index a7596e9fdf06..8a5ebd118313 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -2023,6 +2023,8 @@ registers, find a list below: | |||
2023 | PPC | KVM_REG_PPC_WORT | 64 | 2023 | PPC | KVM_REG_PPC_WORT | 64 |
2024 | PPC | KVM_REG_PPC_SPRG9 | 64 | 2024 | PPC | KVM_REG_PPC_SPRG9 | 64 |
2025 | PPC | KVM_REG_PPC_DBSR | 32 | 2025 | PPC | KVM_REG_PPC_DBSR | 32 |
2026 | PPC | KVM_REG_PPC_TIDR | 64 | ||
2027 | PPC | KVM_REG_PPC_PSSCR | 64 | ||
2026 | PPC | KVM_REG_PPC_TM_GPR0 | 64 | 2028 | PPC | KVM_REG_PPC_TM_GPR0 | 64 |
2027 | ... | 2029 | ... |
2028 | PPC | KVM_REG_PPC_TM_GPR31 | 64 | 2030 | PPC | KVM_REG_PPC_TM_GPR31 | 64 |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 0e584ee57730..9556de61b1bb 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -517,6 +517,8 @@ struct kvm_vcpu_arch { | |||
517 | ulong tcscr; | 517 | ulong tcscr; |
518 | ulong acop; | 518 | ulong acop; |
519 | ulong wort; | 519 | ulong wort; |
520 | ulong tid; | ||
521 | ulong psscr; | ||
520 | ulong shadow_srr1; | 522 | ulong shadow_srr1; |
521 | #endif | 523 | #endif |
522 | u32 vrsave; /* also USPRG0 */ | 524 | u32 vrsave; /* also USPRG0 */ |
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 0fb1326c3ea2..3603b6f51b11 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h | |||
@@ -573,6 +573,10 @@ struct kvm_get_htab_header { | |||
573 | #define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba) | 573 | #define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba) |
574 | #define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb) | 574 | #define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb) |
575 | 575 | ||
576 | /* POWER9 registers */ | ||
577 | #define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc) | ||
578 | #define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd) | ||
579 | |||
576 | /* Transactional Memory checkpointed state: | 580 | /* Transactional Memory checkpointed state: |
577 | * This is all GPRs, all VSX regs and a subset of SPRs | 581 | * This is all GPRs, all VSX regs and a subset of SPRs |
578 | */ | 582 | */ |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index c833d88c423d..a4f6d5e32a81 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -548,6 +548,8 @@ int main(void) | |||
548 | DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr)); | 548 | DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr)); |
549 | DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop)); | 549 | DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop)); |
550 | DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort)); | 550 | DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort)); |
551 | DEFINE(VCPU_TID, offsetof(struct kvm_vcpu, arch.tid)); | ||
552 | DEFINE(VCPU_PSSCR, offsetof(struct kvm_vcpu, arch.psscr)); | ||
551 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map)); | 553 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map)); |
552 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); | 554 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); |
553 | DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads)); | 555 | DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads)); |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 13b6e6154c90..14eeacc82336 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -1230,6 +1230,12 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
1230 | case KVM_REG_PPC_WORT: | 1230 | case KVM_REG_PPC_WORT: |
1231 | *val = get_reg_val(id, vcpu->arch.wort); | 1231 | *val = get_reg_val(id, vcpu->arch.wort); |
1232 | break; | 1232 | break; |
1233 | case KVM_REG_PPC_TIDR: | ||
1234 | *val = get_reg_val(id, vcpu->arch.tid); | ||
1235 | break; | ||
1236 | case KVM_REG_PPC_PSSCR: | ||
1237 | *val = get_reg_val(id, vcpu->arch.psscr); | ||
1238 | break; | ||
1233 | case KVM_REG_PPC_VPA_ADDR: | 1239 | case KVM_REG_PPC_VPA_ADDR: |
1234 | spin_lock(&vcpu->arch.vpa_update_lock); | 1240 | spin_lock(&vcpu->arch.vpa_update_lock); |
1235 | *val = get_reg_val(id, vcpu->arch.vpa.next_gpa); | 1241 | *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, | |||
1431 | case KVM_REG_PPC_WORT: | 1437 | case KVM_REG_PPC_WORT: |
1432 | vcpu->arch.wort = set_reg_val(id, *val); | 1438 | vcpu->arch.wort = set_reg_val(id, *val); |
1433 | break; | 1439 | break; |
1440 | case KVM_REG_PPC_TIDR: | ||
1441 | vcpu->arch.tid = set_reg_val(id, *val); | ||
1442 | break; | ||
1443 | case KVM_REG_PPC_PSSCR: | ||
1444 | vcpu->arch.psscr = set_reg_val(id, *val) & PSSCR_GUEST_VIS; | ||
1445 | break; | ||
1434 | case KVM_REG_PPC_VPA_ADDR: | 1446 | case KVM_REG_PPC_VPA_ADDR: |
1435 | addr = set_reg_val(id, *val); | 1447 | addr = set_reg_val(id, *val); |
1436 | r = -EINVAL; | 1448 | r = -EINVAL; |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index c7dd251ac05d..499be609c80e 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -523,6 +523,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
523 | * * | 523 | * * |
524 | *****************************************************************************/ | 524 | *****************************************************************************/ |
525 | 525 | ||
526 | /* Stack frame offsets */ | ||
527 | #define STACK_SLOT_TID (112-16) | ||
528 | #define STACK_SLOT_PSSCR (112-24) | ||
529 | |||
526 | .global kvmppc_hv_entry | 530 | .global kvmppc_hv_entry |
527 | kvmppc_hv_entry: | 531 | kvmppc_hv_entry: |
528 | 532 | ||
@@ -700,6 +704,14 @@ kvmppc_got_guest: | |||
700 | mtspr SPRN_PURR,r7 | 704 | mtspr SPRN_PURR,r7 |
701 | mtspr SPRN_SPURR,r8 | 705 | mtspr SPRN_SPURR,r8 |
702 | 706 | ||
707 | /* Save host values of some registers */ | ||
708 | BEGIN_FTR_SECTION | ||
709 | mfspr r5, SPRN_TIDR | ||
710 | mfspr r6, SPRN_PSSCR | ||
711 | std r5, STACK_SLOT_TID(r1) | ||
712 | std r6, STACK_SLOT_PSSCR(r1) | ||
713 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) | ||
714 | |||
703 | BEGIN_FTR_SECTION | 715 | BEGIN_FTR_SECTION |
704 | /* Set partition DABR */ | 716 | /* Set partition DABR */ |
705 | /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ | 717 | /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ |
@@ -824,6 +836,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) | |||
824 | mtspr SPRN_PID, r7 | 836 | mtspr SPRN_PID, r7 |
825 | mtspr SPRN_WORT, r8 | 837 | mtspr SPRN_WORT, r8 |
826 | BEGIN_FTR_SECTION | 838 | BEGIN_FTR_SECTION |
839 | /* POWER8-only registers */ | ||
827 | ld r5, VCPU_TCSCR(r4) | 840 | ld r5, VCPU_TCSCR(r4) |
828 | ld r6, VCPU_ACOP(r4) | 841 | ld r6, VCPU_ACOP(r4) |
829 | ld r7, VCPU_CSIGR(r4) | 842 | ld r7, VCPU_CSIGR(r4) |
@@ -832,7 +845,14 @@ BEGIN_FTR_SECTION | |||
832 | mtspr SPRN_ACOP, r6 | 845 | mtspr SPRN_ACOP, r6 |
833 | mtspr SPRN_CSIGR, r7 | 846 | mtspr SPRN_CSIGR, r7 |
834 | mtspr SPRN_TACR, r8 | 847 | mtspr SPRN_TACR, r8 |
835 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) | 848 | FTR_SECTION_ELSE |
849 | /* POWER9-only registers */ | ||
850 | ld r5, VCPU_TID(r4) | ||
851 | ld r6, VCPU_PSSCR(r4) | ||
852 | oris r6, r6, PSSCR_EC@h /* This makes stop trap to HV */ | ||
853 | mtspr SPRN_TIDR, r5 | ||
854 | mtspr SPRN_PSSCR, r6 | ||
855 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) | ||
836 | 8: | 856 | 8: |
837 | 857 | ||
838 | /* | 858 | /* |
@@ -1362,7 +1382,14 @@ BEGIN_FTR_SECTION | |||
1362 | std r6, VCPU_ACOP(r9) | 1382 | std r6, VCPU_ACOP(r9) |
1363 | std r7, VCPU_CSIGR(r9) | 1383 | std r7, VCPU_CSIGR(r9) |
1364 | std r8, VCPU_TACR(r9) | 1384 | std r8, VCPU_TACR(r9) |
1365 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) | 1385 | FTR_SECTION_ELSE |
1386 | mfspr r5, SPRN_TIDR | ||
1387 | mfspr r6, SPRN_PSSCR | ||
1388 | std r5, VCPU_TID(r9) | ||
1389 | rldicl r6, r6, 4, 50 /* r6 &= PSSCR_GUEST_VIS */ | ||
1390 | rotldi r6, r6, 60 | ||
1391 | std r6, VCPU_PSSCR(r9) | ||
1392 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) | ||
1366 | /* | 1393 | /* |
1367 | * Restore various registers to 0, where non-zero values | 1394 | * Restore various registers to 0, where non-zero values |
1368 | * set by the guest could disrupt the host. | 1395 | * set by the guest could disrupt the host. |
@@ -1531,6 +1558,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
1531 | slbia | 1558 | slbia |
1532 | ptesync | 1559 | ptesync |
1533 | 1560 | ||
1561 | /* Restore host values of some registers */ | ||
1562 | BEGIN_FTR_SECTION | ||
1563 | ld r5, STACK_SLOT_TID(r1) | ||
1564 | ld r6, STACK_SLOT_PSSCR(r1) | ||
1565 | mtspr SPRN_TIDR, r5 | ||
1566 | mtspr SPRN_PSSCR, r6 | ||
1567 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) | ||
1568 | |||
1534 | /* | 1569 | /* |
1535 | * POWER7/POWER8 guest -> host partition switch code. | 1570 | * POWER7/POWER8 guest -> host partition switch code. |
1536 | * We don't have to lock against tlbies but we do | 1571 | * We don't have to lock against tlbies but we do |