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} |