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.


f5de549646b4cf321c0ca3af78c70a940c8184d7
[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/icc_bus.h>
24
25 #define MAX_APICS 256
26
27
28 struct ipi_thunk_data {
29     struct vm_device * target;
30     uint64_t val;
31 };
32
33 struct int_cmd_reg {
34     union {
35         uint64_t val;
36
37         struct {
38             uint32_t lo;
39             uint32_t hi;
40         } __attribute__((packed));
41
42         struct {
43             uint_t vec           : 8;
44             uint_t msg_type      : 3;
45             uint_t dst_mode      : 1;
46             uint_t del_status    : 1;
47             uint_t rsvd1         : 1;
48             uint_t lvl           : 1;
49             uint_t trig_mode     : 1;
50             uint_t rem_rd_status : 2;
51             uint_t dst_shorthand : 2;
52             uint64_t rsvd2       : 36;
53             uint32_t dst         : 8;
54         } __attribute__((packed));
55     } __attribute__((packed));
56 } __attribute__((packed));
57
58
59
60
61 struct apic_data {
62     struct guest_info * core;
63     struct v3_icc_ops * ops;
64     
65     void * priv_data;
66     int present;
67 };
68
69
70 struct icc_bus_state {
71     struct apic_data apics[MAX_APICS];
72 };
73
74 static struct v3_device_ops dev_ops = {
75     .free = NULL,
76     .reset = NULL,
77     .start = NULL,
78     .stop = NULL,
79 };
80
81
82
83
84 int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num) {
85     struct icc_bus_state * state = (struct icc_bus_state *)icc_bus->private_data;
86     struct apic_data * apic = &(state->apics[apic_num]);    
87
88
89     struct int_cmd_reg icr;
90     icr.lo = irq_num;
91
92
93     char * type = NULL;
94     char * dest = NULL;
95     char foo[8];
96
97     switch (icr.dst_shorthand) {
98         case 0x0:
99             sprintf(foo, "%d", icr.dst);
100             dest = foo;
101             break;
102         case 0x1:
103             dest = "(self)";
104             break;
105         case 0x2:
106             dest = "(broadcast inclusive)";
107             break;
108         case 0x3:
109             dest = "(broadcast)";
110             break;
111     }
112
113     switch (icr.msg_type) {
114         case 0x0:
115             type = "";
116             break;
117         case 0x4:
118             type = "(NMI)";
119             break;
120         case 0x5:
121             type = "(INIT)";
122             break;
123         case 0x6:
124             type = "(Startup)";
125             break;
126     }
127
128
129     PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", 
130                type, dest, V3_Get_CPU(), apic_num);
131
132     apic->ops->raise_intr(apic->core, irq_num & 0xff, apic->priv_data);
133
134     //V3_Call_On_CPU(apic_num,  icc_force_exit, (void *)(uint64_t)(val & 0xff));
135
136     return 0;
137 }
138
139
140
141 /* THIS IS A BIG ASSUMPTION: APIC PHYSID == LOGID == CORENUM */
142
143 int v3_icc_register_apic(struct guest_info  * core, struct vm_device * icc_bus, 
144                          uint8_t apic_num, struct v3_icc_ops * ops, void * priv_data) {
145     struct icc_bus_state * icc = (struct icc_bus_state *)icc_bus->private_data;
146     struct apic_data * apic = &(icc->apics[apic_num]);
147
148     if (apic->present == 1) {
149         PrintError("Attempt to re-register apic %u\n", apic_num);
150         return -1;
151     }
152     
153     apic->present = 1;
154     apic->priv_data = priv_data;
155     apic->core = core;
156     apic->ops = ops;
157    
158     PrintDebug("Registered apic%u\n", apic_num);
159
160     return 0;
161 }
162
163
164
165
166 static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
167     PrintDebug("Creating ICC_BUS\n");
168
169     char * name = v3_cfg_val(cfg, "name");
170
171     struct icc_bus_state * icc_bus = (struct icc_bus_state *)V3_Malloc(sizeof(struct icc_bus_state));
172     memset(icc_bus, 0, sizeof(struct icc_bus_state));
173
174     struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
175
176     if (v3_attach_device(vm, dev) == -1) {
177         PrintError("Could not attach device %s\n", name);
178         return -1;
179     }
180
181     return 0;
182 }
183
184
185
186 device_register("ICC_BUS", icc_bus_init)