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