summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorSimon Guo <wei.guo.simon@gmail.com>2018-05-23 03:02:00 -0400
committerPaul Mackerras <paulus@ozlabs.org>2018-05-31 20:30:05 -0400
commit533082ae86e2f1ff6cb9eca7a25202a81fc0567e (patch)
tree73670cd71af29f9ead14ab83432eb64fbf3ca7c5 /arch/powerpc
parent13989b65ebb74c05c577dbbcc111e1fdd7da763a (diff)
KVM: PPC: Book3S PR: Emulate mtspr/mfspr using active TM SPRs
The mfspr/mtspr on TM SPRs(TEXASR/TFIAR/TFHAR) are non-privileged instructions and can be executed by PR KVM guest in problem state without trapping into the host. We only emulate mtspr/mfspr texasr/tfiar/tfhar in guest PR=0 state. When we are emulating mtspr tm sprs in guest PR=0 state, the emulation result needs to be visible to guest PR=1 state. That is, the actual TM SPR val should be loaded into actual registers. We already flush TM SPRs into vcpu when switching out of CPU, and load TM SPRs when switching back. This patch corrects mfspr()/mtspr() emulation for TM SPRs to make the actual source/dest be the actual TM SPRs. Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h1
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c58
-rw-r--r--arch/powerpc/kvm/book3s_pr.c2
3 files changed, 50 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index fc15ad9dfc3b..43e8bb18c2d7 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -210,6 +210,7 @@ extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
210extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, 210extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
211 unsigned int vec); 211 unsigned int vec);
212extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags); 212extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags);
213extern void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac);
213extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, 214extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
214 bool upper, u32 val); 215 bool upper, u32 val);
215extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); 216extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index f81a921e0865..c4e3ec63f253 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -24,6 +24,7 @@
24#include <asm/switch_to.h> 24#include <asm/switch_to.h>
25#include <asm/time.h> 25#include <asm/time.h>
26#include "book3s.h" 26#include "book3s.h"
27#include <asm/asm-prototypes.h>
27 28
28#define OP_19_XOP_RFID 18 29#define OP_19_XOP_RFID 18
29#define OP_19_XOP_RFI 50 30#define OP_19_XOP_RFI 50
@@ -523,13 +524,38 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
523 break; 524 break;
524#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 525#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
525 case SPRN_TFHAR: 526 case SPRN_TFHAR:
526 vcpu->arch.tfhar = spr_val;
527 break;
528 case SPRN_TEXASR: 527 case SPRN_TEXASR:
529 vcpu->arch.texasr = spr_val;
530 break;
531 case SPRN_TFIAR: 528 case SPRN_TFIAR:
532 vcpu->arch.tfiar = spr_val; 529 if (!cpu_has_feature(CPU_FTR_TM))
530 break;
531
532 if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
533 kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
534 emulated = EMULATE_AGAIN;
535 break;
536 }
537
538 if (MSR_TM_ACTIVE(kvmppc_get_msr(vcpu)) &&
539 !((MSR_TM_SUSPENDED(kvmppc_get_msr(vcpu))) &&
540 (sprn == SPRN_TFHAR))) {
541 /* it is illegal to mtspr() TM regs in
542 * other than non-transactional state, with
543 * the exception of TFHAR in suspend state.
544 */
545 kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
546 emulated = EMULATE_AGAIN;
547 break;
548 }
549
550 tm_enable();
551 if (sprn == SPRN_TFHAR)
552 mtspr(SPRN_TFHAR, spr_val);
553 else if (sprn == SPRN_TEXASR)
554 mtspr(SPRN_TEXASR, spr_val);
555 else
556 mtspr(SPRN_TFIAR, spr_val);
557 tm_disable();
558
533 break; 559 break;
534#endif 560#endif
535#endif 561#endif
@@ -676,13 +702,25 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
676 break; 702 break;
677#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 703#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
678 case SPRN_TFHAR: 704 case SPRN_TFHAR:
679 *spr_val = vcpu->arch.tfhar;
680 break;
681 case SPRN_TEXASR: 705 case SPRN_TEXASR:
682 *spr_val = vcpu->arch.texasr;
683 break;
684 case SPRN_TFIAR: 706 case SPRN_TFIAR:
685 *spr_val = vcpu->arch.tfiar; 707 if (!cpu_has_feature(CPU_FTR_TM))
708 break;
709
710 if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
711 kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
712 emulated = EMULATE_AGAIN;
713 break;
714 }
715
716 tm_enable();
717 if (sprn == SPRN_TFHAR)
718 *spr_val = mfspr(SPRN_TFHAR);
719 else if (sprn == SPRN_TEXASR)
720 *spr_val = mfspr(SPRN_TEXASR);
721 else if (sprn == SPRN_TFIAR)
722 *spr_val = mfspr(SPRN_TFIAR);
723 tm_disable();
686 break; 724 break;
687#endif 725#endif
688#endif 726#endif
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index dcb577fde9cd..c0f45c83f683 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -918,7 +918,7 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)
918 918
919#ifdef CONFIG_PPC_BOOK3S_64 919#ifdef CONFIG_PPC_BOOK3S_64
920 920
921static void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac) 921void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac)
922{ 922{
923 /* Inject the Interrupt Cause field and trigger a guest interrupt */ 923 /* Inject the Interrupt Cause field and trigger a guest interrupt */
924 vcpu->arch.fscr &= ~(0xffULL << 56); 924 vcpu->arch.fscr &= ~(0xffULL << 56);