4 * Copyright 2015 Google Inc.
6 * See LICENSE for details.
10 #include <sys/types.h>
14 #include <parlib/arch/arch.h>
15 #include <parlib/ros_debug.h>
25 #include <vmm/virtio.h>
26 #include <vmm/virtio_mmio.h>
27 #include <vmm/virtio_ids.h>
28 #include <vmm/virtio_config.h>
29 #include <vmm/sched.h>
31 #define IOAPIC_CONFIG 0x100
32 #define IOAPIC_NUM_PINS 24
35 int apic_id_mask = 0xf0;
37 #define DPRINTF(fmt, ...) \
38 if (debug_ioapic) { fprintf(stderr, "ioapic: " fmt , ## __VA_ARGS__); }
48 static struct ioapic ioapic[1];
50 static uint32_t ioapic_read(struct guest_thread *vm_thread, int ix,
53 uint32_t ret = (uint32_t)-1;
54 uint32_t reg = ioapic[ix].reg;
57 DPRINTF("ioapic_read ix %x return 0x%x\n", ix, reg);
61 DPRINTF("ioapic_read %x 0x%x\n", ix, (int)reg);
70 return ioapic[ix].arbid;
73 if (reg >= 0 && reg < (IOAPIC_NUM_PINS*2 + 0x10)) {
74 //bx_io_redirect_entry_t *entry = ioredtbl + index;
75 //data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
76 ret = ioapic[ix].value[reg];
77 DPRINTF("IOAPIC_READ %x: %x return %08x\n", ix, reg, ret);
80 DPRINTF("IOAPIC READ: %x BAD INDEX 0x%x\n", ix, reg);
88 static void ioapic_write(struct guest_thread *vm_thread, int ix,
89 uint64_t offset, uint32_t value)
92 uint32_t reg = ioapic[ix].reg;
93 struct virtual_machine *vm = gth_to_vm(vm_thread);
97 DPRINTF("ioapic_write ix %x set reg 0x%x\n", ix, value);
98 ioapic[ix].reg = value;
102 for (int i = 0; i < VIRTIO_MMIO_MAX_NUM_DEV; i++) {
103 if (vm->virtio_mmio_devices[i] == NULL)
106 /* The first IRQ register starts at 0x10, and there are two 32-bit
107 * registers for each IRQ. The first 8 bits of the value assigned to
108 * 'reg' is the interrupt vector. */
109 irqreg = (vm->virtio_mmio_devices[i]->irq) * 2 + 0x10;
110 if (reg == irqreg && (value & 0xff) != 0) {
111 vm->virtio_mmio_devices[i]->vec = value & 0xff;
112 DPRINTF("irq vector for irq number %d is: %lx\n",
113 vm->virtio_mmio_devices[i]->irq, value & 0xff);
119 DPRINTF("IOAPIC_WRITE: Set %d ID to %d\n", ix, value);
120 ioapic[ix].id = value;
124 DPRINTF("IOAPIC_WRITE: Can't write %d\n", reg);
126 if (reg >= 0 && reg < (IOAPIC_NUM_PINS*2 + 0x10)) {
127 ioapic[ix].value[reg] = value;
128 DPRINTF("IOAPIC %x: set %08x to %016x\n", ix, reg, value);
130 DPRINTF("IOAPIC WRITE: %x BAD INDEX 0x%x\n", ix, reg);
137 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
138 uint64_t *regp, int store)
140 /* TODO(ganshun): compute an index for the ioapic array. */
142 uint32_t offset = gpa & 0xfffff;
143 /* basic sanity tests. */
144 DPRINTF("%s: %p 0x%x %p %s\n", __func__, (void *)gpa, destreg, regp, store ? "write" : "read");
146 if ((offset != 0) && (offset != 0x10)) {
147 DPRINTF("Bad register offset: 0x%x and has to be 0x0 or 0x10\n", offset);
152 ioapic_write(vm_thread, ix, offset, *regp);
154 *regp = ioapic_read(vm_thread, ix, offset);