2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_dev_mgr.h>
21 #include <palacios/vmm_sprintf.h>
22 #include <palacios/vm_guest.h>
23 #include <devices/apic_regs.h>
24 #include <devices/apic.h>
28 struct icc_bus_internal {
29 struct vm_device * apic[MAX_APIC];
32 static struct v3_device_ops dev_ops = {
39 int v3_icc_register_apic(struct v3_vm_info *info, struct vm_device *icc_bus, struct vm_device *apic, uint32_t apic_num)
41 struct icc_bus_internal * icc = (struct icc_bus_internal *)icc_bus->private_data;
43 if (apic_num < MAX_APIC) {
44 if (icc->apic[apic_num]) {
45 PrintError("Attempt to re-register apic %u\n", apic_num);
48 icc->apic[apic_num] = apic;
49 PrintDebug("Registered apic or ioapic %u\n", apic_num);
53 PrintError("Too many apics for icc bus!");
58 struct ipi_thunk_data {
59 struct vm_device *target;
63 static void icc_force_exit(void *val)
68 int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t apic_num, uint32_t val) {
69 struct icc_bus_internal * internal = (struct icc_bus_internal *)icc_bus->private_data;
71 struct int_cmd_reg icr;
74 char *type = NULL, *dest = NULL;
77 switch (icr.dst_shorthand)
80 sprintf(foo, "%d", icr.dst);
87 dest = "(broadcast inclusive)";
110 PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", type, dest, V3_Get_CPU(), apic_num);
112 v3_apic_raise_intr(internal->apic[apic_num], val & 0xff);
114 V3_Call_On_CPU(apic_num, icc_force_exit, (void *)(uint64_t)(val & 0xff));
120 static int init_icc_bus_internal_state(struct icc_bus_internal* icc) {
122 for (i=0;i<MAX_APIC;i++) { icc->apic[i]=0; }
126 static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
127 PrintDebug("Creating ICC_BUS\n");
128 char * name = v3_cfg_val(cfg, "name");
130 struct icc_bus_internal * icc_bus = (struct icc_bus_internal *)V3_Malloc(sizeof(struct icc_bus_internal));
132 struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
134 if (v3_attach_device(vm, dev) == -1) {
135 PrintError("Could not attach device %s\n", name);
139 init_icc_bus_internal_state(icc_bus);
146 device_register("ICC_BUS", icc_bus_init)