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