xref: /freebsd/sys/amd64/vmm/io/vatpic.c (revision dda5b39711dab90ae1c5624bdd6ff7453177df31)
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 
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 
76 	int		acnt[8];	/* sum of pin asserts and deasserts */
77 	int		priority;	/* current pin priority */
78 };
79 
80 struct vatpic {
81 	struct vm	*vm;
82 	struct mtx	mtx;
83 	struct atpic	atpic[2];
84 	uint8_t		elc[2];
85 };
86 
87 #define	VATPIC_CTR0(vatpic, fmt)					\
88 	VM_CTR0((vatpic)->vm, fmt)
89 
90 #define	VATPIC_CTR1(vatpic, fmt, a1)					\
91 	VM_CTR1((vatpic)->vm, fmt, a1)
92 
93 #define	VATPIC_CTR2(vatpic, fmt, a1, a2)				\
94 	VM_CTR2((vatpic)->vm, fmt, a1, a2)
95 
96 #define	VATPIC_CTR3(vatpic, fmt, a1, a2, a3)				\
97 	VM_CTR3((vatpic)->vm, fmt, a1, a2, a3)
98 
99 #define	VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4)			\
100 	VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4)
101 
102 
103 static __inline int
104 vatpic_get_highest_isrpin(struct atpic *atpic)
105 {
106 	int bit, pin;
107 	int i;
108 
109 	for (i = 0; i <= 7; i++) {
110 		pin = ((i + 7 - atpic->priority) & 0x7);
111                 bit = (1 << pin);
112 
113 		if (atpic->service & bit)
114 			return (pin);
115 	}
116 
117 	return (-1);
118 }
119 
120 static __inline int
121 vatpic_get_highest_irrpin(struct atpic *atpic)
122 {
123 	int bit, pin;
124 	int i, j;
125 
126 	for (i = 0; i <= 7; i++) {
127 		pin = ((i + 7 - atpic->priority) & 0x7);
128 		bit = (1 << pin);
129 		if (atpic->service & bit)
130 			break;
131 	}
132 
133 	for (j = 0; j < i; j++) {
134 		pin = ((j + 7 - atpic->priority) & 0x7);
135 		bit = (1 << pin);
136 		if (atpic->request & bit && (~atpic->mask & bit))
137 			return (pin);
138 	}
139 
140 	return (-1);
141 }
142 
143 static void
144 vatpic_notify_intr(struct vatpic *vatpic)
145 {
146 	struct atpic *atpic;
147 	int pin;
148 
149 	KASSERT(VATPIC_LOCKED(vatpic), ("vatpic_notify_intr not locked"));
150 
151 	/* XXX master only */
152 	atpic = &vatpic->atpic[0];
153 
154 	if ((pin = vatpic_get_highest_irrpin(atpic)) != -1) {
155 		VATPIC_CTR4(vatpic, "atpic notify pin = %d "
156 		    "(imr 0x%x irr 0x%x isr 0x%x)", pin,
157 		    atpic->mask, atpic->request, atpic->service);
158 		lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0);
159 		vioapic_pulse_irq(vatpic->vm, 0);
160 	} else {
161 		VATPIC_CTR3(vatpic, "atpic no eligible interrupts "
162 		    "(imr 0x%x irr 0x%x isr 0x%x)",
163 		    atpic->mask, atpic->request, atpic->service);
164 	}
165 }
166 
167 static int
168 vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
169 {
170 	VATPIC_CTR1(vatpic, "atpic icw1 0x%x", val);
171 
172 	atpic->ready = false;
173 
174 	atpic->icw_num = 1;
175 	atpic->mask = 0;
176 	atpic->priority = 0;
177 	atpic->rd_cmd_reg = 0;
178 
179 	if ((val & ICW1_SNGL) != 0) {
180 		VATPIC_CTR0(vatpic, "vatpic cascade mode required");
181 		return (-1);
182 	}
183 
184 	if ((val & ICW1_IC4) == 0) {
185 		VATPIC_CTR0(vatpic, "vatpic icw4 required");
186 		return (-1);
187 	}
188 
189 	atpic->icw_num++;
190 
191 	return (0);
192 }
193 
194 static int
195 vatpic_icw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
196 {
197 	VATPIC_CTR1(vatpic, "atpic icw2 0x%x", val);
198 
199 	atpic->irq_base = val & 0xf8;
200 
201 	atpic->icw_num++;
202 
203 	return (0);
204 }
205 
206 static int
207 vatpic_icw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
208 {
209 	VATPIC_CTR1(vatpic, "atpic icw3 0x%x", val);
210 
211 	atpic->icw_num++;
212 
213 	return (0);
214 }
215 
216 static int
217 vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
218 {
219 	VATPIC_CTR1(vatpic, "atpic icw4 0x%x", val);
220 
221 	if ((val & ICW4_8086) == 0) {
222 		VATPIC_CTR0(vatpic, "vatpic microprocessor mode required");
223 		return (-1);
224 	}
225 
226 	if ((val & ICW4_AEOI) != 0)
227 		atpic->aeoi = true;
228 
229 	atpic->icw_num = 0;
230 	atpic->ready = true;
231 
232 	return (0);
233 }
234 
235 static int
236 vatpic_ocw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
237 {
238 	VATPIC_CTR1(vatpic, "atpic ocw1 0x%x", val);
239 
240 	atpic->mask = val & 0xff;
241 
242 	return (0);
243 }
244 
245 static int
246 vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
247 {
248 	VATPIC_CTR1(vatpic, "atpic ocw2 0x%x", val);
249 
250 	atpic->rotate = ((val & OCW2_R) != 0);
251 
252 	if ((val & OCW2_EOI) != 0) {
253 		int isr_bit;
254 
255 		if ((val & OCW2_SL) != 0) {
256 			/* specific EOI */
257 			isr_bit = val & 0x7;
258 		} else {
259 			/* non-specific EOI */
260 			isr_bit = vatpic_get_highest_isrpin(atpic);
261 		}
262 
263 		if (isr_bit != -1) {
264 			atpic->service &= ~(1 << isr_bit);
265 
266 			if (atpic->rotate)
267 				atpic->priority = isr_bit;
268 		}
269 	} else if ((val & OCW2_SL) != 0 && atpic->rotate == true) {
270 		/* specific priority */
271 		atpic->priority = val & 0x7;
272 	}
273 
274 	return (0);
275 }
276 
277 static int
278 vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
279 {
280 	VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val);
281 
282 	atpic->poll = ((val & OCW3_P) != 0);
283 
284 	if (val & OCW3_RR) {
285 		/* read register command */
286 		atpic->rd_cmd_reg = val & OCW3_RIS;
287 	}
288 
289 	return (0);
290 }
291 
292 static void
293 vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate)
294 {
295 	struct atpic *atpic;
296 	int oldcnt, newcnt;
297 	bool level;
298 
299 	KASSERT(pin >= 0 && pin < 16,
300 	    ("vatpic_set_pinstate: invalid pin number %d", pin));
301 	KASSERT(VATPIC_LOCKED(vatpic),
302 	    ("vatpic_set_pinstate: vatpic is not locked"));
303 
304 	atpic = &vatpic->atpic[pin >> 3];
305 
306 	oldcnt = atpic->acnt[pin & 0x7];
307 	if (newstate)
308 		atpic->acnt[pin & 0x7]++;
309 	else
310 		atpic->acnt[pin & 0x7]--;
311 	newcnt = atpic->acnt[pin & 0x7];
312 
313 	if (newcnt < 0) {
314 		VATPIC_CTR2(vatpic, "atpic pin%d: bad acnt %d", pin, newcnt);
315 	}
316 
317 	level = ((vatpic->elc[pin >> 3] & (1 << (pin & 0x7))) != 0);
318 
319 	if ((oldcnt == 0 && newcnt == 1) || (newcnt > 0 && level == true)) {
320 		/* rising edge or level */
321 		VATPIC_CTR1(vatpic, "atpic pin%d: asserted", pin);
322 		atpic->request |= (1 << (pin & 0x7));
323 	} else if (oldcnt == 1 && newcnt == 0) {
324 		/* falling edge */
325 		VATPIC_CTR1(vatpic, "atpic pin%d: deasserted", pin);
326 	} else {
327 		VATPIC_CTR3(vatpic, "atpic pin%d: %s, ignored, acnt %d",
328 		    pin, newstate ? "asserted" : "deasserted", newcnt);
329 	}
330 
331 	vatpic_notify_intr(vatpic);
332 }
333 
334 static int
335 vatpic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate)
336 {
337 	struct vatpic *vatpic;
338 	struct atpic *atpic;
339 
340 	if (irq < 0 || irq > 15)
341 		return (EINVAL);
342 
343 	vatpic = vm_atpic(vm);
344 	atpic = &vatpic->atpic[irq >> 3];
345 
346 	if (atpic->ready == false)
347 		return (0);
348 
349 	VATPIC_LOCK(vatpic);
350 	switch (irqstate) {
351 	case IRQSTATE_ASSERT:
352 		vatpic_set_pinstate(vatpic, irq, true);
353 		break;
354 	case IRQSTATE_DEASSERT:
355 		vatpic_set_pinstate(vatpic, irq, false);
356 		break;
357 	case IRQSTATE_PULSE:
358 		vatpic_set_pinstate(vatpic, irq, true);
359 		vatpic_set_pinstate(vatpic, irq, false);
360 		break;
361 	default:
362 		panic("vatpic_set_irqstate: invalid irqstate %d", irqstate);
363 	}
364 	VATPIC_UNLOCK(vatpic);
365 
366 	return (0);
367 }
368 
369 int
370 vatpic_assert_irq(struct vm *vm, int irq)
371 {
372 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT));
373 }
374 
375 int
376 vatpic_deassert_irq(struct vm *vm, int irq)
377 {
378 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT));
379 }
380 
381 int
382 vatpic_pulse_irq(struct vm *vm, int irq)
383 {
384 	return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE));
385 }
386 
387 int
388 vatpic_pending_intr(struct vm *vm, int *vecptr)
389 {
390 	struct vatpic *vatpic;
391 	struct atpic *atpic;
392 	int pin;
393 
394 	vatpic = vm_atpic(vm);
395 
396 	/* XXX master only */
397 	atpic = &vatpic->atpic[0];
398 
399 	VATPIC_LOCK(vatpic);
400 
401 	pin = vatpic_get_highest_irrpin(atpic);
402 	if (pin == -1)
403 		pin = 7;
404 
405 	*vecptr = atpic->irq_base + pin;
406 
407 	VATPIC_UNLOCK(vatpic);
408 
409 	return (1);
410 }
411 
412 void
413 vatpic_intr_accepted(struct vm *vm, int vector)
414 {
415 	struct vatpic *vatpic;
416 	struct atpic *atpic;
417 	int pin;
418 
419 	vatpic = vm_atpic(vm);
420 
421 	/* XXX master only */
422 	atpic = &vatpic->atpic[0];
423 
424 	VATPIC_LOCK(vatpic);
425 	pin = vector & 0x7;
426 
427 	if (atpic->acnt[pin] == 0)
428 		atpic->request &= ~(1 << pin);
429 
430 	if (atpic->aeoi == true) {
431 		if (atpic->rotate == true)
432 			atpic->priority = pin;
433 	} else {
434 		atpic->service |= (1 << pin);
435 	}
436 
437 	vatpic_notify_intr(vatpic);
438 
439 	VATPIC_UNLOCK(vatpic);
440 }
441 
442 int
443 vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
444 {
445 	struct vatpic *vatpic;
446 	struct atpic *atpic;
447 	int error;
448 	uint8_t val;
449 
450 	vatpic = vm_atpic(vm);
451 	atpic = &vatpic->atpic[0];
452 
453 	if (vmexit->u.inout.bytes != 1)
454 		return (-1);
455 
456 	if (vmexit->u.inout.in) {
457 		VATPIC_LOCK(vatpic);
458 		if (atpic->poll) {
459 			VATPIC_CTR0(vatpic, "vatpic polled mode not "
460 			    "supported");
461 			VATPIC_UNLOCK(vatpic);
462 			return (-1);
463 		} else {
464 			if (vmexit->u.inout.port & ICU_IMR_OFFSET) {
465 				/* read interrrupt mask register */
466 				vmexit->u.inout.eax = atpic->mask;
467 			} else {
468 				if (atpic->rd_cmd_reg == OCW3_RIS) {
469 					/* read interrupt service register */
470 					vmexit->u.inout.eax = atpic->service;
471 				} else {
472 					/* read interrupt request register */
473 					vmexit->u.inout.eax = atpic->request;
474 				}
475 			}
476 		}
477 		VATPIC_UNLOCK(vatpic);
478 
479 		return (0);
480 	}
481 
482 	val = vmexit->u.inout.eax;
483 
484 	VATPIC_LOCK(vatpic);
485 
486 	if (vmexit->u.inout.port & ICU_IMR_OFFSET) {
487 		if (atpic->ready) {
488 			error = vatpic_ocw1(vatpic, atpic, val);
489 		} else {
490 			switch (atpic->icw_num) {
491 			case 2:
492 				error = vatpic_icw2(vatpic, atpic, val);
493 				break;
494 			case 3:
495 				error = vatpic_icw3(vatpic, atpic, val);
496 				break;
497 			case 4:
498 				error = vatpic_icw4(vatpic, atpic, val);
499 				break;
500 			}
501 		}
502 	} else {
503 		if (val & (1 << 4))
504 			error = vatpic_icw1(vatpic, atpic, val);
505 
506 		if (atpic->ready) {
507 			if (val & (1 << 3))
508 				error = vatpic_ocw3(vatpic, atpic, val);
509 			else
510 				error = vatpic_ocw2(vatpic, atpic, val);
511 		}
512 	}
513 
514 	if (atpic->ready)
515 		vatpic_notify_intr(vatpic);
516 
517 	VATPIC_UNLOCK(vatpic);
518 
519 	return (error);
520 }
521 
522 int
523 vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
524 {
525 	if (vmexit->u.inout.bytes != 1)
526 		return (-1);
527 
528 	if (vmexit->u.inout.in) {
529 		if (vmexit->u.inout.port & ICU_IMR_OFFSET) {
530 			/* all interrupts masked */
531 			vmexit->u.inout.eax = 0xff;
532 		} else {
533 			vmexit->u.inout.eax = 0x00;
534 		}
535 	}
536 
537 	/* Pretend all accesses to the slave 8259 are alright */
538 	return (0);
539 }
540 
541 int
542 vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
543 {
544 	struct vatpic *vatpic;
545 	bool is_master;
546 
547 	vatpic = vm_atpic(vm);
548 	is_master = (vmexit->u.inout.port == IO_ELCR1);
549 
550 	if (vmexit->u.inout.bytes != 1)
551 		return (-1);
552 
553 	if (vmexit->u.inout.in) {
554 		if (is_master)
555 			vmexit->u.inout.eax = vatpic->elc[0];
556 		else
557 			vmexit->u.inout.eax = vatpic->elc[1];
558 	} else {
559 		/*
560 		 * For the master PIC the cascade channel (IRQ2), the
561 		 * heart beat timer (IRQ0), and the keyboard
562 		 * controller (IRQ1) cannot be programmed for level
563 		 * mode.
564 		 *
565 		 * For the slave PIC the real time clock (IRQ8) and
566 		 * the floating point error interrupt (IRQ13) cannot
567 		 * be programmed for level mode.
568 		 */
569 		if (is_master)
570 			vatpic->elc[0] = (vmexit->u.inout.eax & 0xf8);
571 		else
572 			vatpic->elc[1] = (vmexit->u.inout.eax & 0xde);
573 	}
574 
575 	return (0);
576 }
577 
578 struct vatpic *
579 vatpic_init(struct vm *vm)
580 {
581 	struct vatpic *vatpic;
582 
583 	vatpic = malloc(sizeof(struct vatpic), M_VATPIC, M_WAITOK | M_ZERO);
584 	vatpic->vm = vm;
585 
586 	mtx_init(&vatpic->mtx, "vatpic lock", NULL, MTX_SPIN);
587 
588 	return (vatpic);
589 }
590 
591 void
592 vatpic_cleanup(struct vatpic *vatpic)
593 {
594 	free(vatpic, M_VATPIC);
595 }
596