mftb is serialising (dispatch next-to-complete) so it is heavy weight
for a mfspr. Avoid reading it multiple times in the entry or exit paths.
A small number of cycles delay to timers is tolerable.

-118 cycles (9137) POWER9 virt-mode NULL hcall

Reviewed-by: Fabiano Rosas <faro...@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npig...@gmail.com>
---
 arch/powerpc/kvm/book3s_hv.c          | 4 ++--
 arch/powerpc/kvm/book3s_hv_p9_entry.c | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 82976f734bd1..6e6cfb10e9bb 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -3896,7 +3896,7 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, 
u64 time_limit,
         *
         * XXX: Another day's problem.
         */
-       mtspr(SPRN_DEC, vcpu->arch.dec_expires - mftb());
+       mtspr(SPRN_DEC, vcpu->arch.dec_expires - tb);
 
        if (kvmhv_on_pseries()) {
                /*
@@ -4019,7 +4019,7 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, 
u64 time_limit,
        vc->in_guest = 0;
 
        next_timer = timer_get_next_tb();
-       set_dec(next_timer - mftb());
+       set_dec(next_timer - tb);
        /* We may have raced with new irq work */
        if (test_irq_work_pending())
                set_dec(1);
diff --git a/arch/powerpc/kvm/book3s_hv_p9_entry.c 
b/arch/powerpc/kvm/book3s_hv_p9_entry.c
index 0ff9ddb5e7ca..bd8cf0a65ce8 100644
--- a/arch/powerpc/kvm/book3s_hv_p9_entry.c
+++ b/arch/powerpc/kvm/book3s_hv_p9_entry.c
@@ -203,7 +203,8 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 
time_limit, unsigned long lpc
        unsigned long host_dawr1;
        unsigned long host_dawrx1;
 
-       hdec = time_limit - mftb();
+       tb = mftb();
+       hdec = time_limit - tb;
        if (hdec < 0)
                return BOOK3S_INTERRUPT_HV_DECREMENTER;
 
@@ -215,7 +216,7 @@ int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 
time_limit, unsigned long lpc
        vcpu->arch.ceded = 0;
 
        if (vc->tb_offset) {
-               u64 new_tb = mftb() + vc->tb_offset;
+               u64 new_tb = tb + vc->tb_offset;
                mtspr(SPRN_TBU40, new_tb);
                tb = mftb();
                if ((tb & 0xffffff) < (new_tb & 0xffffff))
-- 
2.23.0

Reply via email to