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