KVM: PPC: Book3S HV P9: Use host timer accounting to avoid decrementer read
authorNicholas Piggin <npiggin@gmail.com>
Tue, 23 Nov 2021 09:51:42 +0000 (19:51 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 24 Nov 2021 10:08:56 +0000 (21:08 +1100)
There is no need to save away the host DEC value, as it is derived
from the host timer subsystem which maintains the next timer time,
so it can be restored from there.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20211123095231.1036501-5-npiggin@gmail.com
arch/powerpc/include/asm/time.h
arch/powerpc/kernel/time.c
arch/powerpc/kvm/book3s_hv.c

index 8c2c3dd4ddbac31bb102b6f1dfd325869b0a4884..fd09b4797fd77b454b1288ce3476844415eea642 100644 (file)
@@ -111,6 +111,11 @@ static inline unsigned long test_irq_work_pending(void)
 
 DECLARE_PER_CPU(u64, decrementers_next_tb);
 
+static inline u64 timer_get_next_tb(void)
+{
+       return __this_cpu_read(decrementers_next_tb);
+}
+
 /* Convert timebase ticks to nanoseconds */
 unsigned long long tb_to_ns(unsigned long long tb_ticks);
 
index cae8f03a44fe07ac569a20a8c1a8d45b5903fe17..374950afec2fb22fdb791714f462dfa227b1e9d1 100644 (file)
@@ -107,6 +107,7 @@ struct clock_event_device decrementer_clockevent = {
 EXPORT_SYMBOL(decrementer_clockevent);
 
 DEFINE_PER_CPU(u64, decrementers_next_tb);
+EXPORT_SYMBOL_GPL(decrementers_next_tb);
 static DEFINE_PER_CPU(struct clock_event_device, decrementers);
 
 #define XSEC_PER_SEC (1024*1024)
index c7dbdec183b9a1795ee2cdbdb25a6a1c908cea00..3322edbafc64b68ed6325ec54ab699b509637dd3 100644 (file)
@@ -3873,18 +3873,17 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
        struct p9_host_os_sprs host_os_sprs;
        s64 dec;
-       u64 tb;
+       u64 tb, next_timer;
        int trap, save_pmu;
 
        WARN_ON_ONCE(vcpu->arch.ceded);
 
-       dec = mfspr(SPRN_DEC);
        tb = mftb();
-       if (dec < 0)
+       next_timer = timer_get_next_tb();
+       if (tb >= next_timer)
                return BOOK3S_INTERRUPT_HV_DECREMENTER;
-       local_paca->kvm_hstate.dec_expires = dec + tb;
-       if (local_paca->kvm_hstate.dec_expires < time_limit)
-               time_limit = local_paca->kvm_hstate.dec_expires;
+       if (next_timer < time_limit)
+               time_limit = next_timer;
 
        save_p9_host_os_sprs(&host_os_sprs);
 
@@ -4063,7 +4062,8 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
        vc->entry_exit_map = 0x101;
        vc->in_guest = 0;
 
-       set_dec(local_paca->kvm_hstate.dec_expires - mftb());
+       next_timer = timer_get_next_tb();
+       set_dec(next_timer - mftb());
        /* We may have raced with new irq work */
        if (test_irq_work_pending())
                set_dec(1);