xref: /freebsd/sys/amd64/vmm/io/vatpic.c (revision 0957b409)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/queue.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/systm.h>
40 
41 #include <x86/apicreg.h>
42 #include <dev/ic/i8259.h>
43 
44 #include <machine/vmm.h>
45 
46 #include "vmm_ktr.h"
47 #include "vmm_lapic.h"
48 #include "vioapic.h"
49 #include "vatpic.h"
50 
51 static MALLOC_DEFINE(M_VATPIC, "atpic", "bhyve virtual atpic (8259)");
52 
53 #define	VATPIC_LOCK(vatpic)		mtx_lock_spin(&((vatpic)->mtx))
54 #define	VATPIC_UNLOCK(vatpic)		mtx_unlock_spin(&((vatpic)->mtx))
55 #define	VATPIC_LOCKED(vatpic)		mtx_owned(&((vatpic)->mtx))
56 
57 enum irqstate {
58 	IRQSTATE_ASSERT,
59 	IRQSTATE_DEASSERT,
60 	IRQSTATE_PULSE
61 };
62 
63 struct atpic {
64 	bool		ready;
65 	int		icw_num;
66 	int		rd_cmd_reg;
67 
68 	bool		aeoi;
69 	bool		poll;
70 	bool		rotate;
71 	bool		sfn;		/* special fully-nested mode */
72 
73 	int		irq_base;
74 	uint8_t		request;	/* Interrupt Request Register (IIR) */
75 	uint8_t		service;	/* Interrupt Service (ISR) */
76 	uint8_t		mask;		/* Interrupt Mask Register (IMR) */
77 	uint8_t		smm;		/* special mask mode */
78 
79 	int		acnt[8];	/* sum of pin asserts and deasserts */
80 	int		lowprio;	/* lowest priority irq */
81 
82 	bool		intr_raised;
83 };
84 
85 struct vatpic {
86 	struct vm	*vm;
87 	struct mtx	mtx;
88 	struct atpic	atpic[2];
89 	uint8_t		elc[2];
90 };
91 
92 #define	VATPIC_CTR0(vatpic, fmt)					\
93 	VM_CTR0((vatpic)->vm, fmt)
94 
95 #define	VATPIC_CTR1(vatpic, fmt, a1)					\
96 	VM_CTR1((vatpic)->vm, fmt, a1)
97 
98 #define	VATPIC_CTR2(vatpic, fmt, a1, a2)				\
99 	VM_CTR2((vatpic)->vm, fmt, a1, a2)
100 
101 #define	VATPIC_CTR3(vatpic, fmt, a1, a2, a3)				\
102 	VM_CTR3((vatpic)->vm, fmt, a1, a2, a3)
103 
104 #define	VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4)			\
105 	VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4)
106 
107 /*
108  * Loop over all the pins in priority order from highest to lowest.
109  */
110 #define	ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar)			\
111 	for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7;		\
112 	    tmpvar < 8;							\
113 	    tmpvar++, pinvar = (pinvar + 1) & 0x7)
114 
115 static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate);
116 
117 static __inline bool
118 master_atpic(struct vatpic *vatpic, struct atpic *atpic)
119 {
120 
121 	if (atpic == &vatpic->atpic[0])
122 		return (true);
123 	else
124 		return (false);
125 }
126 
127 static __inline int
128 vatpic_get_highest_isrpin(struct atpic *atpic)
129 {
130 	int bit, pin;
131 	int i;
132 
133 	ATPIC_PIN_FOREACH(pin, atpic, i) {
134                 bit = (1 << pin);
135 
136 		if (atpic->service & bit) {
137 			/*
138 			 * An IS bit that is masked by an IMR bit will not be
139 			 * cleared by a non-specific EOI in Special Mask Mode.
140 			 */
141 			if (atpic->smm && (atpic->mask & bit) != 0)
142 				continue;
143 			else
144 				return (pin);
145 		}
146 	}
147 
148 	return (-1);
149 }
150 
151 static __inline int
152 vatpic_get_highest_irrpin(struct atpic *atpic)
153 {
154 	int serviced;
155 	int bit, pin, tmp;
156 
157 	/*
158 	 * In 'Special Fully-Nested Mode' when an interrupt request from
159 	 * a slave is in service, the slave is not locked out from the
160 	 * master's priority logic.
161 	 */
162 	serviced = atpic->service;
163 	if (atpic->sfn)
164 		serviced &= ~(1 << 2);
165 
166 	/*
167 	 * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits
168 	 * further interrupts at that level and enables interrupts from all
169 	 * other levels that are not masked. In other words the ISR has no
170 	 * bearing on the levels that can generate interrupts.
171 	 */
172 	if (atpic->smm)
173 		serviced = 0;
174 
175 	ATPIC_PIN_FOREACH(pin, atpic, tmp) {
176 		bit = 1 << pin;
177 
178 		/*
179 		 * If there is already an interrupt in service at the same
180 		 * or higher priority then bail.
181 		 */
182 		if ((serviced & bit) != 0)
183 			break;
184 
185 		/*
186 		 * If an interrupt is asserted and not masked then return
187 		 * the corresponding 'pin' to the caller.
188 		 */
189 		if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0)
190 			return (pin);
191 	}
192 
193 	return (-1);
194 }
195 
196 static void
197 vatpic_notify_intr(struct vatpic *vatpic)
198 {
199 	struct atpic *atpic;
200 	int pin;
201 
202 	KASSERT(VATPIC_LOCKED(vatpic), ("vatpic_notify_intr not locked"));
203 
204 	/*
205 	 * First check the slave.
206 	 */
207 	atpic = &vatpic->atpic[1];
208 	if (!atpic->intr_raised &&
209 	    (pin = vatpic_get_highest_irrpin(atpic)) != -1) {
210 		VATPIC_CTR4(vatpic, "atpic slave notify pin = %d "
211 		    "(imr 0x%x irr 0x%x isr 0x%x)", pin,
212 		    atpic->mask, atpic->request, atpic->service);
213 
214 		/*
215 		 * Cascade the request from the slave to the master.
216 		 */
217 		atpic->intr_raised = true;
218 		vatpic_set_pinstate(vatpic, 2, true);
219 		vatpic_set_pinstate(vatpic, 2, false);
220 	} else {
221 		VATPIC_CTR3(vatpic, "atpic slave no eligible interrupts "
222 		    "(imr 0x%x irr 0x%x isr 0x%x)",
223 		    atpic->mask, atpic->request, atpic->service);
224 	}
225 
226 	/*
227 	 * Then check the master.
228 	 */
229 	atpic = &vatpic->atpic[0];
230 	if (!atpic->intr_raised &&
231 	    (pin = vatpic_get_highest_irrpin(atpic)) != -1) {
232 		VATPIC_CTR4(vatpic, "atpic master notify pin = %d "
233 		    "(imr 0x%x irr 0x%x isr 0x%x)", pin,
234 		    atpic->mask, atpic->request, atpic->service);
235 
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 		lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0);
263 		vioapic_pulse_irq(vatpic->vm, 0);
264 	} else {
265 		VATPIC_CTR3(vatpic, "atpic master no eligible interrupts "
266 		    "(imr 0x%x irr 0x%x isr 0x%x)",
267 		    atpic->mask, atpic->request, atpic->service);
268 	}
269 }
270 
271 static int
272 vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
273 {
274 	VATPIC_CTR1(vatpic, "atpic icw1 0x%x", val);
275 
276 	atpic->ready = false;
277 
278 	atpic->icw_num = 1;
279 	atpic->request = 0;
280 	atpic->mask = 0;
281 	atpic->lowprio = 7;
282 	atpic->rd_cmd_reg = 0;
283 	atpic->poll = 0;
284 	atpic->smm = 0;
285 
286 	if ((val & ICW1_SNGL) != 0) {
287 		VATPIC_CTR0(vatpic, "vatpic cascade mode required");
288 		return (-1);
289 	}
290 
291 	if ((val & ICW1_IC4) == 0) {
292 		VATPIC_CTR0(vatpic, "vatpic icw4 required");
293 		return (-1);
294 	}
295 
296 	atpic->icw_num++;
297 
298 	return (0);
299 }
300 
301 static int
302 vatpic_icw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
303 {
304 	VATPIC_CTR1(vatpic, "atpic icw2 0x%x", val);
305 
306 	atpic->irq_base = val & 0xf8;
307 
308 	atpic->icw_num++;
309 
310 	return (0);
311 }
312 
313 static int
314 vatpic_icw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
315 {
316 	VATPIC_CTR1(vatpic, "atpic icw3 0x%x", val);
317 
318 	atpic->icw_num++;
319 
320 	return (0);
321 }
322 
323 static int
324 vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
325 {
326 	VATPIC_CTR1(vatpic, "atpic icw4 0x%x", val);
327 
328 	if ((val & ICW4_8086) == 0) {
329 		VATPIC_CTR0(vatpic, "vatpic microprocessor mode required");
330 		return (-1);
331 	}
332 
333 	if ((val & ICW4_AEOI) != 0)
334 		atpic->aeoi = true;
335 
336 	if ((val & ICW4_SFNM) != 0) {
337 		if (master_atpic(vatpic, atpic)) {
338 			atpic->sfn = true;
339 		} else {
340 			VATPIC_CTR1(vatpic, "Ignoring special fully nested "
341 			    "mode on slave atpic: %#x", val);
342 		}
343 	}
344 
345 	atpic->icw_num = 0;
346 	atpic->ready = true;
347 
348 	return (0);
349 }
350 
351 static int
352 vatpic_ocw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
353 {
354 	VATPIC_CTR1(vatpic, "atpic ocw1 0x%x", val);
355 
356 	atpic->mask = val & 0xff;
357 
358 	return (0);
359 }
360 
361 static int
362 vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
363 {
364 	VATPIC_CTR1(vatpic, "atpic ocw2 0x%x", val);
365 
366 	atpic->rotate = ((val & OCW2_R) != 0);
367 
368 	if ((val & OCW2_EOI) != 0) {
369 		int isr_bit;
370 
371 		if ((val & OCW2_SL) != 0) {
372 			/* specific EOI */
373 			isr_bit = val & 0x7;
374 		} else {
375 			/* non-specific EOI */
376 			isr_bit = vatpic_get_highest_isrpin(atpic);
377 		}
378 
379 		if (isr_bit != -1) {
380 			atpic->service &= ~(1 << isr_bit);
381 
382 			if (atpic->rotate)
383 				atpic->lowprio = isr_bit;
384 		}
385 	} else if ((val & OCW2_SL) != 0 && atpic->rotate == true) {
386 		/* specific priority */
387 		atpic->lowprio = val & 0x7;
388 	}
389 
390 	return (0);
391 }
392 
393 static int
394 vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
395 {
396 	VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val);
397 
398 	if (val & OCW3_ESMM) {
399 		atpic->smm = val & OCW3_SMM ? 1 : 0;
400 		VATPIC_CTR2(vatpic, "%s atpic special mask mode %s",
401 		    master_atpic(vatpic, atpic) ? "master" : "slave",
402 		    atpic->smm ?  "enabled" : "disabled");
403 	}
404 
405 	if (val & OCW3_RR) {
406 		/* read register command */
407 		atpic->rd_cmd_reg = val & OCW3_RIS;
408 
409 		/* Polling mode */
410 		atpic->poll = ((val & OCW3_P) != 0);
411 	}
412 
413 	return (0);
414 }
415 
416 static void
417 vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate)
418 {
419 	struct atpic *atpic;
420 	int oldcnt, newcnt;
421 	bool level;
422 
423 	KASSERT(pin >= 0 && pin < 16,
424 	    ("vatpic_set_pinstate: invalid pin number %d", pin));
425 	KASSERT(VATPIC_LOCKED(vatpic),
426 	    ("vatpic_set_pinstate: vatpic is not locked"));
427 
428 	atpic = &vatpic->atpic[pin >> 3];
429 
430 	oldcnt = atpic->acnt[pin & 0x7];
431 	if (newstate)
432 		atpic->acnt[pin & 0x7]++;
433 	else
434 		atpic->acnt[pin & 0x7]--;
435 	newcnt = atpic->acnt[pin & 0x7];
436 
437 	if (newcnt < 0) {
438 		VATPIC_CTR2(vatpic, "atpic pin%d: bad acnt %d", pin, newcnt);
439 	}
440 
441 	level = ((vatpic->elc[pin >> 3] & (1 << (pin & 0x7))) != 0);
442 
443 	if ((oldcnt == 0 && newcnt == 1) || (newcnt > 0 && level == true)) {
444 		/* rising edge or level */
445 		VATPIC_CTR1(vatpic, "atpic pin%d: asserted", pin);
446 		atpic->request |= (1 << (pin & 0x7));
447 	} else if (oldcnt == 1 && newcnt == 0) {
448 		/* falling edge */
449 		VATPIC_CTR1(vatpic, "atpic pin%d: deasserted", pin);
450 		if (level)
451 			atpic->request &= ~(1 << (pin & 0x7));
452 	} else {
453 		VATPIC_CTR3(vatpic, "atpic pin%d: %s, ignored, acnt %d",
454 		    pin, newstate ? "asserted" : "deasserted", newcnt);
455 	}
456 
457 	vatpic_notify_intr(vatpic);
458 }
459 
460 static int
461 vatpic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate)
462 {
463 	struct vatpic *vatpic;
464 	struct atpic *atpic;
465 
466 	if (irq < 0 || irq > 15)
467 		return (EINVAL);
468 
469 	vatpic = vm_atpic(vm);
470 	atpic = &vatpic->atpic[irq >> 3];
471 
472 	if (atpic->ready == false)
473 		return (0);
474 
475 	VATPIC_LOCK(vatpic);
476 	switch (irqstate) {
477 	case IRQSTATE_ASSERT:
478 		vatpic_set_pinstate(vatpic, irq, true);
479 		break;
480 	case IRQSTATE_DEASSERT:
481 		vatpic_set_pinstate(vatpic, irq, false);
482 		break;
483 	case IRQSTATE_PULSE:
484 		vatpic_set_pinstate(vatpic, irq, true);
485 		vatpic_set_pinstate(vatpic, irq, false);
486 		break;
487 	default:
488 		panic("vatpic_set_irqstate: invalid irqstate %d", irqstate);
489 	}
490 	VATPIC_UNLOCK(vatpic);
491 
492 	return (0);
493 }
494 
495 int
496 vatpic_assert_irq(struct vm *vm, int irq)
497 {
498 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT));
499 }
500 
501 int
502 vatpic_deassert_irq(struct vm *vm, int irq)
503 {
504 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT));
505 }
506 
507 int
508 vatpic_pulse_irq(struct vm *vm, int irq)
509 {
510 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE));
511 }
512 
513 int
514 vatpic_set_irq_trigger(struct vm *vm, int irq, enum vm_intr_trigger trigger)
515 {
516 	struct vatpic *vatpic;
517 
518 	if (irq < 0 || irq > 15)
519 		return (EINVAL);
520 
521 	/*
522 	 * See comment in vatpic_elc_handler.  These IRQs must be
523 	 * edge triggered.
524 	 */
525 	if (trigger == LEVEL_TRIGGER) {
526 		switch (irq) {
527 		case 0:
528 		case 1:
529 		case 2:
530 		case 8:
531 		case 13:
532 			return (EINVAL);
533 		}
534 	}
535 
536 	vatpic = vm_atpic(vm);
537 
538 	VATPIC_LOCK(vatpic);
539 
540 	if (trigger == LEVEL_TRIGGER)
541 		vatpic->elc[irq >> 3] |=  1 << (irq & 0x7);
542 	else
543 		vatpic->elc[irq >> 3] &=  ~(1 << (irq & 0x7));
544 
545 	VATPIC_UNLOCK(vatpic);
546 
547 	return (0);
548 }
549 
550 void
551 vatpic_pending_intr(struct vm *vm, int *vecptr)
552 {
553 	struct vatpic *vatpic;
554 	struct atpic *atpic;
555 	int pin;
556 
557 	vatpic = vm_atpic(vm);
558 
559 	atpic = &vatpic->atpic[0];
560 
561 	VATPIC_LOCK(vatpic);
562 
563 	pin = vatpic_get_highest_irrpin(atpic);
564 	if (pin == 2) {
565 		atpic = &vatpic->atpic[1];
566 		pin = vatpic_get_highest_irrpin(atpic);
567 	}
568 
569 	/*
570 	 * If there are no pins active at this moment then return the spurious
571 	 * interrupt vector instead.
572 	 */
573 	if (pin == -1)
574 		pin = 7;
575 
576 	KASSERT(pin >= 0 && pin <= 7, ("%s: invalid pin %d", __func__, pin));
577 	*vecptr = atpic->irq_base + pin;
578 
579 	VATPIC_UNLOCK(vatpic);
580 }
581 
582 static void
583 vatpic_pin_accepted(struct atpic *atpic, int pin)
584 {
585 	atpic->intr_raised = false;
586 
587 	if (atpic->acnt[pin] == 0)
588 		atpic->request &= ~(1 << pin);
589 
590 	if (atpic->aeoi == true) {
591 		if (atpic->rotate == true)
592 			atpic->lowprio = pin;
593 	} else {
594 		atpic->service |= (1 << pin);
595 	}
596 }
597 
598 void
599 vatpic_intr_accepted(struct vm *vm, int vector)
600 {
601 	struct vatpic *vatpic;
602 	int pin;
603 
604 	vatpic = vm_atpic(vm);
605 
606 	VATPIC_LOCK(vatpic);
607 
608 	pin = vector & 0x7;
609 
610 	if ((vector & ~0x7) == vatpic->atpic[1].irq_base) {
611 		vatpic_pin_accepted(&vatpic->atpic[1], pin);
612 		/*
613 		 * If this vector originated from the slave,
614 		 * accept the cascaded interrupt too.
615 		 */
616 		vatpic_pin_accepted(&vatpic->atpic[0], 2);
617 	} else {
618 		vatpic_pin_accepted(&vatpic->atpic[0], pin);
619 	}
620 
621 	vatpic_notify_intr(vatpic);
622 
623 	VATPIC_UNLOCK(vatpic);
624 }
625 
626 static int
627 vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
628 	    int bytes, uint32_t *eax)
629 {
630 	int pin;
631 
632 	VATPIC_LOCK(vatpic);
633 
634 	if (atpic->poll) {
635 		atpic->poll = 0;
636 		pin = vatpic_get_highest_irrpin(atpic);
637 		if (pin >= 0) {
638 			vatpic_pin_accepted(atpic, pin);
639 			*eax = 0x80 | pin;
640 		} else {
641 			*eax = 0;
642 		}
643 	} else {
644 		if (port & ICU_IMR_OFFSET) {
645 			/* read interrrupt mask register */
646 			*eax = atpic->mask;
647 		} else {
648 			if (atpic->rd_cmd_reg == OCW3_RIS) {
649 				/* read interrupt service register */
650 				*eax = atpic->service;
651 			} else {
652 				/* read interrupt request register */
653 				*eax = atpic->request;
654 			}
655 		}
656 	}
657 
658 	VATPIC_UNLOCK(vatpic);
659 
660 	return (0);
661 
662 }
663 
664 static int
665 vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
666     int bytes, uint32_t *eax)
667 {
668 	int error;
669 	uint8_t val;
670 
671 	error = 0;
672 	val = *eax;
673 
674 	VATPIC_LOCK(vatpic);
675 
676 	if (port & ICU_IMR_OFFSET) {
677 		switch (atpic->icw_num) {
678 		case 2:
679 			error = vatpic_icw2(vatpic, atpic, val);
680 			break;
681 		case 3:
682 			error = vatpic_icw3(vatpic, atpic, val);
683 			break;
684 		case 4:
685 			error = vatpic_icw4(vatpic, atpic, val);
686 			break;
687 		default:
688 			error = vatpic_ocw1(vatpic, atpic, val);
689 			break;
690 		}
691 	} else {
692 		if (val & (1 << 4))
693 			error = vatpic_icw1(vatpic, atpic, val);
694 
695 		if (atpic->ready) {
696 			if (val & (1 << 3))
697 				error = vatpic_ocw3(vatpic, atpic, val);
698 			else
699 				error = vatpic_ocw2(vatpic, atpic, val);
700 		}
701 	}
702 
703 	if (atpic->ready)
704 		vatpic_notify_intr(vatpic);
705 
706 	VATPIC_UNLOCK(vatpic);
707 
708 	return (error);
709 }
710 
711 int
712 vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
713     uint32_t *eax)
714 {
715 	struct vatpic *vatpic;
716 	struct atpic *atpic;
717 
718 	vatpic = vm_atpic(vm);
719 	atpic = &vatpic->atpic[0];
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 int
732 vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
733     uint32_t *eax)
734 {
735 	struct vatpic *vatpic;
736 	struct atpic *atpic;
737 
738 	vatpic = vm_atpic(vm);
739 	atpic = &vatpic->atpic[1];
740 
741 	if (bytes != 1)
742 		return (-1);
743 
744 	if (in) {
745 		return (vatpic_read(vatpic, atpic, in, port, bytes, eax));
746 	}
747 
748 	return (vatpic_write(vatpic, atpic, in, port, bytes, eax));
749 }
750 
751 int
752 vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
753     uint32_t *eax)
754 {
755 	struct vatpic *vatpic;
756 	bool is_master;
757 
758 	vatpic = vm_atpic(vm);
759 	is_master = (port == IO_ELCR1);
760 
761 	if (bytes != 1)
762 		return (-1);
763 
764 	VATPIC_LOCK(vatpic);
765 
766 	if (in) {
767 		if (is_master)
768 			*eax = vatpic->elc[0];
769 		else
770 			*eax = vatpic->elc[1];
771 	} else {
772 		/*
773 		 * For the master PIC the cascade channel (IRQ2), the
774 		 * heart beat timer (IRQ0), and the keyboard
775 		 * controller (IRQ1) cannot be programmed for level
776 		 * mode.
777 		 *
778 		 * For the slave PIC the real time clock (IRQ8) and
779 		 * the floating point error interrupt (IRQ13) cannot
780 		 * be programmed for level mode.
781 		 */
782 		if (is_master)
783 			vatpic->elc[0] = (*eax & 0xf8);
784 		else
785 			vatpic->elc[1] = (*eax & 0xde);
786 	}
787 
788 	VATPIC_UNLOCK(vatpic);
789 
790 	return (0);
791 }
792 
793 struct vatpic *
794 vatpic_init(struct vm *vm)
795 {
796 	struct vatpic *vatpic;
797 
798 	vatpic = malloc(sizeof(struct vatpic), M_VATPIC, M_WAITOK | M_ZERO);
799 	vatpic->vm = vm;
800 
801 	mtx_init(&vatpic->mtx, "vatpic lock", NULL, MTX_SPIN);
802 
803 	return (vatpic);
804 }
805 
806 void
807 vatpic_cleanup(struct vatpic *vatpic)
808 {
809 	free(vatpic, M_VATPIC);
810 }
811