|
59 | 59 | #define MAX_APIC_VECTOR 256
|
60 | 60 | #define APIC_VECTORS_PER_REG 32
|
61 | 61 |
|
62 |
| -static bool lapic_timer_advance_dynamic __read_mostly; |
| 62 | +/* |
| 63 | + * Enable local APIC timer advancement (tscdeadline mode only) with adaptive |
| 64 | + * tuning. When enabled, KVM programs the host timer event to fire early, i.e. |
| 65 | + * before the deadline expires, to account for the delay between taking the |
| 66 | + * VM-Exit (to inject the guest event) and the subsequent VM-Enter to resume |
| 67 | + * the guest, i.e. so that the interrupt arrives in the guest with minimal |
| 68 | + * latency relative to the deadline programmed by the guest. |
| 69 | + */ |
| 70 | +static bool lapic_timer_advance __read_mostly = true; |
| 71 | +module_param(lapic_timer_advance, bool, 0444); |
| 72 | + |
63 | 73 | #define LAPIC_TIMER_ADVANCE_ADJUST_MIN 100 /* clock cycles */
|
64 | 74 | #define LAPIC_TIMER_ADVANCE_ADJUST_MAX 10000 /* clock cycles */
|
65 | 75 | #define LAPIC_TIMER_ADVANCE_NS_INIT 1000
|
@@ -1854,16 +1864,14 @@ static void __kvm_wait_lapic_expire(struct kvm_vcpu *vcpu)
|
1854 | 1864 | guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
|
1855 | 1865 | trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline);
|
1856 | 1866 |
|
1857 |
| - if (lapic_timer_advance_dynamic) { |
1858 |
| - adjust_lapic_timer_advance(vcpu, guest_tsc - tsc_deadline); |
1859 |
| - /* |
1860 |
| - * If the timer fired early, reread the TSC to account for the |
1861 |
| - * overhead of the above adjustment to avoid waiting longer |
1862 |
| - * than is necessary. |
1863 |
| - */ |
1864 |
| - if (guest_tsc < tsc_deadline) |
1865 |
| - guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc()); |
1866 |
| - } |
| 1867 | + adjust_lapic_timer_advance(vcpu, guest_tsc - tsc_deadline); |
| 1868 | + |
| 1869 | + /* |
| 1870 | + * If the timer fired early, reread the TSC to account for the overhead |
| 1871 | + * of the above adjustment to avoid waiting longer than is necessary. |
| 1872 | + */ |
| 1873 | + if (guest_tsc < tsc_deadline) |
| 1874 | + guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc()); |
1867 | 1875 |
|
1868 | 1876 | if (guest_tsc < tsc_deadline)
|
1869 | 1877 | __wait_lapic_expire(vcpu, tsc_deadline - guest_tsc);
|
@@ -2812,7 +2820,7 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
|
2812 | 2820 | return HRTIMER_NORESTART;
|
2813 | 2821 | }
|
2814 | 2822 |
|
2815 |
| -int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns) |
| 2823 | +int kvm_create_lapic(struct kvm_vcpu *vcpu) |
2816 | 2824 | {
|
2817 | 2825 | struct kvm_lapic *apic;
|
2818 | 2826 |
|
@@ -2845,13 +2853,8 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns)
|
2845 | 2853 | hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
|
2846 | 2854 | HRTIMER_MODE_ABS_HARD);
|
2847 | 2855 | apic->lapic_timer.timer.function = apic_timer_fn;
|
2848 |
| - if (timer_advance_ns == -1) { |
| 2856 | + if (lapic_timer_advance) |
2849 | 2857 | apic->lapic_timer.timer_advance_ns = LAPIC_TIMER_ADVANCE_NS_INIT;
|
2850 |
| - lapic_timer_advance_dynamic = true; |
2851 |
| - } else { |
2852 |
| - apic->lapic_timer.timer_advance_ns = timer_advance_ns; |
2853 |
| - lapic_timer_advance_dynamic = false; |
2854 |
| - } |
2855 | 2858 |
|
2856 | 2859 | /*
|
2857 | 2860 | * Stuff the APIC ENABLE bit in lieu of temporarily incrementing
|
|
0 commit comments