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