summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h2
-rw-r--r--arch/powerpc/include/asm/kvm_host.h4
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c16
-rw-r--r--arch/powerpc/kvm/book3s_pr.c11
4 files changed, 21 insertions, 12 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index f52f65694527..a20cc0bbd048 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -83,8 +83,6 @@ struct kvmppc_vcpu_book3s {
u64 sdr1;
u64 hior;
u64 msr_mask;
- u64 purr_offset;
- u64 spurr_offset;
#ifdef CONFIG_PPC_BOOK3S_32
u32 vsid_pool[VSID_POOL_SIZE];
u32 vsid_next;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index bb66d8b8efdf..4a58731a0a72 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -503,8 +503,8 @@ struct kvm_vcpu_arch {
#ifdef CONFIG_BOOKE
u32 decar;
#endif
- u32 tbl;
- u32 tbu;
+ /* Time base value when we entered the guest */
+ u64 entry_tb;
u32 tcr;
ulong tsr; /* we need to perform set/clr_bits() which requires ulong */
u32 ivor[64];
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 3f295269af37..3565e775b61b 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -439,12 +439,6 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
(mfmsr() & MSR_HV))
vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
break;
- case SPRN_PURR:
- to_book3s(vcpu)->purr_offset = spr_val - get_tb();
- break;
- case SPRN_SPURR:
- to_book3s(vcpu)->spurr_offset = spr_val - get_tb();
- break;
case SPRN_GQR0:
case SPRN_GQR1:
case SPRN_GQR2:
@@ -572,10 +566,16 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
*spr_val = 0;
break;
case SPRN_PURR:
- *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+ /*
+ * On exit we would have updated purr
+ */
+ *spr_val = vcpu->arch.purr;
break;
case SPRN_SPURR:
- *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+ /*
+ * On exit we would have updated spurr
+ */
+ *spr_val = vcpu->arch.spurr;
break;
case SPRN_GQR0:
case SPRN_GQR1:
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 8eef1e519077..671f5c92a54d 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -120,6 +120,11 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
#ifdef CONFIG_PPC_BOOK3S_64
svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
#endif
+ /*
+ * Now also save the current time base value. We use this
+ * to find the guest purr and spurr value.
+ */
+ vcpu->arch.entry_tb = get_tb();
svcpu->in_use = true;
}
@@ -166,6 +171,12 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
#ifdef CONFIG_PPC_BOOK3S_64
vcpu->arch.shadow_fscr = svcpu->shadow_fscr;
#endif
+ /*
+ * Update purr and spurr using time base on exit.
+ */
+ vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb;
+ vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb;
+
svcpu->in_use = false;
out: