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