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