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) 2015, The V3VEE Project <http://www.v3vee.org>
11 * All rights reserved.
13 * Author: Peter Dinda <pdinda@northwestern.edu>
15 * This is free software. You are permitted to use,
16 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
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>
26 #include <palacios/vmm_xml.h>
33 MEM = Total size of memory in the GPA (in MB)
34 ROS_MEM = Total size of memory for the ROS (in MB) (<RAM)
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
40 CORES = Total number of cores in VM
41 ROS_CORES = Total numbber of cores for the ROS
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
50 <file id="hrtelf" filename="hrtelf.o" />
53 <mem ... >RAM</mem> (MB) Note these are
54 <cores count="CORES" ...> backward compatible
57 <ros cores="ROS_CORES" mem="ROS_MEM" /> (MB)
58 <hrt file_id="hrtelf" /hrt>
63 #ifndef V3_CONFIG_DEBUG_HVM
65 #define PrintDebug(fmt, args...)
70 PrintDebug(VM_NONE,VCORE_NONE, "hvm: init\n");
76 PrintDebug(VM_NONE,VCORE_NONE, "hvm: deinit\n");
81 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
83 int v3_init_hvm_vm(struct v3_vm_info *vm, struct v3_xml *config)
85 v3_cfg_tree_t *hvm_config;
86 v3_cfg_tree_t *ros_config;
87 v3_cfg_tree_t *hrt_config;
93 PrintDebug(vm, VCORE_NONE, "hvm: vm init\n");
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;
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");
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");
113 if (!(ros_config=v3_cfg_subtree(hvm_config,"ros"))) {
114 PrintError(vm,VCORE_NONE,"hvm: HVM configuration without ROS block...\n");
118 if (!(ros_cores=v3_cfg_val(ros_config,"cores"))) {
119 PrintError(vm,VCORE_NONE,"hvm: ROS block without cores...\n");
123 vm->hvm_state.first_hrt_core = ((uint32_t)atoi(ros_cores));
125 if (!(ros_mem=v3_cfg_val(ros_config,"mem"))) {
126 PrintError(vm,VCORE_NONE,"hvm: ROS block without mem...\n");
130 vm->hvm_state.first_hrt_gpa = ((uint64_t)atoi(ros_mem))*1024*1024;
132 if (!(hrt_config=v3_cfg_subtree(hvm_config,"hrt"))) {
133 PrintError(vm,VCORE_NONE,"hvm: HVM configuration without HRT block...\n");
137 if (!(hrt_file_id=v3_cfg_val(hrt_config,"file_id"))) {
138 PrintError(vm,VCORE_NONE,"hvm: HRT block without file_id...\n");
142 vm->hvm_state.hrt_file = v3_cfg_get_file(vm,hrt_file_id);
144 if (!vm->hvm_state.hrt_file) {
145 PrintError(vm,VCORE_NONE,"hvm: HRT block contains bad file_id (%s)\n",hrt_file_id);
149 // XXX sanity check config here
151 vm->hvm_state.is_hvm=1;
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,
160 (void*) vm->hvm_state.first_hrt_gpa,
161 (void*)vm->mem_size-1,
163 vm->hvm_state.hrt_file->tag);
165 V3_Print(vm,VCORE_NONE,"hvm: This is a pure ROS VM\n");
171 int v3_deinit_hvm_vm(struct v3_vm_info *vm)
173 PrintDebug(vm, VCORE_NONE, "hvm: HVM deinit\n");
178 int v3_init_hvm_core(struct guest_info *core)
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;
189 int v3_deinit_hvm_core(struct guest_info *core)
195 uint64_t v3_get_hvm_ros_memsize(struct v3_vm_info *vm)
197 if (vm->hvm_state.is_hvm) {
198 return vm->hvm_state.first_hrt_gpa;
203 uint64_t v3_get_hvm_hrt_memsize(struct v3_vm_info *vm)
205 if (vm->hvm_state.is_hvm) {
206 return vm->mem_size - vm->hvm_state.first_hrt_gpa;
212 uint32_t v3_get_hvm_ros_cores(struct v3_vm_info *vm)
214 if (vm->hvm_state.is_hvm) {
215 return vm->hvm_state.first_hrt_core;
217 return vm->num_cores;
221 uint32_t v3_get_hvm_hrt_cores(struct v3_vm_info *vm)
223 if (vm->hvm_state.is_hvm) {
224 return vm->num_cores - vm->hvm_state.first_hrt_core;
231 int v3_is_hvm_ros_mem_gpa(struct v3_vm_info *vm, addr_t gpa)
233 if (vm->hvm_state.is_hvm) {
234 return gpa>=0 && gpa<vm->hvm_state.first_hrt_gpa;
240 int v3_is_hvm_hrt_mem_gpa(struct v3_vm_info *vm, addr_t gpa)
242 if (vm->hvm_state.is_hvm) {
243 return gpa>=vm->hvm_state.first_hrt_gpa && gpa<vm->mem_size;
249 int v3_is_hvm_hrt_core(struct guest_info *core)
251 return core->hvm_state.is_hrt;
254 int v3_is_hvm_ros_core(struct guest_info *core)
256 return !core->hvm_state.is_hrt;
259 int v3_hvm_should_deliver_ipi(struct guest_info *src, struct guest_info *dest)
262 // ioapic or msi to apic
263 return !dest->hvm_state.is_hrt;
266 return src->hvm_state.is_hrt || (!src->hvm_state.is_hrt && !dest->hvm_state.is_hrt) ;
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)
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
278 *num_apics = vm->hvm_state.first_hrt_core;
280 // Non-HVM shows all cores/APICs to apic, msi, etc.
282 *num_apics = vm->num_cores;
286 if (core->hvm_state.is_hrt) {
287 // HRT core/apic sees all apics
288 // (this policy may change...)
290 *num_apics = vm->num_cores;
292 // non-HRT core/apic sees only non-HRT cores/apics
294 *num_apics = vm->hvm_state.first_hrt_core;