blob: 4b80e613096bebfaf58f57c66ab1ac9db89c6a26 [file] [log] [blame]
Thomas Gleixner20c8ccb2019-06-04 10:11:32 +02001// SPDX-License-Identifier: GPL-2.0-only
Eddie Dong97222cc2007-09-12 10:58:04 +03002
3/*
4 * Local APIC virtualization
5 *
6 * Copyright (C) 2006 Qumranet, Inc.
7 * Copyright (C) 2007 Novell
8 * Copyright (C) 2007 Intel
Nicolas Kaiser9611c182010-10-06 14:23:22 +02009 * Copyright 2009 Red Hat, Inc. and/or its affiliates.
Eddie Dong97222cc2007-09-12 10:58:04 +030010 *
11 * Authors:
12 * Dor Laor <dor.laor@qumranet.com>
13 * Gregory Haskins <ghaskins@novell.com>
14 * Yaozu (Eddie) Dong <eddie.dong@intel.com>
15 *
16 * Based on Xen 3.1 code, Copyright (c) 2004, Intel Corporation.
Eddie Dong97222cc2007-09-12 10:58:04 +030017 */
18
Avi Kivityedf88412007-12-16 11:02:48 +020019#include <linux/kvm_host.h>
Eddie Dong97222cc2007-09-12 10:58:04 +030020#include <linux/kvm.h>
21#include <linux/mm.h>
22#include <linux/highmem.h>
23#include <linux/smp.h>
24#include <linux/hrtimer.h>
25#include <linux/io.h>
Paul Gortmaker1767e932016-07-13 20:19:00 -040026#include <linux/export.h>
Roman Zippel6f6d6a12008-05-01 04:34:28 -070027#include <linux/math64.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/slab.h>
Eddie Dong97222cc2007-09-12 10:58:04 +030029#include <asm/processor.h>
30#include <asm/msr.h>
31#include <asm/page.h>
32#include <asm/current.h>
33#include <asm/apicdef.h>
Marcelo Tosattid0659d92014-12-16 09:08:15 -050034#include <asm/delay.h>
Arun Sharma600634972011-07-26 16:09:06 -070035#include <linux/atomic.h>
Gleb Natapovc5cc4212012-08-05 15:58:30 +030036#include <linux/jump_label.h>
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -030037#include "kvm_cache_regs.h"
Eddie Dong97222cc2007-09-12 10:58:04 +030038#include "irq.h"
彭浩(Richard)88197e62020-05-21 05:57:49 +000039#include "ioapic.h"
Marcelo Tosatti229456f2009-06-17 09:22:14 -030040#include "trace.h"
Gleb Natapovfc61b802009-07-05 17:39:35 +030041#include "x86.h"
Avi Kivity00b27a32011-11-23 16:30:32 +020042#include "cpuid.h"
Andrey Smetanin5c9194122015-11-10 15:36:34 +030043#include "hyperv.h"
Eddie Dong97222cc2007-09-12 10:58:04 +030044
Marcelo Tosattib682b812009-02-10 20:41:41 -020045#ifndef CONFIG_X86_64
46#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
47#else
48#define mod_64(x, y) ((x) % (y))
49#endif
50
Eddie Dong97222cc2007-09-12 10:58:04 +030051#define PRId64 "d"
52#define PRIx64 "llx"
53#define PRIu64 "u"
54#define PRIo64 "o"
55
Eddie Dong97222cc2007-09-12 10:58:04 +030056/* 14 is the version for Xeon and Pentium 8.4.8*/
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -050057#define APIC_VERSION (0x14UL | ((KVM_APIC_LVT_NUM - 1) << 16))
Eddie Dong97222cc2007-09-12 10:58:04 +030058#define LAPIC_MMIO_LENGTH (1 << 12)
59/* followed define is not in apicdef.h */
Eddie Dong97222cc2007-09-12 10:58:04 +030060#define MAX_APIC_VECTOR 256
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +090061#define APIC_VECTORS_PER_REG 32
Eddie Dong97222cc2007-09-12 10:58:04 +030062
Wanpeng Lid0f5a862019-09-17 16:16:26 +080063static bool lapic_timer_advance_dynamic __read_mostly;
Wanpeng Lia0f00372019-09-26 08:54:03 +080064#define LAPIC_TIMER_ADVANCE_ADJUST_MIN 100 /* clock cycles */
65#define LAPIC_TIMER_ADVANCE_ADJUST_MAX 10000 /* clock cycles */
66#define LAPIC_TIMER_ADVANCE_NS_INIT 1000
67#define LAPIC_TIMER_ADVANCE_NS_MAX 5000
Wanpeng Li3b8a5df2018-10-09 09:02:08 +080068/* step-by-step approximation to mitigate fluctuation */
69#define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
70
Michael S. Tsirkina0c9a8222012-04-11 18:49:55 +030071static inline int apic_test_vector(int vec, void *bitmap)
72{
73 return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
74}
75
Yang Zhang10606912013-04-11 19:21:38 +080076bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector)
77{
78 struct kvm_lapic *apic = vcpu->arch.apic;
79
80 return apic_test_vector(vector, apic->regs + APIC_ISR) ||
81 apic_test_vector(vector, apic->regs + APIC_IRR);
82}
83
Michael S. Tsirkin8680b942012-06-24 19:24:26 +030084static inline int __apic_test_and_set_vector(int vec, void *bitmap)
85{
86 return __test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
87}
88
89static inline int __apic_test_and_clear_vector(int vec, void *bitmap)
90{
91 return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
92}
93
Cun Li6e4e3b42021-01-11 23:24:35 +080094__read_mostly DEFINE_STATIC_KEY_DEFERRED_FALSE(apic_hw_disabled, HZ);
95__read_mostly DEFINE_STATIC_KEY_DEFERRED_FALSE(apic_sw_disabled, HZ);
Gleb Natapovf8c1ea12012-08-05 15:58:31 +030096
Eddie Dong97222cc2007-09-12 10:58:04 +030097static inline int apic_enabled(struct kvm_lapic *apic)
98{
Gleb Natapovc48f1492012-08-05 15:58:33 +030099 return kvm_apic_sw_enabled(apic) && kvm_apic_hw_enabled(apic);
Gleb Natapov54e98182012-08-05 15:58:32 +0300100}
101
Eddie Dong97222cc2007-09-12 10:58:04 +0300102#define LVT_MASK \
103 (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK)
104
105#define LINT_MASK \
106 (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
107 APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
108
Radim Krčmář6e500432016-12-15 18:06:46 +0100109static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
110{
111 return apic->vcpu->vcpu_id;
112}
113
Paolo Bonzini199a8b82020-05-05 06:45:35 -0400114static bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu)
Wanpeng Li0c5f81d2019-07-06 09:26:51 +0800115{
116 return pi_inject_timer && kvm_vcpu_apicv_active(vcpu);
117}
Paolo Bonzini199a8b82020-05-05 06:45:35 -0400118
119bool kvm_can_use_hv_timer(struct kvm_vcpu *vcpu)
120{
121 return kvm_x86_ops.set_hv_timer
122 && !(kvm_mwait_in_guest(vcpu->kvm) ||
123 kvm_can_post_timer_interrupt(vcpu));
124}
125EXPORT_SYMBOL_GPL(kvm_can_use_hv_timer);
Wanpeng Li0c5f81d2019-07-06 09:26:51 +0800126
127static bool kvm_use_posted_timer_interrupt(struct kvm_vcpu *vcpu)
128{
129 return kvm_can_post_timer_interrupt(vcpu) && vcpu->mode == IN_GUEST_MODE;
130}
131
Radim Krčmáře45115b2016-07-12 22:09:19 +0200132static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
133 u32 dest_id, struct kvm_lapic ***cluster, u16 *mask) {
134 switch (map->mode) {
135 case KVM_APIC_MODE_X2APIC: {
136 u32 offset = (dest_id >> 16) * 16;
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200137 u32 max_apic_id = map->max_apic_id;
Radim Krčmář3548a252015-02-12 19:41:33 +0100138
Radim Krčmáře45115b2016-07-12 22:09:19 +0200139 if (offset <= max_apic_id) {
140 u8 cluster_size = min(max_apic_id - offset + 1, 16U);
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100141
Paolo Bonzini1d487e92019-04-11 11:16:47 +0200142 offset = array_index_nospec(offset, map->max_apic_id + 1);
Radim Krčmáře45115b2016-07-12 22:09:19 +0200143 *cluster = &map->phys_map[offset];
144 *mask = dest_id & (0xffff >> (16 - cluster_size));
145 } else {
146 *mask = 0;
147 }
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100148
Radim Krčmáře45115b2016-07-12 22:09:19 +0200149 return true;
150 }
151 case KVM_APIC_MODE_XAPIC_FLAT:
152 *cluster = map->xapic_flat_map;
153 *mask = dest_id & 0xff;
154 return true;
155 case KVM_APIC_MODE_XAPIC_CLUSTER:
Radim Krčmář444fdad2016-11-22 20:20:14 +0100156 *cluster = map->xapic_cluster_map[(dest_id >> 4) & 0xf];
Radim Krčmáře45115b2016-07-12 22:09:19 +0200157 *mask = dest_id & 0xf;
158 return true;
159 default:
160 /* Not optimized. */
161 return false;
162 }
Eddie Dong97222cc2007-09-12 10:58:04 +0300163}
164
Radim Krčmářaf1bae52016-07-12 22:09:30 +0200165static void kvm_apic_map_free(struct rcu_head *rcu)
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100166{
Radim Krčmářaf1bae52016-07-12 22:09:30 +0200167 struct kvm_apic_map *map = container_of(rcu, struct kvm_apic_map, rcu);
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100168
Radim Krčmářaf1bae52016-07-12 22:09:30 +0200169 kvfree(map);
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100170}
171
Paolo Bonzini44d52712020-06-22 16:37:42 +0200172/*
173 * CLEAN -> DIRTY and UPDATE_IN_PROGRESS -> DIRTY changes happen without a lock.
174 *
175 * DIRTY -> UPDATE_IN_PROGRESS and UPDATE_IN_PROGRESS -> CLEAN happen with
176 * apic_map_lock_held.
177 */
178enum {
179 CLEAN,
180 UPDATE_IN_PROGRESS,
181 DIRTY
182};
183
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800184void kvm_recalculate_apic_map(struct kvm *kvm)
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300185{
186 struct kvm_apic_map *new, *old = NULL;
187 struct kvm_vcpu *vcpu;
188 int i;
Radim Krčmář6e500432016-12-15 18:06:46 +0100189 u32 max_id = 255; /* enough space for any xAPIC ID */
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300190
Paolo Bonzini44d52712020-06-22 16:37:42 +0200191 /* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map. */
192 if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800193 return;
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800194
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300195 mutex_lock(&kvm->arch.apic_map_lock);
Paolo Bonzini44d52712020-06-22 16:37:42 +0200196 /*
197 * Read kvm->arch.apic_map_dirty before kvm->arch.apic_map
198 * (if clean) or the APIC registers (if dirty).
199 */
200 if (atomic_cmpxchg_acquire(&kvm->arch.apic_map_dirty,
201 DIRTY, UPDATE_IN_PROGRESS) == CLEAN) {
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800202 /* Someone else has updated the map. */
203 mutex_unlock(&kvm->arch.apic_map_lock);
204 return;
205 }
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300206
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200207 kvm_for_each_vcpu(i, vcpu, kvm)
208 if (kvm_apic_present(vcpu))
Radim Krčmář6e500432016-12-15 18:06:46 +0100209 max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200210
Michal Hockoa7c3e902017-05-08 15:57:09 -0700211 new = kvzalloc(sizeof(struct kvm_apic_map) +
Ben Gardon254272c2019-02-11 11:02:50 -0800212 sizeof(struct kvm_lapic *) * ((u64)max_id + 1),
213 GFP_KERNEL_ACCOUNT);
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200214
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300215 if (!new)
216 goto out;
217
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200218 new->max_apic_id = max_id;
219
Nadav Amit173beed2014-11-02 11:54:54 +0200220 kvm_for_each_vcpu(i, vcpu, kvm) {
221 struct kvm_lapic *apic = vcpu->arch.apic;
Radim Krčmáře45115b2016-07-12 22:09:19 +0200222 struct kvm_lapic **cluster;
223 u16 mask;
Radim Krčmář5bd5db32016-12-15 18:06:48 +0100224 u32 ldr;
225 u8 xapic_id;
226 u32 x2apic_id;
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300227
Radim Krčmářdf04d1d2015-01-29 22:33:35 +0100228 if (!kvm_apic_present(vcpu))
229 continue;
230
Radim Krčmář5bd5db32016-12-15 18:06:48 +0100231 xapic_id = kvm_xapic_id(apic);
232 x2apic_id = kvm_x2apic_id(apic);
233
234 /* Hotplug hack: see kvm_apic_match_physical_addr(), ... */
235 if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) &&
236 x2apic_id <= new->max_apic_id)
237 new->phys_map[x2apic_id] = apic;
238 /*
239 * ... xAPIC ID of VCPUs with APIC ID > 0xff will wrap-around,
240 * prevent them from masking VCPUs with APIC ID <= 0xff.
241 */
242 if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
243 new->phys_map[xapic_id] = apic;
Radim Krčmář3548a252015-02-12 19:41:33 +0100244
Radim Krcmarb14c8762019-08-13 23:37:37 -0400245 if (!kvm_apic_sw_enabled(apic))
246 continue;
247
Radim Krčmář6e500432016-12-15 18:06:46 +0100248 ldr = kvm_lapic_get_reg(apic, APIC_LDR);
249
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100250 if (apic_x2apic_mode(apic)) {
251 new->mode |= KVM_APIC_MODE_X2APIC;
252 } else if (ldr) {
253 ldr = GET_APIC_LOGICAL_ID(ldr);
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -0500254 if (kvm_lapic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT)
Radim Krčmář3b5a5ff2015-02-12 19:41:34 +0100255 new->mode |= KVM_APIC_MODE_XAPIC_FLAT;
256 else
257 new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER;
258 }
259
Radim Krčmáře45115b2016-07-12 22:09:19 +0200260 if (!kvm_apic_map_get_logical_dest(new, ldr, &cluster, &mask))
Radim Krčmář3548a252015-02-12 19:41:33 +0100261 continue;
262
Radim Krčmáře45115b2016-07-12 22:09:19 +0200263 if (mask)
264 cluster[ffs(mask) - 1] = apic;
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300265 }
266out:
267 old = rcu_dereference_protected(kvm->arch.apic_map,
268 lockdep_is_held(&kvm->arch.apic_map_lock));
269 rcu_assign_pointer(kvm->arch.apic_map, new);
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800270 /*
Paolo Bonzini44d52712020-06-22 16:37:42 +0200271 * Write kvm->arch.apic_map before clearing apic->apic_map_dirty.
272 * If another update has come in, leave it DIRTY.
Wanpeng Li4abaffc2020-02-26 10:41:02 +0800273 */
Paolo Bonzini44d52712020-06-22 16:37:42 +0200274 atomic_cmpxchg_release(&kvm->arch.apic_map_dirty,
275 UPDATE_IN_PROGRESS, CLEAN);
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300276 mutex_unlock(&kvm->arch.apic_map_lock);
277
278 if (old)
Radim Krčmářaf1bae52016-07-12 22:09:30 +0200279 call_rcu(&old->rcu, kvm_apic_map_free);
Yang Zhangc7c9c562013-01-25 10:18:51 +0800280
Steve Rutherfordb053b2a2015-07-29 23:32:35 -0700281 kvm_make_scan_ioapic_request(kvm);
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300282}
283
Nadav Amit1e1b6c22014-08-19 00:03:00 +0300284static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
285{
Radim Krčmáře4627552014-10-30 15:06:45 +0100286 bool enabled = val & APIC_SPIV_APIC_ENABLED;
Nadav Amit1e1b6c22014-08-19 00:03:00 +0300287
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500288 kvm_lapic_set_reg(apic, APIC_SPIV, val);
Radim Krčmáře4627552014-10-30 15:06:45 +0100289
290 if (enabled != apic->sw_enabled) {
291 apic->sw_enabled = enabled;
Peng Haoeb1ff0a2018-12-04 17:42:50 +0800292 if (enabled)
Cun Li6e4e3b42021-01-11 23:24:35 +0800293 static_branch_slow_dec_deferred(&apic_sw_disabled);
Peng Haoeb1ff0a2018-12-04 17:42:50 +0800294 else
Cun Li6e4e3b42021-01-11 23:24:35 +0800295 static_branch_inc(&apic_sw_disabled.key);
Radim Krcmarb14c8762019-08-13 23:37:37 -0400296
Paolo Bonzini44d52712020-06-22 16:37:42 +0200297 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Nadav Amit1e1b6c22014-08-19 00:03:00 +0300298 }
Vitaly Kuznetsov2f15d022021-04-22 11:29:48 +0200299
300 /* Check if there are APF page ready requests pending */
301 if (enabled)
302 kvm_make_request(KVM_REQ_APF_READY, apic->vcpu);
Nadav Amit1e1b6c22014-08-19 00:03:00 +0300303}
304
Radim Krčmářa92e2542016-07-12 22:09:22 +0200305static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300306{
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500307 kvm_lapic_set_reg(apic, APIC_ID, id << 24);
Paolo Bonzini44d52712020-06-22 16:37:42 +0200308 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300309}
310
311static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
312{
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500313 kvm_lapic_set_reg(apic, APIC_LDR, id);
Paolo Bonzini44d52712020-06-22 16:37:42 +0200314 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300315}
316
Wanpeng Liae6f2492020-08-19 16:55:26 +0800317static inline void kvm_apic_set_dfr(struct kvm_lapic *apic, u32 val)
318{
319 kvm_lapic_set_reg(apic, APIC_DFR, val);
320 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
321}
322
Dr. David Alan Gilberte872fa92017-11-17 11:52:49 +0000323static inline u32 kvm_apic_calc_x2apic_ldr(u32 id)
324{
325 return ((id >> 4) << 16) | (1 << (id & 0xf));
326}
327
Radim Krčmářa92e2542016-07-12 22:09:22 +0200328static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u32 id)
Radim Krčmář257b9a52015-05-22 18:45:11 +0200329{
Dr. David Alan Gilberte872fa92017-11-17 11:52:49 +0000330 u32 ldr = kvm_apic_calc_x2apic_ldr(id);
Radim Krčmář257b9a52015-05-22 18:45:11 +0200331
Radim Krčmář6e500432016-12-15 18:06:46 +0100332 WARN_ON_ONCE(id != apic->vcpu->vcpu_id);
333
Radim Krčmářa92e2542016-07-12 22:09:22 +0200334 kvm_lapic_set_reg(apic, APIC_ID, id);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500335 kvm_lapic_set_reg(apic, APIC_LDR, ldr);
Paolo Bonzini44d52712020-06-22 16:37:42 +0200336 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Radim Krčmář257b9a52015-05-22 18:45:11 +0200337}
338
Eddie Dong97222cc2007-09-12 10:58:04 +0300339static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
340{
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -0500341 return !(kvm_lapic_get_reg(apic, lvt_type) & APIC_LVT_MASKED);
Eddie Dong97222cc2007-09-12 10:58:04 +0300342}
343
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +0800344static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
345{
Radim Krčmářf30ebc32014-10-30 15:06:47 +0100346 return apic->lapic_timer.timer_mode == APIC_LVT_TIMER_ONESHOT;
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +0800347}
348
Eddie Dong97222cc2007-09-12 10:58:04 +0300349static inline int apic_lvtt_period(struct kvm_lapic *apic)
350{
Radim Krčmářf30ebc32014-10-30 15:06:47 +0100351 return apic->lapic_timer.timer_mode == APIC_LVT_TIMER_PERIODIC;
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +0800352}
353
354static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
355{
Radim Krčmářf30ebc32014-10-30 15:06:47 +0100356 return apic->lapic_timer.timer_mode == APIC_LVT_TIMER_TSCDEADLINE;
Eddie Dong97222cc2007-09-12 10:58:04 +0300357}
358
Jan Kiszkacc6e4622008-10-20 10:20:03 +0200359static inline int apic_lvt_nmi_mode(u32 lvt_val)
360{
361 return (lvt_val & (APIC_MODE_MASK | APIC_LVT_MASKED)) == APIC_DM_NMI;
362}
363
Gleb Natapovfc61b802009-07-05 17:39:35 +0300364void kvm_apic_set_version(struct kvm_vcpu *vcpu)
365{
366 struct kvm_lapic *apic = vcpu->arch.apic;
Gleb Natapovfc61b802009-07-05 17:39:35 +0300367 u32 v = APIC_VERSION;
368
Paolo Bonzinibce87cc2016-01-08 13:48:51 +0100369 if (!lapic_in_kernel(vcpu))
Gleb Natapovfc61b802009-07-05 17:39:35 +0300370 return;
371
Vitaly Kuznetsov0bcc3fb2018-02-09 14:01:33 +0100372 /*
373 * KVM emulates 82093AA datasheet (with in-kernel IOAPIC implementation)
374 * which doesn't have EOI register; Some buggy OSes (e.g. Windows with
375 * Hyper-V role) disable EOI broadcast in lapic not checking for IOAPIC
376 * version first and level-triggered interrupts never get EOIed in
377 * IOAPIC.
378 */
Xiaoyao Li565b7822020-07-08 14:50:53 +0800379 if (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) &&
Vitaly Kuznetsov0bcc3fb2018-02-09 14:01:33 +0100380 !ioapic_in_kernel(vcpu->kvm))
Gleb Natapovfc61b802009-07-05 17:39:35 +0300381 v |= APIC_LVR_DIRECTED_EOI;
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500382 kvm_lapic_set_reg(apic, APIC_LVR, v);
Gleb Natapovfc61b802009-07-05 17:39:35 +0300383}
384
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500385static const unsigned int apic_lvt_mask[KVM_APIC_LVT_NUM] = {
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +0800386 LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */
Eddie Dong97222cc2007-09-12 10:58:04 +0300387 LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
388 LVT_MASK | APIC_MODE_MASK, /* LVTPC */
389 LINT_MASK, LINT_MASK, /* LVT0-1 */
390 LVT_MASK /* LVTERR */
391};
392
393static int find_highest_vector(void *bitmap)
394{
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900395 int vec;
396 u32 *reg;
Eddie Dong97222cc2007-09-12 10:58:04 +0300397
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900398 for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG;
399 vec >= 0; vec -= APIC_VECTORS_PER_REG) {
400 reg = bitmap + REG_POS(vec);
401 if (*reg)
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100402 return __fls(*reg) + vec;
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900403 }
Eddie Dong97222cc2007-09-12 10:58:04 +0300404
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900405 return -1;
Eddie Dong97222cc2007-09-12 10:58:04 +0300406}
407
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300408static u8 count_vectors(void *bitmap)
409{
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900410 int vec;
411 u32 *reg;
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300412 u8 count = 0;
Takuya Yoshikawaecba9a52012-09-05 19:30:01 +0900413
414 for (vec = 0; vec < MAX_APIC_VECTOR; vec += APIC_VECTORS_PER_REG) {
415 reg = bitmap + REG_POS(vec);
416 count += hweight32(*reg);
417 }
418
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300419 return count;
420}
421
Liran Alone7387b02017-12-24 18:12:54 +0200422bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr)
Yang Zhanga20ed542013-04-11 19:25:15 +0800423{
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100424 u32 i, vec;
Liran Alone7387b02017-12-24 18:12:54 +0200425 u32 pir_val, irr_val, prev_irr_val;
426 int max_updated_irr;
427
428 max_updated_irr = -1;
429 *max_irr = -1;
Yang Zhanga20ed542013-04-11 19:25:15 +0800430
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100431 for (i = vec = 0; i <= 7; i++, vec += 32) {
Paolo Bonziniad361092016-09-20 16:15:05 +0200432 pir_val = READ_ONCE(pir[i]);
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100433 irr_val = *((u32 *)(regs + APIC_IRR + i * 0x10));
Paolo Bonziniad361092016-09-20 16:15:05 +0200434 if (pir_val) {
Liran Alone7387b02017-12-24 18:12:54 +0200435 prev_irr_val = irr_val;
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100436 irr_val |= xchg(&pir[i], 0);
437 *((u32 *)(regs + APIC_IRR + i * 0x10)) = irr_val;
Liran Alone7387b02017-12-24 18:12:54 +0200438 if (prev_irr_val != irr_val) {
439 max_updated_irr =
440 __fls(irr_val ^ prev_irr_val) + vec;
441 }
Paolo Bonziniad361092016-09-20 16:15:05 +0200442 }
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100443 if (irr_val)
Liran Alone7387b02017-12-24 18:12:54 +0200444 *max_irr = __fls(irr_val) + vec;
Yang Zhanga20ed542013-04-11 19:25:15 +0800445 }
Paolo Bonzini810e6de2016-12-19 13:05:46 +0100446
Liran Alone7387b02017-12-24 18:12:54 +0200447 return ((max_updated_irr != -1) &&
448 (max_updated_irr == *max_irr));
Yang Zhanga20ed542013-04-11 19:25:15 +0800449}
Wincy Van705699a2015-02-03 23:58:17 +0800450EXPORT_SYMBOL_GPL(__kvm_apic_update_irr);
451
Liran Alone7387b02017-12-24 18:12:54 +0200452bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir, int *max_irr)
Wincy Van705699a2015-02-03 23:58:17 +0800453{
454 struct kvm_lapic *apic = vcpu->arch.apic;
455
Liran Alone7387b02017-12-24 18:12:54 +0200456 return __kvm_apic_update_irr(pir, apic->regs, max_irr);
Wincy Van705699a2015-02-03 23:58:17 +0800457}
Yang Zhanga20ed542013-04-11 19:25:15 +0800458EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
459
Gleb Natapov33e4c682009-06-11 11:06:51 +0300460static inline int apic_search_irr(struct kvm_lapic *apic)
Eddie Dong97222cc2007-09-12 10:58:04 +0300461{
Gleb Natapov33e4c682009-06-11 11:06:51 +0300462 return find_highest_vector(apic->regs + APIC_IRR);
Eddie Dong97222cc2007-09-12 10:58:04 +0300463}
464
465static inline int apic_find_highest_irr(struct kvm_lapic *apic)
466{
467 int result;
468
Yang Zhangc7c9c562013-01-25 10:18:51 +0800469 /*
470 * Note that irr_pending is just a hint. It will be always
471 * true with virtual interrupt delivery enabled.
472 */
Gleb Natapov33e4c682009-06-11 11:06:51 +0300473 if (!apic->irr_pending)
474 return -1;
475
476 result = apic_search_irr(apic);
Eddie Dong97222cc2007-09-12 10:58:04 +0300477 ASSERT(result == -1 || result >= 16);
478
479 return result;
480}
481
Gleb Natapov33e4c682009-06-11 11:06:51 +0300482static inline void apic_clear_irr(int vec, struct kvm_lapic *apic)
483{
Wanpeng Li56cc2402014-08-05 12:42:24 +0800484 struct kvm_vcpu *vcpu;
485
486 vcpu = apic->vcpu;
487
Andrey Smetanind62caab2015-11-10 15:36:33 +0300488 if (unlikely(vcpu->arch.apicv_active)) {
Paolo Bonzinib95234c2016-12-19 13:57:33 +0100489 /* need to update RVI */
Wei Yangee171d22019-03-31 19:17:22 -0700490 kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR);
Jason Baronb36464772021-01-14 22:27:56 -0500491 static_call(kvm_x86_hwapic_irr_update)(vcpu,
Paolo Bonzinib95234c2016-12-19 13:57:33 +0100492 apic_find_highest_irr(apic));
Nadav Amitf210f752014-11-16 23:49:07 +0200493 } else {
494 apic->irr_pending = false;
Wei Yangee171d22019-03-31 19:17:22 -0700495 kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR);
Nadav Amitf210f752014-11-16 23:49:07 +0200496 if (apic_search_irr(apic) != -1)
497 apic->irr_pending = true;
Wanpeng Li56cc2402014-08-05 12:42:24 +0800498 }
Gleb Natapov33e4c682009-06-11 11:06:51 +0300499}
500
Sean Christopherson25bb2cf2020-08-12 10:51:29 -0700501void kvm_apic_clear_irr(struct kvm_vcpu *vcpu, int vec)
502{
503 apic_clear_irr(vec, vcpu->arch.apic);
504}
505EXPORT_SYMBOL_GPL(kvm_apic_clear_irr);
506
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300507static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
508{
Wanpeng Li56cc2402014-08-05 12:42:24 +0800509 struct kvm_vcpu *vcpu;
Paolo Bonzinifc57ac22014-05-14 17:40:58 +0200510
Wanpeng Li56cc2402014-08-05 12:42:24 +0800511 if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
512 return;
513
514 vcpu = apic->vcpu;
515
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300516 /*
Wanpeng Li56cc2402014-08-05 12:42:24 +0800517 * With APIC virtualization enabled, all caching is disabled
518 * because the processor can modify ISR under the hood. Instead
519 * just set SVI.
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300520 */
Andrey Smetanind62caab2015-11-10 15:36:33 +0300521 if (unlikely(vcpu->arch.apicv_active))
Jason Baronb36464772021-01-14 22:27:56 -0500522 static_call(kvm_x86_hwapic_isr_update)(vcpu, vec);
Wanpeng Li56cc2402014-08-05 12:42:24 +0800523 else {
524 ++apic->isr_count;
525 BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
526 /*
527 * ISR (in service register) bit is set when injecting an interrupt.
528 * The highest vector is injected. Thus the latest bit set matches
529 * the highest bit in ISR.
530 */
531 apic->highest_isr_cache = vec;
532 }
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300533}
534
Paolo Bonzinifc57ac22014-05-14 17:40:58 +0200535static inline int apic_find_highest_isr(struct kvm_lapic *apic)
536{
537 int result;
538
539 /*
540 * Note that isr_count is always 1, and highest_isr_cache
541 * is always -1, with APIC virtualization enabled.
542 */
543 if (!apic->isr_count)
544 return -1;
545 if (likely(apic->highest_isr_cache != -1))
546 return apic->highest_isr_cache;
547
548 result = find_highest_vector(apic->regs + APIC_ISR);
549 ASSERT(result == -1 || result >= 16);
550
551 return result;
552}
553
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300554static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
555{
Paolo Bonzinifc57ac22014-05-14 17:40:58 +0200556 struct kvm_vcpu *vcpu;
557 if (!__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR))
558 return;
559
560 vcpu = apic->vcpu;
561
562 /*
563 * We do get here for APIC virtualization enabled if the guest
564 * uses the Hyper-V APIC enlightenment. In this case we may need
565 * to trigger a new interrupt delivery by writing the SVI field;
566 * on the other hand isr_count and highest_isr_cache are unused
567 * and must be left alone.
568 */
Andrey Smetanind62caab2015-11-10 15:36:33 +0300569 if (unlikely(vcpu->arch.apicv_active))
Jason Baronb36464772021-01-14 22:27:56 -0500570 static_call(kvm_x86_hwapic_isr_update)(vcpu,
571 apic_find_highest_isr(apic));
Paolo Bonzinifc57ac22014-05-14 17:40:58 +0200572 else {
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300573 --apic->isr_count;
Paolo Bonzinifc57ac22014-05-14 17:40:58 +0200574 BUG_ON(apic->isr_count < 0);
575 apic->highest_isr_cache = -1;
576 }
Michael S. Tsirkin8680b942012-06-24 19:24:26 +0300577}
578
Yang, Sheng6e5d8652007-09-12 18:03:11 +0800579int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
580{
Gleb Natapov33e4c682009-06-11 11:06:51 +0300581 /* This may race with setting of irr in __apic_accept_irq() and
582 * value returned may be wrong, but kvm_vcpu_kick() in __apic_accept_irq
583 * will cause vmexit immediately and the value will be recalculated
584 * on the next vmentry.
585 */
Paolo Bonzinif8543d62016-01-08 13:42:24 +0100586 return apic_find_highest_irr(vcpu->arch.apic);
Yang, Sheng6e5d8652007-09-12 18:03:11 +0800587}
Paolo Bonzini76dfafd52016-12-19 17:17:11 +0100588EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
Yang, Sheng6e5d8652007-09-12 18:03:11 +0800589
Gleb Natapov6da7e3f2009-03-05 16:34:44 +0200590static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
Yang Zhangb4f22252013-04-11 19:21:37 +0800591 int vector, int level, int trig_mode,
Joerg Roedel9e4aabe2016-02-29 16:04:43 +0100592 struct dest_map *dest_map);
Gleb Natapov6da7e3f2009-03-05 16:34:44 +0200593
Yang Zhangb4f22252013-04-11 19:21:37 +0800594int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
Joerg Roedel9e4aabe2016-02-29 16:04:43 +0100595 struct dest_map *dest_map)
Eddie Dong97222cc2007-09-12 10:58:04 +0300596{
Zhang Xiantaoad312c72007-12-13 23:50:52 +0800597 struct kvm_lapic *apic = vcpu->arch.apic;
Zhang Xiantao8be54532007-12-02 22:35:57 +0800598
Gleb Natapov58c2dde2009-03-05 16:35:04 +0200599 return __apic_accept_irq(apic, irq->delivery_mode, irq->vector,
Yang Zhangb4f22252013-04-11 19:21:37 +0800600 irq->level, irq->trig_mode, dest_map);
Eddie Dong97222cc2007-09-12 10:58:04 +0300601}
602
Miaohe Lin1a686232019-11-09 17:46:49 +0800603static int __pv_send_ipi(unsigned long *ipi_bitmap, struct kvm_apic_map *map,
604 struct kvm_lapic_irq *irq, u32 min)
605{
606 int i, count = 0;
607 struct kvm_vcpu *vcpu;
608
609 if (min > map->max_apic_id)
610 return 0;
611
612 for_each_set_bit(i, ipi_bitmap,
613 min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) {
614 if (map->phys_map[min + i]) {
615 vcpu = map->phys_map[min + i]->vcpu;
616 count += kvm_apic_set_irq(vcpu, irq, NULL);
617 }
618 }
619
620 return count;
621}
622
Wanpeng Li4180bf12018-07-23 14:39:54 +0800623int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
Wanpeng Libdf7ffc2018-08-30 10:03:30 +0800624 unsigned long ipi_bitmap_high, u32 min,
Wanpeng Li4180bf12018-07-23 14:39:54 +0800625 unsigned long icr, int op_64_bit)
626{
Wanpeng Li4180bf12018-07-23 14:39:54 +0800627 struct kvm_apic_map *map;
Wanpeng Li4180bf12018-07-23 14:39:54 +0800628 struct kvm_lapic_irq irq = {0};
629 int cluster_size = op_64_bit ? 64 : 32;
Miaohe Lin1a686232019-11-09 17:46:49 +0800630 int count;
631
632 if (icr & (APIC_DEST_MASK | APIC_SHORT_MASK))
633 return -KVM_EINVAL;
Wanpeng Li4180bf12018-07-23 14:39:54 +0800634
635 irq.vector = icr & APIC_VECTOR_MASK;
636 irq.delivery_mode = icr & APIC_MODE_MASK;
637 irq.level = (icr & APIC_INT_ASSERT) != 0;
638 irq.trig_mode = icr & APIC_INT_LEVELTRIG;
639
Wanpeng Li4180bf12018-07-23 14:39:54 +0800640 rcu_read_lock();
641 map = rcu_dereference(kvm->arch.apic_map);
642
Miaohe Lin1a686232019-11-09 17:46:49 +0800643 count = -EOPNOTSUPP;
644 if (likely(map)) {
645 count = __pv_send_ipi(&ipi_bitmap_low, map, &irq, min);
646 min += cluster_size;
647 count += __pv_send_ipi(&ipi_bitmap_high, map, &irq, min);
Wanpeng Li38ab0122018-11-20 09:39:30 +0800648 }
649
Wanpeng Li4180bf12018-07-23 14:39:54 +0800650 rcu_read_unlock();
651 return count;
652}
653
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300654static int pv_eoi_put_user(struct kvm_vcpu *vcpu, u8 val)
655{
Paolo Bonzini4e335d92017-05-02 16:20:18 +0200656
657 return kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.pv_eoi.data, &val,
658 sizeof(val));
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300659}
660
661static int pv_eoi_get_user(struct kvm_vcpu *vcpu, u8 *val)
662{
Paolo Bonzini4e335d92017-05-02 16:20:18 +0200663
664 return kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.pv_eoi.data, val,
665 sizeof(*val));
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300666}
667
668static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
669{
670 return vcpu->arch.pv_eoi.msr_val & KVM_MSR_ENABLED;
671}
672
673static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
674{
675 u8 val;
Miaohe Lin23520b22020-02-21 22:04:46 +0800676 if (pv_eoi_get_user(vcpu, &val) < 0) {
Yi Wang0d888002019-07-06 01:08:48 +0800677 printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
Chen Fan96893972014-01-02 17:14:11 +0800678 (unsigned long long)vcpu->arch.pv_eoi.msr_val);
Miaohe Lin23520b22020-02-21 22:04:46 +0800679 return false;
680 }
Stephen Zhangde7860c82020-12-18 15:51:37 +0800681 return val & KVM_PV_EOI_ENABLED;
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300682}
683
684static void pv_eoi_set_pending(struct kvm_vcpu *vcpu)
685{
686 if (pv_eoi_put_user(vcpu, KVM_PV_EOI_ENABLED) < 0) {
Yi Wang0d888002019-07-06 01:08:48 +0800687 printk(KERN_WARNING "Can't set EOI MSR value: 0x%llx\n",
Chen Fan96893972014-01-02 17:14:11 +0800688 (unsigned long long)vcpu->arch.pv_eoi.msr_val);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300689 return;
690 }
691 __set_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention);
692}
693
694static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu)
695{
696 if (pv_eoi_put_user(vcpu, KVM_PV_EOI_DISABLED) < 0) {
Yi Wang0d888002019-07-06 01:08:48 +0800697 printk(KERN_WARNING "Can't clear EOI MSR value: 0x%llx\n",
Chen Fan96893972014-01-02 17:14:11 +0800698 (unsigned long long)vcpu->arch.pv_eoi.msr_val);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +0300699 return;
700 }
701 __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention);
702}
703
Paolo Bonzinib3c045d2016-12-18 21:47:54 +0100704static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr)
705{
Paolo Bonzini3d927892016-12-19 13:29:03 +0100706 int highest_irr;
Liran Alonfa59cc02017-12-24 18:12:53 +0200707 if (apic->vcpu->arch.apicv_active)
Jason Baronb36464772021-01-14 22:27:56 -0500708 highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu);
Paolo Bonzini76dfafd52016-12-19 17:17:11 +0100709 else
710 highest_irr = apic_find_highest_irr(apic);
Paolo Bonzinib3c045d2016-12-18 21:47:54 +0100711 if (highest_irr == -1 || (highest_irr & 0xF0) <= ppr)
712 return -1;
713 return highest_irr;
714}
715
716static bool __apic_update_ppr(struct kvm_lapic *apic, u32 *new_ppr)
Eddie Dong97222cc2007-09-12 10:58:04 +0300717{
Avi Kivity3842d132010-07-27 12:30:24 +0300718 u32 tpr, isrv, ppr, old_ppr;
Eddie Dong97222cc2007-09-12 10:58:04 +0300719 int isr;
720
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -0500721 old_ppr = kvm_lapic_get_reg(apic, APIC_PROCPRI);
722 tpr = kvm_lapic_get_reg(apic, APIC_TASKPRI);
Eddie Dong97222cc2007-09-12 10:58:04 +0300723 isr = apic_find_highest_isr(apic);
724 isrv = (isr != -1) ? isr : 0;
725
726 if ((tpr & 0xf0) >= (isrv & 0xf0))
727 ppr = tpr & 0xff;
728 else
729 ppr = isrv & 0xf0;
730
Paolo Bonzinib3c045d2016-12-18 21:47:54 +0100731 *new_ppr = ppr;
732 if (old_ppr != ppr)
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500733 kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr);
Paolo Bonzinib3c045d2016-12-18 21:47:54 +0100734
735 return ppr < old_ppr;
736}
737
738static void apic_update_ppr(struct kvm_lapic *apic)
739{
740 u32 ppr;
741
Paolo Bonzini26fbbee2016-12-18 13:54:58 +0100742 if (__apic_update_ppr(apic, &ppr) &&
743 apic_has_interrupt_for_ppr(apic, ppr) != -1)
Paolo Bonzinib3c045d2016-12-18 21:47:54 +0100744 kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +0300745}
746
Paolo Bonzinieb90f342016-12-18 14:02:21 +0100747void kvm_apic_update_ppr(struct kvm_vcpu *vcpu)
748{
749 apic_update_ppr(vcpu->arch.apic);
750}
751EXPORT_SYMBOL_GPL(kvm_apic_update_ppr);
752
Eddie Dong97222cc2007-09-12 10:58:04 +0300753static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
754{
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500755 kvm_lapic_set_reg(apic, APIC_TASKPRI, tpr);
Eddie Dong97222cc2007-09-12 10:58:04 +0300756 apic_update_ppr(apic);
757}
758
Radim Krčmář03d22492015-02-12 19:41:31 +0100759static bool kvm_apic_broadcast(struct kvm_lapic *apic, u32 mda)
Eddie Dong97222cc2007-09-12 10:58:04 +0300760{
Radim Krčmářb4535b52016-12-15 18:06:47 +0100761 return mda == (apic_x2apic_mode(apic) ?
762 X2APIC_BROADCAST : APIC_BROADCAST);
Eddie Dong97222cc2007-09-12 10:58:04 +0300763}
764
Radim Krčmář03d22492015-02-12 19:41:31 +0100765static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 mda)
Nadav Amit394457a2014-10-03 00:30:52 +0300766{
Radim Krčmář03d22492015-02-12 19:41:31 +0100767 if (kvm_apic_broadcast(apic, mda))
768 return true;
769
770 if (apic_x2apic_mode(apic))
Radim Krčmář6e500432016-12-15 18:06:46 +0100771 return mda == kvm_x2apic_id(apic);
Radim Krčmář03d22492015-02-12 19:41:31 +0100772
Radim Krčmář5bd5db32016-12-15 18:06:48 +0100773 /*
774 * Hotplug hack: Make LAPIC in xAPIC mode also accept interrupts as if
775 * it were in x2APIC mode. Hotplugged VCPUs start in xAPIC mode and
776 * this allows unique addressing of VCPUs with APIC ID over 0xff.
777 * The 0xff condition is needed because writeable xAPIC ID.
778 */
779 if (kvm_x2apic_id(apic) > 0xff && mda == kvm_x2apic_id(apic))
780 return true;
781
Radim Krčmářb4535b52016-12-15 18:06:47 +0100782 return mda == kvm_xapic_id(apic);
Nadav Amit394457a2014-10-03 00:30:52 +0300783}
784
Radim Krčmář52c233a2015-01-29 22:48:48 +0100785static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
Eddie Dong97222cc2007-09-12 10:58:04 +0300786{
Gleb Natapov0105d1a2009-07-05 17:39:36 +0300787 u32 logical_id;
788
Nadav Amit394457a2014-10-03 00:30:52 +0300789 if (kvm_apic_broadcast(apic, mda))
Radim Krčmář9368b562015-01-29 22:48:49 +0100790 return true;
Nadav Amit394457a2014-10-03 00:30:52 +0300791
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -0500792 logical_id = kvm_lapic_get_reg(apic, APIC_LDR);
Eddie Dong97222cc2007-09-12 10:58:04 +0300793
Radim Krčmář9368b562015-01-29 22:48:49 +0100794 if (apic_x2apic_mode(apic))
Radim Krčmář8a395362015-01-29 22:48:51 +0100795 return ((logical_id >> 16) == (mda >> 16))
796 && (logical_id & mda & 0xffff) != 0;
Radim Krčmář9368b562015-01-29 22:48:49 +0100797
798 logical_id = GET_APIC_LOGICAL_ID(logical_id);
Eddie Dong97222cc2007-09-12 10:58:04 +0300799
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -0500800 switch (kvm_lapic_get_reg(apic, APIC_DFR)) {
Eddie Dong97222cc2007-09-12 10:58:04 +0300801 case APIC_DFR_FLAT:
Radim Krčmář9368b562015-01-29 22:48:49 +0100802 return (logical_id & mda) != 0;
Eddie Dong97222cc2007-09-12 10:58:04 +0300803 case APIC_DFR_CLUSTER:
Radim Krčmář9368b562015-01-29 22:48:49 +0100804 return ((logical_id >> 4) == (mda >> 4))
805 && (logical_id & mda & 0xf) != 0;
Eddie Dong97222cc2007-09-12 10:58:04 +0300806 default:
Radim Krčmář9368b562015-01-29 22:48:49 +0100807 return false;
Eddie Dong97222cc2007-09-12 10:58:04 +0300808 }
Eddie Dong97222cc2007-09-12 10:58:04 +0300809}
810
Radim Krčmářc5192652016-07-12 22:09:28 +0200811/* The KVM local APIC implementation has two quirks:
812 *
Radim Krčmářb4535b52016-12-15 18:06:47 +0100813 * - Real hardware delivers interrupts destined to x2APIC ID > 0xff to LAPICs
814 * in xAPIC mode if the "destination & 0xff" matches its xAPIC ID.
815 * KVM doesn't do that aliasing.
Radim Krčmářc5192652016-07-12 22:09:28 +0200816 *
817 * - in-kernel IOAPIC messages have to be delivered directly to
818 * x2APIC, because the kernel does not support interrupt remapping.
819 * In order to support broadcast without interrupt remapping, x2APIC
820 * rewrites the destination of non-IPI messages from APIC_BROADCAST
821 * to X2APIC_BROADCAST.
822 *
823 * The broadcast quirk can be disabled with KVM_CAP_X2APIC_API. This is
824 * important when userspace wants to use x2APIC-format MSIs, because
825 * APIC_BROADCAST (0xff) is a legal route for "cluster 0, CPUs 0-7".
Radim Krčmář03d22492015-02-12 19:41:31 +0100826 */
Radim Krčmářc5192652016-07-12 22:09:28 +0200827static u32 kvm_apic_mda(struct kvm_vcpu *vcpu, unsigned int dest_id,
828 struct kvm_lapic *source, struct kvm_lapic *target)
Radim Krčmář03d22492015-02-12 19:41:31 +0100829{
830 bool ipi = source != NULL;
Radim Krčmář03d22492015-02-12 19:41:31 +0100831
Radim Krčmářc5192652016-07-12 22:09:28 +0200832 if (!vcpu->kvm->arch.x2apic_broadcast_quirk_disabled &&
Radim Krčmářb4535b52016-12-15 18:06:47 +0100833 !ipi && dest_id == APIC_BROADCAST && apic_x2apic_mode(target))
Radim Krčmář03d22492015-02-12 19:41:31 +0100834 return X2APIC_BROADCAST;
835
Radim Krčmářb4535b52016-12-15 18:06:47 +0100836 return dest_id;
Radim Krčmář03d22492015-02-12 19:41:31 +0100837}
838
Radim Krčmář52c233a2015-01-29 22:48:48 +0100839bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
Peter Xu5c69d5c2019-12-04 20:07:20 +0100840 int shorthand, unsigned int dest, int dest_mode)
Eddie Dong97222cc2007-09-12 10:58:04 +0300841{
Zhang Xiantaoad312c72007-12-13 23:50:52 +0800842 struct kvm_lapic *target = vcpu->arch.apic;
Radim Krčmářc5192652016-07-12 22:09:28 +0200843 u32 mda = kvm_apic_mda(vcpu, dest, source, target);
Eddie Dong97222cc2007-09-12 10:58:04 +0300844
Zachary Amsdenbd371392010-06-14 11:42:15 -1000845 ASSERT(target);
Peter Xu5c69d5c2019-12-04 20:07:20 +0100846 switch (shorthand) {
Eddie Dong97222cc2007-09-12 10:58:04 +0300847 case APIC_DEST_NOSHORT:
Radim Krčmář3697f302015-01-29 22:48:50 +0100848 if (dest_mode == APIC_DEST_PHYSICAL)
Radim Krčmář03d22492015-02-12 19:41:31 +0100849 return kvm_apic_match_physical_addr(target, mda);
Gleb Natapov343f94f2009-03-05 16:34:54 +0200850 else
Radim Krčmář03d22492015-02-12 19:41:31 +0100851 return kvm_apic_match_logical_addr(target, mda);
Eddie Dong97222cc2007-09-12 10:58:04 +0300852 case APIC_DEST_SELF:
Radim Krčmář9368b562015-01-29 22:48:49 +0100853 return target == source;
Eddie Dong97222cc2007-09-12 10:58:04 +0300854 case APIC_DEST_ALLINC:
Radim Krčmář9368b562015-01-29 22:48:49 +0100855 return true;
Eddie Dong97222cc2007-09-12 10:58:04 +0300856 case APIC_DEST_ALLBUT:
Radim Krčmář9368b562015-01-29 22:48:49 +0100857 return target != source;
Eddie Dong97222cc2007-09-12 10:58:04 +0300858 default:
Radim Krčmář9368b562015-01-29 22:48:49 +0100859 return false;
Eddie Dong97222cc2007-09-12 10:58:04 +0300860 }
Eddie Dong97222cc2007-09-12 10:58:04 +0300861}
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -0500862EXPORT_SYMBOL_GPL(kvm_apic_match_dest);
Eddie Dong97222cc2007-09-12 10:58:04 +0300863
Feng Wu520040142016-01-25 16:53:33 +0800864int kvm_vector_to_index(u32 vector, u32 dest_vcpus,
865 const unsigned long *bitmap, u32 bitmap_size)
866{
867 u32 mod;
868 int i, idx = -1;
869
870 mod = vector % dest_vcpus;
871
872 for (i = 0; i <= mod; i++) {
873 idx = find_next_bit(bitmap, bitmap_size, idx + 1);
874 BUG_ON(idx == bitmap_size);
875 }
876
877 return idx;
878}
879
Radim Krčmář4efd8052016-02-12 15:00:15 +0100880static void kvm_apic_disabled_lapic_found(struct kvm *kvm)
881{
882 if (!kvm->arch.disabled_lapic_found) {
883 kvm->arch.disabled_lapic_found = true;
884 printk(KERN_INFO
885 "Disabled LAPIC found during irq injection\n");
886 }
887}
888
Radim Krčmářc5192652016-07-12 22:09:28 +0200889static bool kvm_apic_is_broadcast_dest(struct kvm *kvm, struct kvm_lapic **src,
890 struct kvm_lapic_irq *irq, struct kvm_apic_map *map)
891{
892 if (kvm->arch.x2apic_broadcast_quirk_disabled) {
893 if ((irq->dest_id == APIC_BROADCAST &&
894 map->mode != KVM_APIC_MODE_X2APIC))
895 return true;
896 if (irq->dest_id == X2APIC_BROADCAST)
897 return true;
898 } else {
899 bool x2apic_ipi = src && *src && apic_x2apic_mode(*src);
900 if (irq->dest_id == (x2apic_ipi ?
901 X2APIC_BROADCAST : APIC_BROADCAST))
902 return true;
903 }
904
905 return false;
906}
907
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200908/* Return true if the interrupt can be handled by using *bitmap as index mask
909 * for valid destinations in *dst array.
910 * Return false if kvm_apic_map_get_dest_lapic did nothing useful.
911 * Note: we may have zero kvm_lapic destinations when we return true, which
912 * means that the interrupt should be dropped. In this case, *bitmap would be
913 * zero and *dst undefined.
914 */
915static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
916 struct kvm_lapic **src, struct kvm_lapic_irq *irq,
917 struct kvm_apic_map *map, struct kvm_lapic ***dst,
918 unsigned long *bitmap)
919{
920 int i, lowest;
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200921
922 if (irq->shorthand == APIC_DEST_SELF && src) {
923 *dst = src;
924 *bitmap = 1;
925 return true;
926 } else if (irq->shorthand)
927 return false;
928
Radim Krčmářc5192652016-07-12 22:09:28 +0200929 if (!map || kvm_apic_is_broadcast_dest(kvm, src, irq, map))
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200930 return false;
931
932 if (irq->dest_mode == APIC_DEST_PHYSICAL) {
Radim Krčmář0ca52e72016-07-12 22:09:20 +0200933 if (irq->dest_id > map->max_apic_id) {
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200934 *bitmap = 0;
935 } else {
Paolo Bonzini1d487e92019-04-11 11:16:47 +0200936 u32 dest_id = array_index_nospec(irq->dest_id, map->max_apic_id + 1);
937 *dst = &map->phys_map[dest_id];
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200938 *bitmap = 1;
939 }
940 return true;
941 }
942
Radim Krčmáře45115b2016-07-12 22:09:19 +0200943 *bitmap = 0;
944 if (!kvm_apic_map_get_logical_dest(map, irq->dest_id, dst,
945 (u16 *)bitmap))
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200946 return false;
947
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200948 if (!kvm_lowest_prio_delivery(irq))
949 return true;
950
951 if (!kvm_vector_hashing_enabled()) {
952 lowest = -1;
953 for_each_set_bit(i, bitmap, 16) {
954 if (!(*dst)[i])
955 continue;
956 if (lowest < 0)
957 lowest = i;
958 else if (kvm_apic_compare_prio((*dst)[i]->vcpu,
959 (*dst)[lowest]->vcpu) < 0)
960 lowest = i;
961 }
962 } else {
963 if (!*bitmap)
964 return true;
965
966 lowest = kvm_vector_to_index(irq->vector, hweight16(*bitmap),
967 bitmap, 16);
968
969 if (!(*dst)[lowest]) {
970 kvm_apic_disabled_lapic_found(kvm);
971 *bitmap = 0;
972 return true;
973 }
974 }
975
976 *bitmap = (lowest >= 0) ? 1 << lowest : 0;
977
978 return true;
979}
980
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300981bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
Joerg Roedel9e4aabe2016-02-29 16:04:43 +0100982 struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map)
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300983{
984 struct kvm_apic_map *map;
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200985 unsigned long bitmap;
986 struct kvm_lapic **dst = NULL;
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300987 int i;
Radim Krčmář64aa47b2016-07-12 22:09:18 +0200988 bool ret;
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300989
990 *r = -1;
991
992 if (irq->shorthand == APIC_DEST_SELF) {
Yang Zhangb4f22252013-04-11 19:21:37 +0800993 *r = kvm_apic_set_irq(src->vcpu, irq, dest_map);
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300994 return true;
995 }
996
Gleb Natapov1e08ec42012-09-13 17:19:24 +0300997 rcu_read_lock();
998 map = rcu_dereference(kvm->arch.apic_map);
999
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001000 ret = kvm_apic_map_get_dest_lapic(kvm, &src, irq, map, &dst, &bitmap);
Paolo Bonzini0624fca2018-10-01 16:07:18 +02001001 if (ret) {
1002 *r = 0;
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001003 for_each_set_bit(i, &bitmap, 16) {
1004 if (!dst[i])
1005 continue;
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001006 *r += kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map);
Radim Krčmář3548a252015-02-12 19:41:33 +01001007 }
Paolo Bonzini0624fca2018-10-01 16:07:18 +02001008 }
Radim Krčmář3548a252015-02-12 19:41:33 +01001009
Gleb Natapov1e08ec42012-09-13 17:19:24 +03001010 rcu_read_unlock();
1011 return ret;
1012}
1013
Feng Wu6228a0d2016-01-25 16:53:34 +08001014/*
Miaohe Lin00116792019-12-11 14:26:23 +08001015 * This routine tries to handle interrupts in posted mode, here is how
Feng Wu6228a0d2016-01-25 16:53:34 +08001016 * it deals with different cases:
1017 * - For single-destination interrupts, handle it in posted mode
1018 * - Else if vector hashing is enabled and it is a lowest-priority
1019 * interrupt, handle it in posted mode and use the following mechanism
Miaohe Lin67b0ae42019-12-11 14:26:22 +08001020 * to find the destination vCPU.
Feng Wu6228a0d2016-01-25 16:53:34 +08001021 * 1. For lowest-priority interrupts, store all the possible
1022 * destination vCPUs in an array.
1023 * 2. Use "guest vector % max number of destination vCPUs" to find
1024 * the right destination vCPU in the array for the lowest-priority
1025 * interrupt.
1026 * - Otherwise, use remapped mode to inject the interrupt.
1027 */
Feng Wu8feb4a02015-09-18 22:29:47 +08001028bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
1029 struct kvm_vcpu **dest_vcpu)
1030{
1031 struct kvm_apic_map *map;
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001032 unsigned long bitmap;
1033 struct kvm_lapic **dst = NULL;
Feng Wu8feb4a02015-09-18 22:29:47 +08001034 bool ret = false;
Feng Wu8feb4a02015-09-18 22:29:47 +08001035
1036 if (irq->shorthand)
1037 return false;
1038
1039 rcu_read_lock();
1040 map = rcu_dereference(kvm->arch.apic_map);
1041
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001042 if (kvm_apic_map_get_dest_lapic(kvm, NULL, irq, map, &dst, &bitmap) &&
1043 hweight16(bitmap) == 1) {
1044 unsigned long i = find_first_bit(&bitmap, 16);
Feng Wu8feb4a02015-09-18 22:29:47 +08001045
Radim Krčmář64aa47b2016-07-12 22:09:18 +02001046 if (dst[i]) {
1047 *dest_vcpu = dst[i]->vcpu;
1048 ret = true;
Feng Wu8feb4a02015-09-18 22:29:47 +08001049 }
Feng Wu8feb4a02015-09-18 22:29:47 +08001050 }
1051
Feng Wu8feb4a02015-09-18 22:29:47 +08001052 rcu_read_unlock();
1053 return ret;
1054}
1055
Eddie Dong97222cc2007-09-12 10:58:04 +03001056/*
1057 * Add a pending IRQ into lapic.
1058 * Return 1 if successfully added and 0 if discarded.
1059 */
1060static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
Yang Zhangb4f22252013-04-11 19:21:37 +08001061 int vector, int level, int trig_mode,
Joerg Roedel9e4aabe2016-02-29 16:04:43 +01001062 struct dest_map *dest_map)
Eddie Dong97222cc2007-09-12 10:58:04 +03001063{
Gleb Natapov6da7e3f2009-03-05 16:34:44 +02001064 int result = 0;
He, Qingc5ec1532007-09-03 17:07:41 +03001065 struct kvm_vcpu *vcpu = apic->vcpu;
Eddie Dong97222cc2007-09-12 10:58:04 +03001066
Paolo Bonzinia183b632014-09-11 11:51:02 +02001067 trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
1068 trig_mode, vector);
Eddie Dong97222cc2007-09-12 10:58:04 +03001069 switch (delivery_mode) {
Eddie Dong97222cc2007-09-12 10:58:04 +03001070 case APIC_DM_LOWEST:
Gleb Natapove1035712009-03-05 16:34:59 +02001071 vcpu->arch.apic_arb_prio++;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001072 fallthrough;
Gleb Natapove1035712009-03-05 16:34:59 +02001073 case APIC_DM_FIXED:
Paolo Bonzinibdaffe12015-07-29 15:03:06 +02001074 if (unlikely(trig_mode && !level))
1075 break;
1076
Eddie Dong97222cc2007-09-12 10:58:04 +03001077 /* FIXME add logic for vcpu on reset */
1078 if (unlikely(!apic_enabled(apic)))
1079 break;
1080
Jan Kiszka11f5cc02013-07-25 09:58:45 +02001081 result = 1;
1082
Joerg Roedel9daa5002016-02-29 16:04:44 +01001083 if (dest_map) {
Joerg Roedel9e4aabe2016-02-29 16:04:43 +01001084 __set_bit(vcpu->vcpu_id, dest_map->map);
Joerg Roedel9daa5002016-02-29 16:04:44 +01001085 dest_map->vectors[vcpu->vcpu_id] = vector;
1086 }
Avi Kivitya5d36f82009-12-29 12:42:16 +02001087
Paolo Bonzinibdaffe12015-07-29 15:03:06 +02001088 if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) {
1089 if (trig_mode)
Wei Yangee171d22019-03-31 19:17:22 -07001090 kvm_lapic_set_vector(vector,
1091 apic->regs + APIC_TMR);
Paolo Bonzinibdaffe12015-07-29 15:03:06 +02001092 else
Wei Yangee171d22019-03-31 19:17:22 -07001093 kvm_lapic_clear_vector(vector,
1094 apic->regs + APIC_TMR);
Paolo Bonzinibdaffe12015-07-29 15:03:06 +02001095 }
1096
Jason Baronb36464772021-01-14 22:27:56 -05001097 if (static_call(kvm_x86_deliver_posted_interrupt)(vcpu, vector)) {
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05001098 kvm_lapic_set_irr(vector, apic);
Yang Zhang5a717852013-04-11 19:25:16 +08001099 kvm_make_request(KVM_REQ_EVENT, vcpu);
1100 kvm_vcpu_kick(vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03001101 }
Eddie Dong97222cc2007-09-12 10:58:04 +03001102 break;
1103
1104 case APIC_DM_REMRD:
Raghavendra K T24d21662013-08-26 14:18:35 +05301105 result = 1;
1106 vcpu->arch.pv.pv_unhalted = 1;
1107 kvm_make_request(KVM_REQ_EVENT, vcpu);
1108 kvm_vcpu_kick(vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03001109 break;
1110
1111 case APIC_DM_SMI:
Paolo Bonzini64d60672015-05-07 11:36:11 +02001112 result = 1;
1113 kvm_make_request(KVM_REQ_SMI, vcpu);
1114 kvm_vcpu_kick(vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03001115 break;
Sheng Yang3419ffc2008-05-15 09:52:48 +08001116
Eddie Dong97222cc2007-09-12 10:58:04 +03001117 case APIC_DM_NMI:
Gleb Natapov6da7e3f2009-03-05 16:34:44 +02001118 result = 1;
Sheng Yang3419ffc2008-05-15 09:52:48 +08001119 kvm_inject_nmi(vcpu);
Jan Kiszka26df99c2008-09-26 09:30:54 +02001120 kvm_vcpu_kick(vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03001121 break;
1122
1123 case APIC_DM_INIT:
Julian Stecklinaa52315e2012-01-16 14:02:20 +01001124 if (!trig_mode || level) {
Gleb Natapov6da7e3f2009-03-05 16:34:44 +02001125 result = 1;
Jan Kiszka66450a22013-03-13 12:42:34 +01001126 /* assumes that there are only KVM_APIC_INIT/SIPI */
1127 apic->pending_events = (1UL << KVM_APIC_INIT);
Avi Kivity3842d132010-07-27 12:30:24 +03001128 kvm_make_request(KVM_REQ_EVENT, vcpu);
He, Qingc5ec1532007-09-03 17:07:41 +03001129 kvm_vcpu_kick(vcpu);
He, Qingc5ec1532007-09-03 17:07:41 +03001130 }
Eddie Dong97222cc2007-09-12 10:58:04 +03001131 break;
1132
1133 case APIC_DM_STARTUP:
Jan Kiszka66450a22013-03-13 12:42:34 +01001134 result = 1;
1135 apic->sipi_vector = vector;
1136 /* make sure sipi_vector is visible for the receiver */
1137 smp_wmb();
1138 set_bit(KVM_APIC_SIPI, &apic->pending_events);
1139 kvm_make_request(KVM_REQ_EVENT, vcpu);
1140 kvm_vcpu_kick(vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03001141 break;
1142
Jan Kiszka23930f92008-09-26 09:30:52 +02001143 case APIC_DM_EXTINT:
1144 /*
1145 * Should only be called by kvm_apic_local_deliver() with LVT0,
1146 * before NMI watchdog was enabled. Already handled by
1147 * kvm_apic_accept_pic_intr().
1148 */
1149 break;
1150
Eddie Dong97222cc2007-09-12 10:58:04 +03001151 default:
1152 printk(KERN_ERR "TODO: unsupported delivery mode %x\n",
1153 delivery_mode);
1154 break;
1155 }
1156 return result;
1157}
1158
Nitesh Narayan Lal7ee30bc2019-11-07 07:53:43 -05001159/*
1160 * This routine identifies the destination vcpus mask meant to receive the
1161 * IOAPIC interrupts. It either uses kvm_apic_map_get_dest_lapic() to find
1162 * out the destination vcpus array and set the bitmap or it traverses to
1163 * each available vcpu to identify the same.
1164 */
1165void kvm_bitmap_or_dest_vcpus(struct kvm *kvm, struct kvm_lapic_irq *irq,
1166 unsigned long *vcpu_bitmap)
1167{
1168 struct kvm_lapic **dest_vcpu = NULL;
1169 struct kvm_lapic *src = NULL;
1170 struct kvm_apic_map *map;
1171 struct kvm_vcpu *vcpu;
1172 unsigned long bitmap;
1173 int i, vcpu_idx;
1174 bool ret;
1175
1176 rcu_read_lock();
1177 map = rcu_dereference(kvm->arch.apic_map);
1178
1179 ret = kvm_apic_map_get_dest_lapic(kvm, &src, irq, map, &dest_vcpu,
1180 &bitmap);
1181 if (ret) {
1182 for_each_set_bit(i, &bitmap, 16) {
1183 if (!dest_vcpu[i])
1184 continue;
1185 vcpu_idx = dest_vcpu[i]->vcpu->vcpu_idx;
1186 __set_bit(vcpu_idx, vcpu_bitmap);
1187 }
1188 } else {
1189 kvm_for_each_vcpu(i, vcpu, kvm) {
1190 if (!kvm_apic_present(vcpu))
1191 continue;
1192 if (!kvm_apic_match_dest(vcpu, NULL,
Peter Xub4b29632019-12-04 20:07:16 +01001193 irq->shorthand,
Nitesh Narayan Lal7ee30bc2019-11-07 07:53:43 -05001194 irq->dest_id,
1195 irq->dest_mode))
1196 continue;
1197 __set_bit(i, vcpu_bitmap);
1198 }
1199 }
1200 rcu_read_unlock();
1201}
1202
Gleb Natapove1035712009-03-05 16:34:59 +02001203int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
Eddie Dong97222cc2007-09-12 10:58:04 +03001204{
Gleb Natapove1035712009-03-05 16:34:59 +02001205 return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio;
Zhang Xiantao8be54532007-12-02 22:35:57 +08001206}
1207
Paolo Bonzini3bb345f2015-07-29 10:43:18 +02001208static bool kvm_ioapic_handles_vector(struct kvm_lapic *apic, int vector)
1209{
Andrey Smetanin63086302015-11-10 15:36:32 +03001210 return test_bit(vector, apic->vcpu->arch.ioapic_handled_vectors);
Paolo Bonzini3bb345f2015-07-29 10:43:18 +02001211}
1212
Yang Zhangc7c9c562013-01-25 10:18:51 +08001213static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
1214{
Steve Rutherford7543a632015-07-29 23:21:41 -07001215 int trigger_mode;
Paolo Bonzini3bb345f2015-07-29 10:43:18 +02001216
Steve Rutherford7543a632015-07-29 23:21:41 -07001217 /* Eoi the ioapic only if the ioapic doesn't own the vector. */
1218 if (!kvm_ioapic_handles_vector(apic, vector))
1219 return;
1220
1221 /* Request a KVM exit to inform the userspace IOAPIC. */
1222 if (irqchip_split(apic->vcpu->kvm)) {
1223 apic->vcpu->arch.pending_ioapic_eoi = vector;
1224 kvm_make_request(KVM_REQ_IOAPIC_EOI_EXIT, apic->vcpu);
1225 return;
Yang Zhangc7c9c562013-01-25 10:18:51 +08001226 }
Steve Rutherford7543a632015-07-29 23:21:41 -07001227
1228 if (apic_test_vector(vector, apic->regs + APIC_TMR))
1229 trigger_mode = IOAPIC_LEVEL_TRIG;
1230 else
1231 trigger_mode = IOAPIC_EDGE_TRIG;
1232
1233 kvm_ioapic_update_eoi(apic->vcpu, vector, trigger_mode);
Yang Zhangc7c9c562013-01-25 10:18:51 +08001234}
1235
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03001236static int apic_set_eoi(struct kvm_lapic *apic)
Eddie Dong97222cc2007-09-12 10:58:04 +03001237{
1238 int vector = apic_find_highest_isr(apic);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03001239
1240 trace_kvm_eoi(apic, vector);
1241
Eddie Dong97222cc2007-09-12 10:58:04 +03001242 /*
1243 * Not every write EOI will has corresponding ISR,
1244 * one example is when Kernel check timer on setup_IO_APIC
1245 */
1246 if (vector == -1)
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03001247 return vector;
Eddie Dong97222cc2007-09-12 10:58:04 +03001248
Michael S. Tsirkin8680b942012-06-24 19:24:26 +03001249 apic_clear_isr(vector, apic);
Eddie Dong97222cc2007-09-12 10:58:04 +03001250 apic_update_ppr(apic);
1251
Vitaly Kuznetsovf2bc14b2021-01-26 14:48:12 +01001252 if (to_hv_vcpu(apic->vcpu) &&
1253 test_bit(vector, to_hv_synic(apic->vcpu)->vec_bitmap))
Andrey Smetanin5c9194122015-11-10 15:36:34 +03001254 kvm_hv_synic_send_eoi(apic->vcpu, vector);
1255
Yang Zhangc7c9c562013-01-25 10:18:51 +08001256 kvm_ioapic_send_eoi(apic, vector);
Avi Kivity3842d132010-07-27 12:30:24 +03001257 kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03001258 return vector;
Eddie Dong97222cc2007-09-12 10:58:04 +03001259}
1260
Yang Zhangc7c9c562013-01-25 10:18:51 +08001261/*
1262 * this interface assumes a trap-like exit, which has already finished
1263 * desired side effect including vISR and vPPR update.
1264 */
1265void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector)
1266{
1267 struct kvm_lapic *apic = vcpu->arch.apic;
1268
1269 trace_kvm_eoi(apic, vector);
1270
1271 kvm_ioapic_send_eoi(apic, vector);
1272 kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
1273}
1274EXPORT_SYMBOL_GPL(kvm_apic_set_eoi_accelerated);
1275
Wanpeng Lid5361672020-03-26 10:20:02 +08001276void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high)
Eddie Dong97222cc2007-09-12 10:58:04 +03001277{
Gleb Natapov58c2dde2009-03-05 16:35:04 +02001278 struct kvm_lapic_irq irq;
Eddie Dong97222cc2007-09-12 10:58:04 +03001279
Gleb Natapov58c2dde2009-03-05 16:35:04 +02001280 irq.vector = icr_low & APIC_VECTOR_MASK;
1281 irq.delivery_mode = icr_low & APIC_MODE_MASK;
1282 irq.dest_mode = icr_low & APIC_DEST_MASK;
Paolo Bonzinib7cb2232015-04-21 14:57:05 +02001283 irq.level = (icr_low & APIC_INT_ASSERT) != 0;
Gleb Natapov58c2dde2009-03-05 16:35:04 +02001284 irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
1285 irq.shorthand = icr_low & APIC_SHORT_MASK;
James Sullivan93bbf0b2015-03-18 19:26:03 -06001286 irq.msi_redir_hint = false;
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001287 if (apic_x2apic_mode(apic))
1288 irq.dest_id = icr_high;
1289 else
1290 irq.dest_id = GET_APIC_DEST_FIELD(icr_high);
Eddie Dong97222cc2007-09-12 10:58:04 +03001291
Gleb Natapov1000ff82009-07-07 16:00:57 +03001292 trace_kvm_apic_ipi(icr_low, irq.dest_id);
1293
Yang Zhangb4f22252013-04-11 19:21:37 +08001294 kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq, NULL);
Eddie Dong97222cc2007-09-12 10:58:04 +03001295}
1296
1297static u32 apic_get_tmcct(struct kvm_lapic *apic)
1298{
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001299 ktime_t remaining, now;
Marcelo Tosattib682b812009-02-10 20:41:41 -02001300 s64 ns;
Kevin Pedretti9da8f4e2007-10-21 08:55:50 +02001301 u32 tmcct;
Eddie Dong97222cc2007-09-12 10:58:04 +03001302
1303 ASSERT(apic != NULL);
1304
Kevin Pedretti9da8f4e2007-10-21 08:55:50 +02001305 /* if initial count is 0, current count should also be 0 */
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001306 if (kvm_lapic_get_reg(apic, APIC_TMICT) == 0 ||
Andy Honigb963a222013-11-19 14:12:18 -08001307 apic->lapic_timer.period == 0)
Kevin Pedretti9da8f4e2007-10-21 08:55:50 +02001308 return 0;
1309
Paolo Bonzini55878592016-10-25 15:23:49 +02001310 now = ktime_get();
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001311 remaining = ktime_sub(apic->lapic_timer.target_expiration, now);
Marcelo Tosattib682b812009-02-10 20:41:41 -02001312 if (ktime_to_ns(remaining) < 0)
Thomas Gleixner8b0e1952016-12-25 12:30:41 +01001313 remaining = 0;
Eddie Dong97222cc2007-09-12 10:58:04 +03001314
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03001315 ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
1316 tmcct = div64_u64(ns,
1317 (APIC_BUS_CYCLE_NS * apic->divide_count));
Eddie Dong97222cc2007-09-12 10:58:04 +03001318
1319 return tmcct;
1320}
1321
Avi Kivityb209749f2007-10-22 16:50:39 +02001322static void __report_tpr_access(struct kvm_lapic *apic, bool write)
1323{
1324 struct kvm_vcpu *vcpu = apic->vcpu;
1325 struct kvm_run *run = vcpu->run;
1326
Avi Kivitya8eeb042010-05-10 12:34:53 +03001327 kvm_make_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu);
Marcelo Tosatti5fdbf972008-06-27 14:58:02 -03001328 run->tpr_access.rip = kvm_rip_read(vcpu);
Avi Kivityb209749f2007-10-22 16:50:39 +02001329 run->tpr_access.is_write = write;
1330}
1331
1332static inline void report_tpr_access(struct kvm_lapic *apic, bool write)
1333{
1334 if (apic->vcpu->arch.tpr_access_reporting)
1335 __report_tpr_access(apic, write);
1336}
1337
Eddie Dong97222cc2007-09-12 10:58:04 +03001338static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
1339{
1340 u32 val = 0;
1341
1342 if (offset >= LAPIC_MMIO_LENGTH)
1343 return 0;
1344
1345 switch (offset) {
1346 case APIC_ARBPRI:
Eddie Dong97222cc2007-09-12 10:58:04 +03001347 break;
1348
1349 case APIC_TMCCT: /* Timer CCR */
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08001350 if (apic_lvtt_tscdeadline(apic))
1351 return 0;
1352
Eddie Dong97222cc2007-09-12 10:58:04 +03001353 val = apic_get_tmcct(apic);
1354 break;
Avi Kivity4a4541a2012-07-22 17:41:00 +03001355 case APIC_PROCPRI:
1356 apic_update_ppr(apic);
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001357 val = kvm_lapic_get_reg(apic, offset);
Avi Kivity4a4541a2012-07-22 17:41:00 +03001358 break;
Avi Kivityb209749f2007-10-22 16:50:39 +02001359 case APIC_TASKPRI:
1360 report_tpr_access(apic, false);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001361 fallthrough;
Eddie Dong97222cc2007-09-12 10:58:04 +03001362 default:
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001363 val = kvm_lapic_get_reg(apic, offset);
Eddie Dong97222cc2007-09-12 10:58:04 +03001364 break;
1365 }
1366
1367 return val;
1368}
1369
Gregory Haskinsd76685c42009-06-01 12:54:50 -04001370static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev)
1371{
1372 return container_of(dev, struct kvm_lapic, dev);
1373}
1374
Paolo Bonzini01402cf2019-07-05 14:57:58 +02001375#define APIC_REG_MASK(reg) (1ull << ((reg) >> 4))
1376#define APIC_REGS_MASK(first, count) \
1377 (APIC_REG_MASK(first) * ((1ull << (count)) - 1))
1378
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05001379int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001380 void *data)
Michael S. Tsirkinbda90202009-06-29 22:24:32 +03001381{
Eddie Dong97222cc2007-09-12 10:58:04 +03001382 unsigned char alignment = offset & 0xf;
1383 u32 result;
Guo Chaod5b0b5b2012-06-28 15:22:57 +08001384 /* this bitmask has a bit cleared for each reserved register */
Paolo Bonzini01402cf2019-07-05 14:57:58 +02001385 u64 valid_reg_mask =
1386 APIC_REG_MASK(APIC_ID) |
1387 APIC_REG_MASK(APIC_LVR) |
1388 APIC_REG_MASK(APIC_TASKPRI) |
1389 APIC_REG_MASK(APIC_PROCPRI) |
1390 APIC_REG_MASK(APIC_LDR) |
1391 APIC_REG_MASK(APIC_DFR) |
1392 APIC_REG_MASK(APIC_SPIV) |
1393 APIC_REGS_MASK(APIC_ISR, APIC_ISR_NR) |
1394 APIC_REGS_MASK(APIC_TMR, APIC_ISR_NR) |
1395 APIC_REGS_MASK(APIC_IRR, APIC_ISR_NR) |
1396 APIC_REG_MASK(APIC_ESR) |
1397 APIC_REG_MASK(APIC_ICR) |
1398 APIC_REG_MASK(APIC_ICR2) |
1399 APIC_REG_MASK(APIC_LVTT) |
1400 APIC_REG_MASK(APIC_LVTTHMR) |
1401 APIC_REG_MASK(APIC_LVTPC) |
1402 APIC_REG_MASK(APIC_LVT0) |
1403 APIC_REG_MASK(APIC_LVT1) |
1404 APIC_REG_MASK(APIC_LVTERR) |
1405 APIC_REG_MASK(APIC_TMICT) |
1406 APIC_REG_MASK(APIC_TMCCT) |
1407 APIC_REG_MASK(APIC_TDCR);
Eddie Dong97222cc2007-09-12 10:58:04 +03001408
Paolo Bonzini01402cf2019-07-05 14:57:58 +02001409 /* ARBPRI is not valid on x2APIC */
1410 if (!apic_x2apic_mode(apic))
1411 valid_reg_mask |= APIC_REG_MASK(APIC_ARBPRI);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001412
Jim Mattson218bf772021-06-02 13:52:24 -07001413 if (alignment + len > 4)
1414 return 1;
1415
Yi Wang0d888002019-07-06 01:08:48 +08001416 if (offset > 0x3f0 || !(valid_reg_mask & APIC_REG_MASK(offset)))
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001417 return 1;
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001418
Eddie Dong97222cc2007-09-12 10:58:04 +03001419 result = __apic_read(apic, offset & ~0xf);
1420
Marcelo Tosatti229456f2009-06-17 09:22:14 -03001421 trace_kvm_apic_read(offset, result);
1422
Eddie Dong97222cc2007-09-12 10:58:04 +03001423 switch (len) {
1424 case 1:
1425 case 2:
1426 case 4:
1427 memcpy(data, (char *)&result + alignment, len);
1428 break;
1429 default:
1430 printk(KERN_ERR "Local APIC read with len = %x, "
1431 "should be 1,2, or 4 instead\n", len);
1432 break;
1433 }
Michael S. Tsirkinbda90202009-06-29 22:24:32 +03001434 return 0;
Eddie Dong97222cc2007-09-12 10:58:04 +03001435}
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05001436EXPORT_SYMBOL_GPL(kvm_lapic_reg_read);
Eddie Dong97222cc2007-09-12 10:58:04 +03001437
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001438static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
1439{
Vitaly Kuznetsovd1766202018-08-02 17:08:16 +02001440 return addr >= apic->base_address &&
1441 addr < apic->base_address + LAPIC_MMIO_LENGTH;
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001442}
1443
Nikolay Nikolaeve32edf42015-03-26 14:39:28 +00001444static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001445 gpa_t address, int len, void *data)
1446{
1447 struct kvm_lapic *apic = to_lapic(this);
1448 u32 offset = address - apic->base_address;
1449
1450 if (!apic_mmio_in_range(apic, address))
1451 return -EOPNOTSUPP;
1452
Vitaly Kuznetsovd1766202018-08-02 17:08:16 +02001453 if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
1454 if (!kvm_check_has_quirk(vcpu->kvm,
1455 KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
1456 return -EOPNOTSUPP;
1457
1458 memset(data, 0xff, len);
1459 return 0;
1460 }
1461
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05001462 kvm_lapic_reg_read(apic, offset, len, data);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03001463
1464 return 0;
1465}
1466
Eddie Dong97222cc2007-09-12 10:58:04 +03001467static void update_divide_count(struct kvm_lapic *apic)
1468{
1469 u32 tmp1, tmp2, tdcr;
1470
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001471 tdcr = kvm_lapic_get_reg(apic, APIC_TDCR);
Eddie Dong97222cc2007-09-12 10:58:04 +03001472 tmp1 = tdcr & 0xf;
1473 tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03001474 apic->divide_count = 0x1 << (tmp2 & 0x7);
Eddie Dong97222cc2007-09-12 10:58:04 +03001475}
1476
Wanpeng Liccbfa1d2017-10-05 18:54:24 -07001477static void limit_periodic_timer_frequency(struct kvm_lapic *apic)
1478{
1479 /*
1480 * Do not allow the guest to program periodic timers with small
1481 * interval, since the hrtimers are not throttled by the host
1482 * scheduler.
1483 */
Wanpeng Lidedf9c52017-10-05 18:54:25 -07001484 if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
Wanpeng Liccbfa1d2017-10-05 18:54:24 -07001485 s64 min_period = min_timer_period_us * 1000LL;
1486
1487 if (apic->lapic_timer.period < min_period) {
1488 pr_info_ratelimited(
1489 "kvm: vcpu %i: requested %lld ns "
1490 "lapic timer period limited to %lld ns\n",
1491 apic->vcpu->vcpu_id,
1492 apic->lapic_timer.period, min_period);
1493 apic->lapic_timer.period = min_period;
1494 }
1495 }
1496}
1497
Wanpeng Li94be4b82020-03-24 14:32:10 +08001498static void cancel_hv_timer(struct kvm_lapic *apic);
1499
Wanpeng Lie898da72021-06-07 00:19:43 -07001500static void cancel_apic_timer(struct kvm_lapic *apic)
1501{
1502 hrtimer_cancel(&apic->lapic_timer.timer);
1503 preempt_disable();
1504 if (apic->lapic_timer.hv_timer_in_use)
1505 cancel_hv_timer(apic);
1506 preempt_enable();
1507}
1508
Radim Krčmářb6ac0692015-06-05 20:57:41 +02001509static void apic_update_lvtt(struct kvm_lapic *apic)
1510{
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001511 u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) &
Radim Krčmářb6ac0692015-06-05 20:57:41 +02001512 apic->lapic_timer.timer_mode_mask;
1513
1514 if (apic->lapic_timer.timer_mode != timer_mode) {
Wanpeng Lic69518c2017-10-05 03:53:51 -07001515 if (apic_lvtt_tscdeadline(apic) != (timer_mode ==
Wanpeng Lidedf9c52017-10-05 18:54:25 -07001516 APIC_LVT_TIMER_TSCDEADLINE)) {
Wanpeng Lie898da72021-06-07 00:19:43 -07001517 cancel_apic_timer(apic);
Radim Krčmář44275932017-10-06 19:25:55 +02001518 kvm_lapic_set_reg(apic, APIC_TMICT, 0);
1519 apic->lapic_timer.period = 0;
1520 apic->lapic_timer.tscdeadline = 0;
Wanpeng Lidedf9c52017-10-05 18:54:25 -07001521 }
Radim Krčmářb6ac0692015-06-05 20:57:41 +02001522 apic->lapic_timer.timer_mode = timer_mode;
Wanpeng Lidedf9c52017-10-05 18:54:25 -07001523 limit_periodic_timer_frequency(apic);
Radim Krčmářb6ac0692015-06-05 20:57:41 +02001524 }
1525}
1526
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001527/*
1528 * On APICv, this test will cause a busy wait
1529 * during a higher-priority task.
1530 */
1531
1532static bool lapic_timer_int_injected(struct kvm_vcpu *vcpu)
1533{
1534 struct kvm_lapic *apic = vcpu->arch.apic;
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05001535 u32 reg = kvm_lapic_get_reg(apic, APIC_LVTT);
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001536
1537 if (kvm_apic_hw_enabled(apic)) {
1538 int vec = reg & APIC_VECTOR_MASK;
Marcelo Tosattif9339862015-02-02 15:26:08 -02001539 void *bitmap = apic->regs + APIC_ISR;
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001540
Andrey Smetanind62caab2015-11-10 15:36:33 +03001541 if (vcpu->arch.apicv_active)
Marcelo Tosattif9339862015-02-02 15:26:08 -02001542 bitmap = apic->regs + APIC_IRR;
1543
1544 if (apic_test_vector(vec, bitmap))
1545 return true;
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001546 }
1547 return false;
1548}
1549
Sean Christophersonb6aa57c2019-04-17 10:15:34 -07001550static inline void __wait_lapic_expire(struct kvm_vcpu *vcpu, u64 guest_cycles)
1551{
1552 u64 timer_advance_ns = vcpu->arch.apic->lapic_timer.timer_advance_ns;
1553
1554 /*
1555 * If the guest TSC is running at a different ratio than the host, then
1556 * convert the delay to nanoseconds to achieve an accurate delay. Note
1557 * that __delay() uses delay_tsc whenever the hardware has TSC, thus
1558 * always for VMX enabled hardware.
1559 */
1560 if (vcpu->arch.tsc_scaling_ratio == kvm_default_tsc_scaling_ratio) {
1561 __delay(min(guest_cycles,
1562 nsec_to_cycles(vcpu, timer_advance_ns)));
1563 } else {
1564 u64 delay_ns = guest_cycles * 1000000ULL;
1565 do_div(delay_ns, vcpu->arch.virtual_tsc_khz);
1566 ndelay(min_t(u32, delay_ns, timer_advance_ns));
1567 }
1568}
1569
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001570static inline void adjust_lapic_timer_advance(struct kvm_vcpu *vcpu,
Wanpeng Liec0671d2019-05-20 16:18:08 +08001571 s64 advance_expire_delta)
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001572{
1573 struct kvm_lapic *apic = vcpu->arch.apic;
Sean Christopherson39497d72019-04-17 10:15:32 -07001574 u32 timer_advance_ns = apic->lapic_timer.timer_advance_ns;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001575 u64 ns;
1576
Wanpeng Lid0f5a862019-09-17 16:16:26 +08001577 /* Do not adjust for tiny fluctuations or large random spikes. */
1578 if (abs(advance_expire_delta) > LAPIC_TIMER_ADVANCE_ADJUST_MAX ||
1579 abs(advance_expire_delta) < LAPIC_TIMER_ADVANCE_ADJUST_MIN)
1580 return;
1581
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001582 /* too early */
Wanpeng Liec0671d2019-05-20 16:18:08 +08001583 if (advance_expire_delta < 0) {
1584 ns = -advance_expire_delta * 1000000ULL;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001585 do_div(ns, vcpu->arch.virtual_tsc_khz);
Wanpeng Lid0f5a862019-09-17 16:16:26 +08001586 timer_advance_ns -= ns/LAPIC_TIMER_ADVANCE_ADJUST_STEP;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001587 } else {
1588 /* too late */
Wanpeng Liec0671d2019-05-20 16:18:08 +08001589 ns = advance_expire_delta * 1000000ULL;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001590 do_div(ns, vcpu->arch.virtual_tsc_khz);
Wanpeng Lid0f5a862019-09-17 16:16:26 +08001591 timer_advance_ns += ns/LAPIC_TIMER_ADVANCE_ADJUST_STEP;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001592 }
1593
Wanpeng Lia0f00372019-09-26 08:54:03 +08001594 if (unlikely(timer_advance_ns > LAPIC_TIMER_ADVANCE_NS_MAX))
1595 timer_advance_ns = LAPIC_TIMER_ADVANCE_NS_INIT;
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001596 apic->lapic_timer.timer_advance_ns = timer_advance_ns;
1597}
1598
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001599static void __kvm_wait_lapic_expire(struct kvm_vcpu *vcpu)
Wanpeng Li84ea3ac2019-05-20 16:18:05 +08001600{
1601 struct kvm_lapic *apic = vcpu->arch.apic;
1602 u64 guest_tsc, tsc_deadline;
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001603
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001604 tsc_deadline = apic->lapic_timer.expired_tscdeadline;
1605 apic->lapic_timer.expired_tscdeadline = 0;
Haozhong Zhang4ba76532015-10-20 15:39:07 +08001606 guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
Wanpeng Liec0671d2019-05-20 16:18:08 +08001607 apic->lapic_timer.advance_expire_delta = guest_tsc - tsc_deadline;
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001608
Wanpeng Li9805cf02021-05-18 05:00:35 -07001609 if (lapic_timer_advance_dynamic) {
1610 adjust_lapic_timer_advance(vcpu, apic->lapic_timer.advance_expire_delta);
1611 /*
1612 * If the timer fired early, reread the TSC to account for the
1613 * overhead of the above adjustment to avoid waiting longer
1614 * than is necessary.
1615 */
1616 if (guest_tsc < tsc_deadline)
1617 guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
1618 }
1619
Marcelo Tosattid0659d92014-12-16 09:08:15 -05001620 if (guest_tsc < tsc_deadline)
Sean Christophersonb6aa57c2019-04-17 10:15:34 -07001621 __wait_lapic_expire(vcpu, tsc_deadline - guest_tsc);
Radim Krčmář5d87db72014-10-10 19:15:08 +02001622}
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001623
1624void kvm_wait_lapic_expire(struct kvm_vcpu *vcpu)
1625{
Wanpeng Li010fd372020-09-10 17:50:41 +08001626 if (lapic_in_kernel(vcpu) &&
1627 vcpu->arch.apic->lapic_timer.expired_tscdeadline &&
1628 vcpu->arch.apic->lapic_timer.timer_advance_ns &&
1629 lapic_timer_int_injected(vcpu))
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001630 __kvm_wait_lapic_expire(vcpu);
1631}
Wanpeng Lib6c4bc62019-05-20 16:18:09 +08001632EXPORT_SYMBOL_GPL(kvm_wait_lapic_expire);
Radim Krčmář5d87db72014-10-10 19:15:08 +02001633
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001634static void kvm_apic_inject_pending_timer_irqs(struct kvm_lapic *apic)
1635{
1636 struct kvm_timer *ktimer = &apic->lapic_timer;
1637
1638 kvm_apic_local_deliver(apic, APIC_LVTT);
Haiwei Li17ac43a2020-01-16 16:50:21 +08001639 if (apic_lvtt_tscdeadline(apic)) {
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001640 ktimer->tscdeadline = 0;
Haiwei Li17ac43a2020-01-16 16:50:21 +08001641 } else if (apic_lvtt_oneshot(apic)) {
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001642 ktimer->tscdeadline = 0;
1643 ktimer->target_expiration = 0;
1644 }
1645}
1646
Wanpeng Liae95f562020-04-28 14:23:28 +08001647static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001648{
1649 struct kvm_vcpu *vcpu = apic->vcpu;
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001650 struct kvm_timer *ktimer = &apic->lapic_timer;
1651
1652 if (atomic_read(&apic->lapic_timer.pending))
1653 return;
1654
1655 if (apic_lvtt_tscdeadline(apic) || ktimer->hv_timer_in_use)
1656 ktimer->expired_tscdeadline = ktimer->tscdeadline;
1657
Wanpeng Liae95f562020-04-28 14:23:28 +08001658 if (!from_timer_fn && vcpu->arch.apicv_active) {
1659 WARN_ON(kvm_get_running_vcpu() != vcpu);
1660 kvm_apic_inject_pending_timer_irqs(apic);
1661 return;
1662 }
1663
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001664 if (kvm_use_posted_timer_interrupt(apic->vcpu)) {
Sean Christophersonbeda4302021-03-04 18:18:08 -08001665 /*
1666 * Ensure the guest's timer has truly expired before posting an
1667 * interrupt. Open code the relevant checks to avoid querying
1668 * lapic_timer_int_injected(), which will be false since the
1669 * interrupt isn't yet injected. Waiting until after injecting
1670 * is not an option since that won't help a posted interrupt.
1671 */
1672 if (vcpu->arch.apic->lapic_timer.expired_tscdeadline &&
1673 vcpu->arch.apic->lapic_timer.timer_advance_ns)
1674 __kvm_wait_lapic_expire(vcpu);
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001675 kvm_apic_inject_pending_timer_irqs(apic);
1676 return;
1677 }
1678
1679 atomic_inc(&apic->lapic_timer.pending);
Marcelo Tosatti084071d2021-05-25 10:41:17 -03001680 kvm_make_request(KVM_REQ_UNBLOCK, vcpu);
Wanpeng Li68ca76632020-09-10 17:50:40 +08001681 if (from_timer_fn)
1682 kvm_vcpu_kick(vcpu);
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08001683}
1684
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001685static void start_sw_tscdeadline(struct kvm_lapic *apic)
1686{
Sean Christopherson39497d72019-04-17 10:15:32 -07001687 struct kvm_timer *ktimer = &apic->lapic_timer;
1688 u64 guest_tsc, tscdeadline = ktimer->tscdeadline;
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001689 u64 ns = 0;
1690 ktime_t expire;
1691 struct kvm_vcpu *vcpu = apic->vcpu;
1692 unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz;
1693 unsigned long flags;
1694 ktime_t now;
1695
1696 if (unlikely(!tscdeadline || !this_tsc_khz))
1697 return;
1698
1699 local_irq_save(flags);
1700
Paolo Bonzini55878592016-10-25 15:23:49 +02001701 now = ktime_get();
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001702 guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
Liran Alonc09d65d2019-04-16 20:36:34 +03001703
1704 ns = (tscdeadline - guest_tsc) * 1000000ULL;
1705 do_div(ns, this_tsc_khz);
1706
1707 if (likely(tscdeadline > guest_tsc) &&
Sean Christopherson39497d72019-04-17 10:15:32 -07001708 likely(ns > apic->lapic_timer.timer_advance_ns)) {
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001709 expire = ktime_add_ns(now, ns);
Sean Christopherson39497d72019-04-17 10:15:32 -07001710 expire = ktime_sub_ns(expire, ktimer->timer_advance_ns);
Sebastian Andrzej Siewior2c0d2782019-07-26 20:30:55 +02001711 hrtimer_start(&ktimer->timer, expire, HRTIMER_MODE_ABS_HARD);
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001712 } else
Wanpeng Liae95f562020-04-28 14:23:28 +08001713 apic_timer_expired(apic, false);
Yunhong Jiang53f9eed2016-06-13 14:20:00 -07001714
1715 local_irq_restore(flags);
1716}
1717
Peter Shier24647e02018-10-10 15:56:53 -07001718static inline u64 tmict_to_ns(struct kvm_lapic *apic, u32 tmict)
1719{
1720 return (u64)tmict * APIC_BUS_CYCLE_NS * (u64)apic->divide_count;
1721}
1722
Wanpeng Lic301b902017-10-06 07:38:32 -07001723static void update_target_expiration(struct kvm_lapic *apic, uint32_t old_divisor)
1724{
1725 ktime_t now, remaining;
1726 u64 ns_remaining_old, ns_remaining_new;
1727
Peter Shier24647e02018-10-10 15:56:53 -07001728 apic->lapic_timer.period =
1729 tmict_to_ns(apic, kvm_lapic_get_reg(apic, APIC_TMICT));
Wanpeng Lic301b902017-10-06 07:38:32 -07001730 limit_periodic_timer_frequency(apic);
1731
1732 now = ktime_get();
1733 remaining = ktime_sub(apic->lapic_timer.target_expiration, now);
1734 if (ktime_to_ns(remaining) < 0)
1735 remaining = 0;
1736
1737 ns_remaining_old = ktime_to_ns(remaining);
1738 ns_remaining_new = mul_u64_u32_div(ns_remaining_old,
1739 apic->divide_count, old_divisor);
1740
1741 apic->lapic_timer.tscdeadline +=
1742 nsec_to_cycles(apic->vcpu, ns_remaining_new) -
1743 nsec_to_cycles(apic->vcpu, ns_remaining_old);
1744 apic->lapic_timer.target_expiration = ktime_add_ns(now, ns_remaining_new);
1745}
1746
Peter Shier24647e02018-10-10 15:56:53 -07001747static bool set_target_expiration(struct kvm_lapic *apic, u32 count_reg)
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001748{
1749 ktime_t now;
1750 u64 tscl = rdtsc();
Peter Shier24647e02018-10-10 15:56:53 -07001751 s64 deadline;
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001752
Paolo Bonzini55878592016-10-25 15:23:49 +02001753 now = ktime_get();
Peter Shier24647e02018-10-10 15:56:53 -07001754 apic->lapic_timer.period =
1755 tmict_to_ns(apic, kvm_lapic_get_reg(apic, APIC_TMICT));
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001756
Radim Krčmář5d74a692017-10-06 19:25:54 +02001757 if (!apic->lapic_timer.period) {
1758 apic->lapic_timer.tscdeadline = 0;
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001759 return false;
Wanpeng Li7d7f7da2016-10-24 18:23:09 +08001760 }
1761
Wanpeng Liccbfa1d2017-10-05 18:54:24 -07001762 limit_periodic_timer_frequency(apic);
Peter Shier24647e02018-10-10 15:56:53 -07001763 deadline = apic->lapic_timer.period;
1764
1765 if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
1766 if (unlikely(count_reg != APIC_TMICT)) {
1767 deadline = tmict_to_ns(apic,
1768 kvm_lapic_get_reg(apic, count_reg));
1769 if (unlikely(deadline <= 0))
1770 deadline = apic->lapic_timer.period;
1771 else if (unlikely(deadline > apic->lapic_timer.period)) {
1772 pr_info_ratelimited(
1773 "kvm: vcpu %i: requested lapic timer restore with "
1774 "starting count register %#x=%u (%lld ns) > initial count (%lld ns). "
1775 "Using initial count to start timer.\n",
1776 apic->vcpu->vcpu_id,
1777 count_reg,
1778 kvm_lapic_get_reg(apic, count_reg),
1779 deadline, apic->lapic_timer.period);
1780 kvm_lapic_set_reg(apic, count_reg, 0);
1781 deadline = apic->lapic_timer.period;
1782 }
1783 }
1784 }
Wanpeng Li7d7f7da2016-10-24 18:23:09 +08001785
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001786 apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
Peter Shier24647e02018-10-10 15:56:53 -07001787 nsec_to_cycles(apic->vcpu, deadline);
1788 apic->lapic_timer.target_expiration = ktime_add_ns(now, deadline);
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001789
1790 return true;
1791}
1792
1793static void advance_periodic_target_expiration(struct kvm_lapic *apic)
1794{
David Vrabeld8f2f492018-05-18 16:55:46 +01001795 ktime_t now = ktime_get();
1796 u64 tscl = rdtsc();
1797 ktime_t delta;
1798
1799 /*
1800 * Synchronize both deadlines to the same time source or
1801 * differences in the periods (caused by differences in the
1802 * underlying clocks or numerical approximation errors) will
1803 * cause the two to drift apart over time as the errors
1804 * accumulate.
1805 */
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001806 apic->lapic_timer.target_expiration =
1807 ktime_add_ns(apic->lapic_timer.target_expiration,
1808 apic->lapic_timer.period);
David Vrabeld8f2f492018-05-18 16:55:46 +01001809 delta = ktime_sub(apic->lapic_timer.target_expiration, now);
1810 apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
1811 nsec_to_cycles(apic->vcpu, delta);
Wanpeng Li7d7f7da2016-10-24 18:23:09 +08001812}
1813
Anthoine Bourgeoisecf08da2018-04-29 22:05:58 +00001814static void start_sw_period(struct kvm_lapic *apic)
1815{
1816 if (!apic->lapic_timer.period)
1817 return;
1818
1819 if (ktime_after(ktime_get(),
1820 apic->lapic_timer.target_expiration)) {
Wanpeng Liae95f562020-04-28 14:23:28 +08001821 apic_timer_expired(apic, false);
Anthoine Bourgeoisecf08da2018-04-29 22:05:58 +00001822
1823 if (apic_lvtt_oneshot(apic))
1824 return;
1825
1826 advance_periodic_target_expiration(apic);
1827 }
1828
1829 hrtimer_start(&apic->lapic_timer.timer,
1830 apic->lapic_timer.target_expiration,
He Zheedec6e02020-03-20 15:06:07 +08001831 HRTIMER_MODE_ABS_HARD);
Anthoine Bourgeoisecf08da2018-04-29 22:05:58 +00001832}
1833
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001834bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
1835{
Wanpeng Li91005302016-08-03 12:04:12 +08001836 if (!lapic_in_kernel(vcpu))
1837 return false;
1838
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001839 return vcpu->arch.apic->lapic_timer.hv_timer_in_use;
1840}
1841EXPORT_SYMBOL_GPL(kvm_lapic_hv_timer_in_use);
1842
Wanpeng Li7e810a32016-10-24 18:23:12 +08001843static void cancel_hv_timer(struct kvm_lapic *apic)
Wanpeng Libd97ad02016-06-30 08:52:49 +08001844{
Wanpeng Li1d518c62017-07-25 00:43:15 -07001845 WARN_ON(preemptible());
Paolo Bonzinia749e242017-06-29 17:14:50 +02001846 WARN_ON(!apic->lapic_timer.hv_timer_in_use);
Jason Baronb36464772021-01-14 22:27:56 -05001847 static_call(kvm_x86_cancel_hv_timer)(apic->vcpu);
Wanpeng Libd97ad02016-06-30 08:52:49 +08001848 apic->lapic_timer.hv_timer_in_use = false;
1849}
1850
Paolo Bonzinia749e242017-06-29 17:14:50 +02001851static bool start_hv_timer(struct kvm_lapic *apic)
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001852{
1853 struct kvm_timer *ktimer = &apic->lapic_timer;
Sean Christophersonf9927982019-04-16 13:32:46 -07001854 struct kvm_vcpu *vcpu = apic->vcpu;
1855 bool expired;
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001856
Wanpeng Li1d518c62017-07-25 00:43:15 -07001857 WARN_ON(preemptible());
Paolo Bonzini199a8b82020-05-05 06:45:35 -04001858 if (!kvm_can_use_hv_timer(vcpu))
Paolo Bonzinia749e242017-06-29 17:14:50 +02001859 return false;
1860
Radim Krčmář86bbc1e2017-10-06 19:25:53 +02001861 if (!ktimer->tscdeadline)
1862 return false;
1863
Jason Baronb36464772021-01-14 22:27:56 -05001864 if (static_call(kvm_x86_set_hv_timer)(vcpu, ktimer->tscdeadline, &expired))
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001865 return false;
1866
1867 ktimer->hv_timer_in_use = true;
1868 hrtimer_cancel(&ktimer->timer);
1869
1870 /*
Sean Christophersonf1ba5cf2019-04-16 13:32:45 -07001871 * To simplify handling the periodic timer, leave the hv timer running
1872 * even if the deadline timer has expired, i.e. rely on the resulting
1873 * VM-Exit to recompute the periodic timer's target expiration.
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001874 */
Sean Christophersonf1ba5cf2019-04-16 13:32:45 -07001875 if (!apic_lvtt_period(apic)) {
1876 /*
1877 * Cancel the hv timer if the sw timer fired while the hv timer
1878 * was being programmed, or if the hv timer itself expired.
1879 */
1880 if (atomic_read(&ktimer->pending)) {
1881 cancel_hv_timer(apic);
Sean Christophersonf9927982019-04-16 13:32:46 -07001882 } else if (expired) {
Wanpeng Liae95f562020-04-28 14:23:28 +08001883 apic_timer_expired(apic, false);
Sean Christophersonf1ba5cf2019-04-16 13:32:45 -07001884 cancel_hv_timer(apic);
1885 }
Wanpeng Lic8533542017-06-29 06:28:09 -07001886 }
Paolo Bonzinia749e242017-06-29 17:14:50 +02001887
Sean Christophersonf9927982019-04-16 13:32:46 -07001888 trace_kvm_hv_timer_state(vcpu->vcpu_id, ktimer->hv_timer_in_use);
Sean Christophersonf1ba5cf2019-04-16 13:32:45 -07001889
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001890 return true;
1891}
1892
Paolo Bonzinia749e242017-06-29 17:14:50 +02001893static void start_sw_timer(struct kvm_lapic *apic)
Wanpeng Li196f20c2016-06-28 14:54:19 +08001894{
Paolo Bonzinia749e242017-06-29 17:14:50 +02001895 struct kvm_timer *ktimer = &apic->lapic_timer;
Wanpeng Li1d518c62017-07-25 00:43:15 -07001896
1897 WARN_ON(preemptible());
Paolo Bonzinia749e242017-06-29 17:14:50 +02001898 if (apic->lapic_timer.hv_timer_in_use)
1899 cancel_hv_timer(apic);
1900 if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
1901 return;
Paolo Bonzini35ee9e42017-06-29 17:14:50 +02001902
Paolo Bonzinia749e242017-06-29 17:14:50 +02001903 if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
1904 start_sw_period(apic);
1905 else if (apic_lvtt_tscdeadline(apic))
1906 start_sw_tscdeadline(apic);
1907 trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false);
1908}
1909
1910static void restart_apic_timer(struct kvm_lapic *apic)
1911{
Wanpeng Li1d518c62017-07-25 00:43:15 -07001912 preempt_disable();
Sean Christopherson4ca88b32019-04-16 13:32:47 -07001913
1914 if (!apic_lvtt_period(apic) && atomic_read(&apic->lapic_timer.pending))
1915 goto out;
1916
Paolo Bonzinia749e242017-06-29 17:14:50 +02001917 if (!start_hv_timer(apic))
1918 start_sw_timer(apic);
Sean Christopherson4ca88b32019-04-16 13:32:47 -07001919out:
Wanpeng Li1d518c62017-07-25 00:43:15 -07001920 preempt_enable();
Wanpeng Li196f20c2016-06-28 14:54:19 +08001921}
1922
Eddie Dong97222cc2007-09-12 10:58:04 +03001923void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
1924{
1925 struct kvm_lapic *apic = vcpu->arch.apic;
1926
Wanpeng Li1d518c62017-07-25 00:43:15 -07001927 preempt_disable();
1928 /* If the preempt notifier has already run, it also called apic_timer_expired */
1929 if (!apic->lapic_timer.hv_timer_in_use)
1930 goto out;
Davidlohr Buesoda4ad882020-04-23 22:48:37 -07001931 WARN_ON(rcuwait_active(&vcpu->wait));
Wanpeng Liae95f562020-04-28 14:23:28 +08001932 apic_timer_expired(apic, false);
Wanpeng Lid981dd12021-04-28 19:08:02 +08001933 cancel_hv_timer(apic);
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001934
1935 if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
1936 advance_periodic_target_expiration(apic);
Paolo Bonzinia749e242017-06-29 17:14:50 +02001937 restart_apic_timer(apic);
Wanpeng Li8003c9a2016-10-24 18:23:13 +08001938 }
Wanpeng Li1d518c62017-07-25 00:43:15 -07001939out:
1940 preempt_enable();
Eddie Dong97222cc2007-09-12 10:58:04 +03001941}
1942EXPORT_SYMBOL_GPL(kvm_lapic_expired_hv_timer);
1943
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001944void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu)
1945{
Paolo Bonzinia749e242017-06-29 17:14:50 +02001946 restart_apic_timer(vcpu->arch.apic);
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001947}
1948EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_hv_timer);
1949
1950void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu)
1951{
1952 struct kvm_lapic *apic = vcpu->arch.apic;
1953
Wanpeng Li1d518c62017-07-25 00:43:15 -07001954 preempt_disable();
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001955 /* Possibly the TSC deadline timer is not enabled yet */
Paolo Bonzinia749e242017-06-29 17:14:50 +02001956 if (apic->lapic_timer.hv_timer_in_use)
1957 start_sw_timer(apic);
Wanpeng Li1d518c62017-07-25 00:43:15 -07001958 preempt_enable();
Yunhong Jiangce7a0582016-06-13 14:20:01 -07001959}
1960EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_sw_timer);
1961
Paolo Bonzinia749e242017-06-29 17:14:50 +02001962void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu)
1963{
1964 struct kvm_lapic *apic = vcpu->arch.apic;
1965
1966 WARN_ON(!apic->lapic_timer.hv_timer_in_use);
1967 restart_apic_timer(apic);
1968}
1969
Peter Shier24647e02018-10-10 15:56:53 -07001970static void __start_apic_timer(struct kvm_lapic *apic, u32 count_reg)
Eddie Dong97222cc2007-09-12 10:58:04 +03001971{
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03001972 atomic_set(&apic->lapic_timer.pending, 0);
Avi Kivity0b975a32008-02-24 14:37:50 +02001973
Paolo Bonzinia749e242017-06-29 17:14:50 +02001974 if ((apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
Peter Shier24647e02018-10-10 15:56:53 -07001975 && !set_target_expiration(apic, count_reg))
Paolo Bonzinia749e242017-06-29 17:14:50 +02001976 return;
1977
1978 restart_apic_timer(apic);
Eddie Dong97222cc2007-09-12 10:58:04 +03001979}
1980
Peter Shier24647e02018-10-10 15:56:53 -07001981static void start_apic_timer(struct kvm_lapic *apic)
1982{
1983 __start_apic_timer(apic, APIC_TMICT);
1984}
1985
Jan Kiszkacc6e4622008-10-20 10:20:03 +02001986static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
1987{
Radim Krčmář59fd1322015-06-30 22:19:16 +02001988 bool lvt0_in_nmi_mode = apic_lvt_nmi_mode(lvt0_val);
Jan Kiszkacc6e4622008-10-20 10:20:03 +02001989
Radim Krčmář59fd1322015-06-30 22:19:16 +02001990 if (apic->lvt0_in_nmi_mode != lvt0_in_nmi_mode) {
1991 apic->lvt0_in_nmi_mode = lvt0_in_nmi_mode;
1992 if (lvt0_in_nmi_mode) {
Radim Krčmář42720132015-07-01 15:31:49 +02001993 atomic_inc(&apic->vcpu->kvm->arch.vapics_in_nmi_mode);
Radim Krčmář59fd1322015-06-30 22:19:16 +02001994 } else
1995 atomic_dec(&apic->vcpu->kvm->arch.vapics_in_nmi_mode);
1996 }
Jan Kiszkacc6e4622008-10-20 10:20:03 +02001997}
1998
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05001999int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
Eddie Dong97222cc2007-09-12 10:58:04 +03002000{
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002001 int ret = 0;
Eddie Dong97222cc2007-09-12 10:58:04 +03002002
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002003 trace_kvm_apic_write(reg, val);
Eddie Dong97222cc2007-09-12 10:58:04 +03002004
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002005 switch (reg) {
Eddie Dong97222cc2007-09-12 10:58:04 +03002006 case APIC_ID: /* Local APIC ID */
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002007 if (!apic_x2apic_mode(apic))
Radim Krčmářa92e2542016-07-12 22:09:22 +02002008 kvm_apic_set_xapic_id(apic, val >> 24);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002009 else
2010 ret = 1;
Eddie Dong97222cc2007-09-12 10:58:04 +03002011 break;
2012
2013 case APIC_TASKPRI:
Avi Kivityb209749f2007-10-22 16:50:39 +02002014 report_tpr_access(apic, true);
Eddie Dong97222cc2007-09-12 10:58:04 +03002015 apic_set_tpr(apic, val & 0xff);
2016 break;
2017
2018 case APIC_EOI:
2019 apic_set_eoi(apic);
2020 break;
2021
2022 case APIC_LDR:
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002023 if (!apic_x2apic_mode(apic))
Gleb Natapov1e08ec42012-09-13 17:19:24 +03002024 kvm_apic_set_ldr(apic, val & APIC_LDR_MASK);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002025 else
2026 ret = 1;
Eddie Dong97222cc2007-09-12 10:58:04 +03002027 break;
2028
2029 case APIC_DFR:
Wanpeng Liae6f2492020-08-19 16:55:26 +08002030 if (!apic_x2apic_mode(apic))
2031 kvm_apic_set_dfr(apic, val | 0x0FFFFFFF);
2032 else
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002033 ret = 1;
Eddie Dong97222cc2007-09-12 10:58:04 +03002034 break;
2035
Gleb Natapovfc61b802009-07-05 17:39:35 +03002036 case APIC_SPIV: {
2037 u32 mask = 0x3ff;
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002038 if (kvm_lapic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
Gleb Natapovfc61b802009-07-05 17:39:35 +03002039 mask |= APIC_SPIV_DIRECTED_EOI;
Gleb Natapovf8c1ea12012-08-05 15:58:31 +03002040 apic_set_spiv(apic, val & mask);
Eddie Dong97222cc2007-09-12 10:58:04 +03002041 if (!(val & APIC_SPIV_APIC_ENABLED)) {
2042 int i;
2043 u32 lvt_val;
2044
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002045 for (i = 0; i < KVM_APIC_LVT_NUM; i++) {
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002046 lvt_val = kvm_lapic_get_reg(apic,
Eddie Dong97222cc2007-09-12 10:58:04 +03002047 APIC_LVTT + 0x10 * i);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002048 kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i,
Eddie Dong97222cc2007-09-12 10:58:04 +03002049 lvt_val | APIC_LVT_MASKED);
2050 }
Radim Krčmářb6ac0692015-06-05 20:57:41 +02002051 apic_update_lvtt(apic);
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002052 atomic_set(&apic->lapic_timer.pending, 0);
Eddie Dong97222cc2007-09-12 10:58:04 +03002053
2054 }
2055 break;
Gleb Natapovfc61b802009-07-05 17:39:35 +03002056 }
Eddie Dong97222cc2007-09-12 10:58:04 +03002057 case APIC_ICR:
2058 /* No delay here, so we always clear the pending bit */
Wanpeng Li2b0911d2019-09-05 14:26:27 +08002059 val &= ~(1 << 12);
Wanpeng Lid5361672020-03-26 10:20:02 +08002060 kvm_apic_send_ipi(apic, val, kvm_lapic_get_reg(apic, APIC_ICR2));
Wanpeng Li2b0911d2019-09-05 14:26:27 +08002061 kvm_lapic_set_reg(apic, APIC_ICR, val);
Eddie Dong97222cc2007-09-12 10:58:04 +03002062 break;
2063
2064 case APIC_ICR2:
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002065 if (!apic_x2apic_mode(apic))
2066 val &= 0xff000000;
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002067 kvm_lapic_set_reg(apic, APIC_ICR2, val);
Eddie Dong97222cc2007-09-12 10:58:04 +03002068 break;
2069
Jan Kiszka23930f92008-09-26 09:30:52 +02002070 case APIC_LVT0:
Jan Kiszkacc6e4622008-10-20 10:20:03 +02002071 apic_manage_nmi_watchdog(apic, val);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002072 fallthrough;
Eddie Dong97222cc2007-09-12 10:58:04 +03002073 case APIC_LVTTHMR:
2074 case APIC_LVTPC:
Eddie Dong97222cc2007-09-12 10:58:04 +03002075 case APIC_LVT1:
Marios Pomonis4bf79cb2019-12-11 12:47:46 -08002076 case APIC_LVTERR: {
Eddie Dong97222cc2007-09-12 10:58:04 +03002077 /* TODO: Check vector */
Marios Pomonis4bf79cb2019-12-11 12:47:46 -08002078 size_t size;
2079 u32 index;
2080
Gleb Natapovc48f1492012-08-05 15:58:33 +03002081 if (!kvm_apic_sw_enabled(apic))
Eddie Dong97222cc2007-09-12 10:58:04 +03002082 val |= APIC_LVT_MASKED;
Marios Pomonis4bf79cb2019-12-11 12:47:46 -08002083 size = ARRAY_SIZE(apic_lvt_mask);
2084 index = array_index_nospec(
2085 (reg - APIC_LVTT) >> 4, size);
2086 val &= apic_lvt_mask[index];
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002087 kvm_lapic_set_reg(apic, reg, val);
Eddie Dong97222cc2007-09-12 10:58:04 +03002088 break;
Marios Pomonis4bf79cb2019-12-11 12:47:46 -08002089 }
Eddie Dong97222cc2007-09-12 10:58:04 +03002090
Radim Krčmářb6ac0692015-06-05 20:57:41 +02002091 case APIC_LVTT:
Gleb Natapovc48f1492012-08-05 15:58:33 +03002092 if (!kvm_apic_sw_enabled(apic))
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002093 val |= APIC_LVT_MASKED;
2094 val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002095 kvm_lapic_set_reg(apic, APIC_LVTT, val);
Radim Krčmářb6ac0692015-06-05 20:57:41 +02002096 apic_update_lvtt(apic);
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002097 break;
2098
Eddie Dong97222cc2007-09-12 10:58:04 +03002099 case APIC_TMICT:
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002100 if (apic_lvtt_tscdeadline(apic))
2101 break;
2102
Wanpeng Lie898da72021-06-07 00:19:43 -07002103 cancel_apic_timer(apic);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002104 kvm_lapic_set_reg(apic, APIC_TMICT, val);
Eddie Dong97222cc2007-09-12 10:58:04 +03002105 start_apic_timer(apic);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002106 break;
Eddie Dong97222cc2007-09-12 10:58:04 +03002107
Wanpeng Lic301b902017-10-06 07:38:32 -07002108 case APIC_TDCR: {
2109 uint32_t old_divisor = apic->divide_count;
2110
Wanpeng Lia445fc42020-07-31 11:12:20 +08002111 kvm_lapic_set_reg(apic, APIC_TDCR, val & 0xb);
Eddie Dong97222cc2007-09-12 10:58:04 +03002112 update_divide_count(apic);
Wanpeng Lic301b902017-10-06 07:38:32 -07002113 if (apic->divide_count != old_divisor &&
2114 apic->lapic_timer.period) {
2115 hrtimer_cancel(&apic->lapic_timer.timer);
2116 update_target_expiration(apic, old_divisor);
2117 restart_apic_timer(apic);
2118 }
Eddie Dong97222cc2007-09-12 10:58:04 +03002119 break;
Wanpeng Lic301b902017-10-06 07:38:32 -07002120 }
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002121 case APIC_ESR:
Yi Wang0d888002019-07-06 01:08:48 +08002122 if (apic_x2apic_mode(apic) && val != 0)
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002123 ret = 1;
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002124 break;
2125
2126 case APIC_SELF_IPI:
2127 if (apic_x2apic_mode(apic)) {
Haiwei Li9c2475f2020-07-21 16:23:54 +08002128 kvm_lapic_reg_write(apic, APIC_ICR,
2129 APIC_DEST_SELF | (val & APIC_VECTOR_MASK));
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002130 } else
2131 ret = 1;
2132 break;
Eddie Dong97222cc2007-09-12 10:58:04 +03002133 default:
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002134 ret = 1;
Eddie Dong97222cc2007-09-12 10:58:04 +03002135 break;
2136 }
Yi Wang0d888002019-07-06 01:08:48 +08002137
Wanpeng Li4abaffc2020-02-26 10:41:02 +08002138 kvm_recalculate_apic_map(apic->vcpu->kvm);
2139
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002140 return ret;
2141}
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002142EXPORT_SYMBOL_GPL(kvm_lapic_reg_write);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002143
Nikolay Nikolaeve32edf42015-03-26 14:39:28 +00002144static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002145 gpa_t address, int len, const void *data)
2146{
2147 struct kvm_lapic *apic = to_lapic(this);
2148 unsigned int offset = address - apic->base_address;
2149 u32 val;
2150
2151 if (!apic_mmio_in_range(apic, address))
2152 return -EOPNOTSUPP;
2153
Vitaly Kuznetsovd1766202018-08-02 17:08:16 +02002154 if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
2155 if (!kvm_check_has_quirk(vcpu->kvm,
2156 KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
2157 return -EOPNOTSUPP;
2158
2159 return 0;
2160 }
2161
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002162 /*
2163 * APIC register must be aligned on 128-bits boundary.
2164 * 32/64/128 bits registers must be accessed thru 32 bits.
2165 * Refer SDM 8.4.1
2166 */
Yi Wang0d888002019-07-06 01:08:48 +08002167 if (len != 4 || (offset & 0xf))
Sheng Yang756975b2009-07-06 11:05:39 +08002168 return 0;
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002169
2170 val = *(u32*)data;
2171
Yi Wang0d888002019-07-06 01:08:48 +08002172 kvm_lapic_reg_write(apic, offset & 0xff0, val);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002173
Michael S. Tsirkinbda90202009-06-29 22:24:32 +03002174 return 0;
Eddie Dong97222cc2007-09-12 10:58:04 +03002175}
2176
Kevin Tian58fbbf22011-08-30 13:56:17 +03002177void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
2178{
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002179 kvm_lapic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
Kevin Tian58fbbf22011-08-30 13:56:17 +03002180}
2181EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
2182
Yang Zhang83d4c282013-01-25 10:18:49 +08002183/* emulate APIC access in a trap manner */
2184void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
2185{
2186 u32 val = 0;
2187
2188 /* hw has done the conditional check and inst decode */
2189 offset &= 0xff0;
2190
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002191 kvm_lapic_reg_read(vcpu->arch.apic, offset, 4, &val);
Yang Zhang83d4c282013-01-25 10:18:49 +08002192
2193 /* TODO: optimize to just emulate side effect w/o one more write */
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002194 kvm_lapic_reg_write(vcpu->arch.apic, offset, val);
Yang Zhang83d4c282013-01-25 10:18:49 +08002195}
2196EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);
2197
Rusty Russelld5894442007-10-08 10:48:30 +10002198void kvm_free_lapic(struct kvm_vcpu *vcpu)
Eddie Dong97222cc2007-09-12 10:58:04 +03002199{
Gleb Natapovf8c1ea12012-08-05 15:58:31 +03002200 struct kvm_lapic *apic = vcpu->arch.apic;
2201
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002202 if (!vcpu->arch.apic)
Eddie Dong97222cc2007-09-12 10:58:04 +03002203 return;
2204
Gleb Natapovf8c1ea12012-08-05 15:58:31 +03002205 hrtimer_cancel(&apic->lapic_timer.timer);
Eddie Dong97222cc2007-09-12 10:58:04 +03002206
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002207 if (!(vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE))
Cun Li6e4e3b42021-01-11 23:24:35 +08002208 static_branch_slow_dec_deferred(&apic_hw_disabled);
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002209
Radim Krčmáře4627552014-10-30 15:06:45 +01002210 if (!apic->sw_enabled)
Cun Li6e4e3b42021-01-11 23:24:35 +08002211 static_branch_slow_dec_deferred(&apic_sw_disabled);
Eddie Dong97222cc2007-09-12 10:58:04 +03002212
Gleb Natapovf8c1ea12012-08-05 15:58:31 +03002213 if (apic->regs)
2214 free_page((unsigned long)apic->regs);
2215
2216 kfree(apic);
Eddie Dong97222cc2007-09-12 10:58:04 +03002217}
2218
2219/*
2220 *----------------------------------------------------------------------
2221 * LAPIC interface
2222 *----------------------------------------------------------------------
2223 */
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002224u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
2225{
2226 struct kvm_lapic *apic = vcpu->arch.apic;
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002227
Wanpeng Lia970e9b2020-09-10 17:50:36 +08002228 if (!kvm_apic_present(vcpu) || !apic_lvtt_tscdeadline(apic))
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002229 return 0;
2230
2231 return apic->lapic_timer.tscdeadline;
2232}
2233
2234void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
2235{
2236 struct kvm_lapic *apic = vcpu->arch.apic;
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002237
Wanpeng Li27503832020-09-10 17:50:37 +08002238 if (!kvm_apic_present(vcpu) || !apic_lvtt_tscdeadline(apic))
Liu, Jinsonga3e06bb2011-09-22 16:55:52 +08002239 return;
2240
2241 hrtimer_cancel(&apic->lapic_timer.timer);
2242 apic->lapic_timer.tscdeadline = data;
2243 start_apic_timer(apic);
2244}
2245
Eddie Dong97222cc2007-09-12 10:58:04 +03002246void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
2247{
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002248 struct kvm_lapic *apic = vcpu->arch.apic;
Eddie Dong97222cc2007-09-12 10:58:04 +03002249
Avi Kivityb93463a2007-10-25 16:52:32 +02002250 apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002251 | (kvm_lapic_get_reg(apic, APIC_TASKPRI) & 4));
Eddie Dong97222cc2007-09-12 10:58:04 +03002252}
2253
2254u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
2255{
Eddie Dong97222cc2007-09-12 10:58:04 +03002256 u64 tpr;
2257
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002258 tpr = (u64) kvm_lapic_get_reg(vcpu->arch.apic, APIC_TASKPRI);
Eddie Dong97222cc2007-09-12 10:58:04 +03002259
2260 return (tpr & 0xf0) >> 4;
2261}
2262
2263void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
2264{
Yang Zhang8d146952013-01-25 10:18:50 +08002265 u64 old_value = vcpu->arch.apic_base;
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002266 struct kvm_lapic *apic = vcpu->arch.apic;
Eddie Dong97222cc2007-09-12 10:58:04 +03002267
Jim Mattsonc7dd15b2016-11-09 09:50:11 -08002268 if (!apic)
Eddie Dong97222cc2007-09-12 10:58:04 +03002269 value |= MSR_IA32_APICBASE_BSP;
Gleb Natapovc5af89b2009-06-09 15:56:26 +03002270
Jan Kiszkae66d2ae2013-12-29 02:29:30 +01002271 vcpu->arch.apic_base = value;
2272
Jim Mattsonc7dd15b2016-11-09 09:50:11 -08002273 if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
Xiaoyao Liaedbaf42020-07-09 12:34:23 +08002274 kvm_update_cpuid_runtime(vcpu);
Jim Mattsonc7dd15b2016-11-09 09:50:11 -08002275
2276 if (!apic)
2277 return;
2278
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002279 /* update jump label if enable bit changes */
Andrew Jones0dce7cd2014-01-15 13:39:59 +01002280 if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
Radim Krčmář49bd29b2016-07-12 22:09:23 +02002281 if (value & MSR_IA32_APICBASE_ENABLE) {
2282 kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
Cun Li6e4e3b42021-01-11 23:24:35 +08002283 static_branch_slow_dec_deferred(&apic_hw_disabled);
Vitaly Kuznetsov2f15d022021-04-22 11:29:48 +02002284 /* Check if there are APF page ready requests pending */
2285 kvm_make_request(KVM_REQ_APF_READY, vcpu);
Wanpeng Li187ca842016-08-03 12:04:13 +08002286 } else {
Cun Li6e4e3b42021-01-11 23:24:35 +08002287 static_branch_inc(&apic_hw_disabled.key);
Paolo Bonzini44d52712020-06-22 16:37:42 +02002288 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Wanpeng Li187ca842016-08-03 12:04:13 +08002289 }
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002290 }
2291
Jim Mattson8d860bb2018-05-09 16:56:05 -04002292 if (((old_value ^ value) & X2APIC_ENABLE) && (value & X2APIC_ENABLE))
2293 kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
2294
2295 if ((old_value ^ value) & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE))
Jason Baronb36464772021-01-14 22:27:56 -05002296 static_call(kvm_x86_set_virtual_apic_mode)(vcpu);
Yang Zhang8d146952013-01-25 10:18:50 +08002297
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002298 apic->base_address = apic->vcpu->arch.apic_base &
Eddie Dong97222cc2007-09-12 10:58:04 +03002299 MSR_IA32_APICBASE_BASE;
2300
Nadav Amitdb324fe2014-11-02 11:54:59 +02002301 if ((value & MSR_IA32_APICBASE_ENABLE) &&
2302 apic->base_address != APIC_DEFAULT_PHYS_BASE)
2303 pr_warn_once("APIC base relocation is unsupported by KVM");
Eddie Dong97222cc2007-09-12 10:58:04 +03002304}
2305
Suravee Suthikulpanitb26a6952019-11-14 14:15:04 -06002306void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
2307{
2308 struct kvm_lapic *apic = vcpu->arch.apic;
2309
2310 if (vcpu->arch.apicv_active) {
2311 /* irr_pending is always true when apicv is activated. */
2312 apic->irr_pending = true;
2313 apic->isr_count = 1;
2314 } else {
2315 apic->irr_pending = (apic_search_irr(apic) != -1);
2316 apic->isr_count = count_vectors(apic->regs + APIC_ISR);
2317 }
2318}
2319EXPORT_SYMBOL_GPL(kvm_apic_update_apicv);
2320
Nadav Amitd28bc9d2015-04-13 14:34:08 +03002321void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
Eddie Dong97222cc2007-09-12 10:58:04 +03002322{
Radim Krčmářb7e31be2018-03-01 15:24:25 +01002323 struct kvm_lapic *apic = vcpu->arch.apic;
Eddie Dong97222cc2007-09-12 10:58:04 +03002324 int i;
2325
Radim Krčmářb7e31be2018-03-01 15:24:25 +01002326 if (!apic)
2327 return;
Eddie Dong97222cc2007-09-12 10:58:04 +03002328
Eddie Dong97222cc2007-09-12 10:58:04 +03002329 /* Stop the timer in case it's a reset to an active apic */
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002330 hrtimer_cancel(&apic->lapic_timer.timer);
Eddie Dong97222cc2007-09-12 10:58:04 +03002331
Radim Krčmář4d8e7722016-07-12 22:09:25 +02002332 if (!init_event) {
2333 kvm_lapic_set_base(vcpu, APIC_DEFAULT_PHYS_BASE |
2334 MSR_IA32_APICBASE_ENABLE);
Radim Krčmářa92e2542016-07-12 22:09:22 +02002335 kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
Radim Krčmář4d8e7722016-07-12 22:09:25 +02002336 }
Gleb Natapovfc61b802009-07-05 17:39:35 +03002337 kvm_apic_set_version(apic->vcpu);
Eddie Dong97222cc2007-09-12 10:58:04 +03002338
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002339 for (i = 0; i < KVM_APIC_LVT_NUM; i++)
2340 kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
Radim Krčmářb6ac0692015-06-05 20:57:41 +02002341 apic_update_lvtt(apic);
Jan H. Schönherr52b54192017-05-20 13:24:32 +02002342 if (kvm_vcpu_is_reset_bsp(vcpu) &&
2343 kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED))
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002344 kvm_lapic_set_reg(apic, APIC_LVT0,
Nadav Amit90de4a12015-04-13 01:53:41 +03002345 SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002346 apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
Eddie Dong97222cc2007-09-12 10:58:04 +03002347
Wanpeng Liae6f2492020-08-19 16:55:26 +08002348 kvm_apic_set_dfr(apic, 0xffffffffU);
Gleb Natapovf8c1ea12012-08-05 15:58:31 +03002349 apic_set_spiv(apic, 0xff);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002350 kvm_lapic_set_reg(apic, APIC_TASKPRI, 0);
Radim Krčmářc028dd62015-05-22 19:22:10 +02002351 if (!apic_x2apic_mode(apic))
2352 kvm_apic_set_ldr(apic, 0);
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002353 kvm_lapic_set_reg(apic, APIC_ESR, 0);
2354 kvm_lapic_set_reg(apic, APIC_ICR, 0);
2355 kvm_lapic_set_reg(apic, APIC_ICR2, 0);
2356 kvm_lapic_set_reg(apic, APIC_TDCR, 0);
2357 kvm_lapic_set_reg(apic, APIC_TMICT, 0);
Eddie Dong97222cc2007-09-12 10:58:04 +03002358 for (i = 0; i < 8; i++) {
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002359 kvm_lapic_set_reg(apic, APIC_IRR + 0x10 * i, 0);
2360 kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
2361 kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
Eddie Dong97222cc2007-09-12 10:58:04 +03002362 }
Suravee Suthikulpanitb26a6952019-11-14 14:15:04 -06002363 kvm_apic_update_apicv(vcpu);
Michael S. Tsirkin8680b942012-06-24 19:24:26 +03002364 apic->highest_isr_cache = -1;
Kevin Pedrettib33ac882007-10-21 08:54:53 +02002365 update_divide_count(apic);
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002366 atomic_set(&apic->lapic_timer.pending, 0);
Gleb Natapovc5af89b2009-06-09 15:56:26 +03002367 if (kvm_vcpu_is_bsp(vcpu))
Gleb Natapov5dbc8f32012-08-05 15:58:27 +03002368 kvm_lapic_set_base(vcpu,
2369 vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002370 vcpu->arch.pv_eoi.msr_val = 0;
Eddie Dong97222cc2007-09-12 10:58:04 +03002371 apic_update_ppr(apic);
Jan H. Schönherr4191db22017-10-25 16:43:27 +02002372 if (vcpu->arch.apicv_active) {
Jason Baronb36464772021-01-14 22:27:56 -05002373 static_call(kvm_x86_apicv_post_state_restore)(vcpu);
2374 static_call(kvm_x86_hwapic_irr_update)(vcpu, -1);
2375 static_call(kvm_x86_hwapic_isr_update)(vcpu, -1);
Jan H. Schönherr4191db22017-10-25 16:43:27 +02002376 }
Eddie Dong97222cc2007-09-12 10:58:04 +03002377
Gleb Natapove1035712009-03-05 16:34:59 +02002378 vcpu->arch.apic_arb_prio = 0;
Gleb Natapov41383772012-04-19 14:06:29 +03002379 vcpu->arch.apic_attention = 0;
Wanpeng Li4abaffc2020-02-26 10:41:02 +08002380
2381 kvm_recalculate_apic_map(vcpu->kvm);
Eddie Dong97222cc2007-09-12 10:58:04 +03002382}
2383
Eddie Dong97222cc2007-09-12 10:58:04 +03002384/*
2385 *----------------------------------------------------------------------
2386 * timer interface
2387 *----------------------------------------------------------------------
2388 */
Eddie Dong1b9778d2007-09-03 16:56:58 +03002389
Avi Kivity2a6eac92012-07-26 18:01:51 +03002390static bool lapic_is_periodic(struct kvm_lapic *apic)
Eddie Dong97222cc2007-09-12 10:58:04 +03002391{
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002392 return apic_lvtt_period(apic);
Eddie Dong97222cc2007-09-12 10:58:04 +03002393}
2394
Marcelo Tosatti3d808402008-04-11 14:53:26 -03002395int apic_has_pending_timer(struct kvm_vcpu *vcpu)
2396{
Gleb Natapov54e98182012-08-05 15:58:32 +03002397 struct kvm_lapic *apic = vcpu->arch.apic;
Marcelo Tosatti3d808402008-04-11 14:53:26 -03002398
Paolo Bonzini1e3161b42016-01-08 13:41:16 +01002399 if (apic_enabled(apic) && apic_lvt_enabled(apic, APIC_LVTT))
Gleb Natapov54e98182012-08-05 15:58:32 +03002400 return atomic_read(&apic->lapic_timer.pending);
Marcelo Tosatti3d808402008-04-11 14:53:26 -03002401
2402 return 0;
2403}
2404
Avi Kivity89342082011-11-10 14:57:21 +02002405int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
Eddie Dong1b9778d2007-09-03 16:56:58 +03002406{
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002407 u32 reg = kvm_lapic_get_reg(apic, lvt_type);
Jan Kiszka23930f92008-09-26 09:30:52 +02002408 int vector, mode, trig_mode;
Eddie Dong1b9778d2007-09-03 16:56:58 +03002409
Gleb Natapovc48f1492012-08-05 15:58:33 +03002410 if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
Jan Kiszka23930f92008-09-26 09:30:52 +02002411 vector = reg & APIC_VECTOR_MASK;
2412 mode = reg & APIC_MODE_MASK;
2413 trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
Yang Zhangb4f22252013-04-11 19:21:37 +08002414 return __apic_accept_irq(apic, mode, vector, 1, trig_mode,
2415 NULL);
Jan Kiszka23930f92008-09-26 09:30:52 +02002416 }
2417 return 0;
2418}
2419
Jan Kiszka8fdb2352008-10-20 10:20:02 +02002420void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
Jan Kiszka23930f92008-09-26 09:30:52 +02002421{
Jan Kiszka8fdb2352008-10-20 10:20:02 +02002422 struct kvm_lapic *apic = vcpu->arch.apic;
2423
2424 if (apic)
2425 kvm_apic_local_deliver(apic, APIC_LVT0);
Eddie Dong1b9778d2007-09-03 16:56:58 +03002426}
2427
Gregory Haskinsd76685c42009-06-01 12:54:50 -04002428static const struct kvm_io_device_ops apic_mmio_ops = {
2429 .read = apic_mmio_read,
2430 .write = apic_mmio_write,
Gregory Haskinsd76685c42009-06-01 12:54:50 -04002431};
2432
Avi Kivitye9d90d42012-07-26 18:01:50 +03002433static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
2434{
2435 struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
Avi Kivity2a6eac92012-07-26 18:01:51 +03002436 struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic, lapic_timer);
Avi Kivitye9d90d42012-07-26 18:01:50 +03002437
Wanpeng Liae95f562020-04-28 14:23:28 +08002438 apic_timer_expired(apic, true);
Avi Kivitye9d90d42012-07-26 18:01:50 +03002439
Avi Kivity2a6eac92012-07-26 18:01:51 +03002440 if (lapic_is_periodic(apic)) {
Wanpeng Li8003c9a2016-10-24 18:23:13 +08002441 advance_periodic_target_expiration(apic);
Avi Kivitye9d90d42012-07-26 18:01:50 +03002442 hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
2443 return HRTIMER_RESTART;
2444 } else
2445 return HRTIMER_NORESTART;
2446}
2447
Sean Christophersonc3941d92019-04-17 10:15:33 -07002448int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns)
Eddie Dong97222cc2007-09-12 10:58:04 +03002449{
2450 struct kvm_lapic *apic;
2451
2452 ASSERT(vcpu != NULL);
Eddie Dong97222cc2007-09-12 10:58:04 +03002453
Ben Gardon254272c2019-02-11 11:02:50 -08002454 apic = kzalloc(sizeof(*apic), GFP_KERNEL_ACCOUNT);
Eddie Dong97222cc2007-09-12 10:58:04 +03002455 if (!apic)
2456 goto nomem;
2457
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002458 vcpu->arch.apic = apic;
Eddie Dong97222cc2007-09-12 10:58:04 +03002459
Ben Gardon254272c2019-02-11 11:02:50 -08002460 apic->regs = (void *)get_zeroed_page(GFP_KERNEL_ACCOUNT);
Takuya Yoshikawaafc20182011-03-05 12:40:20 +09002461 if (!apic->regs) {
Eddie Dong97222cc2007-09-12 10:58:04 +03002462 printk(KERN_ERR "malloc apic regs error for vcpu %x\n",
2463 vcpu->vcpu_id);
Rusty Russelld5894442007-10-08 10:48:30 +10002464 goto nomem_free_apic;
Eddie Dong97222cc2007-09-12 10:58:04 +03002465 }
Eddie Dong97222cc2007-09-12 10:58:04 +03002466 apic->vcpu = vcpu;
2467
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002468 hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
Sebastian Andrzej Siewior2c0d2782019-07-26 20:30:55 +02002469 HRTIMER_MODE_ABS_HARD);
Avi Kivitye9d90d42012-07-26 18:01:50 +03002470 apic->lapic_timer.timer.function = apic_timer_fn;
Sean Christophersonc3941d92019-04-17 10:15:33 -07002471 if (timer_advance_ns == -1) {
Wanpeng Lia0f00372019-09-26 08:54:03 +08002472 apic->lapic_timer.timer_advance_ns = LAPIC_TIMER_ADVANCE_NS_INIT;
Wanpeng Lid0f5a862019-09-17 16:16:26 +08002473 lapic_timer_advance_dynamic = true;
Sean Christophersonc3941d92019-04-17 10:15:33 -07002474 } else {
2475 apic->lapic_timer.timer_advance_ns = timer_advance_ns;
Wanpeng Lid0f5a862019-09-17 16:16:26 +08002476 lapic_timer_advance_dynamic = false;
Sean Christophersonc3941d92019-04-17 10:15:33 -07002477 }
2478
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002479 /*
2480 * APIC is created enabled. This will prevent kvm_lapic_set_base from
Wei Yangee171d22019-03-31 19:17:22 -07002481 * thinking that APIC state has changed.
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002482 */
2483 vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
Cun Li6e4e3b42021-01-11 23:24:35 +08002484 static_branch_inc(&apic_sw_disabled.key); /* sw disabled at reset */
Gregory Haskinsd76685c42009-06-01 12:54:50 -04002485 kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
Eddie Dong97222cc2007-09-12 10:58:04 +03002486
2487 return 0;
Rusty Russelld5894442007-10-08 10:48:30 +10002488nomem_free_apic:
2489 kfree(apic);
Saar Amara251fb902019-05-06 11:29:16 +03002490 vcpu->arch.apic = NULL;
Eddie Dong97222cc2007-09-12 10:58:04 +03002491nomem:
Eddie Dong97222cc2007-09-12 10:58:04 +03002492 return -ENOMEM;
2493}
Eddie Dong97222cc2007-09-12 10:58:04 +03002494
2495int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
2496{
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002497 struct kvm_lapic *apic = vcpu->arch.apic;
Paolo Bonzinib3c045d2016-12-18 21:47:54 +01002498 u32 ppr;
Eddie Dong97222cc2007-09-12 10:58:04 +03002499
Paolo Bonzini72c3bcd2020-11-27 08:53:52 +01002500 if (!kvm_apic_present(vcpu))
Eddie Dong97222cc2007-09-12 10:58:04 +03002501 return -1;
2502
Paolo Bonzinib3c045d2016-12-18 21:47:54 +01002503 __apic_update_ppr(apic, &ppr);
2504 return apic_has_interrupt_for_ppr(apic, ppr);
Eddie Dong97222cc2007-09-12 10:58:04 +03002505}
Sean Christopherson25bb2cf2020-08-12 10:51:29 -07002506EXPORT_SYMBOL_GPL(kvm_apic_has_interrupt);
Eddie Dong97222cc2007-09-12 10:58:04 +03002507
Qing He40487c62007-09-17 14:47:13 +08002508int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)
2509{
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002510 u32 lvt0 = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LVT0);
Qing He40487c62007-09-17 14:47:13 +08002511
Gleb Natapovc48f1492012-08-05 15:58:33 +03002512 if (!kvm_apic_hw_enabled(vcpu->arch.apic))
Miaohe Lin3ce4dc12020-01-18 10:50:37 +08002513 return 1;
Chris Lalancettee7dca5c2010-06-16 17:11:12 -04002514 if ((lvt0 & APIC_LVT_MASKED) == 0 &&
2515 GET_APIC_DELIVERY_MODE(lvt0) == APIC_MODE_EXTINT)
Miaohe Lin3ce4dc12020-01-18 10:50:37 +08002516 return 1;
2517 return 0;
Qing He40487c62007-09-17 14:47:13 +08002518}
2519
Eddie Dong1b9778d2007-09-03 16:56:58 +03002520void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
2521{
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002522 struct kvm_lapic *apic = vcpu->arch.apic;
Eddie Dong1b9778d2007-09-03 16:56:58 +03002523
Gleb Natapov54e98182012-08-05 15:58:32 +03002524 if (atomic_read(&apic->lapic_timer.pending) > 0) {
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08002525 kvm_apic_inject_pending_timer_irqs(apic);
Jan Kiszkaf1ed0452013-04-28 14:00:41 +02002526 atomic_set(&apic->lapic_timer.pending, 0);
Eddie Dong1b9778d2007-09-03 16:56:58 +03002527 }
2528}
2529
Eddie Dong97222cc2007-09-12 10:58:04 +03002530int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
2531{
2532 int vector = kvm_apic_has_interrupt(vcpu);
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002533 struct kvm_lapic *apic = vcpu->arch.apic;
Paolo Bonzini4d82d122016-12-18 21:43:41 +01002534 u32 ppr;
Eddie Dong97222cc2007-09-12 10:58:04 +03002535
2536 if (vector == -1)
2537 return -1;
2538
Wanpeng Li56cc2402014-08-05 12:42:24 +08002539 /*
2540 * We get here even with APIC virtualization enabled, if doing
2541 * nested virtualization and L1 runs with the "acknowledge interrupt
2542 * on exit" mode. Then we cannot inject the interrupt via RVI,
2543 * because the process would deliver it through the IDT.
2544 */
2545
Eddie Dong97222cc2007-09-12 10:58:04 +03002546 apic_clear_irr(vector, apic);
Vitaly Kuznetsovf2bc14b2021-01-26 14:48:12 +01002547 if (to_hv_vcpu(vcpu) && test_bit(vector, to_hv_synic(vcpu)->auto_eoi_bitmap)) {
Paolo Bonzini4d82d122016-12-18 21:43:41 +01002548 /*
2549 * For auto-EOI interrupts, there might be another pending
2550 * interrupt above PPR, so check whether to raise another
2551 * KVM_REQ_EVENT.
2552 */
Andrey Smetanin5c9194122015-11-10 15:36:34 +03002553 apic_update_ppr(apic);
Paolo Bonzini4d82d122016-12-18 21:43:41 +01002554 } else {
2555 /*
2556 * For normal interrupts, PPR has been raised and there cannot
2557 * be a higher-priority pending interrupt---except if there was
2558 * a concurrent interrupt injection, but that would have
2559 * triggered KVM_REQ_EVENT already.
2560 */
2561 apic_set_isr(vector, apic);
2562 __apic_update_ppr(apic, &ppr);
Andrey Smetanin5c9194122015-11-10 15:36:34 +03002563 }
2564
Eddie Dong97222cc2007-09-12 10:58:04 +03002565 return vector;
2566}
Eddie Dong96ad2cc2007-09-06 12:22:56 +03002567
Radim Krčmářa92e2542016-07-12 22:09:22 +02002568static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
2569 struct kvm_lapic_state *s, bool set)
2570{
2571 if (apic_x2apic_mode(vcpu->arch.apic)) {
2572 u32 *id = (u32 *)(s->regs + APIC_ID);
Dr. David Alan Gilbert12806ba2017-11-17 11:52:50 +00002573 u32 *ldr = (u32 *)(s->regs + APIC_LDR);
Radim Krčmářa92e2542016-07-12 22:09:22 +02002574
Radim Krčmář371313132016-07-12 22:09:27 +02002575 if (vcpu->kvm->arch.x2apic_format) {
2576 if (*id != vcpu->vcpu_id)
2577 return -EINVAL;
2578 } else {
2579 if (set)
2580 *id >>= 24;
2581 else
2582 *id <<= 24;
2583 }
Dr. David Alan Gilbert12806ba2017-11-17 11:52:50 +00002584
2585 /* In x2APIC mode, the LDR is fixed and based on the id */
2586 if (set)
2587 *ldr = kvm_apic_calc_x2apic_ldr(*id);
Radim Krčmářa92e2542016-07-12 22:09:22 +02002588 }
2589
2590 return 0;
2591}
2592
2593int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
2594{
2595 memcpy(s->regs, vcpu->arch.apic->regs, sizeof(*s));
Peter Shier24647e02018-10-10 15:56:53 -07002596
2597 /*
2598 * Get calculated timer current count for remaining timer period (if
2599 * any) and store it in the returned register set.
2600 */
2601 __kvm_lapic_set_reg(s->regs, APIC_TMCCT,
2602 __apic_read(vcpu->arch.apic, APIC_TMCCT));
2603
Radim Krčmářa92e2542016-07-12 22:09:22 +02002604 return kvm_apic_state_fixup(vcpu, s, false);
2605}
2606
2607int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
Eddie Dong96ad2cc2007-09-06 12:22:56 +03002608{
Zhang Xiantaoad312c72007-12-13 23:50:52 +08002609 struct kvm_lapic *apic = vcpu->arch.apic;
Radim Krčmářa92e2542016-07-12 22:09:22 +02002610 int r;
2611
Gleb Natapov5dbc8f32012-08-05 15:58:27 +03002612 kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
Gleb Natapov64eb0622012-08-08 15:24:36 +03002613 /* set SPIV separately to get count of SW disabled APICs right */
2614 apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
Radim Krčmářa92e2542016-07-12 22:09:22 +02002615
2616 r = kvm_apic_state_fixup(vcpu, s, true);
Wanpeng Li4abaffc2020-02-26 10:41:02 +08002617 if (r) {
2618 kvm_recalculate_apic_map(vcpu->kvm);
Radim Krčmářa92e2542016-07-12 22:09:22 +02002619 return r;
Wanpeng Li4abaffc2020-02-26 10:41:02 +08002620 }
Jordan Borgner0e96f312018-10-28 12:58:28 +00002621 memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
Radim Krčmářa92e2542016-07-12 22:09:22 +02002622
Paolo Bonzini44d52712020-06-22 16:37:42 +02002623 atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
Wanpeng Li4abaffc2020-02-26 10:41:02 +08002624 kvm_recalculate_apic_map(vcpu->kvm);
Gleb Natapovfc61b802009-07-05 17:39:35 +03002625 kvm_apic_set_version(vcpu);
2626
Eddie Dong96ad2cc2007-09-06 12:22:56 +03002627 apic_update_ppr(apic);
Marcelo Tosattid3c7b772009-02-23 10:57:41 -03002628 hrtimer_cancel(&apic->lapic_timer.timer);
Wanpeng Li35737d22021-03-04 08:35:18 +08002629 apic->lapic_timer.expired_tscdeadline = 0;
Radim Krčmářb6ac0692015-06-05 20:57:41 +02002630 apic_update_lvtt(apic);
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002631 apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
Eddie Dong96ad2cc2007-09-06 12:22:56 +03002632 update_divide_count(apic);
Peter Shier24647e02018-10-10 15:56:53 -07002633 __start_apic_timer(apic, APIC_TMCCT);
Suravee Suthikulpanitb26a6952019-11-14 14:15:04 -06002634 kvm_apic_update_apicv(vcpu);
Michael S. Tsirkin8680b942012-06-24 19:24:26 +03002635 apic->highest_isr_cache = -1;
Andrey Smetanind62caab2015-11-10 15:36:33 +03002636 if (vcpu->arch.apicv_active) {
Jason Baronb36464772021-01-14 22:27:56 -05002637 static_call(kvm_x86_apicv_post_state_restore)(vcpu);
2638 static_call(kvm_x86_hwapic_irr_update)(vcpu,
Wei Wang4114c272014-11-05 10:53:43 +08002639 apic_find_highest_irr(apic));
Jason Baronb36464772021-01-14 22:27:56 -05002640 static_call(kvm_x86_hwapic_isr_update)(vcpu,
Tiejun Chenb4eef9b2014-12-22 10:32:57 +01002641 apic_find_highest_isr(apic));
Andrey Smetanind62caab2015-11-10 15:36:33 +03002642 }
Avi Kivity3842d132010-07-27 12:30:24 +03002643 kvm_make_request(KVM_REQ_EVENT, vcpu);
Steve Rutherford49df6392015-07-29 23:21:40 -07002644 if (ioapic_in_kernel(vcpu->kvm))
2645 kvm_rtc_eoi_tracking_restore_one(vcpu);
Radim Krčmář0669a512015-10-30 15:48:20 +01002646
2647 vcpu->arch.apic_arb_prio = 0;
Radim Krčmářa92e2542016-07-12 22:09:22 +02002648
2649 return 0;
Eddie Dong96ad2cc2007-09-06 12:22:56 +03002650}
Eddie Donga3d7f852007-09-03 16:15:12 +03002651
Avi Kivity2f52d582008-01-16 12:49:30 +02002652void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
Eddie Donga3d7f852007-09-03 16:15:12 +03002653{
Eddie Donga3d7f852007-09-03 16:15:12 +03002654 struct hrtimer *timer;
2655
Wanpeng Li0c5f81d2019-07-06 09:26:51 +08002656 if (!lapic_in_kernel(vcpu) ||
2657 kvm_can_post_timer_interrupt(vcpu))
Eddie Donga3d7f852007-09-03 16:15:12 +03002658 return;
2659
Gleb Natapov54e98182012-08-05 15:58:32 +03002660 timer = &vcpu->arch.apic->lapic_timer.timer;
Eddie Donga3d7f852007-09-03 16:15:12 +03002661 if (hrtimer_cancel(timer))
Sebastian Andrzej Siewior2c0d2782019-07-26 20:30:55 +02002662 hrtimer_start_expires(timer, HRTIMER_MODE_ABS_HARD);
Eddie Donga3d7f852007-09-03 16:15:12 +03002663}
Avi Kivityb93463a2007-10-25 16:52:32 +02002664
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002665/*
2666 * apic_sync_pv_eoi_from_guest - called on vmexit or cancel interrupt
2667 *
2668 * Detect whether guest triggered PV EOI since the
2669 * last entry. If yes, set EOI on guests's behalf.
2670 * Clear PV EOI in guest memory in any case.
2671 */
2672static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
2673 struct kvm_lapic *apic)
2674{
2675 bool pending;
2676 int vector;
2677 /*
2678 * PV EOI state is derived from KVM_APIC_PV_EOI_PENDING in host
2679 * and KVM_PV_EOI_ENABLED in guest memory as follows:
2680 *
2681 * KVM_APIC_PV_EOI_PENDING is unset:
2682 * -> host disabled PV EOI.
2683 * KVM_APIC_PV_EOI_PENDING is set, KVM_PV_EOI_ENABLED is set:
2684 * -> host enabled PV EOI, guest did not execute EOI yet.
2685 * KVM_APIC_PV_EOI_PENDING is set, KVM_PV_EOI_ENABLED is unset:
2686 * -> host enabled PV EOI, guest executed EOI.
2687 */
2688 BUG_ON(!pv_eoi_enabled(vcpu));
2689 pending = pv_eoi_get_pending(vcpu);
2690 /*
2691 * Clear pending bit in any case: it will be set again on vmentry.
2692 * While this might not be ideal from performance point of view,
2693 * this makes sure pv eoi is only enabled when we know it's safe.
2694 */
2695 pv_eoi_clr_pending(vcpu);
2696 if (pending)
2697 return;
2698 vector = apic_set_eoi(apic);
2699 trace_kvm_pv_eoi(apic, vector);
2700}
2701
Avi Kivityb93463a2007-10-25 16:52:32 +02002702void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
2703{
2704 u32 data;
Avi Kivityb93463a2007-10-25 16:52:32 +02002705
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002706 if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
2707 apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
2708
Gleb Natapov41383772012-04-19 14:06:29 +03002709 if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
Avi Kivityb93463a2007-10-25 16:52:32 +02002710 return;
2711
Paolo Bonzini4e335d92017-05-02 16:20:18 +02002712 if (kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
2713 sizeof(u32)))
Nicholas Krause603242a2015-08-05 10:44:40 -04002714 return;
Avi Kivityb93463a2007-10-25 16:52:32 +02002715
2716 apic_set_tpr(vcpu->arch.apic, data & 0xff);
2717}
2718
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002719/*
2720 * apic_sync_pv_eoi_to_guest - called before vmentry
2721 *
2722 * Detect whether it's safe to enable PV EOI and
2723 * if yes do so.
2724 */
2725static void apic_sync_pv_eoi_to_guest(struct kvm_vcpu *vcpu,
2726 struct kvm_lapic *apic)
2727{
2728 if (!pv_eoi_enabled(vcpu) ||
2729 /* IRR set or many bits in ISR: could be nested. */
2730 apic->irr_pending ||
2731 /* Cache not set: could be safe but we don't bother. */
2732 apic->highest_isr_cache == -1 ||
2733 /* Need EOI to update ioapic. */
Paolo Bonzini3bb345f2015-07-29 10:43:18 +02002734 kvm_ioapic_handles_vector(apic, apic->highest_isr_cache)) {
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002735 /*
2736 * PV EOI was disabled by apic_sync_pv_eoi_from_guest
2737 * so we need not do anything here.
2738 */
2739 return;
2740 }
2741
2742 pv_eoi_set_pending(apic->vcpu);
2743}
2744
Avi Kivityb93463a2007-10-25 16:52:32 +02002745void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
2746{
2747 u32 data, tpr;
2748 int max_irr, max_isr;
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002749 struct kvm_lapic *apic = vcpu->arch.apic;
Avi Kivityb93463a2007-10-25 16:52:32 +02002750
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002751 apic_sync_pv_eoi_to_guest(vcpu, apic);
2752
Gleb Natapov41383772012-04-19 14:06:29 +03002753 if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
Avi Kivityb93463a2007-10-25 16:52:32 +02002754 return;
2755
Suravee Suthikulpanitdfb95952016-05-04 14:09:41 -05002756 tpr = kvm_lapic_get_reg(apic, APIC_TASKPRI) & 0xff;
Avi Kivityb93463a2007-10-25 16:52:32 +02002757 max_irr = apic_find_highest_irr(apic);
2758 if (max_irr < 0)
2759 max_irr = 0;
2760 max_isr = apic_find_highest_isr(apic);
2761 if (max_isr < 0)
2762 max_isr = 0;
2763 data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
2764
Paolo Bonzini4e335d92017-05-02 16:20:18 +02002765 kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
2766 sizeof(u32));
Avi Kivityb93463a2007-10-25 16:52:32 +02002767}
2768
Andy Honigfda4e2e2013-11-20 10:23:22 -08002769int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
Avi Kivityb93463a2007-10-25 16:52:32 +02002770{
Andy Honigfda4e2e2013-11-20 10:23:22 -08002771 if (vapic_addr) {
Paolo Bonzini4e335d92017-05-02 16:20:18 +02002772 if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
Andy Honigfda4e2e2013-11-20 10:23:22 -08002773 &vcpu->arch.apic->vapic_cache,
2774 vapic_addr, sizeof(u32)))
2775 return -EINVAL;
Gleb Natapov41383772012-04-19 14:06:29 +03002776 __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
Andy Honigfda4e2e2013-11-20 10:23:22 -08002777 } else {
Gleb Natapov41383772012-04-19 14:06:29 +03002778 __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
Andy Honigfda4e2e2013-11-20 10:23:22 -08002779 }
2780
2781 vcpu->arch.apic->vapic_addr = vapic_addr;
2782 return 0;
Avi Kivityb93463a2007-10-25 16:52:32 +02002783}
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002784
2785int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
2786{
2787 struct kvm_lapic *apic = vcpu->arch.apic;
2788 u32 reg = (msr - APIC_BASE_MSR) << 4;
2789
Paolo Bonzini35754c92015-07-29 12:05:37 +02002790 if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(apic))
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002791 return 1;
2792
Nadav Amitc69d3d92014-11-26 17:56:25 +02002793 if (reg == APIC_ICR2)
2794 return 1;
2795
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002796 /* if this is ICR write vector before command */
Radim Krčmářdecdc282014-11-26 17:07:05 +01002797 if (reg == APIC_ICR)
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002798 kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
2799 return kvm_lapic_reg_write(apic, reg, (u32)data);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002800}
2801
2802int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
2803{
2804 struct kvm_lapic *apic = vcpu->arch.apic;
2805 u32 reg = (msr - APIC_BASE_MSR) << 4, low, high = 0;
2806
Paolo Bonzini35754c92015-07-29 12:05:37 +02002807 if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(apic))
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002808 return 1;
2809
Yi Wang0d888002019-07-06 01:08:48 +08002810 if (reg == APIC_DFR || reg == APIC_ICR2)
Nadav Amitc69d3d92014-11-26 17:56:25 +02002811 return 1;
Nadav Amitc69d3d92014-11-26 17:56:25 +02002812
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002813 if (kvm_lapic_reg_read(apic, reg, 4, &low))
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002814 return 1;
Radim Krčmářdecdc282014-11-26 17:07:05 +01002815 if (reg == APIC_ICR)
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002816 kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
Gleb Natapov0105d1a2009-07-05 17:39:36 +03002817
2818 *data = (((u64)high) << 32) | low;
2819
2820 return 0;
2821}
Gleb Natapov10388a02010-01-17 15:51:23 +02002822
2823int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data)
2824{
2825 struct kvm_lapic *apic = vcpu->arch.apic;
2826
Paolo Bonzinibce87cc2016-01-08 13:48:51 +01002827 if (!lapic_in_kernel(vcpu))
Gleb Natapov10388a02010-01-17 15:51:23 +02002828 return 1;
2829
2830 /* if this is ICR write vector before command */
2831 if (reg == APIC_ICR)
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002832 kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
2833 return kvm_lapic_reg_write(apic, reg, (u32)data);
Gleb Natapov10388a02010-01-17 15:51:23 +02002834}
2835
2836int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
2837{
2838 struct kvm_lapic *apic = vcpu->arch.apic;
2839 u32 low, high = 0;
2840
Paolo Bonzinibce87cc2016-01-08 13:48:51 +01002841 if (!lapic_in_kernel(vcpu))
Gleb Natapov10388a02010-01-17 15:51:23 +02002842 return 1;
2843
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002844 if (kvm_lapic_reg_read(apic, reg, 4, &low))
Gleb Natapov10388a02010-01-17 15:51:23 +02002845 return 1;
2846 if (reg == APIC_ICR)
Suravee Suthikulpanit1e6e2752016-05-04 14:09:40 -05002847 kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
Gleb Natapov10388a02010-01-17 15:51:23 +02002848
2849 *data = (((u64)high) << 32) | low;
2850
2851 return 0;
2852}
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002853
Ladi Prosek72bbf932018-10-16 18:49:59 +02002854int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len)
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002855{
2856 u64 addr = data & ~KVM_MSR_ENABLED;
Vitaly Kuznetsova7c42bb2018-10-16 18:50:06 +02002857 struct gfn_to_hva_cache *ghc = &vcpu->arch.pv_eoi.data;
2858 unsigned long new_len;
2859
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002860 if (!IS_ALIGNED(addr, 4))
2861 return 1;
2862
2863 vcpu->arch.pv_eoi.msr_val = data;
2864 if (!pv_eoi_enabled(vcpu))
2865 return 0;
Vitaly Kuznetsova7c42bb2018-10-16 18:50:06 +02002866
2867 if (addr == ghc->gpa && len <= ghc->len)
2868 new_len = ghc->len;
2869 else
2870 new_len = len;
2871
2872 return kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, addr, new_len);
Michael S. Tsirkinae7a2a32012-06-24 19:25:07 +03002873}
Gleb Natapovc5cc4212012-08-05 15:58:30 +03002874
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002875int kvm_apic_accept_events(struct kvm_vcpu *vcpu)
Jan Kiszka66450a22013-03-13 12:42:34 +01002876{
2877 struct kvm_lapic *apic = vcpu->arch.apic;
Paolo Bonzini2b4a2732014-11-24 14:35:24 +01002878 u8 sipi_vector;
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002879 int r;
Gleb Natapov299018f2013-06-03 11:30:02 +03002880 unsigned long pe;
Jan Kiszka66450a22013-03-13 12:42:34 +01002881
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002882 if (!lapic_in_kernel(vcpu))
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002883 return 0;
Jan Kiszka66450a22013-03-13 12:42:34 +01002884
Paolo Bonzinicd7764f2015-06-04 10:41:21 +02002885 /*
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002886 * Read pending events before calling the check_events
2887 * callback.
2888 */
2889 pe = smp_load_acquire(&apic->pending_events);
2890 if (!pe)
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002891 return 0;
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002892
2893 if (is_guest_mode(vcpu)) {
Sean Christophersoncb6a32c2021-03-02 09:45:14 -08002894 r = kvm_check_nested_events(vcpu);
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002895 if (r < 0)
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002896 return r == -EBUSY ? 0 : r;
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002897 /*
2898 * If an event has happened and caused a vmexit,
2899 * we know INITs are latched and therefore
2900 * we will not incorrectly deliver an APIC
2901 * event instead of a vmexit.
2902 */
2903 }
2904
2905 /*
Liran Alon4b9852f2019-08-26 13:24:49 +03002906 * INITs are latched while CPU is in specific states
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002907 * (SMM, VMX root mode, SVM with GIF=0).
Liran Alon4b9852f2019-08-26 13:24:49 +03002908 * Because a CPU cannot be in these states immediately
2909 * after it has processed an INIT signal (and thus in
2910 * KVM_MP_STATE_INIT_RECEIVED state), just eat SIPIs
2911 * and leave the INIT pending.
Paolo Bonzinicd7764f2015-06-04 10:41:21 +02002912 */
Liran Alon27cbe7d2019-11-11 11:16:40 +02002913 if (kvm_vcpu_latch_init(vcpu)) {
Paolo Bonzinicd7764f2015-06-04 10:41:21 +02002914 WARN_ON_ONCE(vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED);
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002915 if (test_bit(KVM_APIC_SIPI, &pe))
Paolo Bonzinicd7764f2015-06-04 10:41:21 +02002916 clear_bit(KVM_APIC_SIPI, &apic->pending_events);
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002917 return 0;
Paolo Bonzinicd7764f2015-06-04 10:41:21 +02002918 }
Gleb Natapov299018f2013-06-03 11:30:02 +03002919
2920 if (test_bit(KVM_APIC_INIT, &pe)) {
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002921 clear_bit(KVM_APIC_INIT, &apic->pending_events);
Nadav Amitd28bc9d2015-04-13 14:34:08 +03002922 kvm_vcpu_reset(vcpu, true);
Jan Kiszka66450a22013-03-13 12:42:34 +01002923 if (kvm_vcpu_is_bsp(apic->vcpu))
2924 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
2925 else
2926 vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
2927 }
Maxim Levitskyf57ad632020-12-03 16:33:19 +02002928 if (test_bit(KVM_APIC_SIPI, &pe)) {
Paolo Bonzini1c96dcc2020-11-05 11:20:49 -05002929 clear_bit(KVM_APIC_SIPI, &apic->pending_events);
Maxim Levitskyf57ad632020-12-03 16:33:19 +02002930 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
2931 /* evaluate pending_events before reading the vector */
2932 smp_rmb();
2933 sipi_vector = apic->sipi_vector;
Tom Lendacky647daca2021-01-04 14:20:01 -06002934 kvm_x86_ops.vcpu_deliver_sipi_vector(vcpu, sipi_vector);
Maxim Levitskyf57ad632020-12-03 16:33:19 +02002935 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
2936 }
Jan Kiszka66450a22013-03-13 12:42:34 +01002937 }
Jim Mattson4fe09bc2021-06-04 10:26:04 -07002938 return 0;
Jan Kiszka66450a22013-03-13 12:42:34 +01002939}
2940
David Matlackcef84c32016-12-16 14:30:36 -08002941void kvm_lapic_exit(void)
2942{
2943 static_key_deferred_flush(&apic_hw_disabled);
2944 static_key_deferred_flush(&apic_sw_disabled);
2945}