xref: /illumos-gate/usr/src/uts/intel/io/vmm/io/vatpic.c (revision 32640292339b07090f10ce34d455f98711077343)
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