diff options
author | Gleb Natapov <gleb@redhat.com> | 2012-08-05 08:58:30 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-08-06 12:00:43 -0400 |
commit | c5cc421ba3219b90f11d151bc55f1608c12830fa (patch) | |
tree | fa21392981697bbc01ed14c8aab98653622c5a33 /arch/x86/kvm/lapic.c | |
parent | a181dc14ed23f7a499542ff4c78532b5f24bb18f (diff) |
KVM: use jump label to optimize checking for HW enabled APIC in APIC_BASE MSR
Usually all APICs are HW enabled so the check can be optimized out.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index c3f14fe51e9b..5b46cab044a5 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/current.h> | 34 | #include <asm/current.h> |
35 | #include <asm/apicdef.h> | 35 | #include <asm/apicdef.h> |
36 | #include <linux/atomic.h> | 36 | #include <linux/atomic.h> |
37 | #include <linux/jump_label.h> | ||
37 | #include "kvm_cache_regs.h" | 38 | #include "kvm_cache_regs.h" |
38 | #include "irq.h" | 39 | #include "irq.h" |
39 | #include "trace.h" | 40 | #include "trace.h" |
@@ -117,9 +118,13 @@ static inline int __apic_test_and_clear_vector(int vec, void *bitmap) | |||
117 | return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 118 | return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
118 | } | 119 | } |
119 | 120 | ||
121 | struct static_key_deferred apic_hw_disabled __read_mostly; | ||
122 | |||
120 | static inline int apic_hw_enabled(struct kvm_lapic *apic) | 123 | static inline int apic_hw_enabled(struct kvm_lapic *apic) |
121 | { | 124 | { |
122 | return (apic)->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE; | 125 | if (static_key_false(&apic_hw_disabled.key)) |
126 | return apic->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE; | ||
127 | return MSR_IA32_APICBASE_ENABLE; | ||
123 | } | 128 | } |
124 | 129 | ||
125 | static inline int apic_sw_enabled(struct kvm_lapic *apic) | 130 | static inline int apic_sw_enabled(struct kvm_lapic *apic) |
@@ -1055,6 +1060,9 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu) | |||
1055 | 1060 | ||
1056 | hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer); | 1061 | hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer); |
1057 | 1062 | ||
1063 | if (!(vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)) | ||
1064 | static_key_slow_dec_deferred(&apic_hw_disabled); | ||
1065 | |||
1058 | if (vcpu->arch.apic->regs) | 1066 | if (vcpu->arch.apic->regs) |
1059 | free_page((unsigned long)vcpu->arch.apic->regs); | 1067 | free_page((unsigned long)vcpu->arch.apic->regs); |
1060 | 1068 | ||
@@ -1125,6 +1133,14 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) | |||
1125 | return; | 1133 | return; |
1126 | } | 1134 | } |
1127 | 1135 | ||
1136 | /* update jump label if enable bit changes */ | ||
1137 | if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) { | ||
1138 | if (value & MSR_IA32_APICBASE_ENABLE) | ||
1139 | static_key_slow_dec_deferred(&apic_hw_disabled); | ||
1140 | else | ||
1141 | static_key_slow_inc(&apic_hw_disabled.key); | ||
1142 | } | ||
1143 | |||
1128 | if (!kvm_vcpu_is_bsp(apic->vcpu)) | 1144 | if (!kvm_vcpu_is_bsp(apic->vcpu)) |
1129 | value &= ~MSR_IA32_APICBASE_BSP; | 1145 | value &= ~MSR_IA32_APICBASE_BSP; |
1130 | 1146 | ||
@@ -1311,6 +1327,11 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu) | |||
1311 | HRTIMER_MODE_ABS); | 1327 | HRTIMER_MODE_ABS); |
1312 | apic->lapic_timer.timer.function = apic_timer_fn; | 1328 | apic->lapic_timer.timer.function = apic_timer_fn; |
1313 | 1329 | ||
1330 | /* | ||
1331 | * APIC is created enabled. This will prevent kvm_lapic_set_base from | ||
1332 | * thinking that APIC satet has changed. | ||
1333 | */ | ||
1334 | vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE; | ||
1314 | kvm_lapic_set_base(vcpu, | 1335 | kvm_lapic_set_base(vcpu, |
1315 | APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE); | 1336 | APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE); |
1316 | 1337 | ||
@@ -1598,3 +1619,9 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data) | |||
1598 | return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, | 1619 | return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, |
1599 | addr); | 1620 | addr); |
1600 | } | 1621 | } |
1622 | |||
1623 | void kvm_lapic_init(void) | ||
1624 | { | ||
1625 | /* do not patch jump label more than once per second */ | ||
1626 | jump_label_rate_limit(&apic_hw_disabled, HZ); | ||
1627 | } | ||