Allow Guest to write tscdeadline msr directly. Signed-off-by: Zhimin Feng <fengzhimin@xxxxxxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/kvm/lapic.c | 9 +++++++ arch/x86/kvm/vmx/vmx.c | 56 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 82a51f0d01a2..500fa031297d 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -533,6 +533,7 @@ struct tick_device { struct timer_passth_info { u64 host_tscd; + bool host_in_tscdeadline; struct clock_event_device *curr_dev; void (*orig_event_handler)(struct clock_event_device *dev); @@ -1302,6 +1303,8 @@ struct kvm_x86_ops { void (*migrate_timers)(struct kvm_vcpu *vcpu); void (*msr_filter_changed)(struct kvm_vcpu *vcpu); + void (*set_timer_passthrough)(struct kvm_vcpu *vcpu, bool enable); + int (*host_timer_can_passth)(struct kvm_vcpu *vcpu); }; struct kvm_x86_nested_ops { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 86c33d53c90a..9b2f8b99fbf6 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1508,6 +1508,15 @@ static void apic_update_lvtt(struct kvm_lapic *apic) } apic->lapic_timer.timer_mode = timer_mode; limit_periodic_timer_frequency(apic); + + if (kvm_x86_ops.host_timer_can_passth(apic->vcpu)) { + if (apic_lvtt_tscdeadline(apic)) { + kvm_x86_ops.set_timer_passthrough(apic->vcpu, true); + } else { + if (apic->vcpu->arch.timer_passth_enable) + kvm_x86_ops.set_timer_passthrough(apic->vcpu, false); + } + } } } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 0bf9941df842..0c1b5ee4bb8e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -47,6 +47,7 @@ #include <asm/spec-ctrl.h> #include <asm/virtext.h> #include <asm/vmx.h> +#include <asm/apicdef.h> #include "capabilities.h" #include "cpuid.h" @@ -705,6 +706,8 @@ static bool is_valid_passthrough_msr(u32 msr) case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B: /* PT MSRs. These are handled in pt_update_intercept_for_msr() */ return true; + case MSR_IA32_TSC_DEADLINE: + return true; } r = possible_passthrough_msr_slot(msr) != -ENOENT; @@ -7670,6 +7673,54 @@ static void vmx_migrate_timers(struct kvm_vcpu *vcpu) } } +static void host_lapic_timer_in_deadline(void *junk) +{ + unsigned int v; + struct timer_passth_info *local_timer_info; + int cpu = smp_processor_id(); + + local_timer_info = &per_cpu(passth_info, cpu); + v = apic_read(APIC_LVTT); + local_timer_info->host_in_tscdeadline = (v & APIC_LVT_TIMER_TSCDEADLINE); +} + +static bool host_all_cpu_in_tscdeadline(void) +{ + int cpu; + struct timer_passth_info *local_timer_info; + + for_each_online_cpu(cpu) { + local_timer_info = &per_cpu(passth_info, cpu); + if (!local_timer_info->host_in_tscdeadline) + return false; + } + + return true; +} + +static int vmx_host_timer_can_passth(struct kvm_vcpu *vcpu) +{ + if (!enable_timer_passth || !cpu_has_vmx_msr_bitmap() || + !host_all_cpu_in_tscdeadline()) + return 0; + return 1; +} + +static void vmx_set_timer_passthrough(struct kvm_vcpu *vcpu, bool enable) +{ + if (enable) { + vmx_disable_intercept_for_msr(vcpu, MSR_IA32_TSC_DEADLINE, + MSR_TYPE_RW); + vcpu->arch.timer_passth_enable = 1; + } else { + vmx_enable_intercept_for_msr(vcpu, MSR_IA32_TSC_DEADLINE, + MSR_TYPE_RW); + vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL, + PIN_BASED_VMX_PREEMPTION_TIMER); + vcpu->arch.timer_passth_enable = 0; + } +} + static void hardware_unsetup(void) { if (enable_timer_passth) @@ -7817,6 +7868,8 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .migrate_timers = vmx_migrate_timers, .msr_filter_changed = vmx_msr_filter_changed, + .set_timer_passthrough = vmx_set_timer_passthrough, + .host_timer_can_passth = vmx_host_timer_can_passth, }; static __init int hardware_setup(void) @@ -7987,6 +8040,9 @@ static __init int hardware_setup(void) vmx_set_cpu_caps(); if (enable_timer_passth) + on_each_cpu(host_lapic_timer_in_deadline, NULL, 1); + + if (enable_timer_passth) on_each_cpu(vmx_host_timer_passth_init, NULL, 1); r = alloc_kvm_area(); -- 2.11.0