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