[PATCH 5/6] kvmppc: rewrite guest code - wrtee

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx>

This adds another guest code rewrite support replacing the wrtee instructions
using the magic page mechanism.
This affects all checks of the MSR_EE bit of the guest as well as all writes
to vcpu->arch.msr which now need to be in sync with the guest visible EE bit
(mfmsr needs to fetch the right value of the EE bit). Therefor the
paravirtualization of mfmsr and wrtee using the magic page mechanism is
mutually exclusive since we would miss updates or would need multi
instruction rewrites with both rewritten.

Signed-off-by: Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx>
---

[diffstat]
 arch/powerpc/kvm/booke_guest.c |   18 +++++++++++-------
 arch/powerpc/kvm/emulate.c     |   20 +++++++++++++++++---
 arch/powerpc/kvm/powerpc.c     |    1 +
 include/asm-powerpc/kvm_para.h |    1 +
 include/asm-powerpc/kvm_ppc.h  |    5 +++++
 5 files changed, 35 insertions(+), 10 deletions(-)

[diff]

diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -181,13 +181,13 @@
 		r = vcpu->arch.msr & MSR_ME;
 		break;
 	case BOOKE_INTERRUPT_EXTERNAL:
-		r = vcpu->arch.msr & MSR_EE;
-		break;
 	case BOOKE_INTERRUPT_DECREMENTER:
-		r = vcpu->arch.msr & MSR_EE;
-		break;
 	case BOOKE_INTERRUPT_FIT:
-		r = vcpu->arch.msr & MSR_EE;
+		if (vcpu->arch.pvmem)
+			r = kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT)
+				& MSR_EE;
+		else
+			r = vcpu->arch.msr & MSR_EE;
 		break;
 	case BOOKE_INTERRUPT_WATCHDOG:
 		r = vcpu->arch.msr & MSR_CE;
@@ -212,7 +212,9 @@
 
 	if (vcpu->arch.pvmem) {
 		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR0, vcpu->arch.pc);
-		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR1, vcpu->arch.msr);
+		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR1,
+			(vcpu->arch.msr & ~MSR_EE)
+			| kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT));
 		/* only modified on interrupt delivery path */
 		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_DEAR, vcpu->arch.dear);
 		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_ESR, vcpu->arch.esr);
@@ -562,6 +564,8 @@
 		regs->sprg3 = kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_SPRG3);
 		regs->srr0 = kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR0);
 		regs->srr1 = kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_SRR1);
+		regs->msr = (vcpu->arch.msr & ~MSR_EE)
+			| kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT);
 	}
 
 	return 0;
@@ -576,7 +580,7 @@
 	vcpu->arch.ctr = regs->ctr;
 	vcpu->arch.lr = regs->lr;
 	vcpu->arch.xer = regs->xer;
-	vcpu->arch.msr = regs->msr;
+	kvmppc_set_msr(vcpu, regs->msr);
 	vcpu->arch.srr0 = regs->srr0;
 	vcpu->arch.srr1 = regs->srr1;
 	vcpu->arch.sprg0 = regs->sprg0;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -279,6 +279,8 @@
 					vcpu->arch.dear);
 		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_ESR,
 					vcpu->arch.esr);
+		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT,
+					vcpu->arch.msr & MSR_EE);
 		break;
 	default:
 		printk(KERN_ERR "unknown hypercall %d\n", vcpu->arch.gpr[0]);
@@ -304,6 +306,10 @@
 	switch (get_op(inst)) {
 	case 31:
 		switch (get_xop(inst)) {
+		case 131:                                       /* wrtee */
+			rw = KVM_PPCPV_PVMEM_WRITE;
+			offset = KVM_PPCPV_OFFSET_EEBIT;
+			break;
 		case 339:                                       /* mfspr */
 			sprn = get_sprn(inst);
 			rw = KVM_PPCPV_PVMEM_READ;
@@ -496,7 +502,11 @@
 
 		case 83:                                        /* mfmsr */
 			rt = get_rt(inst);
-			vcpu->arch.gpr[rt] = vcpu->arch.msr;
+			if (vcpu->arch.pvmem)
+				vcpu->arch.gpr[rt] = (vcpu->arch.msr & ~MSR_EE)
+				  | kvmppc_get_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT);
+			else
+				vcpu->arch.gpr[rt] = vcpu->arch.msr;
 			break;
 
 		case 87:                                        /* lbzx */
@@ -523,8 +533,12 @@
 			break;
 
 		case 163:                                       /* wrteei */
-			vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
-			                 | (inst & MSR_EE);
+			if (vcpu->arch.pvmem)
+				kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT,
+						(inst & MSR_EE));
+			else
+				vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+							| (inst & MSR_EE);
 			break;
 
 		case 215:                                       /* stbx */
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -459,6 +459,7 @@
 	kvmppc_check_and_deliver_interrupts(vcpu);
 
 	local_irq_disable();
+
 	kvm_guest_enter();
 	r = __kvmppc_vcpu_run(run, vcpu);
 	kvm_guest_exit();
diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h
--- a/include/asm-powerpc/kvm_para.h
+++ b/include/asm-powerpc/kvm_para.h
@@ -48,6 +48,7 @@
 #define KVM_PPCPV_OFFSET_SRR1	0x14
 #define KVM_PPCPV_OFFSET_DEAR	0x18
 #define KVM_PPCPV_OFFSET_ESR	0x1C
+#define KVM_PPCPV_OFFSET_EEBIT	0x20
 
 static inline int kvm_para_available(void)
 {
diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h
--- a/include/asm-powerpc/kvm_ppc.h
+++ b/include/asm-powerpc/kvm_ppc.h
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
+#include <asm/kvm_para.h>
 
 struct kvm_tlb {
 	struct tlbe guest_tlb[PPC44x_TLB_SIZE];
@@ -87,6 +88,10 @@
 	if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
 		kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
 
+	if (vcpu->arch.pvmem)
+		kvmppc_set_pvreg(vcpu, KVM_PPCPV_OFFSET_EEBIT,
+				(new_msr & MSR_EE));
+
 	vcpu->arch.msr = new_msr;
 
 	if (vcpu->arch.msr & MSR_WE)
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux