1 /*- 2 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 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 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/queue.h> 33 #include <sys/cpuset.h> 34 #include <sys/kernel.h> 35 #include <sys/lock.h> 36 #include <sys/malloc.h> 37 #include <sys/mutex.h> 38 #include <sys/systm.h> 39 40 #include <x86/apicreg.h> 41 #include <dev/ic/i8259.h> 42 43 #include <machine/vmm.h> 44 45 #include "vmm_ktr.h" 46 #include "vmm_lapic.h" 47 #include "vioapic.h" 48 #include "vatpic.h" 49 50 static MALLOC_DEFINE(M_VATPIC, "atpic", "bhyve virtual atpic (8259)"); 51 52 #define VATPIC_LOCK(vatpic) mtx_lock_spin(&((vatpic)->mtx)) 53 #define VATPIC_UNLOCK(vatpic) mtx_unlock_spin(&((vatpic)->mtx)) 54 #define VATPIC_LOCKED(vatpic) mtx_owned(&((vatpic)->mtx)) 55 56 enum irqstate { 57 IRQSTATE_ASSERT, 58 IRQSTATE_DEASSERT, 59 IRQSTATE_PULSE 60 }; 61 62 struct atpic { 63 bool ready; 64 int icw_num; 65 int rd_cmd_reg; 66 67 bool aeoi; 68 bool poll; 69 bool rotate; 70 bool sfn; /* special fully-nested mode */ 71 72 int irq_base; 73 uint8_t request; /* Interrupt Request Register (IIR) */ 74 uint8_t service; /* Interrupt Service (ISR) */ 75 uint8_t mask; /* Interrupt Mask Register (IMR) */ 76 uint8_t smm; /* special mask mode */ 77 78 int acnt[8]; /* sum of pin asserts and deasserts */ 79 int lowprio; /* lowest priority irq */ 80 81 bool intr_raised; 82 }; 83 84 struct vatpic { 85 struct vm *vm; 86 struct mtx mtx; 87 struct atpic atpic[2]; 88 uint8_t elc[2]; 89 }; 90 91 #define VATPIC_CTR0(vatpic, fmt) \ 92 VM_CTR0((vatpic)->vm, fmt) 93 94 #define VATPIC_CTR1(vatpic, fmt, a1) \ 95 VM_CTR1((vatpic)->vm, fmt, a1) 96 97 #define VATPIC_CTR2(vatpic, fmt, a1, a2) \ 98 VM_CTR2((vatpic)->vm, fmt, a1, a2) 99 100 #define VATPIC_CTR3(vatpic, fmt, a1, a2, a3) \ 101 VM_CTR3((vatpic)->vm, fmt, a1, a2, a3) 102 103 #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ 104 VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) 105 106 /* 107 * Loop over all the pins in priority order from highest to lowest. 108 */ 109 #define ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar) \ 110 for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \ 111 tmpvar < 8; \ 112 tmpvar++, pinvar = (pinvar + 1) & 0x7) 113 114 static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); 115 116 static __inline bool 117 master_atpic(struct vatpic *vatpic, struct atpic *atpic) 118 { 119 120 if (atpic == &vatpic->atpic[0]) 121 return (true); 122 else 123 return (false); 124 } 125 126 static __inline int 127 vatpic_get_highest_isrpin(struct atpic *atpic) 128 { 129 int bit, pin; 130 int i; 131 132 ATPIC_PIN_FOREACH(pin, atpic, i) { 133 bit = (1 << pin); 134 135 if (atpic->service & bit) { 136 /* 137 * An IS bit that is masked by an IMR bit will not be 138 * cleared by a non-specific EOI in Special Mask Mode. 139 */ 140 if (atpic->smm && (atpic->mask & bit) != 0) 141 continue; 142 else 143 return (pin); 144 } 145 } 146 147 return (-1); 148 } 149 150 static __inline int 151 vatpic_get_highest_irrpin(struct atpic *atpic) 152 { 153 int serviced; 154 int bit, pin, tmp; 155 156 /* 157 * In 'Special Fully-Nested Mode' when an interrupt request from 158 * a slave is in service, the slave is not locked out from the 159 * master's priority logic. 160 */ 161 serviced = atpic->service; 162 if (atpic->sfn) 163 serviced &= ~(1 << 2); 164 165 /* 166 * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits 167 * further interrupts at that level and enables interrupts from all 168 * other levels that are not masked. In other words the ISR has no 169 * bearing on the levels that can generate interrupts. 170 */ 171 if (atpic->smm) 172 serviced = 0; 173 174 ATPIC_PIN_FOREACH(pin, atpic, tmp) { 175 bit = 1 << pin; 176 177 /* 178 * If there is already an interrupt in service at the same 179 * or higher priority then bail. 180 */ 181 if ((serviced & bit) != 0) 182 break; 183 184 /* 185 * If an interrupt is asserted and not masked then return 186 * the corresponding 'pin' to the caller. 187 */ 188 if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0) 189 return (pin); 190 } 191 192 return (-1); 193 } 194 195 static void 196 vatpic_notify_intr(struct vatpic *vatpic) 197 { 198 struct atpic *atpic; 199 int pin; 200 201 KASSERT(VATPIC_LOCKED(vatpic), ("vatpic_notify_intr not locked")); 202 203 /* 204 * First check the slave. 205 */ 206 atpic = &vatpic->atpic[1]; 207 if (!atpic->intr_raised && 208 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 209 VATPIC_CTR4(vatpic, "atpic slave notify pin = %d " 210 "(imr 0x%x irr 0x%x isr 0x%x)", pin, 211 atpic->mask, atpic->request, atpic->service); 212 213 /* 214 * Cascade the request from the slave to the master. 215 */ 216 atpic->intr_raised = true; 217 vatpic_set_pinstate(vatpic, 2, true); 218 vatpic_set_pinstate(vatpic, 2, false); 219 } else { 220 VATPIC_CTR3(vatpic, "atpic slave no eligible interrupts " 221 "(imr 0x%x irr 0x%x isr 0x%x)", 222 atpic->mask, atpic->request, atpic->service); 223 } 224 225 /* 226 * Then check the master. 227 */ 228 atpic = &vatpic->atpic[0]; 229 if (!atpic->intr_raised && 230 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 231 VATPIC_CTR4(vatpic, "atpic master notify pin = %d " 232 "(imr 0x%x irr 0x%x isr 0x%x)", pin, 233 atpic->mask, atpic->request, atpic->service); 234 235 /* 236 * From Section 3.6.2, "Interrupt Modes", in the 237 * MPtable Specification, Version 1.4 238 * 239 * PIC interrupts are routed to both the Local APIC 240 * and the I/O APIC to support operation in 1 of 3 241 * modes. 242 * 243 * 1. Legacy PIC Mode: the PIC effectively bypasses 244 * all APIC components. In this mode the local APIC is 245 * disabled and LINT0 is reconfigured as INTR to 246 * deliver the PIC interrupt directly to the CPU. 247 * 248 * 2. Virtual Wire Mode: the APIC is treated as a 249 * virtual wire which delivers interrupts from the PIC 250 * to the CPU. In this mode LINT0 is programmed as 251 * ExtINT to indicate that the PIC is the source of 252 * the interrupt. 253 * 254 * 3. Virtual Wire Mode via I/O APIC: PIC interrupts are 255 * fielded by the I/O APIC and delivered to the appropriate 256 * CPU. In this mode the I/O APIC input 0 is programmed 257 * as ExtINT to indicate that the PIC is the source of the 258 * interrupt. 259 */ 260 atpic->intr_raised = true; 261 lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); 262 vioapic_pulse_irq(vatpic->vm, 0); 263 } else { 264 VATPIC_CTR3(vatpic, "atpic master no eligible interrupts " 265 "(imr 0x%x irr 0x%x isr 0x%x)", 266 atpic->mask, atpic->request, atpic->service); 267 } 268 } 269 270 static int 271 vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 272 { 273 VATPIC_CTR1(vatpic, "atpic icw1 0x%x", val); 274 275 atpic->ready = false; 276 277 atpic->icw_num = 1; 278 atpic->request = 0; 279 atpic->mask = 0; 280 atpic->lowprio = 7; 281 atpic->rd_cmd_reg = 0; 282 atpic->poll = 0; 283 atpic->smm = 0; 284 285 if ((val & ICW1_SNGL) != 0) { 286 VATPIC_CTR0(vatpic, "vatpic cascade mode required"); 287 return (-1); 288 } 289 290 if ((val & ICW1_IC4) == 0) { 291 VATPIC_CTR0(vatpic, "vatpic icw4 required"); 292 return (-1); 293 } 294 295 atpic->icw_num++; 296 297 return (0); 298 } 299 300 static int 301 vatpic_icw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 302 { 303 VATPIC_CTR1(vatpic, "atpic icw2 0x%x", val); 304 305 atpic->irq_base = val & 0xf8; 306 307 atpic->icw_num++; 308 309 return (0); 310 } 311 312 static int 313 vatpic_icw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 314 { 315 VATPIC_CTR1(vatpic, "atpic icw3 0x%x", val); 316 317 atpic->icw_num++; 318 319 return (0); 320 } 321 322 static int 323 vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 324 { 325 VATPIC_CTR1(vatpic, "atpic icw4 0x%x", val); 326 327 if ((val & ICW4_8086) == 0) { 328 VATPIC_CTR0(vatpic, "vatpic microprocessor mode required"); 329 return (-1); 330 } 331 332 if ((val & ICW4_AEOI) != 0) 333 atpic->aeoi = true; 334 335 if ((val & ICW4_SFNM) != 0) { 336 if (master_atpic(vatpic, atpic)) { 337 atpic->sfn = true; 338 } else { 339 VATPIC_CTR1(vatpic, "Ignoring special fully nested " 340 "mode on slave atpic: %#x", val); 341 } 342 } 343 344 atpic->icw_num = 0; 345 atpic->ready = true; 346 347 return (0); 348 } 349 350 static int 351 vatpic_ocw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 352 { 353 VATPIC_CTR1(vatpic, "atpic ocw1 0x%x", val); 354 355 atpic->mask = val & 0xff; 356 357 return (0); 358 } 359 360 static int 361 vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 362 { 363 VATPIC_CTR1(vatpic, "atpic ocw2 0x%x", val); 364 365 atpic->rotate = ((val & OCW2_R) != 0); 366 367 if ((val & OCW2_EOI) != 0) { 368 int isr_bit; 369 370 if ((val & OCW2_SL) != 0) { 371 /* specific EOI */ 372 isr_bit = val & 0x7; 373 } else { 374 /* non-specific EOI */ 375 isr_bit = vatpic_get_highest_isrpin(atpic); 376 } 377 378 if (isr_bit != -1) { 379 atpic->service &= ~(1 << isr_bit); 380 381 if (atpic->rotate) 382 atpic->lowprio = isr_bit; 383 } 384 } else if ((val & OCW2_SL) != 0 && atpic->rotate == true) { 385 /* specific priority */ 386 atpic->lowprio = val & 0x7; 387 } 388 389 return (0); 390 } 391 392 static int 393 vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 394 { 395 VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val); 396 397 if (val & OCW3_ESMM) { 398 atpic->smm = val & OCW3_SMM ? 1 : 0; 399 VATPIC_CTR2(vatpic, "%s atpic special mask mode %s", 400 master_atpic(vatpic, atpic) ? "master" : "slave", 401 atpic->smm ? "enabled" : "disabled"); 402 } 403 404 if (val & OCW3_RR) { 405 /* read register command */ 406 atpic->rd_cmd_reg = val & OCW3_RIS; 407 408 /* Polling mode */ 409 atpic->poll = ((val & OCW3_P) != 0); 410 } 411 412 return (0); 413 } 414 415 static void 416 vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate) 417 { 418 struct atpic *atpic; 419 int oldcnt, newcnt; 420 bool level; 421 422 KASSERT(pin >= 0 && pin < 16, 423 ("vatpic_set_pinstate: invalid pin number %d", pin)); 424 KASSERT(VATPIC_LOCKED(vatpic), 425 ("vatpic_set_pinstate: vatpic is not locked")); 426 427 atpic = &vatpic->atpic[pin >> 3]; 428 429 oldcnt = atpic->acnt[pin & 0x7]; 430 if (newstate) 431 atpic->acnt[pin & 0x7]++; 432 else 433 atpic->acnt[pin & 0x7]--; 434 newcnt = atpic->acnt[pin & 0x7]; 435 436 if (newcnt < 0) { 437 VATPIC_CTR2(vatpic, "atpic pin%d: bad acnt %d", pin, newcnt); 438 } 439 440 level = ((vatpic->elc[pin >> 3] & (1 << (pin & 0x7))) != 0); 441 442 if ((oldcnt == 0 && newcnt == 1) || (newcnt > 0 && level == true)) { 443 /* rising edge or level */ 444 VATPIC_CTR1(vatpic, "atpic pin%d: asserted", pin); 445 atpic->request |= (1 << (pin & 0x7)); 446 } else if (oldcnt == 1 && newcnt == 0) { 447 /* falling edge */ 448 VATPIC_CTR1(vatpic, "atpic pin%d: deasserted", pin); 449 if (level) 450 atpic->request &= ~(1 << (pin & 0x7)); 451 } else { 452 VATPIC_CTR3(vatpic, "atpic pin%d: %s, ignored, acnt %d", 453 pin, newstate ? "asserted" : "deasserted", newcnt); 454 } 455 456 vatpic_notify_intr(vatpic); 457 } 458 459 static int 460 vatpic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate) 461 { 462 struct vatpic *vatpic; 463 struct atpic *atpic; 464 465 if (irq < 0 || irq > 15) 466 return (EINVAL); 467 468 vatpic = vm_atpic(vm); 469 atpic = &vatpic->atpic[irq >> 3]; 470 471 if (atpic->ready == false) 472 return (0); 473 474 VATPIC_LOCK(vatpic); 475 switch (irqstate) { 476 case IRQSTATE_ASSERT: 477 vatpic_set_pinstate(vatpic, irq, true); 478 break; 479 case IRQSTATE_DEASSERT: 480 vatpic_set_pinstate(vatpic, irq, false); 481 break; 482 case IRQSTATE_PULSE: 483 vatpic_set_pinstate(vatpic, irq, true); 484 vatpic_set_pinstate(vatpic, irq, false); 485 break; 486 default: 487 panic("vatpic_set_irqstate: invalid irqstate %d", irqstate); 488 } 489 VATPIC_UNLOCK(vatpic); 490 491 return (0); 492 } 493 494 int 495 vatpic_assert_irq(struct vm *vm, int irq) 496 { 497 return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT)); 498 } 499 500 int 501 vatpic_deassert_irq(struct vm *vm, int irq) 502 { 503 return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT)); 504 } 505 506 int 507 vatpic_pulse_irq(struct vm *vm, int irq) 508 { 509 return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE)); 510 } 511 512 int 513 vatpic_set_irq_trigger(struct vm *vm, int irq, enum vm_intr_trigger trigger) 514 { 515 struct vatpic *vatpic; 516 517 if (irq < 0 || irq > 15) 518 return (EINVAL); 519 520 /* 521 * See comment in vatpic_elc_handler. These IRQs must be 522 * edge triggered. 523 */ 524 if (trigger == LEVEL_TRIGGER) { 525 switch (irq) { 526 case 0: 527 case 1: 528 case 2: 529 case 8: 530 case 13: 531 return (EINVAL); 532 } 533 } 534 535 vatpic = vm_atpic(vm); 536 537 VATPIC_LOCK(vatpic); 538 539 if (trigger == LEVEL_TRIGGER) 540 vatpic->elc[irq >> 3] |= 1 << (irq & 0x7); 541 else 542 vatpic->elc[irq >> 3] &= ~(1 << (irq & 0x7)); 543 544 VATPIC_UNLOCK(vatpic); 545 546 return (0); 547 } 548 549 void 550 vatpic_pending_intr(struct vm *vm, int *vecptr) 551 { 552 struct vatpic *vatpic; 553 struct atpic *atpic; 554 int pin; 555 556 vatpic = vm_atpic(vm); 557 558 atpic = &vatpic->atpic[0]; 559 560 VATPIC_LOCK(vatpic); 561 562 pin = vatpic_get_highest_irrpin(atpic); 563 if (pin == 2) { 564 atpic = &vatpic->atpic[1]; 565 pin = vatpic_get_highest_irrpin(atpic); 566 } 567 568 /* 569 * If there are no pins active at this moment then return the spurious 570 * interrupt vector instead. 571 */ 572 if (pin == -1) 573 pin = 7; 574 575 KASSERT(pin >= 0 && pin <= 7, ("%s: invalid pin %d", __func__, pin)); 576 *vecptr = atpic->irq_base + pin; 577 578 VATPIC_UNLOCK(vatpic); 579 } 580 581 static void 582 vatpic_pin_accepted(struct atpic *atpic, int pin) 583 { 584 atpic->intr_raised = false; 585 586 if (atpic->acnt[pin] == 0) 587 atpic->request &= ~(1 << pin); 588 589 if (atpic->aeoi == true) { 590 if (atpic->rotate == true) 591 atpic->lowprio = pin; 592 } else { 593 atpic->service |= (1 << pin); 594 } 595 } 596 597 void 598 vatpic_intr_accepted(struct vm *vm, int vector) 599 { 600 struct vatpic *vatpic; 601 int pin; 602 603 vatpic = vm_atpic(vm); 604 605 VATPIC_LOCK(vatpic); 606 607 pin = vector & 0x7; 608 609 if ((vector & ~0x7) == vatpic->atpic[1].irq_base) { 610 vatpic_pin_accepted(&vatpic->atpic[1], pin); 611 /* 612 * If this vector originated from the slave, 613 * accept the cascaded interrupt too. 614 */ 615 vatpic_pin_accepted(&vatpic->atpic[0], 2); 616 } else { 617 vatpic_pin_accepted(&vatpic->atpic[0], pin); 618 } 619 620 vatpic_notify_intr(vatpic); 621 622 VATPIC_UNLOCK(vatpic); 623 } 624 625 static int 626 vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 627 int bytes, uint32_t *eax) 628 { 629 int pin; 630 631 VATPIC_LOCK(vatpic); 632 633 if (atpic->poll) { 634 atpic->poll = 0; 635 pin = vatpic_get_highest_irrpin(atpic); 636 if (pin >= 0) { 637 vatpic_pin_accepted(atpic, pin); 638 *eax = 0x80 | pin; 639 } else { 640 *eax = 0; 641 } 642 } else { 643 if (port & ICU_IMR_OFFSET) { 644 /* read interrrupt mask register */ 645 *eax = atpic->mask; 646 } else { 647 if (atpic->rd_cmd_reg == OCW3_RIS) { 648 /* read interrupt service register */ 649 *eax = atpic->service; 650 } else { 651 /* read interrupt request register */ 652 *eax = atpic->request; 653 } 654 } 655 } 656 657 VATPIC_UNLOCK(vatpic); 658 659 return (0); 660 661 } 662 663 static int 664 vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 665 int bytes, uint32_t *eax) 666 { 667 int error; 668 uint8_t val; 669 670 error = 0; 671 val = *eax; 672 673 VATPIC_LOCK(vatpic); 674 675 if (port & ICU_IMR_OFFSET) { 676 switch (atpic->icw_num) { 677 case 2: 678 error = vatpic_icw2(vatpic, atpic, val); 679 break; 680 case 3: 681 error = vatpic_icw3(vatpic, atpic, val); 682 break; 683 case 4: 684 error = vatpic_icw4(vatpic, atpic, val); 685 break; 686 default: 687 error = vatpic_ocw1(vatpic, atpic, val); 688 break; 689 } 690 } else { 691 if (val & (1 << 4)) 692 error = vatpic_icw1(vatpic, atpic, val); 693 694 if (atpic->ready) { 695 if (val & (1 << 3)) 696 error = vatpic_ocw3(vatpic, atpic, val); 697 else 698 error = vatpic_ocw2(vatpic, atpic, val); 699 } 700 } 701 702 if (atpic->ready) 703 vatpic_notify_intr(vatpic); 704 705 VATPIC_UNLOCK(vatpic); 706 707 return (error); 708 } 709 710 int 711 vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, 712 uint32_t *eax) 713 { 714 struct vatpic *vatpic; 715 struct atpic *atpic; 716 717 vatpic = vm_atpic(vm); 718 atpic = &vatpic->atpic[0]; 719 720 if (bytes != 1) 721 return (-1); 722 723 if (in) { 724 return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); 725 } 726 727 return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); 728 } 729 730 int 731 vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, 732 uint32_t *eax) 733 { 734 struct vatpic *vatpic; 735 struct atpic *atpic; 736 737 vatpic = vm_atpic(vm); 738 atpic = &vatpic->atpic[1]; 739 740 if (bytes != 1) 741 return (-1); 742 743 if (in) { 744 return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); 745 } 746 747 return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); 748 } 749 750 int 751 vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, 752 uint32_t *eax) 753 { 754 struct vatpic *vatpic; 755 bool is_master; 756 757 vatpic = vm_atpic(vm); 758 is_master = (port == IO_ELCR1); 759 760 if (bytes != 1) 761 return (-1); 762 763 VATPIC_LOCK(vatpic); 764 765 if (in) { 766 if (is_master) 767 *eax = vatpic->elc[0]; 768 else 769 *eax = vatpic->elc[1]; 770 } else { 771 /* 772 * For the master PIC the cascade channel (IRQ2), the 773 * heart beat timer (IRQ0), and the keyboard 774 * controller (IRQ1) cannot be programmed for level 775 * mode. 776 * 777 * For the slave PIC the real time clock (IRQ8) and 778 * the floating point error interrupt (IRQ13) cannot 779 * be programmed for level mode. 780 */ 781 if (is_master) 782 vatpic->elc[0] = (*eax & 0xf8); 783 else 784 vatpic->elc[1] = (*eax & 0xde); 785 } 786 787 VATPIC_UNLOCK(vatpic); 788 789 return (0); 790 } 791 792 struct vatpic * 793 vatpic_init(struct vm *vm) 794 { 795 struct vatpic *vatpic; 796 797 vatpic = malloc(sizeof(struct vatpic), M_VATPIC, M_WAITOK | M_ZERO); 798 vatpic->vm = vm; 799 800 mtx_init(&vatpic->mtx, "vatpic lock", NULL, MTX_SPIN); 801 802 return (vatpic); 803 } 804 805 void 806 vatpic_cleanup(struct vatpic *vatpic) 807 { 808 free(vatpic, M_VATPIC); 809 } 810