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 * This file and its contents are supplied under the terms of the 30 * Common Development and Distribution License ("CDDL"), version 1.0. 31 * You may only use this file in accordance with the terms of version 32 * 1.0 of the CDDL. 33 * 34 * A full copy of the text of the CDDL should have accompanied this 35 * source. A copy of the CDDL is also available via the Internet at 36 * http://www.illumos.org/license/CDDL. 37 * 38 * Copyright 2021 Oxide Computer Company 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 #include <sys/queue.h> 47 #include <sys/kernel.h> 48 #include <sys/kmem.h> 49 #include <sys/mutex.h> 50 #include <sys/systm.h> 51 52 #include <x86/apicreg.h> 53 #include <dev/ic/i8259.h> 54 55 #include <machine/vmm.h> 56 57 #include "vmm_lapic.h" 58 #include "vioapic.h" 59 #include "vatpic.h" 60 61 #define VATPIC_LOCK(vatpic) mutex_enter(&((vatpic)->lock)) 62 #define VATPIC_UNLOCK(vatpic) mutex_exit(&((vatpic)->lock)) 63 #define VATPIC_LOCKED(vatpic) MUTEX_HELD(&((vatpic)->lock)) 64 65 #define IRQ_BASE_MASK 0xf8 66 67 enum irqstate { 68 IRQSTATE_ASSERT, 69 IRQSTATE_DEASSERT, 70 IRQSTATE_PULSE 71 }; 72 73 enum icw_state { 74 IS_ICW1 = 0, 75 IS_ICW2, 76 IS_ICW3, 77 IS_ICW4, 78 }; 79 80 struct atpic { 81 enum icw_state icw_state; 82 83 bool ready; 84 bool auto_eoi; 85 bool poll; 86 bool rotate; 87 bool special_full_nested; 88 bool read_isr_next; 89 bool intr_raised; 90 bool special_mask_mode; 91 92 uint8_t reg_irr; /* Interrupt Request Register (IIR) */ 93 uint8_t reg_isr; /* Interrupt Service (ISR) */ 94 uint8_t reg_imr; /* Interrupt Mask Register (IMR) */ 95 uint8_t irq_base; /* base interrupt vector */ 96 uint8_t lowprio; /* lowest priority irq */ 97 uint8_t elc; /* level-triggered mode bits */ 98 99 uint_t acnt[8]; /* sum of pin asserts and deasserts */ 100 }; 101 102 struct atpic_stats { 103 uint64_t as_interrupts; 104 uint64_t as_saturate_low; 105 uint64_t as_saturate_high; 106 }; 107 108 struct vatpic { 109 struct vm *vm; 110 kmutex_t lock; 111 struct atpic atpic[2]; 112 struct atpic_stats stats; 113 }; 114 115 /* 116 * Loop over all the pins in priority order from highest to lowest. 117 */ 118 #define ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar) \ 119 for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \ 120 tmpvar < 8; \ 121 tmpvar++, pinvar = (pinvar + 1) & 0x7) 122 123 static int vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); 124 125 static __inline bool 126 master_atpic(struct vatpic *vatpic, struct atpic *atpic) 127 { 128 129 if (atpic == &vatpic->atpic[0]) 130 return (true); 131 else 132 return (false); 133 } 134 135 static __inline int 136 vatpic_get_highest_isrpin(struct atpic *atpic) 137 { 138 int bit, pin; 139 int i; 140 141 ATPIC_PIN_FOREACH(pin, atpic, i) { 142 bit = (1 << pin); 143 144 if (atpic->reg_isr & bit) { 145 /* 146 * An IS bit that is masked by an IMR bit will not be 147 * cleared by a non-specific EOI in Special Mask Mode. 148 */ 149 if (atpic->special_mask_mode && 150 (atpic->reg_imr & bit) != 0) { 151 continue; 152 } else { 153 return (pin); 154 } 155 } 156 } 157 158 return (-1); 159 } 160 161 static __inline int 162 vatpic_get_highest_irrpin(struct atpic *atpic) 163 { 164 int serviced; 165 int bit, pin, tmp; 166 167 /* 168 * In 'Special Fully-Nested Mode' when an interrupt request from 169 * a slave is in service, the slave is not locked out from the 170 * master's priority logic. 171 */ 172 serviced = atpic->reg_isr; 173 if (atpic->special_full_nested) 174 serviced &= ~(1 << 2); 175 176 /* 177 * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits 178 * further interrupts at that level and enables interrupts from all 179 * other levels that are not masked. In other words the ISR has no 180 * bearing on the levels that can generate interrupts. 181 */ 182 if (atpic->special_mask_mode) 183 serviced = 0; 184 185 ATPIC_PIN_FOREACH(pin, atpic, tmp) { 186 bit = 1 << pin; 187 188 /* 189 * If there is already an interrupt in service at the same 190 * or higher priority then bail. 191 */ 192 if ((serviced & bit) != 0) 193 break; 194 195 /* 196 * If an interrupt is asserted and not masked then return 197 * the corresponding 'pin' to the caller. 198 */ 199 if ((atpic->reg_irr & bit) != 0 && (atpic->reg_imr & bit) == 0) 200 return (pin); 201 } 202 203 return (-1); 204 } 205 206 static void 207 vatpic_notify_intr(struct vatpic *vatpic) 208 { 209 struct atpic *atpic; 210 int pin; 211 212 ASSERT(VATPIC_LOCKED(vatpic)); 213 214 /* 215 * First check the slave. 216 */ 217 atpic = &vatpic->atpic[1]; 218 if (!atpic->intr_raised && 219 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 220 /* 221 * Cascade the request from the slave to the master. 222 */ 223 atpic->intr_raised = true; 224 if (vatpic_set_pinstate(vatpic, 2, true) == 0) { 225 (void) vatpic_set_pinstate(vatpic, 2, false); 226 } 227 } else { 228 /* No eligible interrupts on slave chip */ 229 } 230 231 /* 232 * Then check the master. 233 */ 234 atpic = &vatpic->atpic[0]; 235 if (!atpic->intr_raised && 236 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 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 (void) lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); 264 (void) vioapic_pulse_irq(vatpic->vm, 0); 265 vatpic->stats.as_interrupts++; 266 } else { 267 /* No eligible interrupts on master chip */ 268 } 269 } 270 271 static int 272 vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 273 { 274 atpic->ready = false; 275 276 atpic->icw_state = IS_ICW1; 277 atpic->reg_irr = 0; 278 atpic->reg_imr = 0; 279 atpic->lowprio = 7; 280 atpic->read_isr_next = false; 281 atpic->poll = false; 282 atpic->special_mask_mode = false; 283 284 if ((val & ICW1_SNGL) != 0) { 285 /* Cascade mode reqired */ 286 return (-1); 287 } 288 289 if ((val & ICW1_IC4) == 0) { 290 /* ICW4 reqired */ 291 return (-1); 292 } 293 294 atpic->icw_state = IS_ICW2; 295 296 return (0); 297 } 298 299 static int 300 vatpic_icw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 301 { 302 atpic->irq_base = val & IRQ_BASE_MASK; 303 atpic->icw_state = IS_ICW3; 304 305 return (0); 306 } 307 308 static int 309 vatpic_icw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 310 { 311 atpic->icw_state = IS_ICW4; 312 313 return (0); 314 } 315 316 static int 317 vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 318 { 319 if ((val & ICW4_8086) == 0) { 320 /* Microprocessor mode required */ 321 return (-1); 322 } 323 324 atpic->auto_eoi = (val & ICW4_AEOI) != 0; 325 if (master_atpic(vatpic, atpic)) { 326 atpic->special_full_nested = (val & ICW4_SFNM) != 0; 327 } 328 329 atpic->icw_state = IS_ICW1; 330 atpic->ready = true; 331 332 return (0); 333 } 334 335 static int 336 vatpic_ocw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 337 { 338 atpic->reg_imr = val; 339 340 return (0); 341 } 342 343 static int 344 vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 345 { 346 atpic->rotate = (val & OCW2_R) != 0; 347 348 if ((val & OCW2_EOI) != 0) { 349 int isr_bit; 350 351 if ((val & OCW2_SL) != 0) { 352 /* specific EOI */ 353 isr_bit = val & 0x7; 354 } else { 355 /* non-specific EOI */ 356 isr_bit = vatpic_get_highest_isrpin(atpic); 357 } 358 359 if (isr_bit != -1) { 360 atpic->reg_isr &= ~(1 << isr_bit); 361 362 if (atpic->rotate) 363 atpic->lowprio = isr_bit; 364 } 365 } else if ((val & OCW2_SL) != 0 && atpic->rotate) { 366 /* specific priority */ 367 atpic->lowprio = val & 0x7; 368 } 369 370 return (0); 371 } 372 373 static int 374 vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 375 { 376 if ((val & OCW3_ESMM) != 0) { 377 atpic->special_mask_mode = (val & OCW3_SMM) != 0; 378 } 379 if ((val & OCW3_RR) != 0) { 380 atpic->read_isr_next = (val & OCW3_RIS) != 0; 381 } 382 if ((val & OCW3_P) != 0) { 383 atpic->poll = true; 384 } 385 386 return (0); 387 } 388 389 static int 390 vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate) 391 { 392 struct atpic *atpic; 393 uint_t oldcnt, newcnt; 394 int err = 0; 395 396 VERIFY(pin >= 0 && pin < 16); 397 ASSERT(VATPIC_LOCKED(vatpic)); 398 399 const int lpin = pin & 0x7; 400 atpic = &vatpic->atpic[pin >> 3]; 401 402 oldcnt = newcnt = atpic->acnt[lpin]; 403 if (newstate) { 404 if (newcnt != UINT_MAX) { 405 newcnt++; 406 } else { 407 err = E2BIG; 408 DTRACE_PROBE2(vatpic__sat_high, struct vatpic *, vatpic, 409 int, pin); 410 vatpic->stats.as_saturate_high++; 411 } 412 } else { 413 if (newcnt != 0) { 414 newcnt--; 415 } else { 416 err = ERANGE; 417 DTRACE_PROBE2(vatpic__sat_low, struct vatpic *, vatpic, 418 int, pin); 419 vatpic->stats.as_saturate_low++; 420 } 421 } 422 atpic->acnt[lpin] = newcnt; 423 424 const bool level = ((atpic->elc & (1 << (lpin))) != 0); 425 if ((oldcnt == 0 && newcnt == 1) || (newcnt > 0 && level == true)) { 426 /* rising edge or level */ 427 DTRACE_PROBE2(vatpic__assert, struct vatpic *, vatpic, 428 int, pin); 429 atpic->reg_irr |= (1 << lpin); 430 } else if (oldcnt == 1 && newcnt == 0) { 431 /* falling edge */ 432 DTRACE_PROBE2(vatpic__deassert, struct vatpic *, vatpic, 433 int, pin); 434 if (level) { 435 atpic->reg_irr &= ~(1 << lpin); 436 } 437 } 438 439 vatpic_notify_intr(vatpic); 440 return (err); 441 } 442 443 static int 444 vatpic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate) 445 { 446 struct vatpic *vatpic; 447 struct atpic *atpic; 448 int err = 0; 449 450 if (irq < 0 || irq > 15) 451 return (EINVAL); 452 453 vatpic = vm_atpic(vm); 454 atpic = &vatpic->atpic[irq >> 3]; 455 456 if (!atpic->ready) 457 return (0); 458 459 VATPIC_LOCK(vatpic); 460 switch (irqstate) { 461 case IRQSTATE_ASSERT: 462 err = vatpic_set_pinstate(vatpic, irq, true); 463 break; 464 case IRQSTATE_DEASSERT: 465 err = vatpic_set_pinstate(vatpic, irq, false); 466 break; 467 case IRQSTATE_PULSE: 468 err = vatpic_set_pinstate(vatpic, irq, true); 469 if (err == 0) { 470 err = vatpic_set_pinstate(vatpic, irq, false); 471 } 472 break; 473 default: 474 panic("vatpic_set_irqstate: invalid irqstate %d", irqstate); 475 } 476 VATPIC_UNLOCK(vatpic); 477 478 return (err); 479 } 480 481 int 482 vatpic_assert_irq(struct vm *vm, int irq) 483 { 484 return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT)); 485 } 486 487 int 488 vatpic_deassert_irq(struct vm *vm, int irq) 489 { 490 return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT)); 491 } 492 493 int 494 vatpic_pulse_irq(struct vm *vm, int irq) 495 { 496 return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE)); 497 } 498 499 int 500 vatpic_set_irq_trigger(struct vm *vm, int irq, enum vm_intr_trigger trigger) 501 { 502 if (irq < 0 || irq > 15) 503 return (EINVAL); 504 505 /* 506 * See comments in vatpic_elc_handler. 507 * These IRQs must be edge triggered. 508 */ 509 if (trigger == LEVEL_TRIGGER) { 510 switch (irq) { 511 case 0: 512 case 1: 513 case 2: 514 case 8: 515 case 13: 516 return (EINVAL); 517 } 518 } 519 520 struct vatpic *vatpic = vm_atpic(vm); 521 struct atpic *atpic = &vatpic->atpic[irq >> 3]; 522 const int pin = irq & 0x7; 523 524 VATPIC_LOCK(vatpic); 525 if (trigger == LEVEL_TRIGGER) { 526 atpic->elc |= (1 << pin); 527 } else { 528 atpic->elc &= ~(1 << pin); 529 } 530 VATPIC_UNLOCK(vatpic); 531 532 return (0); 533 } 534 535 void 536 vatpic_pending_intr(struct vm *vm, int *vecptr) 537 { 538 struct vatpic *vatpic; 539 struct atpic *atpic; 540 int pin; 541 542 vatpic = vm_atpic(vm); 543 544 atpic = &vatpic->atpic[0]; 545 546 VATPIC_LOCK(vatpic); 547 548 pin = vatpic_get_highest_irrpin(atpic); 549 if (pin == 2) { 550 atpic = &vatpic->atpic[1]; 551 pin = vatpic_get_highest_irrpin(atpic); 552 } 553 554 /* 555 * If there are no pins active at this moment then return the spurious 556 * interrupt vector instead. 557 */ 558 if (pin == -1) 559 pin = 7; 560 561 KASSERT(pin >= 0 && pin <= 7, ("%s: invalid pin %d", __func__, pin)); 562 *vecptr = atpic->irq_base + pin; 563 564 VATPIC_UNLOCK(vatpic); 565 } 566 567 static void 568 vatpic_pin_accepted(struct atpic *atpic, int pin) 569 { 570 ASSERT(pin >= 0 && pin < 8); 571 572 atpic->intr_raised = false; 573 574 if (atpic->acnt[pin] == 0) 575 atpic->reg_irr &= ~(1 << pin); 576 577 if (atpic->auto_eoi) { 578 if (atpic->rotate) 579 atpic->lowprio = pin; 580 } else { 581 atpic->reg_isr |= (1 << pin); 582 } 583 } 584 585 void 586 vatpic_intr_accepted(struct vm *vm, int vector) 587 { 588 struct vatpic *vatpic; 589 int pin; 590 591 vatpic = vm_atpic(vm); 592 593 VATPIC_LOCK(vatpic); 594 595 pin = vector & 0x7; 596 597 if ((vector & IRQ_BASE_MASK) == vatpic->atpic[1].irq_base) { 598 vatpic_pin_accepted(&vatpic->atpic[1], pin); 599 /* 600 * If this vector originated from the slave, 601 * accept the cascaded interrupt too. 602 */ 603 vatpic_pin_accepted(&vatpic->atpic[0], 2); 604 } else { 605 vatpic_pin_accepted(&vatpic->atpic[0], pin); 606 } 607 608 vatpic_notify_intr(vatpic); 609 610 VATPIC_UNLOCK(vatpic); 611 } 612 613 static int 614 vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 615 int bytes, uint32_t *eax) 616 { 617 int pin; 618 619 VATPIC_LOCK(vatpic); 620 621 if (atpic->poll) { 622 atpic->poll = false; 623 pin = vatpic_get_highest_irrpin(atpic); 624 if (pin >= 0) { 625 vatpic_pin_accepted(atpic, pin); 626 *eax = 0x80 | pin; 627 } else { 628 *eax = 0; 629 } 630 } else { 631 if (port & ICU_IMR_OFFSET) { 632 /* read interrrupt mask register */ 633 *eax = atpic->reg_imr; 634 } else { 635 if (atpic->read_isr_next) { 636 /* read interrupt service register */ 637 *eax = atpic->reg_isr; 638 } else { 639 /* read interrupt request register */ 640 *eax = atpic->reg_irr; 641 } 642 } 643 } 644 645 VATPIC_UNLOCK(vatpic); 646 647 return (0); 648 649 } 650 651 static int 652 vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 653 int bytes, uint32_t *eax) 654 { 655 int error; 656 uint8_t val; 657 658 error = 0; 659 val = *eax; 660 661 VATPIC_LOCK(vatpic); 662 663 if (port & ICU_IMR_OFFSET) { 664 switch (atpic->icw_state) { 665 case IS_ICW2: 666 error = vatpic_icw2(vatpic, atpic, val); 667 break; 668 case IS_ICW3: 669 error = vatpic_icw3(vatpic, atpic, val); 670 break; 671 case IS_ICW4: 672 error = vatpic_icw4(vatpic, atpic, val); 673 break; 674 default: 675 error = vatpic_ocw1(vatpic, atpic, val); 676 break; 677 } 678 } else { 679 if (val & (1 << 4)) 680 error = vatpic_icw1(vatpic, atpic, val); 681 682 if (atpic->ready) { 683 if (val & (1 << 3)) 684 error = vatpic_ocw3(vatpic, atpic, val); 685 else 686 error = vatpic_ocw2(vatpic, atpic, val); 687 } 688 } 689 690 if (atpic->ready) 691 vatpic_notify_intr(vatpic); 692 693 VATPIC_UNLOCK(vatpic); 694 695 return (error); 696 } 697 698 int 699 vatpic_master_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 700 uint32_t *eax) 701 { 702 struct vatpic *vatpic = arg; 703 struct atpic *atpic = &vatpic->atpic[0]; 704 705 if (bytes != 1) 706 return (-1); 707 708 if (in) { 709 return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); 710 } 711 712 return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); 713 } 714 715 int 716 vatpic_slave_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 717 uint32_t *eax) 718 { 719 struct vatpic *vatpic = arg; 720 struct atpic *atpic = &vatpic->atpic[1]; 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 static const uint8_t vatpic_elc_mask[2] = { 733 /* 734 * For the master PIC the cascade channel (IRQ2), the heart beat timer 735 * (IRQ0), and the keyboard controller (IRQ1) cannot be programmed for 736 * level mode. 737 */ 738 0xf8, 739 /* 740 * For the slave PIC the real time clock (IRQ8) and the floating point 741 * error interrupt (IRQ13) cannot be programmed for level mode. 742 */ 743 0xde 744 }; 745 746 int 747 vatpic_elc_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 748 uint32_t *eax) 749 { 750 struct vatpic *vatpic = arg; 751 struct atpic *atpic = NULL; 752 uint8_t elc_mask = 0; 753 754 switch (port) { 755 case IO_ELCR1: 756 atpic = &vatpic->atpic[0]; 757 elc_mask = vatpic_elc_mask[0]; 758 break; 759 case IO_ELCR2: 760 atpic = &vatpic->atpic[1]; 761 elc_mask = vatpic_elc_mask[1]; 762 break; 763 default: 764 return (-1); 765 } 766 767 if (bytes != 1) 768 return (-1); 769 770 VATPIC_LOCK(vatpic); 771 if (in) { 772 *eax = atpic->elc; 773 } else { 774 atpic->elc = *eax & elc_mask; 775 } 776 VATPIC_UNLOCK(vatpic); 777 778 return (0); 779 } 780 781 struct vatpic * 782 vatpic_init(struct vm *vm) 783 { 784 struct vatpic *vatpic; 785 786 vatpic = kmem_zalloc(sizeof (struct vatpic), KM_SLEEP); 787 vatpic->vm = vm; 788 789 mutex_init(&vatpic->lock, NULL, MUTEX_ADAPTIVE, NULL); 790 791 return (vatpic); 792 } 793 794 void 795 vatpic_cleanup(struct vatpic *vatpic) 796 { 797 mutex_destroy(&vatpic->lock); 798 kmem_free(vatpic, sizeof (*vatpic)); 799 } 800 801 static int 802 vatpic_data_read(void *datap, const vmm_data_req_t *req) 803 { 804 VERIFY3U(req->vdr_class, ==, VDC_ATPIC); 805 VERIFY3U(req->vdr_version, ==, 1); 806 VERIFY3U(req->vdr_len, >=, sizeof (struct vdi_atpic_v1)); 807 808 struct vatpic *vatpic = datap; 809 struct vdi_atpic_v1 *out = req->vdr_data; 810 811 VATPIC_LOCK(vatpic); 812 for (uint_t i = 0; i < 2; i++) { 813 const struct atpic *src = &vatpic->atpic[i]; 814 struct vdi_atpic_chip_v1 *chip = &out->va_chip[i]; 815 816 chip->vac_icw_state = src->icw_state; 817 chip->vac_status = 818 (src->ready ? (1 << 0) : 0) | 819 (src->auto_eoi ? (1 << 1) : 0) | 820 (src->poll ? (1 << 2) : 0) | 821 (src->rotate ? (1 << 3) : 0) | 822 (src->special_full_nested ? (1 << 4) : 0) | 823 (src->read_isr_next ? (1 << 5) : 0) | 824 (src->intr_raised ? (1 << 6) : 0) | 825 (src->special_mask_mode ? (1 << 7) : 0); 826 chip->vac_reg_irr = src->reg_irr; 827 chip->vac_reg_isr = src->reg_isr; 828 chip->vac_reg_imr = src->reg_imr; 829 chip->vac_irq_base = src->irq_base; 830 chip->vac_lowprio = src->lowprio; 831 chip->vac_elc = src->elc; 832 for (uint_t j = 0; j < 8; j++) { 833 chip->vac_level[j] = src->acnt[j]; 834 } 835 } 836 VATPIC_UNLOCK(vatpic); 837 838 return (0); 839 } 840 841 static bool 842 vatpic_data_validate(const struct vdi_atpic_v1 *src) 843 { 844 for (uint_t i = 0; i < 2; i++) { 845 const struct vdi_atpic_chip_v1 *chip = &src->va_chip[i]; 846 847 if (chip->vac_icw_state > IS_ICW4) { 848 return (false); 849 } 850 if ((chip->vac_elc & ~vatpic_elc_mask[i]) != 0) { 851 return (false); 852 } 853 /* 854 * TODO: The state of `intr_raised` could be checked what 855 * resides in the ISR/IRR registers. 856 */ 857 } 858 859 return (true); 860 } 861 862 static int 863 vatpic_data_write(void *datap, const vmm_data_req_t *req) 864 { 865 VERIFY3U(req->vdr_class, ==, VDC_ATPIC); 866 VERIFY3U(req->vdr_version, ==, 1); 867 VERIFY3U(req->vdr_len, >=, sizeof (struct vdi_atpic_v1)); 868 869 struct vatpic *vatpic = datap; 870 const struct vdi_atpic_v1 *src = req->vdr_data; 871 if (!vatpic_data_validate(src)) { 872 return (EINVAL); 873 } 874 875 VATPIC_LOCK(vatpic); 876 for (uint_t i = 0; i < 2; i++) { 877 const struct vdi_atpic_chip_v1 *chip = &src->va_chip[i]; 878 struct atpic *out = &vatpic->atpic[i]; 879 880 out->icw_state = chip->vac_icw_state; 881 882 out->ready = (chip->vac_status & (1 << 0)) != 0; 883 out->auto_eoi = (chip->vac_status & (1 << 1)) != 0; 884 out->poll = (chip->vac_status & (1 << 2)) != 0; 885 out->rotate = (chip->vac_status & (1 << 3)) != 0; 886 out->special_full_nested = (chip->vac_status & (1 << 4)) != 0; 887 out->read_isr_next = (chip->vac_status & (1 << 5)) != 0; 888 out->intr_raised = (chip->vac_status & (1 << 6)) != 0; 889 out->special_mask_mode = (chip->vac_status & (1 << 7)) != 0; 890 891 out->reg_irr = chip->vac_reg_irr; 892 out->reg_isr = chip->vac_reg_isr; 893 out->reg_imr = chip->vac_reg_imr; 894 out->irq_base = chip->vac_irq_base; 895 out->lowprio = chip->vac_lowprio; 896 out->elc = chip->vac_elc; 897 for (uint_t j = 0; j < 8; j++) { 898 out->acnt[j] = chip->vac_level[j]; 899 } 900 } 901 VATPIC_UNLOCK(vatpic); 902 903 return (0); 904 } 905 906 static const vmm_data_version_entry_t atpic_v1 = { 907 .vdve_class = VDC_ATPIC, 908 .vdve_version = 1, 909 .vdve_len_expect = sizeof (struct vdi_atpic_v1), 910 .vdve_readf = vatpic_data_read, 911 .vdve_writef = vatpic_data_write, 912 }; 913 VMM_DATA_VERSION(atpic_v1); 914