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.


Add HVM configuration capability, init/deinit, etc
[palacios.git] / palacios / src / palacios / vmm_hvm.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) 2015, The V3VEE Project <http://www.v3vee.org> 
11  * All rights reserved.
12  *
13  * Author:  Peter Dinda <pdinda@northwestern.edu>
14  *
15  * This is free software.  You are permitted to use,
16  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
17  */
18
19 #include <palacios/vmm_mem.h>
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_util.h>
22 #include <palacios/vmm_emulator.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_debug.h>
25
26 #include <palacios/vmm_xml.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 /*
32
33   MEM     = Total size of memory in the GPA (in MB)
34   ROS_MEM = Total size of memory for the ROS (in MB) (<RAM)
35
36   GPAs [0,ROS_MEM) are what the ROS sees
37   GPAs [ROS_MEM, MEM) are HRT only
38   GPAS [0,MEM) are accessible by the HRT
39
40   CORES   = Total number of cores in VM
41   ROS_CORES = Total numbber of cores for the ROS
42
43   Cores [0,ROS_CORES) are what the ROS sees
44   Cores [ROS_CORES,CORES) are HRT only
45   Cores [0,CORES) are accessible by the HRT
46
47   In a Pal file:
48
49   <files> 
50     <file id="hrtelf" filename="hrtelf.o" />
51   </files>
52
53   <mem ... >RAM</mem>   (MB)  Note these are  
54   <cores count="CORES" ...>   backward compatible
55
56   <hvm enable="y">
57     <ros cores="ROS_CORES" mem="ROS_MEM" /> (MB)
58     <hrt file_id="hrtelf" /hrt>
59   </hvm>
60
61 */
62
63 #ifndef V3_CONFIG_DEBUG_HVM
64 #undef PrintDebug
65 #define PrintDebug(fmt, args...)
66 #endif
67
68 int v3_init_hvm()
69 {
70     PrintDebug(VM_NONE,VCORE_NONE, "hvm: init\n");
71     return 0;
72 }
73
74 int v3_deinit_hvm()
75 {
76     PrintDebug(VM_NONE,VCORE_NONE, "hvm: deinit\n");
77     return 0;
78 }
79
80
81 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
82
83 int v3_init_hvm_vm(struct v3_vm_info *vm, struct v3_xml *config)
84 {
85     v3_cfg_tree_t *hvm_config;
86     v3_cfg_tree_t *ros_config;
87     v3_cfg_tree_t *hrt_config;
88     char *enable;
89     char *ros_cores;
90     char *ros_mem;
91     char *hrt_file_id;
92
93     PrintDebug(vm, VCORE_NONE, "hvm: vm init\n");
94
95     /* 
96        Defaults - all ROS
97     */
98     memset(&vm->hvm_state,0,sizeof(struct v3_vm_hvm));
99     vm->hvm_state.is_hvm=0;
100     vm->hvm_state.first_hrt_core=vm->num_cores;
101     vm->hvm_state.first_hrt_gpa=vm->mem_size;
102
103     if (!config || !(hvm_config=v3_cfg_subtree(config,"hvm"))) {
104         PrintDebug(vm,VCORE_NONE,"hvm: no HVM configuration found (all HW is ROS)\n");
105         goto out_ok;
106     }
107     
108     if (!(enable=v3_cfg_val(hvm_config,"enable")) || strcasecmp(enable,"y")) {
109         PrintDebug(vm,VCORE_NONE,"hvm: HVM configuration disabled (all HW is ROS)\n");
110         goto out_ok;
111     }
112
113     if (!(ros_config=v3_cfg_subtree(hvm_config,"ros"))) { 
114         PrintError(vm,VCORE_NONE,"hvm: HVM configuration without ROS block...\n");
115         return -1;
116     }
117  
118     if (!(ros_cores=v3_cfg_val(ros_config,"cores"))) { 
119         PrintError(vm,VCORE_NONE,"hvm: ROS block without cores...\n");
120         return -1;
121     }
122    
123     vm->hvm_state.first_hrt_core = ((uint32_t)atoi(ros_cores));
124     
125     if (!(ros_mem=v3_cfg_val(ros_config,"mem"))) { 
126         PrintError(vm,VCORE_NONE,"hvm: ROS block without mem...\n");
127         return -1;
128     }
129
130     vm->hvm_state.first_hrt_gpa = ((uint64_t)atoi(ros_mem))*1024*1024;
131         
132     if (!(hrt_config=v3_cfg_subtree(hvm_config,"hrt"))) { 
133         PrintError(vm,VCORE_NONE,"hvm: HVM configuration without HRT block...\n");
134         return -1;
135     }
136  
137     if (!(hrt_file_id=v3_cfg_val(hrt_config,"file_id"))) { 
138         PrintError(vm,VCORE_NONE,"hvm: HRT block without file_id...\n");
139         return -1;
140     }
141
142     vm->hvm_state.hrt_file = v3_cfg_get_file(vm,hrt_file_id);
143     
144     if (!vm->hvm_state.hrt_file) { 
145         PrintError(vm,VCORE_NONE,"hvm: HRT block contains bad file_id (%s)\n",hrt_file_id);
146         return -1;
147     }
148
149     // XXX sanity check config here
150
151     vm->hvm_state.is_hvm=1;
152
153  out_ok:
154     if (vm->hvm_state.is_hvm) {
155         V3_Print(vm,VCORE_NONE,"hvm: [ROS: cores 0..%u, mem 0..%p] [HRT: cores %u..%u, mem %p..%p, file_id=%s (tag %s)]\n",
156                  vm->hvm_state.first_hrt_core-1,
157                  (void*) vm->hvm_state.first_hrt_gpa-1,
158                  vm->hvm_state.first_hrt_core,
159                  vm->num_cores-1,
160                  (void*) vm->hvm_state.first_hrt_gpa,
161                  (void*)vm->mem_size-1,
162                  hrt_file_id,
163                  vm->hvm_state.hrt_file->tag);
164     } else {
165         V3_Print(vm,VCORE_NONE,"hvm: This is a pure ROS VM\n");
166     }
167     return 0;
168     
169 }
170
171 int v3_deinit_hvm_vm(struct v3_vm_info *vm)
172 {
173     PrintDebug(vm, VCORE_NONE, "hvm: HVM deinit\n");
174
175     return 0;
176 }
177
178 int v3_init_hvm_core(struct guest_info *core)
179 {
180     memset(&core->hvm_state,0,sizeof(core->hvm_state));
181     if (core->vm_info->hvm_state.is_hvm) { 
182         if (core->vcpu_id >= core->vm_info->hvm_state.first_hrt_core) { 
183             core->hvm_state.is_hrt=1;
184         }
185     }
186     return 0;
187 }
188
189 int v3_deinit_hvm_core(struct guest_info *core)
190 {
191     return 0;
192 }
193
194
195 uint64_t v3_get_hvm_ros_memsize(struct v3_vm_info *vm)
196 {
197     if (vm->hvm_state.is_hvm) { 
198         return vm->hvm_state.first_hrt_gpa;
199     } else {
200         return vm->mem_size;
201     }
202 }
203 uint64_t v3_get_hvm_hrt_memsize(struct v3_vm_info *vm)
204 {
205     if (vm->hvm_state.is_hvm) { 
206         return vm->mem_size - vm->hvm_state.first_hrt_gpa;
207     } else {
208         return 0;
209     }
210 }
211
212 uint32_t v3_get_hvm_ros_cores(struct v3_vm_info *vm)
213 {
214     if (vm->hvm_state.is_hvm) { 
215         return vm->hvm_state.first_hrt_core;
216     } else {
217         return vm->num_cores;
218     }
219 }
220
221 uint32_t v3_get_hvm_hrt_cores(struct v3_vm_info *vm)
222 {
223     if (vm->hvm_state.is_hvm) { 
224         return vm->num_cores - vm->hvm_state.first_hrt_core;
225     } else {
226         return 0;
227     }
228 }
229
230
231 int v3_is_hvm_ros_mem_gpa(struct v3_vm_info *vm, addr_t gpa)
232 {
233     if (vm->hvm_state.is_hvm) { 
234         return gpa>=0 && gpa<vm->hvm_state.first_hrt_gpa;
235     } else {
236         return 1;
237     }
238 }
239
240 int v3_is_hvm_hrt_mem_gpa(struct v3_vm_info *vm, addr_t gpa)
241 {
242     if (vm->hvm_state.is_hvm) { 
243         return gpa>=vm->hvm_state.first_hrt_gpa && gpa<vm->mem_size;
244     } else {
245         return 0;
246     }
247 }
248
249 int v3_is_hvm_hrt_core(struct guest_info *core)
250 {
251     return core->hvm_state.is_hrt;
252 }
253
254 int v3_is_hvm_ros_core(struct guest_info *core)
255 {
256     return !core->hvm_state.is_hrt;
257 }
258
259 int      v3_hvm_should_deliver_ipi(struct guest_info *src, struct guest_info *dest)
260 {
261     if (!src) {
262         // ioapic or msi to apic
263         return !dest->hvm_state.is_hrt;
264     } else {
265         // apic to apic
266         return src->hvm_state.is_hrt || (!src->hvm_state.is_hrt && !dest->hvm_state.is_hrt) ;
267     }
268 }
269
270 void     v3_hvm_find_apics_seen_by_core(struct guest_info *core, struct v3_vm_info *vm, 
271                                         uint32_t *start_apic, uint32_t *num_apics)
272 {
273     if (!core) { 
274         // Seen from ioapic, msi, etc: 
275         if (vm->hvm_state.is_hvm) {
276             // HVM VM shows only the ROS cores/apics to ioapic, msi, etc
277             *start_apic = 0;
278             *num_apics = vm->hvm_state.first_hrt_core;
279         } else {
280             // Non-HVM shows all cores/APICs to apic, msi, etc.
281             *start_apic = 0;
282             *num_apics = vm->num_cores;
283         }
284     } else {
285         // Seen from apic
286         if (core->hvm_state.is_hrt) { 
287             // HRT core/apic sees all apics
288             // (this policy may change...)
289             *start_apic = 0;
290             *num_apics = vm->num_cores;
291         } else {
292             // non-HRT core/apic sees only non-HRT cores/apics
293             *start_apic = 0 ;
294             *num_apics = vm->hvm_state.first_hrt_core;
295         }
296     }
297 }
298         
299