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