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
master_atpic(struct vatpic * vatpic,struct atpic * atpic)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
vatpic_get_highest_isrpin(struct atpic * atpic)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
vatpic_get_highest_irrpin(struct atpic * atpic)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
vatpic_notify_intr(struct vatpic * vatpic)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
vatpic_icw1(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw2(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw3(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw4(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw1(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw2(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw3(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_set_pinstate(struct vatpic * vatpic,int pin,bool newstate)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
vatpic_set_irqstate(struct vm * vm,int irq,enum irqstate irqstate)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
vatpic_assert_irq(struct vm * vm,int irq)481 vatpic_assert_irq(struct vm *vm, int irq)
482 {
483 return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT));
484 }
485
486 int
vatpic_deassert_irq(struct vm * vm,int irq)487 vatpic_deassert_irq(struct vm *vm, int irq)
488 {
489 return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT));
490 }
491
492 int
vatpic_pulse_irq(struct vm * vm,int irq)493 vatpic_pulse_irq(struct vm *vm, int irq)
494 {
495 return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE));
496 }
497
498 int
vatpic_set_irq_trigger(struct vm * vm,int irq,enum vm_intr_trigger trigger)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
vatpic_pending_intr(struct vm * vm,int * vecptr)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
vatpic_pin_accepted(struct atpic * atpic,int pin)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
vatpic_intr_accepted(struct vm * vm,int vector)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
vatpic_read(struct vatpic * vatpic,struct atpic * atpic,bool in,int port,int bytes,uint32_t * eax)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
vatpic_write(struct vatpic * vatpic,struct atpic * atpic,bool in,int port,int bytes,uint32_t * eax)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
vatpic_master_handler(void * arg,bool in,uint16_t port,uint8_t bytes,uint32_t * eax)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
vatpic_slave_handler(void * arg,bool in,uint16_t port,uint8_t bytes,uint32_t * eax)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
vatpic_elc_handler(void * arg,bool in,uint16_t port,uint8_t bytes,uint32_t * eax)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 *
vatpic_init(struct vm * vm)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
vatpic_cleanup(struct vatpic * vatpic)794 vatpic_cleanup(struct vatpic *vatpic)
795 {
796 mutex_destroy(&vatpic->lock);
797 kmem_free(vatpic, sizeof (*vatpic));
798 }
799
800 static int
vatpic_data_read(void * datap,const vmm_data_req_t * req)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
vatpic_data_validate(const struct vdi_atpic_v1 * src)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
vatpic_data_write(void * datap,const vmm_data_req_t * req)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