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