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