summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2018-03-21 06:32:01 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2018-03-23 09:39:13 -0400
commit4bb3c7a0208fc13ca70598efd109901a7cd45ae7 (patch)
tree603753d07e9d0d0b9900a4c4ecb0c9d55a645d18
parent7672691a08c886e53ccbf8cdca406f8c92ec7a20 (diff)
KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
POWER9 has hardware bugs relating to transactional memory and thread reconfiguration (changes to hardware SMT mode). Specifically, the core does not have enough storage to store a complete checkpoint of all the architected state for all four threads. The DD2.2 version of POWER9 includes hardware modifications designed to allow hypervisor software to implement workarounds for these problems. This patch implements those workarounds in KVM code so that KVM guests see a full, working transactional memory implementation. The problems center around the use of TM suspended state, where the CPU has a checkpointed state but execution is not transactional. The workaround is to implement a "fake suspend" state, which looks to the guest like suspended state but the CPU does not store a checkpoint. In this state, any instruction that would cause a transition to transactional state (rfid, rfebb, mtmsrd, tresume) or would use the checkpointed state (treclaim) causes a "soft patch" interrupt (vector 0x1500) to the hypervisor so that it can be emulated. The trechkpt instruction also causes a soft patch interrupt. On POWER9 DD2.2, we avoid returning to the guest in any state which would require a checkpoint to be present. The trechkpt in the guest entry path which would normally create that checkpoint is replaced by either a transition to fake suspend state, if the guest is in suspend state, or a rollback to the pre-transactional state if the guest is in transactional state. Fake suspend state is indicated by a flag in the PACA plus a new bit in the PSSCR. The new PSSCR bit is write-only and reads back as 0. On exit from the guest, if the guest is in fake suspend state, we still do the treclaim instruction as we would in real suspend state, in order to get into non-transactional state, but we do not save the resulting register state since there was no checkpoint. Emulation of the instructions that cause a softpatch interrupt is handled in two paths. If the guest is in real suspend mode, we call kvmhv_p9_tm_emulation_early() to handle the cases where the guest is transitioning to transactional state. This is called before we do the treclaim in the guest exit path; because we haven't done treclaim, we can get back to the guest with the transaction still active. If the instruction is a case that kvmhv_p9_tm_emulation_early() doesn't handle, or if the guest is in fake suspend state, then we proceed to do the complete guest exit path and subsequently call kvmhv_p9_tm_emulation() in host context with the MMU on. This handles all the cases including the cases that generate program interrupts (illegal instruction or TM Bad Thing) and facility unavailable interrupts. The emulation is reasonably straightforward and is mostly concerned with checking for exception conditions and updating the state of registers such as MSR and CR0. The treclaim emulation takes care to ensure that the TEXASR register gets updated as if it were the guest treclaim instruction that had done failure recording, not the treclaim done in hypervisor state in the guest exit path. With this, the KVM_CAP_PPC_HTM capability returns true (1) even if transactional memory is not available to host userspace. Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/kvm_asm.h2
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h4
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h43
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_asm.h1
-rw-r--r--arch/powerpc/include/asm/kvm_host.h1
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h4
-rw-r--r--arch/powerpc/include/asm/reg.h7
-rw-r--r--arch/powerpc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/kernel/cputable.c1
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S4
-rw-r--r--arch/powerpc/kvm/Makefile7
-rw-r--r--arch/powerpc/kvm/book3s_hv.c18
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S143
-rw-r--r--arch/powerpc/kvm/book3s_hv_tm.c216
-rw-r--r--arch/powerpc/kvm/book3s_hv_tm_builtin.c109
-rw-r--r--arch/powerpc/kvm/powerpc.c5
16 files changed, 557 insertions, 10 deletions
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 09a802bb702f..a790d5cf6ea3 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -108,6 +108,8 @@
108 108
109/* book3s_hv */ 109/* book3s_hv */
110 110
111#define BOOK3S_INTERRUPT_HV_SOFTPATCH 0x1500
112
111/* 113/*
112 * Special trap used to indicate to host that this is a 114 * Special trap used to indicate to host that this is a
113 * passthrough interrupt that could not be handled 115 * passthrough interrupt that could not be handled
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 376ae803b69c..4c02a7378d06 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -241,6 +241,10 @@ extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr,
241 unsigned long mask); 241 unsigned long mask);
242extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); 242extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr);
243 243
244extern int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu);
245extern int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu);
246extern void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu);
247
244extern void kvmppc_entry_trampoline(void); 248extern void kvmppc_entry_trampoline(void);
245extern void kvmppc_hv_entry_trampoline(void); 249extern void kvmppc_hv_entry_trampoline(void);
246extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); 250extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 998f7b7aaa9e..c424e44f4c00 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -472,6 +472,49 @@ static inline void set_dirty_bits_atomic(unsigned long *map, unsigned long i,
472 set_bit_le(i, map); 472 set_bit_le(i, map);
473} 473}
474 474
475static inline u64 sanitize_msr(u64 msr)
476{
477 msr &= ~MSR_HV;
478 msr |= MSR_ME;
479 return msr;
480}
481
482#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
483static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu)
484{
485 vcpu->arch.cr = vcpu->arch.cr_tm;
486 vcpu->arch.xer = vcpu->arch.xer_tm;
487 vcpu->arch.lr = vcpu->arch.lr_tm;
488 vcpu->arch.ctr = vcpu->arch.ctr_tm;
489 vcpu->arch.amr = vcpu->arch.amr_tm;
490 vcpu->arch.ppr = vcpu->arch.ppr_tm;
491 vcpu->arch.dscr = vcpu->arch.dscr_tm;
492 vcpu->arch.tar = vcpu->arch.tar_tm;
493 memcpy(vcpu->arch.gpr, vcpu->arch.gpr_tm,
494 sizeof(vcpu->arch.gpr));
495 vcpu->arch.fp = vcpu->arch.fp_tm;
496 vcpu->arch.vr = vcpu->arch.vr_tm;
497 vcpu->arch.vrsave = vcpu->arch.vrsave_tm;
498}
499
500static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu)
501{
502 vcpu->arch.cr_tm = vcpu->arch.cr;
503 vcpu->arch.xer_tm = vcpu->arch.xer;
504 vcpu->arch.lr_tm = vcpu->arch.lr;
505 vcpu->arch.ctr_tm = vcpu->arch.ctr;
506 vcpu->arch.amr_tm = vcpu->arch.amr;
507 vcpu->arch.ppr_tm = vcpu->arch.ppr;
508 vcpu->arch.dscr_tm = vcpu->arch.dscr;
509 vcpu->arch.tar_tm = vcpu->arch.tar;
510 memcpy(vcpu->arch.gpr_tm, vcpu->arch.gpr,
511 sizeof(vcpu->arch.gpr));
512 vcpu->arch.fp_tm = vcpu->arch.fp;
513 vcpu->arch.vr_tm = vcpu->arch.vr;
514 vcpu->arch.vrsave_tm = vcpu->arch.vrsave;
515}
516#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
517
475#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ 518#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
476 519
477#endif /* __ASM_KVM_BOOK3S_64_H__ */ 520#endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index ab386af2904f..d978fdf698af 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -119,6 +119,7 @@ struct kvmppc_host_state {
119 u8 host_ipi; 119 u8 host_ipi;
120 u8 ptid; /* thread number within subcore when split */ 120 u8 ptid; /* thread number within subcore when split */
121 u8 tid; /* thread number within whole core */ 121 u8 tid; /* thread number within whole core */
122 u8 fake_suspend;
122 struct kvm_vcpu *kvm_vcpu; 123 struct kvm_vcpu *kvm_vcpu;
123 struct kvmppc_vcore *kvm_vcore; 124 struct kvmppc_vcore *kvm_vcore;
124 void __iomem *xics_phys; 125 void __iomem *xics_phys;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 1f53b562726f..deb54293398c 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -610,6 +610,7 @@ struct kvm_vcpu_arch {
610 u64 tfhar; 610 u64 tfhar;
611 u64 texasr; 611 u64 texasr;
612 u64 tfiar; 612 u64 tfiar;
613 u64 orig_texasr;
613 614
614 u32 cr_tm; 615 u32 cr_tm;
615 u64 xer_tm; 616 u64 xer_tm;
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index f1083bcf449c..772eff7fd446 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -232,6 +232,7 @@
232#define PPC_INST_MSGSYNC 0x7c0006ec 232#define PPC_INST_MSGSYNC 0x7c0006ec
233#define PPC_INST_MSGSNDP 0x7c00011c 233#define PPC_INST_MSGSNDP 0x7c00011c
234#define PPC_INST_MSGCLRP 0x7c00015c 234#define PPC_INST_MSGCLRP 0x7c00015c
235#define PPC_INST_MTMSRD 0x7c000164
235#define PPC_INST_MTTMR 0x7c0003dc 236#define PPC_INST_MTTMR 0x7c0003dc
236#define PPC_INST_NOP 0x60000000 237#define PPC_INST_NOP 0x60000000
237#define PPC_INST_PASTE 0x7c20070d 238#define PPC_INST_PASTE 0x7c20070d
@@ -239,8 +240,10 @@
239#define PPC_INST_POPCNTB_MASK 0xfc0007fe 240#define PPC_INST_POPCNTB_MASK 0xfc0007fe
240#define PPC_INST_POPCNTD 0x7c0003f4 241#define PPC_INST_POPCNTD 0x7c0003f4
241#define PPC_INST_POPCNTW 0x7c0002f4 242#define PPC_INST_POPCNTW 0x7c0002f4
243#define PPC_INST_RFEBB 0x4c000124
242#define PPC_INST_RFCI 0x4c000066 244#define PPC_INST_RFCI 0x4c000066
243#define PPC_INST_RFDI 0x4c00004e 245#define PPC_INST_RFDI 0x4c00004e
246#define PPC_INST_RFID 0x4c000024
244#define PPC_INST_RFMCI 0x4c00004c 247#define PPC_INST_RFMCI 0x4c00004c
245#define PPC_INST_MFSPR 0x7c0002a6 248#define PPC_INST_MFSPR 0x7c0002a6
246#define PPC_INST_MFSPR_DSCR 0x7c1102a6 249#define PPC_INST_MFSPR_DSCR 0x7c1102a6
@@ -277,6 +280,7 @@
277#define PPC_INST_TRECHKPT 0x7c0007dd 280#define PPC_INST_TRECHKPT 0x7c0007dd
278#define PPC_INST_TRECLAIM 0x7c00075d 281#define PPC_INST_TRECLAIM 0x7c00075d
279#define PPC_INST_TABORT 0x7c00071d 282#define PPC_INST_TABORT 0x7c00071d
283#define PPC_INST_TSR 0x7c0005dd
280 284
281#define PPC_INST_NAP 0x4c000364 285#define PPC_INST_NAP 0x4c000364
282#define PPC_INST_SLEEP 0x4c0003a4 286#define PPC_INST_SLEEP 0x4c0003a4
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index e6c7eadf6bce..cb0f272ce123 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -156,6 +156,8 @@
156#define PSSCR_SD 0x00400000 /* Status Disable */ 156#define PSSCR_SD 0x00400000 /* Status Disable */
157#define PSSCR_PLS 0xf000000000000000 /* Power-saving Level Status */ 157#define PSSCR_PLS 0xf000000000000000 /* Power-saving Level Status */
158#define PSSCR_GUEST_VIS 0xf0000000000003ff /* Guest-visible PSSCR fields */ 158#define PSSCR_GUEST_VIS 0xf0000000000003ff /* Guest-visible PSSCR fields */
159#define PSSCR_FAKE_SUSPEND 0x00000400 /* Fake-suspend bit (P9 DD2.2) */
160#define PSSCR_FAKE_SUSPEND_LG 10 /* Fake-suspend bit position */
159 161
160/* Floating Point Status and Control Register (FPSCR) Fields */ 162/* Floating Point Status and Control Register (FPSCR) Fields */
161#define FPSCR_FX 0x80000000 /* FPU exception summary */ 163#define FPSCR_FX 0x80000000 /* FPU exception summary */
@@ -237,7 +239,12 @@
237#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ 239#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
238#define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ 240#define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */
239#define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ 241#define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */
242#define TEXASR_ABORT __MASK(63-31) /* terminated by tabort or treclaim */
243#define TEXASR_SUSP __MASK(63-32) /* tx failed in suspended state */
244#define TEXASR_HV __MASK(63-34) /* MSR[HV] when failure occurred */
245#define TEXASR_PR __MASK(63-35) /* MSR[PR] when failure occurred */
240#define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */ 246#define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */
247#define TEXASR_EXACT __MASK(63-37) /* TFIAR value is exact */
241#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ 248#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
242#define SPRN_TIDR 144 /* Thread ID register */ 249#define SPRN_TIDR 144 /* Thread ID register */
243#define SPRN_CTRLF 0x088 250#define SPRN_CTRLF 0x088
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index dbefe30d4daa..daf809a9b88e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -568,6 +568,7 @@ int main(void)
568 OFFSET(VCPU_TFHAR, kvm_vcpu, arch.tfhar); 568 OFFSET(VCPU_TFHAR, kvm_vcpu, arch.tfhar);
569 OFFSET(VCPU_TFIAR, kvm_vcpu, arch.tfiar); 569 OFFSET(VCPU_TFIAR, kvm_vcpu, arch.tfiar);
570 OFFSET(VCPU_TEXASR, kvm_vcpu, arch.texasr); 570 OFFSET(VCPU_TEXASR, kvm_vcpu, arch.texasr);
571 OFFSET(VCPU_ORIG_TEXASR, kvm_vcpu, arch.orig_texasr);
571 OFFSET(VCPU_GPR_TM, kvm_vcpu, arch.gpr_tm); 572 OFFSET(VCPU_GPR_TM, kvm_vcpu, arch.gpr_tm);
572 OFFSET(VCPU_FPRS_TM, kvm_vcpu, arch.fp_tm.fpr); 573 OFFSET(VCPU_FPRS_TM, kvm_vcpu, arch.fp_tm.fpr);
573 OFFSET(VCPU_VRS_TM, kvm_vcpu, arch.vr_tm.vr); 574 OFFSET(VCPU_VRS_TM, kvm_vcpu, arch.vr_tm.vr);
@@ -650,6 +651,7 @@ int main(void)
650 HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi); 651 HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);
651 HSTATE_FIELD(HSTATE_PTID, ptid); 652 HSTATE_FIELD(HSTATE_PTID, ptid);
652 HSTATE_FIELD(HSTATE_TID, tid); 653 HSTATE_FIELD(HSTATE_TID, tid);
654 HSTATE_FIELD(HSTATE_FAKE_SUSPEND, fake_suspend);
653 HSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]); 655 HSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]);
654 HSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]); 656 HSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]);
655 HSTATE_FIELD(HSTATE_MMCRA, host_mmcr[2]); 657 HSTATE_FIELD(HSTATE_MMCRA, host_mmcr[2]);
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 68052eacb827..b3de017bcd71 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -569,7 +569,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
569 .oprofile_type = PPC_OPROFILE_INVALID, 569 .oprofile_type = PPC_OPROFILE_INVALID,
570 .cpu_setup = __setup_cpu_power9, 570 .cpu_setup = __setup_cpu_power9,
571 .cpu_restore = __restore_cpu_power9, 571 .cpu_restore = __restore_cpu_power9,
572 .flush_tlb = __flush_tlb_power9,
573 .machine_check_early = __machine_check_early_realmode_p9, 572 .machine_check_early = __machine_check_early_realmode_p9,
574 .platform = "power9", 573 .platform = "power9",
575 }, 574 },
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 243d072a225a..9df9e0a40250 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1273,7 +1273,7 @@ EXC_REAL_BEGIN(denorm_exception_hv, 0x1500, 0x100)
1273 bne+ denorm_assist 1273 bne+ denorm_assist
1274#endif 1274#endif
1275 1275
1276 KVMTEST_PR(0x1500) 1276 KVMTEST_HV(0x1500)
1277 EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV) 1277 EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
1278EXC_REAL_END(denorm_exception_hv, 0x1500, 0x100) 1278EXC_REAL_END(denorm_exception_hv, 0x1500, 0x100)
1279 1279
@@ -1285,7 +1285,7 @@ EXC_VIRT_END(denorm_exception, 0x5500, 0x100)
1285EXC_VIRT_NONE(0x5500, 0x100) 1285EXC_VIRT_NONE(0x5500, 0x100)
1286#endif 1286#endif
1287 1287
1288TRAMP_KVM_SKIP(PACA_EXGEN, 0x1500) 1288TRAMP_KVM_HV(PACA_EXGEN, 0x1500)
1289 1289
1290#ifdef CONFIG_PPC_DENORMALISATION 1290#ifdef CONFIG_PPC_DENORMALISATION
1291TRAMP_REAL_BEGIN(denorm_assist) 1291TRAMP_REAL_BEGIN(denorm_assist)
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 85ba80de7133..4b19da8c87ae 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -74,9 +74,15 @@ kvm-hv-y += \
74 book3s_64_mmu_hv.o \ 74 book3s_64_mmu_hv.o \
75 book3s_64_mmu_radix.o 75 book3s_64_mmu_radix.o
76 76
77kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \
78 book3s_hv_tm.o
79
77kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ 80kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
78 book3s_hv_rm_xics.o book3s_hv_rm_xive.o 81 book3s_hv_rm_xics.o book3s_hv_rm_xive.o
79 82
83kvm-book3s_64-builtin-tm-objs-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \
84 book3s_hv_tm_builtin.o
85
80ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 86ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
81kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ 87kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
82 book3s_hv_hmi.o \ 88 book3s_hv_hmi.o \
@@ -84,6 +90,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
84 book3s_hv_rm_mmu.o \ 90 book3s_hv_rm_mmu.o \
85 book3s_hv_ras.o \ 91 book3s_hv_ras.o \
86 book3s_hv_builtin.o \ 92 book3s_hv_builtin.o \
93 $(kvm-book3s_64-builtin-tm-objs-y) \
87 $(kvm-book3s_64-builtin-xics-objs-y) 94 $(kvm-book3s_64-builtin-xics-objs-y)
88endif 95endif
89 96
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 89707354c2ef..a043bde4952c 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1206,6 +1206,19 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
1206 r = RESUME_GUEST; 1206 r = RESUME_GUEST;
1207 } 1207 }
1208 break; 1208 break;
1209
1210#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1211 case BOOK3S_INTERRUPT_HV_SOFTPATCH:
1212 /*
1213 * This occurs for various TM-related instructions that
1214 * we need to emulate on POWER9 DD2.2. We have already
1215 * handled the cases where the guest was in real-suspend
1216 * mode and was transitioning to transactional state.
1217 */
1218 r = kvmhv_p9_tm_emulation(vcpu);
1219 break;
1220#endif
1221
1209 case BOOK3S_INTERRUPT_HV_RM_HARD: 1222 case BOOK3S_INTERRUPT_HV_RM_HARD:
1210 r = RESUME_PASSTHROUGH; 1223 r = RESUME_PASSTHROUGH;
1211 break; 1224 break;
@@ -1978,7 +1991,9 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
1978 * turn off the HFSCR bit, which causes those instructions to trap. 1991 * turn off the HFSCR bit, which causes those instructions to trap.
1979 */ 1992 */
1980 vcpu->arch.hfscr = mfspr(SPRN_HFSCR); 1993 vcpu->arch.hfscr = mfspr(SPRN_HFSCR);
1981 if (!cpu_has_feature(CPU_FTR_TM)) 1994 if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
1995 vcpu->arch.hfscr |= HFSCR_TM;
1996 else if (!cpu_has_feature(CPU_FTR_TM_COMP))
1982 vcpu->arch.hfscr &= ~HFSCR_TM; 1997 vcpu->arch.hfscr &= ~HFSCR_TM;
1983 if (cpu_has_feature(CPU_FTR_ARCH_300)) 1998 if (cpu_has_feature(CPU_FTR_ARCH_300))
1984 vcpu->arch.hfscr &= ~HFSCR_MSGP; 1999 vcpu->arch.hfscr &= ~HFSCR_MSGP;
@@ -2242,6 +2257,7 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
2242 tpaca = &paca[cpu]; 2257 tpaca = &paca[cpu];
2243 tpaca->kvm_hstate.kvm_vcpu = vcpu; 2258 tpaca->kvm_hstate.kvm_vcpu = vcpu;
2244 tpaca->kvm_hstate.ptid = cpu - vc->pcpu; 2259 tpaca->kvm_hstate.ptid = cpu - vc->pcpu;
2260 tpaca->kvm_hstate.fake_suspend = 0;
2245 /* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */ 2261 /* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
2246 smp_wmb(); 2262 smp_wmb();
2247 tpaca->kvm_hstate.kvm_vcore = vc; 2263 tpaca->kvm_hstate.kvm_vcore = vc;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index f31f357b8c5a..5af617459244 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -787,12 +787,18 @@ BEGIN_FTR_SECTION
787END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) 787END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
788 788
789#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 789#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
790/*
791 * Branch around the call if both CPU_FTR_TM and
792 * CPU_FTR_P9_TM_HV_ASSIST are off.
793 */
790BEGIN_FTR_SECTION 794BEGIN_FTR_SECTION
795 b 91f
796END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
791 /* 797 /*
792 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR 798 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
793 */ 799 */
794 bl kvmppc_restore_tm 800 bl kvmppc_restore_tm
795END_FTR_SECTION_IFSET(CPU_FTR_TM) 80191:
796#endif 802#endif
797 803
798 /* Load guest PMU registers */ 804 /* Load guest PMU registers */
@@ -915,11 +921,14 @@ BEGIN_FTR_SECTION
915 mtspr SPRN_ACOP, r6 921 mtspr SPRN_ACOP, r6
916 mtspr SPRN_CSIGR, r7 922 mtspr SPRN_CSIGR, r7
917 mtspr SPRN_TACR, r8 923 mtspr SPRN_TACR, r8
924 nop
918FTR_SECTION_ELSE 925FTR_SECTION_ELSE
919 /* POWER9-only registers */ 926 /* POWER9-only registers */
920 ld r5, VCPU_TID(r4) 927 ld r5, VCPU_TID(r4)
921 ld r6, VCPU_PSSCR(r4) 928 ld r6, VCPU_PSSCR(r4)
929 lbz r8, HSTATE_FAKE_SUSPEND(r13)
922 oris r6, r6, PSSCR_EC@h /* This makes stop trap to HV */ 930 oris r6, r6, PSSCR_EC@h /* This makes stop trap to HV */
931 rldimi r6, r8, PSSCR_FAKE_SUSPEND_LG, 63 - PSSCR_FAKE_SUSPEND_LG
923 ld r7, VCPU_HFSCR(r4) 932 ld r7, VCPU_HFSCR(r4)
924 mtspr SPRN_TIDR, r5 933 mtspr SPRN_TIDR, r5
925 mtspr SPRN_PSSCR, r6 934 mtspr SPRN_PSSCR, r6
@@ -1370,6 +1379,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
1370 std r3, VCPU_CTR(r9) 1379 std r3, VCPU_CTR(r9)
1371 std r4, VCPU_XER(r9) 1380 std r4, VCPU_XER(r9)
1372 1381
1382#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1383 /* For softpatch interrupt, go off and do TM instruction emulation */
1384 cmpwi r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
1385 beq kvmppc_tm_emul
1386#endif
1387
1373 /* If this is a page table miss then see if it's theirs or ours */ 1388 /* If this is a page table miss then see if it's theirs or ours */
1374 cmpwi r12, BOOK3S_INTERRUPT_H_DATA_STORAGE 1389 cmpwi r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
1375 beq kvmppc_hdsi 1390 beq kvmppc_hdsi
@@ -1729,12 +1744,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
1729 bl kvmppc_save_fp 1744 bl kvmppc_save_fp
1730 1745
1731#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1746#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1747/*
1748 * Branch around the call if both CPU_FTR_TM and
1749 * CPU_FTR_P9_TM_HV_ASSIST are off.
1750 */
1732BEGIN_FTR_SECTION 1751BEGIN_FTR_SECTION
1752 b 91f
1753END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
1733 /* 1754 /*
1734 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR 1755 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
1735 */ 1756 */
1736 bl kvmppc_save_tm 1757 bl kvmppc_save_tm
1737END_FTR_SECTION_IFSET(CPU_FTR_TM) 175891:
1738#endif 1759#endif
1739 1760
1740 /* Increment yield count if they have a VPA */ 1761 /* Increment yield count if they have a VPA */
@@ -2054,6 +2075,42 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
2054 mtlr r0 2075 mtlr r0
2055 blr 2076 blr
2056 2077
2078#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2079/*
2080 * Softpatch interrupt for transactional memory emulation cases
2081 * on POWER9 DD2.2. This is early in the guest exit path - we
2082 * haven't saved registers or done a treclaim yet.
2083 */
2084kvmppc_tm_emul:
2085 /* Save instruction image in HEIR */
2086 mfspr r3, SPRN_HEIR
2087 stw r3, VCPU_HEIR(r9)
2088
2089 /*
2090 * The cases we want to handle here are those where the guest
2091 * is in real suspend mode and is trying to transition to
2092 * transactional mode.
2093 */
2094 lbz r0, HSTATE_FAKE_SUSPEND(r13)
2095 cmpwi r0, 0 /* keep exiting guest if in fake suspend */
2096 bne guest_exit_cont
2097 rldicl r3, r11, 64 - MSR_TS_S_LG, 62
2098 cmpwi r3, 1 /* or if not in suspend state */
2099 bne guest_exit_cont
2100
2101 /* Call C code to do the emulation */
2102 mr r3, r9
2103 bl kvmhv_p9_tm_emulation_early
2104 nop
2105 ld r9, HSTATE_KVM_VCPU(r13)
2106 li r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
2107 cmpwi r3, 0
2108 beq guest_exit_cont /* continue exiting if not handled */
2109 ld r10, VCPU_PC(r9)
2110 ld r11, VCPU_MSR(r9)
2111 b fast_interrupt_c_return /* go back to guest if handled */
2112#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
2113
2057/* 2114/*
2058 * Check whether an HDSI is an HPTE not found fault or something else. 2115 * Check whether an HDSI is an HPTE not found fault or something else.
2059 * If it is an HPTE not found fault that is due to the guest accessing 2116 * If it is an HPTE not found fault that is due to the guest accessing
@@ -2587,13 +2644,19 @@ _GLOBAL(kvmppc_h_cede) /* r3 = vcpu pointer, r11 = msr, r13 = paca */
2587 bl kvmppc_save_fp 2644 bl kvmppc_save_fp
2588 2645
2589#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2646#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2647/*
2648 * Branch around the call if both CPU_FTR_TM and
2649 * CPU_FTR_P9_TM_HV_ASSIST are off.
2650 */
2590BEGIN_FTR_SECTION 2651BEGIN_FTR_SECTION
2652 b 91f
2653END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
2591 /* 2654 /*
2592 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR 2655 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
2593 */ 2656 */
2594 ld r9, HSTATE_KVM_VCPU(r13) 2657 ld r9, HSTATE_KVM_VCPU(r13)
2595 bl kvmppc_save_tm 2658 bl kvmppc_save_tm
2596END_FTR_SECTION_IFSET(CPU_FTR_TM) 265991:
2597#endif 2660#endif
2598 2661
2599 /* 2662 /*
@@ -2700,12 +2763,18 @@ kvm_end_cede:
2700#endif 2763#endif
2701 2764
2702#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2765#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2766/*
2767 * Branch around the call if both CPU_FTR_TM and
2768 * CPU_FTR_P9_TM_HV_ASSIST are off.
2769 */
2703BEGIN_FTR_SECTION 2770BEGIN_FTR_SECTION
2771 b 91f
2772END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
2704 /* 2773 /*
2705 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR 2774 * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
2706 */ 2775 */
2707 bl kvmppc_restore_tm 2776 bl kvmppc_restore_tm
2708END_FTR_SECTION_IFSET(CPU_FTR_TM) 277791:
2709#endif 2778#endif
2710 2779
2711 /* load up FP state */ 2780 /* load up FP state */
@@ -3046,6 +3115,15 @@ kvmppc_save_tm:
3046 std r1, HSTATE_HOST_R1(r13) 3115 std r1, HSTATE_HOST_R1(r13)
3047 li r3, TM_CAUSE_KVM_RESCHED 3116 li r3, TM_CAUSE_KVM_RESCHED
3048 3117
3118BEGIN_FTR_SECTION
3119 /* Emulation of the treclaim instruction needs TEXASR before treclaim */
3120 mfspr r6, SPRN_TEXASR
3121 std r6, VCPU_ORIG_TEXASR(r9)
3122
3123 rldicl. r8, r8, 64 - MSR_TS_S_LG, 62
3124 beq 3f
3125END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
3126
3049 /* Clear the MSR RI since r1, r13 are all going to be foobar. */ 3127 /* Clear the MSR RI since r1, r13 are all going to be foobar. */
3050 li r5, 0 3128 li r5, 0
3051 mtmsrd r5, 1 3129 mtmsrd r5, 1
@@ -3057,6 +3135,38 @@ kvmppc_save_tm:
3057 SET_SCRATCH0(r13) 3135 SET_SCRATCH0(r13)
3058 GET_PACA(r13) 3136 GET_PACA(r13)
3059 std r9, PACATMSCRATCH(r13) 3137 std r9, PACATMSCRATCH(r13)
3138
3139 /* If doing TM emulation on POWER9 DD2.2, check for fake suspend mode */
3140BEGIN_FTR_SECTION
31413:
3142 lbz r9, HSTATE_FAKE_SUSPEND(r13)
3143 cmpwi r9, 0
3144 beq 2f
3145 /*
3146 * We were in fake suspend, so we are not going to save the
3147 * register state as the guest checkpointed state (since
3148 * we already have it), therefore we can now use any volatile GPR.
3149 */
3150 /* Reload stack pointer and TOC. */
3151 ld r1, HSTATE_HOST_R1(r13)
3152 ld r2, PACATOC(r13)
3153 li r5, MSR_RI
3154 mtmsrd r5, 1
3155 HMT_MEDIUM
3156 ld r6, HSTATE_DSCR(r13)
3157 mtspr SPRN_DSCR, r6
3158 li r0, 0
3159 stb r0, HSTATE_FAKE_SUSPEND(r13)
3160 mfspr r3, SPRN_PSSCR
3161 /* PSSCR_FAKE_SUSPEND is a write-only bit, but clear it anyway */
3162 li r0, PSSCR_FAKE_SUSPEND
3163 andc r3, r3, r0
3164 mtspr SPRN_PSSCR, r3
3165 ld r9, HSTATE_KVM_VCPU(r13)
3166 b 1f
31672:
3168END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
3169
3060 ld r9, HSTATE_KVM_VCPU(r13) 3170 ld r9, HSTATE_KVM_VCPU(r13)
3061 3171
3062 /* Get a few more GPRs free. */ 3172 /* Get a few more GPRs free. */
@@ -3182,6 +3292,15 @@ kvmppc_restore_tm:
3182 mtspr SPRN_TEXASR, r7 3292 mtspr SPRN_TEXASR, r7
3183 3293
3184 /* 3294 /*
3295 * If we are doing TM emulation for the guest on a POWER9 DD2,
3296 * then we don't actually do a trechkpt -- we either set up
3297 * fake-suspend mode, or emulate a TM rollback.
3298 */
3299BEGIN_FTR_SECTION
3300 b .Ldo_tm_fake_load
3301END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
3302
3303 /*
3185 * We need to load up the checkpointed state for the guest. 3304 * We need to load up the checkpointed state for the guest.
3186 * We need to do this early as it will blow away any GPRs, VSRs and 3305 * We need to do this early as it will blow away any GPRs, VSRs and
3187 * some SPRs. 3306 * some SPRs.
@@ -3253,10 +3372,24 @@ kvmppc_restore_tm:
3253 /* Set the MSR RI since we have our registers back. */ 3372 /* Set the MSR RI since we have our registers back. */
3254 li r5, MSR_RI 3373 li r5, MSR_RI
3255 mtmsrd r5, 1 3374 mtmsrd r5, 1
3256 33759:
3257 ld r0, PPC_LR_STKOFF(r1) 3376 ld r0, PPC_LR_STKOFF(r1)
3258 mtlr r0 3377 mtlr r0
3259 blr 3378 blr
3379
3380.Ldo_tm_fake_load:
3381 cmpwi r5, 1 /* check for suspended state */
3382 bgt 10f
3383 stb r5, HSTATE_FAKE_SUSPEND(r13)
3384 b 9b /* and return */
338510: stdu r1, -PPC_MIN_STKFRM(r1)
3386 /* guest is in transactional state, so simulate rollback */
3387 mr r3, r4
3388 bl kvmhv_emulate_tm_rollback
3389 nop
3390 ld r4, HSTATE_KVM_VCPU(r13) /* our vcpu pointer has been trashed */
3391 addi r1, r1, PPC_MIN_STKFRM
3392 b 9b
3260#endif 3393#endif
3261 3394
3262/* 3395/*
diff --git a/arch/powerpc/kvm/book3s_hv_tm.c b/arch/powerpc/kvm/book3s_hv_tm.c
new file mode 100644
index 000000000000..bf710ad3a6d7
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_tm.c
@@ -0,0 +1,216 @@
1/*
2 * Copyright 2017 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2, as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kvm_host.h>
10
11#include <asm/kvm_ppc.h>
12#include <asm/kvm_book3s.h>
13#include <asm/kvm_book3s_64.h>
14#include <asm/reg.h>
15#include <asm/ppc-opcode.h>
16
17static void emulate_tx_failure(struct kvm_vcpu *vcpu, u64 failure_cause)
18{
19 u64 texasr, tfiar;
20 u64 msr = vcpu->arch.shregs.msr;
21
22 tfiar = vcpu->arch.pc & ~0x3ull;
23 texasr = (failure_cause << 56) | TEXASR_ABORT | TEXASR_FS | TEXASR_EXACT;
24 if (MSR_TM_SUSPENDED(vcpu->arch.shregs.msr))
25 texasr |= TEXASR_SUSP;
26 if (msr & MSR_PR) {
27 texasr |= TEXASR_PR;
28 tfiar |= 1;
29 }
30 vcpu->arch.tfiar = tfiar;
31 /* Preserve ROT and TL fields of existing TEXASR */
32 vcpu->arch.texasr = (vcpu->arch.texasr & 0x3ffffff) | texasr;
33}
34
35/*
36 * This gets called on a softpatch interrupt on POWER9 DD2.2 processors.
37 * We expect to find a TM-related instruction to be emulated. The
38 * instruction image is in vcpu->arch.emul_inst. If the guest was in
39 * TM suspended or transactional state, the checkpointed state has been
40 * reclaimed and is in the vcpu struct. The CPU is in virtual mode in
41 * host context.
42 */
43int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
44{
45 u32 instr = vcpu->arch.emul_inst;
46 u64 msr = vcpu->arch.shregs.msr;
47 u64 newmsr, bescr;
48 int ra, rs;
49
50 switch (instr & 0xfc0007ff) {
51 case PPC_INST_RFID:
52 /* XXX do we need to check for PR=0 here? */
53 newmsr = vcpu->arch.shregs.srr1;
54 /* should only get here for Sx -> T1 transition */
55 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) &&
56 MSR_TM_TRANSACTIONAL(newmsr) &&
57 (newmsr & MSR_TM)));
58 newmsr = sanitize_msr(newmsr);
59 vcpu->arch.shregs.msr = newmsr;
60 vcpu->arch.cfar = vcpu->arch.pc - 4;
61 vcpu->arch.pc = vcpu->arch.shregs.srr0;
62 return RESUME_GUEST;
63
64 case PPC_INST_RFEBB:
65 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206)) {
66 /* generate an illegal instruction interrupt */
67 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
68 return RESUME_GUEST;
69 }
70 /* check EBB facility is available */
71 if (!(vcpu->arch.hfscr & HFSCR_EBB)) {
72 /* generate an illegal instruction interrupt */
73 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
74 return RESUME_GUEST;
75 }
76 if ((msr & MSR_PR) && !(vcpu->arch.fscr & FSCR_EBB)) {
77 /* generate a facility unavailable interrupt */
78 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
79 ((u64)FSCR_EBB_LG << 56);
80 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FAC_UNAVAIL);
81 return RESUME_GUEST;
82 }
83 bescr = vcpu->arch.bescr;
84 /* expect to see a S->T transition requested */
85 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) &&
86 ((bescr >> 30) & 3) == 2));
87 bescr &= ~BESCR_GE;
88 if (instr & (1 << 11))
89 bescr |= BESCR_GE;
90 vcpu->arch.bescr = bescr;
91 msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
92 vcpu->arch.shregs.msr = msr;
93 vcpu->arch.cfar = vcpu->arch.pc - 4;
94 vcpu->arch.pc = vcpu->arch.ebbrr;
95 return RESUME_GUEST;
96
97 case PPC_INST_MTMSRD:
98 /* XXX do we need to check for PR=0 here? */
99 rs = (instr >> 21) & 0x1f;
100 newmsr = kvmppc_get_gpr(vcpu, rs);
101 /* check this is a Sx -> T1 transition */
102 WARN_ON_ONCE(!(MSR_TM_SUSPENDED(msr) &&
103 MSR_TM_TRANSACTIONAL(newmsr) &&
104 (newmsr & MSR_TM)));
105 /* mtmsrd doesn't change LE */
106 newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE);
107 newmsr = sanitize_msr(newmsr);
108 vcpu->arch.shregs.msr = newmsr;
109 return RESUME_GUEST;
110
111 case PPC_INST_TSR:
112 /* check for PR=1 and arch 2.06 bit set in PCR */
113 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206)) {
114 /* generate an illegal instruction interrupt */
115 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
116 return RESUME_GUEST;
117 }
118 /* check for TM disabled in the HFSCR or MSR */
119 if (!(vcpu->arch.hfscr & HFSCR_TM)) {
120 /* generate an illegal instruction interrupt */
121 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
122 return RESUME_GUEST;
123 }
124 if (!(msr & MSR_TM)) {
125 /* generate a facility unavailable interrupt */
126 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
127 ((u64)FSCR_TM_LG << 56);
128 kvmppc_book3s_queue_irqprio(vcpu,
129 BOOK3S_INTERRUPT_FAC_UNAVAIL);
130 return RESUME_GUEST;
131 }
132 /* Set CR0 to indicate previous transactional state */
133 vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) |
134 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28);
135 /* L=1 => tresume, L=0 => tsuspend */
136 if (instr & (1 << 21)) {
137 if (MSR_TM_SUSPENDED(msr))
138 msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
139 } else {
140 if (MSR_TM_TRANSACTIONAL(msr))
141 msr = (msr & ~MSR_TS_MASK) | MSR_TS_S;
142 }
143 vcpu->arch.shregs.msr = msr;
144 return RESUME_GUEST;
145
146 case PPC_INST_TRECLAIM:
147 /* check for TM disabled in the HFSCR or MSR */
148 if (!(vcpu->arch.hfscr & HFSCR_TM)) {
149 /* generate an illegal instruction interrupt */
150 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
151 return RESUME_GUEST;
152 }
153 if (!(msr & MSR_TM)) {
154 /* generate a facility unavailable interrupt */
155 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
156 ((u64)FSCR_TM_LG << 56);
157 kvmppc_book3s_queue_irqprio(vcpu,
158 BOOK3S_INTERRUPT_FAC_UNAVAIL);
159 return RESUME_GUEST;
160 }
161 /* If no transaction active, generate TM bad thing */
162 if (!MSR_TM_ACTIVE(msr)) {
163 kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
164 return RESUME_GUEST;
165 }
166 /* If failure was not previously recorded, recompute TEXASR */
167 if (!(vcpu->arch.orig_texasr & TEXASR_FS)) {
168 ra = (instr >> 16) & 0x1f;
169 if (ra)
170 ra = kvmppc_get_gpr(vcpu, ra) & 0xff;
171 emulate_tx_failure(vcpu, ra);
172 }
173
174 copy_from_checkpoint(vcpu);
175
176 /* Set CR0 to indicate previous transactional state */
177 vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) |
178 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28);
179 vcpu->arch.shregs.msr &= ~MSR_TS_MASK;
180 return RESUME_GUEST;
181
182 case PPC_INST_TRECHKPT:
183 /* XXX do we need to check for PR=0 here? */
184 /* check for TM disabled in the HFSCR or MSR */
185 if (!(vcpu->arch.hfscr & HFSCR_TM)) {
186 /* generate an illegal instruction interrupt */
187 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
188 return RESUME_GUEST;
189 }
190 if (!(msr & MSR_TM)) {
191 /* generate a facility unavailable interrupt */
192 vcpu->arch.fscr = (vcpu->arch.fscr & ~(0xffull << 56)) |
193 ((u64)FSCR_TM_LG << 56);
194 kvmppc_book3s_queue_irqprio(vcpu,
195 BOOK3S_INTERRUPT_FAC_UNAVAIL);
196 return RESUME_GUEST;
197 }
198 /* If transaction active or TEXASR[FS] = 0, bad thing */
199 if (MSR_TM_ACTIVE(msr) || !(vcpu->arch.texasr & TEXASR_FS)) {
200 kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
201 return RESUME_GUEST;
202 }
203
204 copy_to_checkpoint(vcpu);
205
206 /* Set CR0 to indicate previous transactional state */
207 vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) |
208 (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28);
209 vcpu->arch.shregs.msr = msr | MSR_TS_S;
210 return RESUME_GUEST;
211 }
212
213 /* What should we do here? We didn't recognize the instruction */
214 WARN_ON_ONCE(1);
215 return RESUME_GUEST;
216}
diff --git a/arch/powerpc/kvm/book3s_hv_tm_builtin.c b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
new file mode 100644
index 000000000000..d98ccfd2b88c
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright 2017 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2, as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kvm_host.h>
10
11#include <asm/kvm_ppc.h>
12#include <asm/kvm_book3s.h>
13#include <asm/kvm_book3s_64.h>
14#include <asm/reg.h>
15#include <asm/ppc-opcode.h>
16
17/*
18 * This handles the cases where the guest is in real suspend mode
19 * and we want to get back to the guest without dooming the transaction.
20 * The caller has checked that the guest is in real-suspend mode
21 * (MSR[TS] = S and the fake-suspend flag is not set).
22 */
23int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)
24{
25 u32 instr = vcpu->arch.emul_inst;
26 u64 newmsr, msr, bescr;
27 int rs;
28
29 switch (instr & 0xfc0007ff) {
30 case PPC_INST_RFID:
31 /* XXX do we need to check for PR=0 here? */
32 newmsr = vcpu->arch.shregs.srr1;
33 /* should only get here for Sx -> T1 transition */
34 if (!(MSR_TM_TRANSACTIONAL(newmsr) && (newmsr & MSR_TM)))
35 return 0;
36 newmsr = sanitize_msr(newmsr);
37 vcpu->arch.shregs.msr = newmsr;
38 vcpu->arch.cfar = vcpu->arch.pc - 4;
39 vcpu->arch.pc = vcpu->arch.shregs.srr0;
40 return 1;
41
42 case PPC_INST_RFEBB:
43 /* check for PR=1 and arch 2.06 bit set in PCR */
44 msr = vcpu->arch.shregs.msr;
45 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206))
46 return 0;
47 /* check EBB facility is available */
48 if (!(vcpu->arch.hfscr & HFSCR_EBB) ||
49 ((msr & MSR_PR) && !(mfspr(SPRN_FSCR) & FSCR_EBB)))
50 return 0;
51 bescr = mfspr(SPRN_BESCR);
52 /* expect to see a S->T transition requested */
53 if (((bescr >> 30) & 3) != 2)
54 return 0;
55 bescr &= ~BESCR_GE;
56 if (instr & (1 << 11))
57 bescr |= BESCR_GE;
58 mtspr(SPRN_BESCR, bescr);
59 msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
60 vcpu->arch.shregs.msr = msr;
61 vcpu->arch.cfar = vcpu->arch.pc - 4;
62 vcpu->arch.pc = mfspr(SPRN_EBBRR);
63 return 1;
64
65 case PPC_INST_MTMSRD:
66 /* XXX do we need to check for PR=0 here? */
67 rs = (instr >> 21) & 0x1f;
68 newmsr = kvmppc_get_gpr(vcpu, rs);
69 msr = vcpu->arch.shregs.msr;
70 /* check this is a Sx -> T1 transition */
71 if (!(MSR_TM_TRANSACTIONAL(newmsr) && (newmsr & MSR_TM)))
72 return 0;
73 /* mtmsrd doesn't change LE */
74 newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE);
75 newmsr = sanitize_msr(newmsr);
76 vcpu->arch.shregs.msr = newmsr;
77 return 1;
78
79 case PPC_INST_TSR:
80 /* we know the MSR has the TS field = S (0b01) here */
81 msr = vcpu->arch.shregs.msr;
82 /* check for PR=1 and arch 2.06 bit set in PCR */
83 if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206))
84 return 0;
85 /* check for TM disabled in the HFSCR or MSR */
86 if (!(vcpu->arch.hfscr & HFSCR_TM) || !(msr & MSR_TM))
87 return 0;
88 /* L=1 => tresume => set TS to T (0b10) */
89 if (instr & (1 << 21))
90 vcpu->arch.shregs.msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
91 /* Set CR0 to 0b0010 */
92 vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | 0x20000000;
93 return 1;
94 }
95
96 return 0;
97}
98
99/*
100 * This is called when we are returning to a guest in TM transactional
101 * state. We roll the guest state back to the checkpointed state.
102 */
103void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu)
104{
105 vcpu->arch.shregs.msr &= ~MSR_TS_MASK; /* go to N state */
106 vcpu->arch.pc = vcpu->arch.tfhar;
107 copy_from_checkpoint(vcpu);
108 vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | 0xa0000000;
109}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 403e642c78f5..677b98e6650f 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -646,10 +646,13 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
646 r = hv_enabled; 646 r = hv_enabled;
647 break; 647 break;
648#endif 648#endif
649#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
649 case KVM_CAP_PPC_HTM: 650 case KVM_CAP_PPC_HTM:
650 r = hv_enabled && 651 r = hv_enabled &&
651 (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM_COMP); 652 (!!(cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM) ||
653 cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST));
652 break; 654 break;
655#endif
653 default: 656 default:
654 r = 0; 657 r = 0;
655 break; 658 break;