Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fe76cff81ffc481d55cbfc08ec6b6929b5d86428
[palacios.git] / palacios / src / devices / icc_bus.c
1 /*
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.
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
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>
25
26 #define MAX_APIC 256
27
28 struct icc_bus_internal {
29     struct vm_device * apic[MAX_APIC];
30 };
31
32 static struct v3_device_ops dev_ops = {
33     .free = NULL,
34     .reset = NULL,
35     .start = NULL,
36     .stop = NULL,
37 };
38
39 int v3_icc_register_apic(struct v3_vm_info *info, struct vm_device *icc_bus, struct vm_device *apic, uint32_t apic_num)
40 {
41     struct icc_bus_internal * icc = (struct icc_bus_internal *)icc_bus->private_data;
42
43     if (apic_num < MAX_APIC) {
44         if (icc->apic[apic_num]) {
45             PrintError("Attempt to re-register apic %u\n", apic_num);
46             return -1;
47         } else {
48             icc->apic[apic_num] = apic;
49             PrintDebug("Registered apic or ioapic %u\n", apic_num);
50             return 0;
51         }
52     } else {
53         PrintError("Too many apics for icc bus!");
54         return -1;
55     }
56 }
57
58 struct ipi_thunk_data {
59     struct vm_device *target;
60     uint64_t          val;
61 } ;
62
63 static void icc_force_exit(void *val)
64 {
65      return;
66 }
67
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;
70
71     struct int_cmd_reg icr;
72     icr.lo = val;
73
74     char *type = NULL, *dest = NULL;
75     char foo[8];
76
77     switch (icr.dst_shorthand)
78     {
79     case 0x0:
80         sprintf(foo, "%d", icr.dst);
81         dest = foo;
82         break;
83     case 0x1:
84         dest = "(self)";
85         break;
86     case 0x2:
87         dest = "(broadcast inclusive)";
88         break;
89     case 0x3:
90         dest = "(broadcast)";
91         break;
92     }
93     switch (icr.msg_type)
94     {
95     case 0x0:
96         type = "";
97         break;
98     case 0x4:
99         type = "(NMI)";
100         break;
101     case 0x5:
102         type = "(INIT)";
103         break;
104     case 0x6:
105         type = "(Startup)";
106         break;
107     }
108
109
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);
111
112     v3_apic_raise_intr(internal->apic[apic_num], val & 0xff);
113
114     V3_Call_On_CPU(apic_num,  icc_force_exit, (void *)(uint64_t)(val & 0xff));
115
116     return 0;
117 }
118
119
120 static int init_icc_bus_internal_state(struct icc_bus_internal* icc) {
121     int i;
122     for (i=0;i<MAX_APIC;i++) { icc->apic[i]=0; }
123     return  0;
124 }
125
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");
129
130     struct icc_bus_internal * icc_bus = (struct icc_bus_internal *)V3_Malloc(sizeof(struct icc_bus_internal));
131
132     struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
133
134     if (v3_attach_device(vm, dev) == -1) {
135         PrintError("Could not attach device %s\n", name);
136         return -1;
137     }
138
139     init_icc_bus_internal_state(icc_bus);
140
141     return 0;
142 }
143
144
145
146 device_register("ICC_BUS", icc_bus_init)