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