#include <palacios/vmm_dev_mgr.h>
#include <palacios/vmm_sprintf.h>
#include <palacios/vm_guest.h>
-#include <devices/apic_regs.h>
-#include <devices/apic.h>
+#include <devices/icc_bus.h>
-#define MAX_APIC 256
+#define MAX_APICS 256
-struct icc_bus_internal {
- struct vm_device * apic[MAX_APIC];
+
+struct ipi_thunk_data {
+ struct vm_device * target;
+ uint64_t val;
+};
+
+struct int_cmd_reg {
+ union {
+ uint64_t val;
+
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } __attribute__((packed));
+
+ struct {
+ uint_t vec : 8;
+ uint_t msg_type : 3;
+ uint_t dst_mode : 1;
+ uint_t del_status : 1;
+ uint_t rsvd1 : 1;
+ uint_t lvl : 1;
+ uint_t trig_mode : 1;
+ uint_t rem_rd_status : 2;
+ uint_t dst_shorthand : 2;
+ uint64_t rsvd2 : 36;
+ uint32_t dst : 8;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
+struct apic_data {
+ struct guest_info * core;
+ struct v3_icc_ops * ops;
+
+ void * priv_data;
+ int present;
+};
+
+
+struct icc_bus_state {
+ struct apic_data apics[MAX_APICS];
};
static struct v3_device_ops dev_ops = {
.stop = NULL,
};
-int v3_icc_register_apic(struct v3_vm_info *info, struct vm_device *icc_bus, struct vm_device *apic, uint32_t apic_num)
-{
- struct icc_bus_internal * icc = (struct icc_bus_internal *)icc_bus->private_data;
-
- if (apic_num < MAX_APIC) {
- if (icc->apic[apic_num]) {
- PrintError("Attempt to re-register apic %u\n", apic_num);
- return -1;
- } else {
- icc->apic[apic_num] = apic;
- PrintDebug("Registered apic or ioapic %u\n", apic_num);
- return 0;
- }
- } else {
- PrintError("Too many apics for icc bus!");
- return -1;
- }
-}
-struct ipi_thunk_data {
- struct vm_device *target;
- uint64_t val;
-} ;
-static void icc_force_exit(void *val)
-{
- return;
-}
-int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t apic_num, uint32_t val) {
- struct icc_bus_internal * internal = (struct icc_bus_internal *)icc_bus->private_data;
+int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num) {
+ struct icc_bus_state * state = (struct icc_bus_state *)icc_bus->private_data;
+ struct apic_data * apic = &(state->apics[apic_num]);
+
struct int_cmd_reg icr;
- icr.lo = val;
+ icr.lo = irq_num;
- char *type = NULL, *dest = NULL;
+
+ char * type = NULL;
+ char * dest = NULL;
char foo[8];
- switch (icr.dst_shorthand)
- {
- case 0x0:
- sprintf(foo, "%d", icr.dst);
- dest = foo;
- break;
- case 0x1:
- dest = "(self)";
- break;
- case 0x2:
- dest = "(broadcast inclusive)";
- break;
- case 0x3:
- dest = "(broadcast)";
- break;
+ switch (icr.dst_shorthand) {
+ case 0x0:
+ sprintf(foo, "%d", icr.dst);
+ dest = foo;
+ break;
+ case 0x1:
+ dest = "(self)";
+ break;
+ case 0x2:
+ dest = "(broadcast inclusive)";
+ break;
+ case 0x3:
+ dest = "(broadcast)";
+ break;
}
- switch (icr.msg_type)
- {
- case 0x0:
- type = "";
- break;
- case 0x4:
- type = "(NMI)";
- break;
- case 0x5:
- type = "(INIT)";
- break;
- case 0x6:
- type = "(Startup)";
- break;
+
+ switch (icr.msg_type) {
+ case 0x0:
+ type = "";
+ break;
+ case 0x4:
+ type = "(NMI)";
+ break;
+ case 0x5:
+ type = "(INIT)";
+ break;
+ case 0x6:
+ type = "(Startup)";
+ break;
}
- PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", type, dest, V3_Get_CPU(), apic_num);
+ PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n",
+ type, dest, V3_Get_CPU(), apic_num);
- v3_apic_raise_intr(internal->apic[apic_num], val & 0xff);
+ apic->ops->raise_intr(apic->core, irq_num & 0xff, apic->priv_data);
- V3_Call_On_CPU(apic_num, icc_force_exit, (void *)(uint64_t)(val & 0xff));
+ //V3_Call_On_CPU(apic_num, icc_force_exit, (void *)(uint64_t)(val & 0xff));
return 0;
}
-static int init_icc_bus_internal_state(struct icc_bus_internal* icc) {
- int i;
- for (i=0;i<MAX_APIC;i++) { icc->apic[i]=0; }
- return 0;
+
+/* THIS IS A BIG ASSUMPTION: APIC PHYSID == LOGID == CORENUM */
+
+int v3_icc_register_apic(struct guest_info * core, struct vm_device * icc_bus,
+ uint8_t apic_num, struct v3_icc_ops * ops, void * priv_data) {
+ struct icc_bus_state * icc = (struct icc_bus_state *)icc_bus->private_data;
+ struct apic_data * apic = &(icc->apics[apic_num]);
+
+ if (apic->present == 1) {
+ PrintError("Attempt to re-register apic %u\n", apic_num);
+ return -1;
+ }
+
+ apic->present = 1;
+ apic->priv_data = priv_data;
+ apic->core = core;
+ apic->ops = ops;
+
+ PrintDebug("Registered apic%u\n", apic_num);
+
+ return 0;
}
+
+
+
static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
PrintDebug("Creating ICC_BUS\n");
+
char * name = v3_cfg_val(cfg, "name");
- struct icc_bus_internal * icc_bus = (struct icc_bus_internal *)V3_Malloc(sizeof(struct icc_bus_internal));
+ struct icc_bus_state * icc_bus = (struct icc_bus_state *)V3_Malloc(sizeof(struct icc_bus_state));
+ memset(icc_bus, 0, sizeof(struct icc_bus_state));
struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
return -1;
}
- init_icc_bus_internal_state(icc_bus);
-
return 0;
}