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 284900 2015-06-28 03:22:26Z neel $");
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
master_atpic(struct vatpic * vatpic,struct atpic * atpic)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
vatpic_get_highest_isrpin(struct atpic * atpic)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
vatpic_get_highest_irrpin(struct atpic * atpic)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
vatpic_notify_intr(struct vatpic * vatpic)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
vatpic_icw1(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw2(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw3(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_icw4(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw1(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw2(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_ocw3(struct vatpic * vatpic,struct atpic * atpic,uint8_t val)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
vatpic_set_pinstate(struct vatpic * vatpic,int pin,bool newstate)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
vatpic_set_irqstate(struct vm * vm,int irq,enum irqstate irqstate)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
vatpic_assert_irq(struct vm * vm,int irq)494 vatpic_assert_irq(struct vm *vm, int irq)
495 {
496 return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT));
497 }
498
499 int
vatpic_deassert_irq(struct vm * vm,int irq)500 vatpic_deassert_irq(struct vm *vm, int irq)
501 {
502 return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT));
503 }
504
505 int
vatpic_pulse_irq(struct vm * vm,int irq)506 vatpic_pulse_irq(struct vm *vm, int irq)
507 {
508 return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE));
509 }
510
511 int
vatpic_set_irq_trigger(struct vm * vm,int irq,enum vm_intr_trigger trigger)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
vatpic_pending_intr(struct vm * vm,int * vecptr)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
vatpic_pin_accepted(struct atpic * atpic,int pin)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
vatpic_intr_accepted(struct vm * vm,int vector)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
vatpic_read(struct vatpic * vatpic,struct atpic * atpic,bool in,int port,int bytes,uint32_t * eax)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
vatpic_write(struct vatpic * vatpic,struct atpic * atpic,bool in,int port,int bytes,uint32_t * eax)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
vatpic_master_handler(struct vm * vm,int vcpuid,bool in,int port,int bytes,uint32_t * eax)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
vatpic_slave_handler(struct vm * vm,int vcpuid,bool in,int port,int bytes,uint32_t * eax)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
vatpic_elc_handler(struct vm * vm,int vcpuid,bool in,int port,int bytes,uint32_t * eax)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 *
vatpic_init(struct vm * vm)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
vatpic_cleanup(struct vatpic * vatpic)805 vatpic_cleanup(struct vatpic *vatpic)
806 {
807 free(vatpic, M_VATPIC);
808 }
809