Deleted Added
full compact
vlapic.c (259779) vlapic.c (259863)
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/amd64/vmm/io/vlapic.c 259779 2013-12-23 19:29:07Z jhb $
26 * $FreeBSD: head/sys/amd64/vmm/io/vlapic.c 259863 2013-12-25 06:46:31Z neel $
27 */
28
29#include <sys/cdefs.h>
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/amd64/vmm/io/vlapic.c 259779 2013-12-23 19:29:07Z jhb $");
30__FBSDID("$FreeBSD: head/sys/amd64/vmm/io/vlapic.c 259863 2013-12-25 06:46:31Z neel $");
31
32#include <sys/param.h>
33#include <sys/lock.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/mutex.h>
37#include <sys/systm.h>
38#include <sys/smp.h>
39
31
32#include <sys/param.h>
33#include <sys/lock.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/mutex.h>
37#include <sys/systm.h>
38#include <sys/smp.h>
39
40#include <machine/clock.h>
41#include <x86/specialreg.h>
42#include <x86/apicreg.h>
43
40#include <x86/specialreg.h>
41#include <x86/apicreg.h>
42
43#include <machine/clock.h>
44#include <machine/smp.h>
45
44#include <machine/vmm.h>
45
46#include <machine/vmm.h>
47
46#include "vmm_stat.h"
48#include "vmm_ipi.h"
47#include "vmm_lapic.h"
48#include "vmm_ktr.h"
49#include "vmm_lapic.h"
50#include "vmm_ktr.h"
51#include "vmm_stat.h"
52
49#include "vlapic.h"
53#include "vlapic.h"
54#include "vlapic_priv.h"
50#include "vioapic.h"
51
52#define VLAPIC_CTR0(vlapic, format) \
53 VCPU_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
54
55#define VLAPIC_CTR1(vlapic, format, p1) \
56 VCPU_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
57
58#define VLAPIC_CTR2(vlapic, format, p1, p2) \
59 VCPU_CTR2((vlapic)->vm, (vlapic)->vcpuid, format, p1, p2)
60
61#define VLAPIC_CTR_IRR(vlapic, msg) \
62do { \
55#include "vioapic.h"
56
57#define VLAPIC_CTR0(vlapic, format) \
58 VCPU_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
59
60#define VLAPIC_CTR1(vlapic, format, p1) \
61 VCPU_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
62
63#define VLAPIC_CTR2(vlapic, format, p1, p2) \
64 VCPU_CTR2((vlapic)->vm, (vlapic)->vcpuid, format, p1, p2)
65
66#define VLAPIC_CTR_IRR(vlapic, msg) \
67do { \
63 uint32_t *irrptr = &(vlapic)->apic.irr0; \
68 uint32_t *irrptr = &(vlapic)->apic_page->irr0; \
64 irrptr[0] = irrptr[0]; /* silence compiler */ \
65 VLAPIC_CTR1((vlapic), msg " irr0 0x%08x", irrptr[0 << 2]); \
66 VLAPIC_CTR1((vlapic), msg " irr1 0x%08x", irrptr[1 << 2]); \
67 VLAPIC_CTR1((vlapic), msg " irr2 0x%08x", irrptr[2 << 2]); \
68 VLAPIC_CTR1((vlapic), msg " irr3 0x%08x", irrptr[3 << 2]); \
69 VLAPIC_CTR1((vlapic), msg " irr4 0x%08x", irrptr[4 << 2]); \
70 VLAPIC_CTR1((vlapic), msg " irr5 0x%08x", irrptr[5 << 2]); \
71 VLAPIC_CTR1((vlapic), msg " irr6 0x%08x", irrptr[6 << 2]); \
72 VLAPIC_CTR1((vlapic), msg " irr7 0x%08x", irrptr[7 << 2]); \
73} while (0)
74
75#define VLAPIC_CTR_ISR(vlapic, msg) \
76do { \
69 irrptr[0] = irrptr[0]; /* silence compiler */ \
70 VLAPIC_CTR1((vlapic), msg " irr0 0x%08x", irrptr[0 << 2]); \
71 VLAPIC_CTR1((vlapic), msg " irr1 0x%08x", irrptr[1 << 2]); \
72 VLAPIC_CTR1((vlapic), msg " irr2 0x%08x", irrptr[2 << 2]); \
73 VLAPIC_CTR1((vlapic), msg " irr3 0x%08x", irrptr[3 << 2]); \
74 VLAPIC_CTR1((vlapic), msg " irr4 0x%08x", irrptr[4 << 2]); \
75 VLAPIC_CTR1((vlapic), msg " irr5 0x%08x", irrptr[5 << 2]); \
76 VLAPIC_CTR1((vlapic), msg " irr6 0x%08x", irrptr[6 << 2]); \
77 VLAPIC_CTR1((vlapic), msg " irr7 0x%08x", irrptr[7 << 2]); \
78} while (0)
79
80#define VLAPIC_CTR_ISR(vlapic, msg) \
81do { \
77 uint32_t *isrptr = &(vlapic)->apic.isr0; \
82 uint32_t *isrptr = &(vlapic)->apic_page->isr0; \
78 isrptr[0] = isrptr[0]; /* silence compiler */ \
79 VLAPIC_CTR1((vlapic), msg " isr0 0x%08x", isrptr[0 << 2]); \
80 VLAPIC_CTR1((vlapic), msg " isr1 0x%08x", isrptr[1 << 2]); \
81 VLAPIC_CTR1((vlapic), msg " isr2 0x%08x", isrptr[2 << 2]); \
82 VLAPIC_CTR1((vlapic), msg " isr3 0x%08x", isrptr[3 << 2]); \
83 VLAPIC_CTR1((vlapic), msg " isr4 0x%08x", isrptr[4 << 2]); \
84 VLAPIC_CTR1((vlapic), msg " isr5 0x%08x", isrptr[5 << 2]); \
85 VLAPIC_CTR1((vlapic), msg " isr6 0x%08x", isrptr[6 << 2]); \
86 VLAPIC_CTR1((vlapic), msg " isr7 0x%08x", isrptr[7 << 2]); \
87} while (0)
88
83 isrptr[0] = isrptr[0]; /* silence compiler */ \
84 VLAPIC_CTR1((vlapic), msg " isr0 0x%08x", isrptr[0 << 2]); \
85 VLAPIC_CTR1((vlapic), msg " isr1 0x%08x", isrptr[1 << 2]); \
86 VLAPIC_CTR1((vlapic), msg " isr2 0x%08x", isrptr[2 << 2]); \
87 VLAPIC_CTR1((vlapic), msg " isr3 0x%08x", isrptr[3 << 2]); \
88 VLAPIC_CTR1((vlapic), msg " isr4 0x%08x", isrptr[4 << 2]); \
89 VLAPIC_CTR1((vlapic), msg " isr5 0x%08x", isrptr[5 << 2]); \
90 VLAPIC_CTR1((vlapic), msg " isr6 0x%08x", isrptr[6 << 2]); \
91 VLAPIC_CTR1((vlapic), msg " isr7 0x%08x", isrptr[7 << 2]); \
92} while (0)
93
89static MALLOC_DEFINE(M_VLAPIC, "vlapic", "vlapic");
90
91#define PRIO(x) ((x) >> 4)
92
93#define VLAPIC_VERSION (16)
94#define VLAPIC_MAXLVT_ENTRIES (APIC_LVT_CMCI)
95
96#define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
97
94#define PRIO(x) ((x) >> 4)
95
96#define VLAPIC_VERSION (16)
97#define VLAPIC_MAXLVT_ENTRIES (APIC_LVT_CMCI)
98
99#define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
100
98enum boot_state {
99 BS_INIT,
100 BS_SIPI,
101 BS_RUNNING
102};
103
104struct vlapic {
105 struct vm *vm;
106 int vcpuid;
107
108 struct LAPIC apic;
109
110 uint32_t esr_pending;
111 int esr_firing;
112
113 struct callout callout; /* vlapic timer */
114 struct bintime timer_fire_bt; /* callout expiry time */
115 struct bintime timer_freq_bt; /* timer frequency */
116 struct bintime timer_period_bt; /* timer period */
117 struct mtx timer_mtx;
118
119 /*
120 * The 'isrvec_stk' is a stack of vectors injected by the local apic.
121 * A vector is popped from the stack when the processor does an EOI.
122 * The vector on the top of the stack is used to compute the
123 * Processor Priority in conjunction with the TPR.
124 */
125 uint8_t isrvec_stk[ISRVEC_STK_SIZE];
126 int isrvec_stk_top;
127
128 uint64_t msr_apicbase;
129 enum boot_state boot_state;
130};
131
132/*
133 * The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
134 * vlapic_callout_handler() and vcpu accesses to the following registers:
135 * - initial count register aka icr_timer
136 * - current count register aka ccr_timer
137 * - divide config register aka dcr_timer
138 * - timer LVT register
139 *

--- 18 unchanged lines hidden (view full) ---

158
159static __inline uint32_t
160vlapic_get_ldr(struct vlapic *vlapic)
161{
162 struct LAPIC *lapic;
163 int apicid;
164 uint32_t ldr;
165
101/*
102 * The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
103 * vlapic_callout_handler() and vcpu accesses to the following registers:
104 * - initial count register aka icr_timer
105 * - current count register aka ccr_timer
106 * - divide config register aka dcr_timer
107 * - timer LVT register
108 *

--- 18 unchanged lines hidden (view full) ---

127
128static __inline uint32_t
129vlapic_get_ldr(struct vlapic *vlapic)
130{
131 struct LAPIC *lapic;
132 int apicid;
133 uint32_t ldr;
134
166 lapic = &vlapic->apic;
135 lapic = vlapic->apic_page;
167 if (x2apic(vlapic)) {
168 apicid = vlapic_get_id(vlapic);
169 ldr = 1 << (apicid & 0xf);
170 ldr |= (apicid & 0xffff0) << 12;
171 return (ldr);
172 } else
173 return (lapic->ldr);
174}
175
176static __inline uint32_t
177vlapic_get_dfr(struct vlapic *vlapic)
178{
179 struct LAPIC *lapic;
180
136 if (x2apic(vlapic)) {
137 apicid = vlapic_get_id(vlapic);
138 ldr = 1 << (apicid & 0xf);
139 ldr |= (apicid & 0xffff0) << 12;
140 return (ldr);
141 } else
142 return (lapic->ldr);
143}
144
145static __inline uint32_t
146vlapic_get_dfr(struct vlapic *vlapic)
147{
148 struct LAPIC *lapic;
149
181 lapic = &vlapic->apic;
150 lapic = vlapic->apic_page;
182 if (x2apic(vlapic))
183 return (0);
184 else
185 return (lapic->dfr);
186}
187
188static void
189vlapic_set_dfr(struct vlapic *vlapic, uint32_t data)
190{
191 uint32_t dfr;
192 struct LAPIC *lapic;
193
194 if (x2apic(vlapic)) {
195 VM_CTR1(vlapic->vm, "write to DFR in x2apic mode: %#x", data);
196 return;
197 }
198
151 if (x2apic(vlapic))
152 return (0);
153 else
154 return (lapic->dfr);
155}
156
157static void
158vlapic_set_dfr(struct vlapic *vlapic, uint32_t data)
159{
160 uint32_t dfr;
161 struct LAPIC *lapic;
162
163 if (x2apic(vlapic)) {
164 VM_CTR1(vlapic->vm, "write to DFR in x2apic mode: %#x", data);
165 return;
166 }
167
199 lapic = &vlapic->apic;
168 lapic = vlapic->apic_page;
200 dfr = (lapic->dfr & APIC_DFR_RESERVED) | (data & APIC_DFR_MODEL_MASK);
201 if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_FLAT)
202 VLAPIC_CTR0(vlapic, "vlapic DFR in Flat Model");
203 else if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_CLUSTER)
204 VLAPIC_CTR0(vlapic, "vlapic DFR in Cluster Model");
205 else
206 VLAPIC_CTR1(vlapic, "vlapic DFR in Unknown Model %#x", dfr);
207

--- 6 unchanged lines hidden (view full) ---

214 struct LAPIC *lapic;
215
216 /* LDR is read-only in x2apic mode */
217 if (x2apic(vlapic)) {
218 VLAPIC_CTR1(vlapic, "write to LDR in x2apic mode: %#x", data);
219 return;
220 }
221
169 dfr = (lapic->dfr & APIC_DFR_RESERVED) | (data & APIC_DFR_MODEL_MASK);
170 if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_FLAT)
171 VLAPIC_CTR0(vlapic, "vlapic DFR in Flat Model");
172 else if ((dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_CLUSTER)
173 VLAPIC_CTR0(vlapic, "vlapic DFR in Cluster Model");
174 else
175 VLAPIC_CTR1(vlapic, "vlapic DFR in Unknown Model %#x", dfr);
176

--- 6 unchanged lines hidden (view full) ---

183 struct LAPIC *lapic;
184
185 /* LDR is read-only in x2apic mode */
186 if (x2apic(vlapic)) {
187 VLAPIC_CTR1(vlapic, "write to LDR in x2apic mode: %#x", data);
188 return;
189 }
190
222 lapic = &vlapic->apic;
191 lapic = vlapic->apic_page;
223 lapic->ldr = data & ~APIC_LDR_RESERVED;
224 VLAPIC_CTR1(vlapic, "vlapic LDR set to %#x", lapic->ldr);
225}
226
227static int
228vlapic_timer_divisor(uint32_t dcr)
229{
230 switch (dcr & 0xB) {

--- 41 unchanged lines hidden (view full) ---

272static uint32_t
273vlapic_get_ccr(struct vlapic *vlapic)
274{
275 struct bintime bt_now, bt_rem;
276 struct LAPIC *lapic;
277 uint32_t ccr;
278
279 ccr = 0;
192 lapic->ldr = data & ~APIC_LDR_RESERVED;
193 VLAPIC_CTR1(vlapic, "vlapic LDR set to %#x", lapic->ldr);
194}
195
196static int
197vlapic_timer_divisor(uint32_t dcr)
198{
199 switch (dcr & 0xB) {

--- 41 unchanged lines hidden (view full) ---

241static uint32_t
242vlapic_get_ccr(struct vlapic *vlapic)
243{
244 struct bintime bt_now, bt_rem;
245 struct LAPIC *lapic;
246 uint32_t ccr;
247
248 ccr = 0;
280 lapic = &vlapic->apic;
249 lapic = vlapic->apic_page;
281
282 VLAPIC_TIMER_LOCK(vlapic);
283 if (callout_active(&vlapic->callout)) {
284 /*
285 * If the timer is scheduled to expire in the future then
286 * compute the value of 'ccr' based on the remaining time.
287 */
288 binuptime(&bt_now);

--- 13 unchanged lines hidden (view full) ---

302}
303
304static void
305vlapic_set_dcr(struct vlapic *vlapic, uint32_t dcr)
306{
307 struct LAPIC *lapic;
308 int divisor;
309
250
251 VLAPIC_TIMER_LOCK(vlapic);
252 if (callout_active(&vlapic->callout)) {
253 /*
254 * If the timer is scheduled to expire in the future then
255 * compute the value of 'ccr' based on the remaining time.
256 */
257 binuptime(&bt_now);

--- 13 unchanged lines hidden (view full) ---

271}
272
273static void
274vlapic_set_dcr(struct vlapic *vlapic, uint32_t dcr)
275{
276 struct LAPIC *lapic;
277 int divisor;
278
310 lapic = &vlapic->apic;
279 lapic = vlapic->apic_page;
311 VLAPIC_TIMER_LOCK(vlapic);
312
313 lapic->dcr_timer = dcr;
314 divisor = vlapic_timer_divisor(dcr);
315 VLAPIC_CTR2(vlapic, "vlapic dcr_timer=%#x, divisor=%d", dcr, divisor);
316
317 /*
318 * Update the timer frequency and the timer period.

--- 6 unchanged lines hidden (view full) ---

325 bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
326
327 VLAPIC_TIMER_UNLOCK(vlapic);
328}
329
330static void
331vlapic_update_errors(struct vlapic *vlapic)
332{
280 VLAPIC_TIMER_LOCK(vlapic);
281
282 lapic->dcr_timer = dcr;
283 divisor = vlapic_timer_divisor(dcr);
284 VLAPIC_CTR2(vlapic, "vlapic dcr_timer=%#x, divisor=%d", dcr, divisor);
285
286 /*
287 * Update the timer frequency and the timer period.

--- 6 unchanged lines hidden (view full) ---

294 bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
295
296 VLAPIC_TIMER_UNLOCK(vlapic);
297}
298
299static void
300vlapic_update_errors(struct vlapic *vlapic)
301{
333 struct LAPIC *lapic = &vlapic->apic;
302 struct LAPIC *lapic;
303
304 lapic = vlapic->apic_page;
334 lapic->esr = vlapic->esr_pending;
335 vlapic->esr_pending = 0;
336}
337
338static void
339vlapic_reset(struct vlapic *vlapic)
340{
341 struct LAPIC *lapic;
342
305 lapic->esr = vlapic->esr_pending;
306 vlapic->esr_pending = 0;
307}
308
309static void
310vlapic_reset(struct vlapic *vlapic)
311{
312 struct LAPIC *lapic;
313
343 lapic = &vlapic->apic;
314 lapic = vlapic->apic_page;
344 bzero(lapic, sizeof(struct LAPIC));
345
346 lapic->version = VLAPIC_VERSION;
347 lapic->version |= (VLAPIC_MAXLVT_ENTRIES << MAXLVTSHIFT);
348 lapic->dfr = 0xffffffff;
349 lapic->svr = APIC_SVR_VECTOR;
350 vlapic_mask_lvts(&lapic->lvt_timer, 6);
351 vlapic_mask_lvts(&lapic->lvt_cmci, 1);
352 vlapic_set_dcr(vlapic, 0);
353
354 if (vlapic->vcpuid == 0)
355 vlapic->boot_state = BS_RUNNING; /* BSP */
356 else
357 vlapic->boot_state = BS_INIT; /* AP */
358}
359
360void
361vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
362{
315 bzero(lapic, sizeof(struct LAPIC));
316
317 lapic->version = VLAPIC_VERSION;
318 lapic->version |= (VLAPIC_MAXLVT_ENTRIES << MAXLVTSHIFT);
319 lapic->dfr = 0xffffffff;
320 lapic->svr = APIC_SVR_VECTOR;
321 vlapic_mask_lvts(&lapic->lvt_timer, 6);
322 vlapic_mask_lvts(&lapic->lvt_cmci, 1);
323 vlapic_set_dcr(vlapic, 0);
324
325 if (vlapic->vcpuid == 0)
326 vlapic->boot_state = BS_RUNNING; /* BSP */
327 else
328 vlapic->boot_state = BS_INIT; /* AP */
329}
330
331void
332vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
333{
363 struct LAPIC *lapic = &vlapic->apic;
334 struct LAPIC *lapic = vlapic->apic_page;
364 uint32_t *irrptr, *tmrptr, mask;
365 int idx;
366
367 if (vector < 0 || vector >= 256)
368 panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
369
370 if (!(lapic->svr & APIC_SVR_ENABLE)) {
371 VLAPIC_CTR1(vlapic, "vlapic is software disabled, ignoring "

--- 24 unchanged lines hidden (view full) ---

396 atomic_clear_int(&tmrptr[idx], mask);
397
398 VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
399}
400
401static __inline uint32_t *
402vlapic_get_lvtptr(struct vlapic *vlapic, uint32_t offset)
403{
335 uint32_t *irrptr, *tmrptr, mask;
336 int idx;
337
338 if (vector < 0 || vector >= 256)
339 panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
340
341 if (!(lapic->svr & APIC_SVR_ENABLE)) {
342 VLAPIC_CTR1(vlapic, "vlapic is software disabled, ignoring "

--- 24 unchanged lines hidden (view full) ---

367 atomic_clear_int(&tmrptr[idx], mask);
368
369 VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
370}
371
372static __inline uint32_t *
373vlapic_get_lvtptr(struct vlapic *vlapic, uint32_t offset)
374{
404 struct LAPIC *lapic = &vlapic->apic;
375 struct LAPIC *lapic = vlapic->apic_page;
405 int i;
406
407 switch (offset) {
408 case APIC_OFFSET_CMCI_LVT:
409 return (&lapic->lvt_cmci);
410 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
411 i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
412 return ((&lapic->lvt_timer) + i);;

--- 10 unchanged lines hidden (view full) ---

423}
424
425static void
426vlapic_set_lvt(struct vlapic *vlapic, uint32_t offset, uint32_t val)
427{
428 uint32_t *lvtptr, mask;
429 struct LAPIC *lapic;
430
376 int i;
377
378 switch (offset) {
379 case APIC_OFFSET_CMCI_LVT:
380 return (&lapic->lvt_cmci);
381 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
382 i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
383 return ((&lapic->lvt_timer) + i);;

--- 10 unchanged lines hidden (view full) ---

394}
395
396static void
397vlapic_set_lvt(struct vlapic *vlapic, uint32_t offset, uint32_t val)
398{
399 uint32_t *lvtptr, mask;
400 struct LAPIC *lapic;
401
431 lapic = &vlapic->apic;
402 lapic = vlapic->apic_page;
432 lvtptr = vlapic_get_lvtptr(vlapic, offset);
433
434 if (offset == APIC_OFFSET_TIMER_LVT)
435 VLAPIC_TIMER_LOCK(vlapic);
436
437 if (!(lapic->svr & APIC_SVR_ENABLE))
438 val |= APIC_LVT_M;
439 mask = APIC_LVT_M | APIC_LVT_DS | APIC_LVT_VECTOR;

--- 30 unchanged lines hidden (view full) ---

470
471 switch (mode) {
472 case APIC_LVT_DM_FIXED:
473 if (vec < 16) {
474 vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR);
475 return (0);
476 }
477 vlapic_set_intr_ready(vlapic, vec, false);
403 lvtptr = vlapic_get_lvtptr(vlapic, offset);
404
405 if (offset == APIC_OFFSET_TIMER_LVT)
406 VLAPIC_TIMER_LOCK(vlapic);
407
408 if (!(lapic->svr & APIC_SVR_ENABLE))
409 val |= APIC_LVT_M;
410 mask = APIC_LVT_M | APIC_LVT_DS | APIC_LVT_VECTOR;

--- 30 unchanged lines hidden (view full) ---

441
442 switch (mode) {
443 case APIC_LVT_DM_FIXED:
444 if (vec < 16) {
445 vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR);
446 return (0);
447 }
448 vlapic_set_intr_ready(vlapic, vec, false);
478 vcpu_notify_event(vlapic->vm, vlapic->vcpuid);
449 vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true);
479 break;
480 case APIC_LVT_DM_NMI:
481 vm_inject_nmi(vlapic->vm, vlapic->vcpuid);
482 break;
483 default:
484 // Other modes ignored
485 return (0);
486 }
487 return (1);
488}
489
490#if 1
491static void
492dump_isrvec_stk(struct vlapic *vlapic)
493{
494 int i;
495 uint32_t *isrptr;
496
450 break;
451 case APIC_LVT_DM_NMI:
452 vm_inject_nmi(vlapic->vm, vlapic->vcpuid);
453 break;
454 default:
455 // Other modes ignored
456 return (0);
457 }
458 return (1);
459}
460
461#if 1
462static void
463dump_isrvec_stk(struct vlapic *vlapic)
464{
465 int i;
466 uint32_t *isrptr;
467
497 isrptr = &vlapic->apic.isr0;
468 isrptr = &vlapic->apic_page->isr0;
498 for (i = 0; i < 8; i++)
499 printf("ISR%d 0x%08x\n", i, isrptr[i * 4]);
500
501 for (i = 0; i <= vlapic->isrvec_stk_top; i++)
502 printf("isrvec_stk[%d] = %d\n", i, vlapic->isrvec_stk[i]);
503}
504#endif
505

--- 8 unchanged lines hidden (view full) ---

514
515 /*
516 * Note that the value on the stack at index 0 is always 0.
517 *
518 * This is a placeholder for the value of ISRV when none of the
519 * bits is set in the ISRx registers.
520 */
521 isrvec = vlapic->isrvec_stk[vlapic->isrvec_stk_top];
469 for (i = 0; i < 8; i++)
470 printf("ISR%d 0x%08x\n", i, isrptr[i * 4]);
471
472 for (i = 0; i <= vlapic->isrvec_stk_top; i++)
473 printf("isrvec_stk[%d] = %d\n", i, vlapic->isrvec_stk[i]);
474}
475#endif
476

--- 8 unchanged lines hidden (view full) ---

485
486 /*
487 * Note that the value on the stack at index 0 is always 0.
488 *
489 * This is a placeholder for the value of ISRV when none of the
490 * bits is set in the ISRx registers.
491 */
492 isrvec = vlapic->isrvec_stk[vlapic->isrvec_stk_top];
522 tpr = vlapic->apic.tpr;
493 tpr = vlapic->apic_page->tpr;
523
524#if 1
525 {
526 int i, lastprio, curprio, vector, idx;
527 uint32_t *isrptr;
528
529 if (vlapic->isrvec_stk_top == 0 && isrvec != 0)
530 panic("isrvec_stk is corrupted: %d", isrvec);

--- 12 unchanged lines hidden (view full) ---

543 lastprio = curprio;
544 }
545
546 /*
547 * Make sure that each bit set in the ISRx registers has a
548 * corresponding entry on the isrvec stack.
549 */
550 i = 1;
494
495#if 1
496 {
497 int i, lastprio, curprio, vector, idx;
498 uint32_t *isrptr;
499
500 if (vlapic->isrvec_stk_top == 0 && isrvec != 0)
501 panic("isrvec_stk is corrupted: %d", isrvec);

--- 12 unchanged lines hidden (view full) ---

514 lastprio = curprio;
515 }
516
517 /*
518 * Make sure that each bit set in the ISRx registers has a
519 * corresponding entry on the isrvec stack.
520 */
521 i = 1;
551 isrptr = &vlapic->apic.isr0;
522 isrptr = &vlapic->apic_page->isr0;
552 for (vector = 0; vector < 256; vector++) {
553 idx = (vector / 32) * 4;
554 if (isrptr[idx] & (1 << (vector % 32))) {
555 if (i > vlapic->isrvec_stk_top ||
556 vlapic->isrvec_stk[i] != vector) {
557 dump_isrvec_stk(vlapic);
558 panic("ISR and isrvec_stk out of sync");
559 }
560 i++;
561 }
562 }
563 }
564#endif
565
566 if (PRIO(tpr) >= PRIO(isrvec))
567 ppr = tpr;
568 else
569 ppr = isrvec & 0xf0;
570
523 for (vector = 0; vector < 256; vector++) {
524 idx = (vector / 32) * 4;
525 if (isrptr[idx] & (1 << (vector % 32))) {
526 if (i > vlapic->isrvec_stk_top ||
527 vlapic->isrvec_stk[i] != vector) {
528 dump_isrvec_stk(vlapic);
529 panic("ISR and isrvec_stk out of sync");
530 }
531 i++;
532 }
533 }
534 }
535#endif
536
537 if (PRIO(tpr) >= PRIO(isrvec))
538 ppr = tpr;
539 else
540 ppr = isrvec & 0xf0;
541
571 vlapic->apic.ppr = ppr;
542 vlapic->apic_page->ppr = ppr;
572 VLAPIC_CTR1(vlapic, "vlapic_update_ppr 0x%02x", ppr);
573}
574
575static void
576vlapic_process_eoi(struct vlapic *vlapic)
577{
543 VLAPIC_CTR1(vlapic, "vlapic_update_ppr 0x%02x", ppr);
544}
545
546static void
547vlapic_process_eoi(struct vlapic *vlapic)
548{
578 struct LAPIC *lapic = &vlapic->apic;
549 struct LAPIC *lapic = vlapic->apic_page;
579 uint32_t *isrptr, *tmrptr;
580 int i, idx, bitpos, vector;
581
582 isrptr = &lapic->isr0;
583 tmrptr = &lapic->tmr0;
584
585 /*
586 * The x86 architecture reserves the the first 32 vectors for use

--- 143 unchanged lines hidden (view full) ---

730 if (callout_pending(&vlapic->callout)) /* callout was reset */
731 goto done;
732
733 if (!callout_active(&vlapic->callout)) /* callout was stopped */
734 goto done;
735
736 callout_deactivate(&vlapic->callout);
737
550 uint32_t *isrptr, *tmrptr;
551 int i, idx, bitpos, vector;
552
553 isrptr = &lapic->isr0;
554 tmrptr = &lapic->tmr0;
555
556 /*
557 * The x86 architecture reserves the the first 32 vectors for use

--- 143 unchanged lines hidden (view full) ---

701 if (callout_pending(&vlapic->callout)) /* callout was reset */
702 goto done;
703
704 if (!callout_active(&vlapic->callout)) /* callout was stopped */
705 goto done;
706
707 callout_deactivate(&vlapic->callout);
708
738 KASSERT(vlapic->apic.icr_timer != 0, ("vlapic timer is disabled"));
709 KASSERT(vlapic->apic_page->icr_timer != 0, ("timer is disabled"));
739
740 vlapic_fire_timer(vlapic);
741
742 if (vlapic_periodic_timer(vlapic)) {
743 binuptime(&btnow);
744 KASSERT(bintime_cmp(&btnow, &vlapic->timer_fire_bt, >=),
745 ("vlapic callout at %#lx.%#lx, expected at %#lx.#%lx",
746 btnow.sec, btnow.frac, vlapic->timer_fire_bt.sec,

--- 37 unchanged lines hidden (view full) ---

784static void
785vlapic_set_icr_timer(struct vlapic *vlapic, uint32_t icr_timer)
786{
787 struct LAPIC *lapic;
788 sbintime_t sbt;
789
790 VLAPIC_TIMER_LOCK(vlapic);
791
710
711 vlapic_fire_timer(vlapic);
712
713 if (vlapic_periodic_timer(vlapic)) {
714 binuptime(&btnow);
715 KASSERT(bintime_cmp(&btnow, &vlapic->timer_fire_bt, >=),
716 ("vlapic callout at %#lx.%#lx, expected at %#lx.#%lx",
717 btnow.sec, btnow.frac, vlapic->timer_fire_bt.sec,

--- 37 unchanged lines hidden (view full) ---

755static void
756vlapic_set_icr_timer(struct vlapic *vlapic, uint32_t icr_timer)
757{
758 struct LAPIC *lapic;
759 sbintime_t sbt;
760
761 VLAPIC_TIMER_LOCK(vlapic);
762
792 lapic = &vlapic->apic;
763 lapic = vlapic->apic_page;
793 lapic->icr_timer = icr_timer;
794
795 vlapic->timer_period_bt = vlapic->timer_freq_bt;
796 bintime_mul(&vlapic->timer_period_bt, icr_timer);
797
798 if (icr_timer != 0) {
799 binuptime(&vlapic->timer_fire_bt);
800 bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);

--- 215 unchanged lines hidden (view full) ---

1016 * This will cause a return to userland.
1017 */
1018 return (1);
1019}
1020
1021int
1022vlapic_pending_intr(struct vlapic *vlapic)
1023{
764 lapic->icr_timer = icr_timer;
765
766 vlapic->timer_period_bt = vlapic->timer_freq_bt;
767 bintime_mul(&vlapic->timer_period_bt, icr_timer);
768
769 if (icr_timer != 0) {
770 binuptime(&vlapic->timer_fire_bt);
771 bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);

--- 215 unchanged lines hidden (view full) ---

987 * This will cause a return to userland.
988 */
989 return (1);
990}
991
992int
993vlapic_pending_intr(struct vlapic *vlapic)
994{
1024 struct LAPIC *lapic = &vlapic->apic;
995 struct LAPIC *lapic = vlapic->apic_page;
1025 int idx, i, bitpos, vector;
1026 uint32_t *irrptr, val;
1027
1028 irrptr = &lapic->irr0;
1029
1030 /*
1031 * The x86 architecture reserves the the first 32 vectors for use
1032 * by the processor.

--- 12 unchanged lines hidden (view full) ---

1045 }
1046 }
1047 return (-1);
1048}
1049
1050void
1051vlapic_intr_accepted(struct vlapic *vlapic, int vector)
1052{
996 int idx, i, bitpos, vector;
997 uint32_t *irrptr, val;
998
999 irrptr = &lapic->irr0;
1000
1001 /*
1002 * The x86 architecture reserves the the first 32 vectors for use
1003 * by the processor.

--- 12 unchanged lines hidden (view full) ---

1016 }
1017 }
1018 return (-1);
1019}
1020
1021void
1022vlapic_intr_accepted(struct vlapic *vlapic, int vector)
1023{
1053 struct LAPIC *lapic = &vlapic->apic;
1024 struct LAPIC *lapic = vlapic->apic_page;
1054 uint32_t *irrptr, *isrptr;
1055 int idx, stk_top;
1056
1057 /*
1058 * clear the ready bit for vector being accepted in irr
1059 * and set the vector as in service in isr.
1060 */
1061 idx = (vector / 32) * 4;

--- 20 unchanged lines hidden (view full) ---

1082}
1083
1084static void
1085lapic_set_svr(struct vlapic *vlapic, uint32_t new)
1086{
1087 struct LAPIC *lapic;
1088 uint32_t old, changed;
1089
1025 uint32_t *irrptr, *isrptr;
1026 int idx, stk_top;
1027
1028 /*
1029 * clear the ready bit for vector being accepted in irr
1030 * and set the vector as in service in isr.
1031 */
1032 idx = (vector / 32) * 4;

--- 20 unchanged lines hidden (view full) ---

1053}
1054
1055static void
1056lapic_set_svr(struct vlapic *vlapic, uint32_t new)
1057{
1058 struct LAPIC *lapic;
1059 uint32_t old, changed;
1060
1090 lapic = &vlapic->apic;
1061 lapic = vlapic->apic_page;
1091 old = lapic->svr;
1092 changed = old ^ new;
1093 if ((changed & APIC_SVR_ENABLE) != 0) {
1094 if ((new & APIC_SVR_ENABLE) == 0) {
1095 /*
1096 * The apic is now disabled so stop the apic timer.
1097 */
1098 VLAPIC_CTR0(vlapic, "vlapic is software-disabled");

--- 11 unchanged lines hidden (view full) ---

1110 }
1111 }
1112 lapic->svr = new;
1113}
1114
1115int
1116vlapic_read(struct vlapic *vlapic, uint64_t offset, uint64_t *data, bool *retu)
1117{
1062 old = lapic->svr;
1063 changed = old ^ new;
1064 if ((changed & APIC_SVR_ENABLE) != 0) {
1065 if ((new & APIC_SVR_ENABLE) == 0) {
1066 /*
1067 * The apic is now disabled so stop the apic timer.
1068 */
1069 VLAPIC_CTR0(vlapic, "vlapic is software-disabled");

--- 11 unchanged lines hidden (view full) ---

1081 }
1082 }
1083 lapic->svr = new;
1084}
1085
1086int
1087vlapic_read(struct vlapic *vlapic, uint64_t offset, uint64_t *data, bool *retu)
1088{
1118 struct LAPIC *lapic = &vlapic->apic;
1089 struct LAPIC *lapic = vlapic->apic_page;
1119 uint32_t *reg;
1120 int i;
1121
1122 if (offset > sizeof(*lapic)) {
1123 *data = 0;
1124 goto done;
1125 }
1126

--- 50 unchanged lines hidden (view full) ---

1177 break;
1178 case APIC_OFFSET_ICR_HI:
1179 *data = lapic->icr_hi;
1180 break;
1181 case APIC_OFFSET_CMCI_LVT:
1182 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
1183 *data = vlapic_get_lvt(vlapic, offset);
1184 break;
1090 uint32_t *reg;
1091 int i;
1092
1093 if (offset > sizeof(*lapic)) {
1094 *data = 0;
1095 goto done;
1096 }
1097

--- 50 unchanged lines hidden (view full) ---

1148 break;
1149 case APIC_OFFSET_ICR_HI:
1150 *data = lapic->icr_hi;
1151 break;
1152 case APIC_OFFSET_CMCI_LVT:
1153 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
1154 *data = vlapic_get_lvt(vlapic, offset);
1155 break;
1185 case APIC_OFFSET_ICR:
1156 case APIC_OFFSET_TIMER_ICR:
1186 *data = lapic->icr_timer;
1187 break;
1157 *data = lapic->icr_timer;
1158 break;
1188 case APIC_OFFSET_CCR:
1159 case APIC_OFFSET_TIMER_CCR:
1189 *data = vlapic_get_ccr(vlapic);
1190 break;
1160 *data = vlapic_get_ccr(vlapic);
1161 break;
1191 case APIC_OFFSET_DCR:
1162 case APIC_OFFSET_TIMER_DCR:
1192 *data = lapic->dcr_timer;
1193 break;
1194 case APIC_OFFSET_RRR:
1195 default:
1196 *data = 0;
1197 break;
1198 }
1199done:
1200 VLAPIC_CTR2(vlapic, "vlapic read offset %#x, data %#lx", offset, *data);
1201 return 0;
1202}
1203
1204int
1205vlapic_write(struct vlapic *vlapic, uint64_t offset, uint64_t data, bool *retu)
1206{
1163 *data = lapic->dcr_timer;
1164 break;
1165 case APIC_OFFSET_RRR:
1166 default:
1167 *data = 0;
1168 break;
1169 }
1170done:
1171 VLAPIC_CTR2(vlapic, "vlapic read offset %#x, data %#lx", offset, *data);
1172 return 0;
1173}
1174
1175int
1176vlapic_write(struct vlapic *vlapic, uint64_t offset, uint64_t data, bool *retu)
1177{
1207 struct LAPIC *lapic = &vlapic->apic;
1178 struct LAPIC *lapic = vlapic->apic_page;
1208 int retval;
1209
1210 VLAPIC_CTR2(vlapic, "vlapic write offset %#x, data %#lx", offset, data);
1211
1212 if (offset > sizeof(*lapic)) {
1213 return 0;
1214 }
1215

--- 31 unchanged lines hidden (view full) ---

1247 retval = 0;
1248 lapic->icr_hi = data;
1249 }
1250 break;
1251 case APIC_OFFSET_CMCI_LVT:
1252 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
1253 vlapic_set_lvt(vlapic, offset, data);
1254 break;
1179 int retval;
1180
1181 VLAPIC_CTR2(vlapic, "vlapic write offset %#x, data %#lx", offset, data);
1182
1183 if (offset > sizeof(*lapic)) {
1184 return 0;
1185 }
1186

--- 31 unchanged lines hidden (view full) ---

1218 retval = 0;
1219 lapic->icr_hi = data;
1220 }
1221 break;
1222 case APIC_OFFSET_CMCI_LVT:
1223 case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
1224 vlapic_set_lvt(vlapic, offset, data);
1225 break;
1255 case APIC_OFFSET_ICR:
1226 case APIC_OFFSET_TIMER_ICR:
1256 vlapic_set_icr_timer(vlapic, data);
1257 break;
1258
1227 vlapic_set_icr_timer(vlapic, data);
1228 break;
1229
1259 case APIC_OFFSET_DCR:
1230 case APIC_OFFSET_TIMER_DCR:
1260 vlapic_set_dcr(vlapic, data);
1261 break;
1262
1263 case APIC_OFFSET_ESR:
1264 vlapic_update_errors(vlapic);
1265 break;
1266 case APIC_OFFSET_VER:
1267 case APIC_OFFSET_APR:
1268 case APIC_OFFSET_PPR:
1269 case APIC_OFFSET_RRR:
1270 case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
1271 case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
1272 case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
1231 vlapic_set_dcr(vlapic, data);
1232 break;
1233
1234 case APIC_OFFSET_ESR:
1235 vlapic_update_errors(vlapic);
1236 break;
1237 case APIC_OFFSET_VER:
1238 case APIC_OFFSET_APR:
1239 case APIC_OFFSET_PPR:
1240 case APIC_OFFSET_RRR:
1241 case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
1242 case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
1243 case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
1273 case APIC_OFFSET_CCR:
1244 case APIC_OFFSET_TIMER_CCR:
1274 default:
1275 // Read only.
1276 break;
1277 }
1278
1279 return (retval);
1280}
1281
1245 default:
1246 // Read only.
1247 break;
1248 }
1249
1250 return (retval);
1251}
1252
1282struct vlapic *
1283vlapic_init(struct vm *vm, int vcpuid)
1253void
1254vlapic_init(struct vlapic *vlapic)
1284{
1255{
1285 struct vlapic *vlapic;
1256 KASSERT(vlapic->vm != NULL, ("vlapic_init: vm is not initialized"));
1257 KASSERT(vlapic->vcpuid >= 0 && vlapic->vcpuid < VM_MAXCPU,
1258 ("vlapic_init: vcpuid is not initialized"));
1259 KASSERT(vlapic->apic_page != NULL, ("vlapic_init: apic_page is not "
1260 "initialized"));
1286
1261
1287 vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO);
1288 vlapic->vm = vm;
1289 vlapic->vcpuid = vcpuid;
1290
1291 /*
1292 * If the vlapic is configured in x2apic mode then it will be
1293 * accessed in the critical section via the MSR emulation code.
1294 *
1295 * Therefore the timer mutex must be a spinlock because blockable
1296 * mutexes cannot be acquired in a critical section.
1297 */
1298 mtx_init(&vlapic->timer_mtx, "vlapic timer mtx", NULL, MTX_SPIN);
1299 callout_init(&vlapic->callout, 1);
1300
1301 vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
1302
1262 /*
1263 * If the vlapic is configured in x2apic mode then it will be
1264 * accessed in the critical section via the MSR emulation code.
1265 *
1266 * Therefore the timer mutex must be a spinlock because blockable
1267 * mutexes cannot be acquired in a critical section.
1268 */
1269 mtx_init(&vlapic->timer_mtx, "vlapic timer mtx", NULL, MTX_SPIN);
1270 callout_init(&vlapic->callout, 1);
1271
1272 vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
1273
1303 if (vcpuid == 0)
1274 if (vlapic->vcpuid == 0)
1304 vlapic->msr_apicbase |= APICBASE_BSP;
1305
1306 vlapic_reset(vlapic);
1275 vlapic->msr_apicbase |= APICBASE_BSP;
1276
1277 vlapic_reset(vlapic);
1307
1308 return (vlapic);
1309}
1310
1311void
1312vlapic_cleanup(struct vlapic *vlapic)
1313{
1314
1315 callout_drain(&vlapic->callout);
1278}
1279
1280void
1281vlapic_cleanup(struct vlapic *vlapic)
1282{
1283
1284 callout_drain(&vlapic->callout);
1316 free(vlapic, M_VLAPIC);
1317}
1318
1319uint64_t
1320vlapic_get_apicbase(struct vlapic *vlapic)
1321{
1322
1323 return (vlapic->msr_apicbase);
1324}

--- 48 unchanged lines hidden (view full) ---

1373
1374 while ((vcpuid = CPU_FFS(&dmask)) != 0) {
1375 vcpuid--;
1376 CPU_CLR(vcpuid, &dmask);
1377 lapic_set_intr(vm, vcpuid, vec, level);
1378 }
1379}
1380
1285}
1286
1287uint64_t
1288vlapic_get_apicbase(struct vlapic *vlapic)
1289{
1290
1291 return (vlapic->msr_apicbase);
1292}

--- 48 unchanged lines hidden (view full) ---

1341
1342 while ((vcpuid = CPU_FFS(&dmask)) != 0) {
1343 vcpuid--;
1344 CPU_CLR(vcpuid, &dmask);
1345 lapic_set_intr(vm, vcpuid, vec, level);
1346 }
1347}
1348
1349void
1350vlapic_post_intr(struct vlapic *vlapic, int hostcpu)
1351{
1352 /*
1353 * Post an interrupt to the vcpu currently running on 'hostcpu'.
1354 *
1355 * This is done by leveraging features like Posted Interrupts (Intel)
1356 * Doorbell MSR (AMD AVIC) that avoid a VM exit.
1357 *
1358 * If neither of these features are available then fallback to
1359 * sending an IPI to 'hostcpu'.
1360 */
1361 ipi_cpu(hostcpu, vmm_ipinum);
1362}
1363
1381bool
1382vlapic_enabled(struct vlapic *vlapic)
1383{
1364bool
1365vlapic_enabled(struct vlapic *vlapic)
1366{
1384 struct LAPIC *lapic = &vlapic->apic;
1367 struct LAPIC *lapic = vlapic->apic_page;
1385
1386 if ((vlapic->msr_apicbase & APICBASE_ENABLED) != 0 &&
1387 (lapic->svr & APIC_SVR_ENABLE) != 0)
1388 return (true);
1389 else
1390 return (false);
1391}
1368
1369 if ((vlapic->msr_apicbase & APICBASE_ENABLED) != 0 &&
1370 (lapic->svr & APIC_SVR_ENABLE) != 0)
1371 return (true);
1372 else
1373 return (false);
1374}