vioapic.c (262350) | vioapic.c (266339) |
---|---|
1/*- 2 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 3 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/*- 2 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 3 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 262350 2014-02-23 00:46:05Z jhb $ | 27 * $FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 266339 2014-05-17 19:11:08Z jhb $ |
28 */ 29 30#include <sys/cdefs.h> | 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 262350 2014-02-23 00:46:05Z jhb $"); | 31__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 266339 2014-05-17 19:11:08Z jhb $"); |
32 33#include <sys/param.h> 34#include <sys/queue.h> 35#include <sys/cpuset.h> 36#include <sys/lock.h> 37#include <sys/mutex.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> --- 177 unchanged lines hidden (view full) --- 217 218int 219vioapic_pulse_irq(struct vm *vm, int irq) 220{ 221 222 return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE)); 223} 224 | 32 33#include <sys/param.h> 34#include <sys/queue.h> 35#include <sys/cpuset.h> 36#include <sys/lock.h> 37#include <sys/mutex.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> --- 177 unchanged lines hidden (view full) --- 217 218int 219vioapic_pulse_irq(struct vm *vm, int irq) 220{ 221 222 return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE)); 223} 224 |
225/* 226 * Reset the vlapic's trigger-mode register to reflect the ioapic pin 227 * configuration. 228 */ 229static void 230vioapic_update_tmr(struct vm *vm, int vcpuid, void *arg) 231{ 232 struct vioapic *vioapic; 233 struct vlapic *vlapic; 234 uint32_t low, high, dest; 235 int delmode, pin, vector; 236 bool level, phys; 237 238 vlapic = vm_lapic(vm, vcpuid); 239 vioapic = vm_ioapic(vm); 240 241 VIOAPIC_LOCK(vioapic); 242 /* 243 * Reset all vectors to be edge-triggered. 244 */ 245 vlapic_reset_tmr(vlapic); 246 for (pin = 0; pin < REDIR_ENTRIES; pin++) { 247 low = vioapic->rtbl[pin].reg; 248 high = vioapic->rtbl[pin].reg >> 32; 249 250 level = low & IOART_TRGRLVL ? true : false; 251 if (!level) 252 continue; 253 254 /* 255 * For a level-triggered 'pin' let the vlapic figure out if 256 * an assertion on this 'pin' would result in an interrupt 257 * being delivered to it. If yes, then it will modify the 258 * TMR bit associated with this vector to level-triggered. 259 */ 260 phys = ((low & IOART_DESTMOD) == IOART_DESTPHY); 261 delmode = low & IOART_DELMOD; 262 vector = low & IOART_INTVEC; 263 dest = high >> APIC_ID_SHIFT; 264 vlapic_set_tmr_level(vlapic, dest, phys, delmode, vector); 265 } 266 VIOAPIC_UNLOCK(vioapic); 267} 268 |
|
225static uint32_t | 269static uint32_t |
226vioapic_read(struct vioapic *vioapic, uint32_t addr) | 270vioapic_read(struct vioapic *vioapic, int vcpuid, uint32_t addr) |
227{ 228 int regnum, pin, rshift; 229 230 regnum = addr & 0xff; 231 switch (regnum) { 232 case IOAPIC_ID: 233 return (vioapic->id); 234 break; --- 18 unchanged lines hidden (view full) --- 253 254 return (vioapic->rtbl[pin].reg >> rshift); 255 } 256 257 return (0); 258} 259 260static void | 271{ 272 int regnum, pin, rshift; 273 274 regnum = addr & 0xff; 275 switch (regnum) { 276 case IOAPIC_ID: 277 return (vioapic->id); 278 break; --- 18 unchanged lines hidden (view full) --- 297 298 return (vioapic->rtbl[pin].reg >> rshift); 299 } 300 301 return (0); 302} 303 304static void |
261vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data) | 305vioapic_write(struct vioapic *vioapic, int vcpuid, uint32_t addr, uint32_t data) |
262{ 263 uint64_t data64, mask64; | 306{ 307 uint64_t data64, mask64; |
308 uint64_t last, changed; |
|
264 int regnum, pin, lshift; | 309 int regnum, pin, lshift; |
310 cpuset_t allvcpus; |
|
265 266 regnum = addr & 0xff; 267 switch (regnum) { 268 case IOAPIC_ID: 269 vioapic->id = data & APIC_ID_MASK; 270 break; 271 case IOAPIC_VER: 272 case IOAPIC_ARB: --- 7 unchanged lines hidden (view full) --- 280 if (regnum >= IOAPIC_REDTBL && 281 regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) { 282 pin = (regnum - IOAPIC_REDTBL) / 2; 283 if ((regnum - IOAPIC_REDTBL) % 2) 284 lshift = 32; 285 else 286 lshift = 0; 287 | 311 312 regnum = addr & 0xff; 313 switch (regnum) { 314 case IOAPIC_ID: 315 vioapic->id = data & APIC_ID_MASK; 316 break; 317 case IOAPIC_VER: 318 case IOAPIC_ARB: --- 7 unchanged lines hidden (view full) --- 326 if (regnum >= IOAPIC_REDTBL && 327 regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) { 328 pin = (regnum - IOAPIC_REDTBL) / 2; 329 if ((regnum - IOAPIC_REDTBL) % 2) 330 lshift = 32; 331 else 332 lshift = 0; 333 |
334 last = vioapic->rtbl[pin].reg; 335 |
|
288 data64 = (uint64_t)data << lshift; 289 mask64 = (uint64_t)0xffffffff << lshift; 290 vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS; 291 vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS; 292 293 VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx", 294 pin, vioapic->rtbl[pin].reg); 295 296 /* | 336 data64 = (uint64_t)data << lshift; 337 mask64 = (uint64_t)0xffffffff << lshift; 338 vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS; 339 vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS; 340 341 VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx", 342 pin, vioapic->rtbl[pin].reg); 343 344 /* |
345 * If any fields in the redirection table entry (except mask 346 * or polarity) have changed then rendezvous all the vcpus 347 * to update their vlapic trigger-mode registers. 348 */ 349 changed = last ^ vioapic->rtbl[pin].reg; 350 if (changed & ~(IOART_INTMASK | IOART_INTPOL)) { 351 VIOAPIC_CTR1(vioapic, "ioapic pin%d: recalculate " 352 "vlapic trigger-mode register", pin); 353 VIOAPIC_UNLOCK(vioapic); 354 allvcpus = vm_active_cpus(vioapic->vm); 355 vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus, 356 vioapic_update_tmr, NULL); 357 VIOAPIC_LOCK(vioapic); 358 } 359 360 /* |
|
297 * Generate an interrupt if the following conditions are met: 298 * - pin is not masked 299 * - previous interrupt has been EOIed 300 * - pin level is asserted 301 */ 302 if ((vioapic->rtbl[pin].reg & IOART_INTMASK) == IOART_INTMCLR && 303 (vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 && 304 (vioapic->rtbl[pin].acnt > 0)) { 305 VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl " 306 "write, acnt %d", pin, vioapic->rtbl[pin].acnt); 307 vioapic_send_intr(vioapic, pin); 308 } 309 } 310} 311 312static int | 361 * Generate an interrupt if the following conditions are met: 362 * - pin is not masked 363 * - previous interrupt has been EOIed 364 * - pin level is asserted 365 */ 366 if ((vioapic->rtbl[pin].reg & IOART_INTMASK) == IOART_INTMCLR && 367 (vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 && 368 (vioapic->rtbl[pin].acnt > 0)) { 369 VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl " 370 "write, acnt %d", pin, vioapic->rtbl[pin].acnt); 371 vioapic_send_intr(vioapic, pin); 372 } 373 } 374} 375 376static int |
313vioapic_mmio_rw(struct vioapic *vioapic, uint64_t gpa, uint64_t *data, 314 int size, bool doread) | 377vioapic_mmio_rw(struct vioapic *vioapic, int vcpuid, uint64_t gpa, 378 uint64_t *data, int size, bool doread) |
315{ 316 uint64_t offset; 317 318 offset = gpa - VIOAPIC_BASE; 319 320 /* 321 * The IOAPIC specification allows 32-bit wide accesses to the 322 * IOREGSEL (offset 0) and IOWIN (offset 16) registers. --- 6 unchanged lines hidden (view full) --- 329 330 VIOAPIC_LOCK(vioapic); 331 if (offset == IOREGSEL) { 332 if (doread) 333 *data = vioapic->ioregsel; 334 else 335 vioapic->ioregsel = *data; 336 } else { | 379{ 380 uint64_t offset; 381 382 offset = gpa - VIOAPIC_BASE; 383 384 /* 385 * The IOAPIC specification allows 32-bit wide accesses to the 386 * IOREGSEL (offset 0) and IOWIN (offset 16) registers. --- 6 unchanged lines hidden (view full) --- 393 394 VIOAPIC_LOCK(vioapic); 395 if (offset == IOREGSEL) { 396 if (doread) 397 *data = vioapic->ioregsel; 398 else 399 vioapic->ioregsel = *data; 400 } else { |
337 if (doread) 338 *data = vioapic_read(vioapic, vioapic->ioregsel); 339 else 340 vioapic_write(vioapic, vioapic->ioregsel, *data); | 401 if (doread) { 402 *data = vioapic_read(vioapic, vcpuid, 403 vioapic->ioregsel); 404 } else { 405 vioapic_write(vioapic, vcpuid, vioapic->ioregsel, 406 *data); 407 } |
341 } 342 VIOAPIC_UNLOCK(vioapic); 343 344 return (0); 345} 346 347int 348vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval, 349 int size, void *arg) 350{ 351 int error; 352 struct vioapic *vioapic; 353 354 vioapic = vm_ioapic(vm); | 408 } 409 VIOAPIC_UNLOCK(vioapic); 410 411 return (0); 412} 413 414int 415vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval, 416 int size, void *arg) 417{ 418 int error; 419 struct vioapic *vioapic; 420 421 vioapic = vm_ioapic(vm); |
355 error = vioapic_mmio_rw(vioapic, gpa, rval, size, true); | 422 error = vioapic_mmio_rw(vioapic, vcpuid, gpa, rval, size, true); |
356 return (error); 357} 358 359int 360vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval, 361 int size, void *arg) 362{ 363 int error; 364 struct vioapic *vioapic; 365 366 vioapic = vm_ioapic(vm); | 423 return (error); 424} 425 426int 427vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval, 428 int size, void *arg) 429{ 430 int error; 431 struct vioapic *vioapic; 432 433 vioapic = vm_ioapic(vm); |
367 error = vioapic_mmio_rw(vioapic, gpa, &wval, size, false); | 434 error = vioapic_mmio_rw(vioapic, vcpuid, gpa, &wval, size, false); |
368 return (error); 369} 370 371void 372vioapic_process_eoi(struct vm *vm, int vcpuid, int vector) 373{ 374 struct vioapic *vioapic; 375 int pin; --- 58 unchanged lines hidden --- | 435 return (error); 436} 437 438void 439vioapic_process_eoi(struct vm *vm, int vcpuid, int vector) 440{ 441 struct vioapic *vioapic; 442 int pin; --- 58 unchanged lines hidden --- |