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