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