github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/startup/create_guests.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include "file_codes.h" 16 #define VMM_DEADLOOP() VMM_DEADLOOP_LOG(CREATE_GUESTS_C) 17 #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(CREATE_GUESTS_C, __condition) 18 #include "vmm_defs.h" 19 #include "vmm_bootstrap_utils.h" 20 #include "gpm_api.h" 21 #include "guest.h" 22 #include "guest_cpu.h" 23 #include "host_cpu.h" 24 #include "hw_utils.h" 25 #include "scheduler.h" 26 #include "layout_host_memory.h" 27 #include "vmm_dbg.h" 28 #include "vmexit_msr.h" 29 #include "device_drivers_manager.h" 30 #include "vmcall_api.h" 31 #include "vmcall.h" 32 #include "host_memory_manager_api.h" 33 #include "vmm_startup.h" 34 #include "vmm_events_data.h" 35 #include "guest_pci_configuration.h" 36 #include "ipc.h" 37 #include "pat_manager.h" 38 #ifdef JLMDEBUG 39 #include "jlmdebug.h" 40 #endif 41 42 // 43 // Read input data structure and create all guests 44 // 45 46 #ifdef FAST_VIEW_SWITCH 47 extern void fvs_initialize(GUEST_HANDLE guest, UINT32 number_of_host_processors); 48 #endif 49 50 #if 0 // not defined 51 static void raise_guest_create_event(GUEST_ID guest_id); // moved to guest.c 52 #endif 53 54 #define PRIMARY_MAGIC 0 55 56 57 // Add CPU to guest 58 void add_cpu_to_guest(const VMM_GUEST_STARTUP* gstartup, GUEST_HANDLE guest, 59 CPU_ID host_cpu_to_allocate, BOOLEAN ready_to_run ) 60 { 61 GUEST_CPU_HANDLE gcpu; 62 const VIRTUAL_CPU_ID* vcpu = NULL; 63 const VMM_GUEST_CPU_STARTUP_STATE* cpus_arr = NULL; 64 65 #ifdef JLMDEBUG1 66 bprint("add_cpu_to_guest guest SU: %p, guest: %d, host: %d\n", 67 gstartup, guest, host_cpu_to_allocate); 68 #endif 69 gcpu = guest_add_cpu(guest); 70 VMM_ASSERT(gcpu); 71 // find init data 72 vcpu= guest_vcpu(gcpu); 73 VMM_ASSERT(vcpu); 74 // register with scheduler 75 scheduler_register_gcpu(gcpu, host_cpu_to_allocate, ready_to_run); 76 #ifdef JLMDEBUG1 77 bprint("done with scheduler_register_gcpu 0x%016lx\n", vcpu); 78 bprint("guest_cpu_id: %d\n", vcpu->guest_cpu_id); 79 bprint("states count: %d\n", gstartup->cpu_states_count); 80 #endif 81 if(vcpu->guest_cpu_id<gstartup->cpu_states_count) { 82 cpus_arr = (const VMM_GUEST_CPU_STARTUP_STATE*)gstartup->cpu_states_array; 83 #ifdef JLMDEBUG 84 if(cpus_arr==NULL) { 85 bprint("cpus_arr is NULL\n"); 86 LOOP_FOREVER 87 } 88 #endif 89 VMM_ASSERT(cpus_arr); 90 VMM_LOG(mask_anonymous, level_trace, 91 "Setting up initial state for the newly created Guest CPU\n"); 92 #ifdef JLMDEBUG1 93 bprint("about to call gcpu_initialize(0x%016lx, 0x%016lx)\n", vcpu, gcpu); 94 #endif 95 gcpu_initialize(gcpu, &(cpus_arr[vcpu->guest_cpu_id])); 96 } 97 else { 98 VMM_LOG(mask_anonymous, level_trace, 99 "Newly created Guest CPU was initialized with the Wait-For-SIPI state\n"); 100 } 101 // host part will be initialized later 102 #ifdef JLMDEBUG1 103 bprint("done with add_cpu_to_guest\n"); 104 #endif 105 } 106 107 // Init guest except for guest memory 108 // Return NULL on error 109 static GUEST_HANDLE init_single_guest(UINT32 number_of_host_processors, 110 const VMM_GUEST_STARTUP* gstartup, 111 const VMM_POLICY *guest_policy) 112 { 113 GUEST_HANDLE guest; 114 UINT32 cpu_affinity = 0; 115 UINT32 bit_number; 116 BOOLEAN ready_to_run = FALSE; 117 118 if ((gstartup->size_of_this_struct!=sizeof(VMM_GUEST_STARTUP)) || 119 (gstartup->version_of_this_struct!=VMM_GUEST_STARTUP_VERSION )) { 120 VMM_LOG(mask_anonymous, level_trace, 121 "ASSERT: unknown guest struct: size: %#x version %d\n", 122 gstartup->size_of_this_struct, gstartup->version_of_this_struct ); 123 return NULL; 124 } 125 #ifdef JLMDEBUG 126 bprint("about to init_single_guest, guest magic: %d\n", 127 gstartup->guest_magic_number); 128 #endif 129 130 // create guest 131 guest= guest_register(gstartup->guest_magic_number, 132 gstartup->physical_memory_size, 133 gstartup->cpu_affinity, guest_policy); 134 if (!guest) { 135 #ifdef JLMDEBUG 136 bprint("guest register failed\n"); 137 LOOP_FOREVER 138 #endif 139 return NULL; 140 } 141 #ifdef FAST_VIEW_SWITCH 142 fvs_initialize(guest, number_of_host_processors); 143 #endif 144 vmexit_guest_initialize(guest_get_id(guest)); 145 if (gstartup->devices_count!=0) { 146 #ifdef JLMDEBUG 147 bprint("vmexit_guest_initialize failed\n"); 148 LOOP_FOREVER 149 #endif 150 return NULL; 151 } 152 if (gstartup->image_size) { 153 guest_set_executable_image( guest, (const UINT8*)gstartup->image_address, 154 gstartup->image_size, gstartup->image_offset_in_guest_physical_memory, 155 BITMAP_GET(gstartup->flags, VMM_GUEST_FLAG_IMAGE_COMPRESSED)!=0); 156 } 157 if(BITMAP_GET(gstartup->flags, VMM_GUEST_FLAG_REAL_BIOS_ACCESS_ENABLE)!=0) { 158 #ifdef JLMDEBUG 159 bprint("calling guest_set_real_BIOS_access_enabled\n"); 160 #endif 161 guest_set_real_BIOS_access_enabled(guest); 162 } 163 msr_vmexit_guest_setup(guest); // setup MSR-related control structure 164 #ifdef JLMDEBUG1 165 bprint("finished msr_vmexit_guest_setup 0x%016lx\n", guest); 166 #endif 167 168 // init cpus. 169 // first init CPUs that has initial state 170 cpu_affinity = gstartup->cpu_affinity; 171 if (cpu_affinity==0) { 172 return NULL; 173 } 174 ready_to_run= (BITMAP_GET(gstartup->flags, VMM_GUEST_FLAG_LAUNCH_IMMEDIATELY)!=0); 175 if (cpu_affinity == (UINT32)-1) { 176 // special case - run on all existing CPUs 177 for(bit_number= 0; bit_number<number_of_host_processors; bit_number++) { 178 #ifdef JLMDEBUG1 179 bprint("bit_number: %d\n", bit_number); 180 bprint("gstartup: %p\n", gstartup); 181 #endif 182 add_cpu_to_guest(gstartup, guest, (CPU_ID)bit_number, ready_to_run); 183 VMM_LOG(mask_anonymous, level_trace, 184 "CPU #%d added successfully to the current guest\n", bit_number); 185 } 186 } 187 #ifdef DEBUG 188 //register_vmcall_services(guest); 189 guest_register_vmcall_services(guest); 190 #endif 191 #ifdef JLMDEBUG 192 bprint("init_single_guest finished, ready_to_run: %d\n", ready_to_run ); 193 #endif 194 return guest; 195 } 196 197 198 // Perform initialization of guests and guest CPUs 199 // Should be called on BSP only while all APs are stopped 200 // Return TRUE for success 201 BOOLEAN initialize_all_guests( UINT32 number_of_host_processors, 202 #if 0 // for later: additional excluded areas 203 int num_excluded, 204 #endif 205 const VMM_MEMORY_LAYOUT* vmm_memory_layout, 206 const VMM_GUEST_STARTUP* primary_guest_startup_state, 207 UINT32 number_of_secondary_guests, 208 const VMM_GUEST_STARTUP* secondary_guests_startup_state_array, 209 const VMM_APPLICATION_PARAMS_STRUCT* application_params) 210 { 211 GUEST_HANDLE primary_guest; 212 GPM_HANDLE primary_guest_startup_gpm; 213 BOOLEAN ok = FALSE; 214 GUEST_CPU_HANDLE gcpu; 215 GUEST_GCPU_ECONTEXT gcpu_context; 216 217 VMM_ASSERT(hw_cpu_id() == 0); 218 VMM_ASSERT(number_of_host_processors > 0); 219 VMM_ASSERT(vmm_memory_layout); 220 VMM_ASSERT(primary_guest_startup_state); 221 222 if (number_of_secondary_guests>0) { 223 VMM_LOG(mask_anonymous, level_trace,"initialize_all_guests ASSERT: Secondary guests are yet not implemented\n"); 224 VMM_ASSERT( secondary_guests_startup_state_array ); 225 // init guests and allocate memory for them 226 // shutdown temporary layout object 227 VMM_DEADLOOP(); 228 return FALSE; 229 } 230 231 // first init primary guest 232 VMM_LOG(mask_anonymous, level_trace,"Init primary guest\n"); 233 234 // BUGBUG: This is a workaround until loader will not do this!!! 235 BITMAP_SET(((VMM_GUEST_STARTUP*)primary_guest_startup_state)->flags, 236 VMM_GUEST_FLAG_REAL_BIOS_ACCESS_ENABLE|VMM_GUEST_FLAG_LAUNCH_IMMEDIATELY); 237 #ifdef JLMDEBUG 238 bprint("initialize_all_guests, %d CPUs\n", number_of_host_processors); 239 #endif 240 // TODO: Uses global policy but should be part of VMM_GUEST_STARTUP structure. 241 ((VMM_GUEST_STARTUP*)primary_guest_startup_state)->guest_magic_number= PRIMARY_MAGIC; 242 primary_guest = init_single_guest(number_of_host_processors, 243 primary_guest_startup_state, NULL); 244 if (!primary_guest) { 245 VMM_LOG(mask_anonymous, level_trace, 246 "initialize_all_guests: Cannot init primary guest\n"); 247 VMM_DEADLOOP(); 248 return FALSE; 249 } 250 guest_set_primary(primary_guest); 251 primary_guest_startup_gpm = guest_get_startup_gpm(primary_guest); 252 253 // init memory layout in the startup gpm 254 // JLM(FIX) change this call 255 #if 1 256 ok = init_memory_layout(vmm_memory_layout, primary_guest_startup_gpm, 257 number_of_secondary_guests > 0, application_params); 258 #else 259 ok = init_memory_layout_from_mbr( num_excluded, vmm_memory_layout, primary_guest_startup_gpm, 260 number_of_secondary_guests > 0, application_params); 261 #endif 262 263 // Set active_gpm to startup gpm 264 for(gcpu = guest_gcpu_first(primary_guest, &gcpu_context); gcpu; gcpu = guest_gcpu_next(&gcpu_context)) { 265 gcpu_set_current_gpm(gcpu, primary_guest_startup_gpm); 266 } 267 VMM_LOG(mask_anonymous, level_trace,"Primary guest initialized successfully\n"); 268 return ok; 269 } 270 271 // Perform initialization of host cpu portion of all guest CPUs that run 272 // on specified host CPU. Should be called on the target host CPU 273 void initialize_host_vmcs_regions( CPU_ID current_cpu_id ) 274 { 275 GUEST_CPU_HANDLE gcpu; 276 SCHEDULER_GCPU_ITERATOR it; 277 278 VMM_ASSERT(current_cpu_id == hw_cpu_id()); 279 for (gcpu = scheduler_same_host_cpu_gcpu_first( &it, current_cpu_id ); 280 gcpu != NULL; gcpu = scheduler_same_host_cpu_gcpu_next( &it )) { 281 // now init the host CPU part for vm-exits 282 host_cpu_vmcs_init(gcpu); 283 } 284 } 285