github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/vmm.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(VMM_C) 17 #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(VMM_C, __condition) 18 #include "vmm_defs.h" 19 #include "vmm_startup.h" 20 #include "vmm_globals.h" 21 #include "vmm_callback.h" 22 #include "libc.h" 23 #include "vmm_serial.h" 24 #include "cli.h" 25 #include "address.h" 26 #include "lock.h" 27 #include "hw_includes.h" 28 #include "heap.h" 29 #include "gdt.h" 30 #include "isr.h" 31 #include "vmm_stack_api.h" 32 #include "e820_abstraction.h" 33 #include "host_memory_manager_api.h" 34 #include "cli_monitor.h" 35 #include "vmcs_init.h" 36 #include "efer_msr_abstraction.h" 37 #include "mtrrs_abstraction.h" 38 #include "guest.h" 39 #include "policy_manager.h" 40 #include "host_cpu.h" 41 #include "scheduler.h" 42 #include "vmm_bootstrap_utils.h" 43 #include "ipc.h" 44 #include "vmexit.h" 45 #include "vmm_dbg.h" 46 #include "vmx_trace.h" 47 #include "event_mgr.h" 48 #include <pat_manager.h> 49 #include "host_pci_configuration.h" 50 #include "guest_pci_configuration.h" 51 #include "vtd.h" 52 #include "ept.h" 53 #include "device_drivers_manager.h" 54 #include "vmx_nmi.h" 55 #include "vmdb.h" 56 #include "vmx_timer.h" 57 #include "guest/guest_cpu/unrestricted_guest.h" 58 #include "vmx_teardown.h" 59 #include "vmcs_api.h" 60 #ifdef FAST_VIEW_SWITCH 61 #include "fvs.h" 62 #endif 63 #include "profiling.h" 64 #ifdef USE_ACPI 65 #include "vmm_acpi.h" 66 #endif 67 68 #define __builtin_va_end(p) 69 #define __builtin_stdarg_start(a,b) 70 #define __builtin_va_arg(a,p) 0 71 72 #ifdef JLMDEBUG 73 #include "jlmdebug.h" 74 #endif 75 76 77 #ifdef JLMDEBUG 78 79 #define PS 0x00000080ULL 80 UINT64 getphysical(UINT64 cr3, UINT64 virt) 81 { 82 UINT64 i1, i2, i3, i4, i5; 83 UINT64 *b1, *b2, *b3, *b4; 84 UINT64 c0, c1, c2, c3, c4; 85 UINT64 phys; 86 87 c0= cr3; 88 c0&= (UINT64)~0xfff; // pml4 89 90 i1= virt>>39; 91 i2= (virt>>30)&(UINT64)0x1ff; 92 i3= (virt>>21)&(UINT64)0x01ff; 93 94 b1= (UINT64*) (c0+sizeof(UINT64)*i1); 95 if((*b1&0x1)==0) { 96 bprint("Mapping failed for b1\n"); 97 return (UINT64)-1; 98 } 99 c1= *b1&~(UINT64)0xfff; 100 b2= (UINT64*) (c1+sizeof(UINT64)*i2); 101 if((*b2&0x1)==0) { 102 bprint("Mapping failed for b2\n"); 103 return (UINT64)-1; 104 } 105 c2= *b2&~(UINT64)0xfff; 106 b3= (UINT64*)(c2+sizeof(UINT64)*i3); 107 if((*b3&0x1)==0) { 108 bprint("Mapping failed for b3\n"); 109 return (UINT64)-1; 110 } 111 if((*b3&PS)!=0) { 112 i4= virt&(UINT64)0x01fffff; 113 c3= *b3; 114 c3&= ~0x01fffff; 115 return c3|i4; 116 } 117 i4= (virt>>12)&(UINT64)0x01ff; 118 i5= virt&(UINT64)0x0fff; 119 c3= *b3&~(UINT64)0xfff; 120 b4= (UINT64*)(c3+sizeof(UINT64)*i4); 121 if((*b4&0x1)==0) { 122 bprint("Mapping failed for b4\n"); 123 return (UINT64)-1; 124 } 125 c4= *b4&~(UINT64)0xfff; 126 phys= c4|i5; 127 return phys; 128 } 129 #endif 130 131 132 BOOLEAN vmcs_sw_shadow_disable[VMM_MAX_CPU_SUPPORTED]; 133 134 typedef struct VMM_INPUT_PARAMS_S { 135 UINT64 local_apic_id; 136 UINT64 startup_struct; 137 UINT64 application_params_struct; // change name 138 } VMM_INPUT_PARAMS; 139 140 // globals 141 VMM_STARTUP_STRUCT vmm_startup_data; 142 CPU_ID g_num_of_cpus = 0; 143 static volatile UINT32 g_application_procs_may_be_launched = FALSE; 144 static volatile UINT32 g_application_procs_launch_the_guest = 0; 145 VMM_PAGING_POLICY g_pg_policy; 146 UINT32 g_is_post_launch = 0; 147 148 extern void *g_vmx_capabilities_ptr; 149 extern UINT64 g_debug_gpa; 150 extern UINT64 g_session_id; 151 extern void setup_data_for_s3(void); 152 153 UINT64 g_additional_heap_pa = 0; 154 UINT32 g_heap_pa_num = 0; 155 UINT64 g_additional_heap_base = 0; 156 extern BOOLEAN build_extend_heap_hpa_to_hva(void); 157 158 #define WAIT_FOR_APPLICATION_PROCS_LAUNCH() \ 159 {while (!g_application_procs_may_be_launched) { hw_pause(); }} 160 161 #define LAUNCH_APPLICATION_PROCS() \ 162 {hw_assign_as_barrier( &g_application_procs_may_be_launched, TRUE);} 163 164 #define WAIT_FOR_APPLICATION_PROCS_LAUNCHED_THE_GUEST( count ) \ 165 {while (g_application_procs_launch_the_guest != (UINT32)(count)) { hw_pause(); }} 166 167 #define APPLICATION_PROC_LAUNCHING_THE_GUEST() \ 168 {hw_interlocked_increment((INT32*)(&g_application_procs_launch_the_guest));} 169 170 171 // main for BSP - should never return. local_apic_id is always 0 172 void vmm_bsp_proc_main(UINT32 local_apic_id, 173 const VMM_STARTUP_STRUCT* startup_struct, 174 const VMM_APPLICATION_PARAMS_STRUCT* application_params_struct); 175 176 // main for APs - should never return 177 void vmm_application_procs_main(UINT32 local_apic_id); 178 int cli_show_memory_layout(unsigned argc, char *args[]); 179 void make_guest_state_compliant(GUEST_CPU_HANDLE gcpu); 180 181 #if defined DEBUG || defined ENABLE_RELEASE_VMM_LOG 182 // implementation 183 INLINE UINT8 lapic_id(void) 184 { 185 CPUID_PARAMS cpuid_params; 186 cpuid_params.m_rax = 1; 187 hw_cpuid(&cpuid_params); 188 return (UINT8) (cpuid_params.m_rbx >> 24) & 0xFF; 189 } 190 #endif 191 192 INLINE void enable_fx_ops(void) 193 { 194 UINT64 CR0_Value = hw_read_cr0(); 195 BITMAP_CLR64(CR0_Value,CR0_TS); 196 197 BITMAP_CLR64(CR0_Value,CR0_MP); 198 hw_write_cr0(CR0_Value); 199 } 200 201 INLINE void enable_ept_during_launch(GUEST_CPU_HANDLE initial_gcpu) 202 { 203 UINT64 guest_cr4; 204 205 #ifdef JLMDEBUG 206 bprint("enable_ept_during_launch\n"); 207 #endif 208 ept_acquire_lock(); 209 // Enable EPT, if it is currently not enabled 210 if( !ept_is_ept_enabled(initial_gcpu) ) { 211 ept_enable(initial_gcpu); 212 //set the right pdtprs into the vmcs. 213 guest_cr4 = gcpu_get_guest_visible_control_reg(initial_gcpu, IA32_CTRL_CR4); 214 ept_set_pdtprs(initial_gcpu, guest_cr4); 215 } 216 ept_release_lock(); 217 } 218 219 // Per CPU type policy setup 220 // Sets policies depending on host CPU features. Should be called on BSP only 221 void vmm_setup_cpu_specific_policies( VMM_POLICY* p_policy ) 222 { 223 CPUID_INFO_STRUCT info; 224 UINT32 cpuid_1_eax; // cpu identification 225 226 cpuid(&info, 1); // get version info 227 cpuid_1_eax = CPUID_VALUE_EAX(info); 228 229 // WSM CPUs has ucode bug that crashes CPU if VTx is ON and CR0.CD=1 230 // prevent this 231 // WSM cpu ids 232 // wsm_a0 - 0x00020650 233 // wsm_b0 - 0x00020651 234 // wsm_e0 - 0x00020654 235 // wsm_t0 - 0x000206c0 236 // wsm_u0 - 0x000206c0 - temp 237 switch (cpuid_1_eax & ~0xF) { 238 case 0x00020650: 239 case 0x000206c0: 240 VMM_LOG(mask_uvmm, level_trace, 241 "Switching ON policy to disable CR0.CD=1 settings\n"); 242 set_cache_policy(p_policy, POL_CACHE_DIS_VIRTUALIZATION); 243 break; 244 default: 245 set_cache_policy(p_policy, POL_CACHE_DIS_NO_INTERVENING); 246 break; 247 } 248 } 249 250 extern void ASM_FUNCTION ITP_JMP_DEADLOOP(void); 251 252 // main 253 // Started in parallel for all available processors 254 // Should never return! 255 void vmm_main_continue(VMM_INPUT_PARAMS* vmm_input_params) 256 { 257 const VMM_STARTUP_STRUCT* startup_struct = (const VMM_STARTUP_STRUCT*)vmm_input_params->startup_struct; 258 const VMM_APPLICATION_PARAMS_STRUCT* application_params_struct = (const VMM_APPLICATION_PARAMS_STRUCT*)(vmm_input_params->application_params_struct); 259 260 UINT32 local_apic_id = (UINT32)(vmm_input_params->local_apic_id); 261 262 if (local_apic_id == 0) { 263 vmm_bsp_proc_main(local_apic_id, startup_struct, application_params_struct); 264 } 265 else { 266 vmm_application_procs_main(local_apic_id); 267 } 268 VMM_BREAKPOINT(); 269 } 270 271 void vmm_main(UINT32 local_apic_id, UINT64 startup_struct_u, 272 UINT64 application_params_struct_u, UINT64 reserved UNUSED) 273 { 274 #ifdef JLMDEBUG 275 bootstrap_partial_reset(); 276 bprint("vmm_main in 64 bit mode\n"); 277 bprint("local_apic_id %d, startup_struct_u %llx\n", local_apic_id, startup_struct_u); 278 bprint("application_params_struct_u %llx, reserved %llx\n", 279 application_params_struct_u, reserved); 280 #endif 281 const VMM_STARTUP_STRUCT* startup_struct = 282 (const VMM_STARTUP_STRUCT*)startup_struct_u; 283 HVA new_stack_pointer = 0; 284 VMM_INPUT_PARAMS input_params; 285 CPU_ID cpu_id = (CPU_ID)local_apic_id; 286 287 vmm_startup_data = *startup_struct; // save for usage during S3 resume 288 { 289 BOOLEAN release_mode=TRUE; 290 VMM_DEBUG_CODE(release_mode = FALSE); 291 if (release_mode) { 292 #ifdef ENABLE_RELEASE_VMM_LOG 293 vmm_startup_data.debug_params.verbosity = 294 vmm_startup_data.debug_params.verbosity && 0x1; 295 // Limits the verbosity level to 1 when 296 // VMM_LOG is enabled in release build 297 vmm_startup_data.debug_params.mask = vmm_startup_data.debug_params.mask & 298 ~((1<< mask_cli)+(1<<mask_anonymous)+(1<<mask_emulator)+ 299 (1<<mask_gdb)+(1<<mask_ept)+(1<<mask_handler)); 300 #else 301 vmm_startup_data.debug_params.mask = vmm_startup_data.debug_params.mask & 302 ~((1<< mask_cli)+(1<<mask_anonymous)+(1<<mask_emulator)+ 303 (1<<mask_gdb)+(1<<mask_ept)+(1<<mask_uvmm)+ 304 (1<<mask_tmm)+(1<<mask_tmsl)+(1<<mask_handler)); 305 #endif 306 } 307 } 308 host_cpu_enable_usage_of_xmm_regs(); 309 310 // setup stack 311 if (!startup_struct || !vmm_stack_caclulate_stack_pointer(startup_struct, cpu_id, &new_stack_pointer)) { 312 VMM_BREAKPOINT(); 313 } 314 input_params.local_apic_id = local_apic_id; 315 input_params.startup_struct = startup_struct_u; 316 input_params.application_params_struct = application_params_struct_u; 317 hw_set_stack_pointer(new_stack_pointer, (main_continue_fn)vmm_main_continue, 318 &input_params); 319 } 320 321 322 // The Boot Strap Processor main routine 323 // Should never return! 324 void vmm_bsp_proc_main(UINT32 local_apic_id, const VMM_STARTUP_STRUCT* startup_struct, 325 const VMM_APPLICATION_PARAMS_STRUCT* application_params_struct) 326 { 327 HVA lowest_stacks_addr = 0; 328 UINT32 stacks_size = 0; 329 HVA heap_address; 330 UINT32 heap_size; 331 HVA heap_last_occupied_address; 332 CPU_ID num_of_cpus = (CPU_ID)startup_struct->number_of_processors_at_boot_time; 333 CPU_ID cpu_id = (CPU_ID)local_apic_id; 334 HPA new_cr3 = 0; 335 const VMM_STARTUP_STRUCT* startup_struct_heap; 336 const VMM_APPLICATION_PARAMS_STRUCT* application_params_heap; 337 const VMM_GUEST_STARTUP* primary_guest_startup; 338 const VMM_GUEST_STARTUP* secondary_guests_array; 339 GUEST_HANDLE nmi_owner_guest, device_default_owner_guest, acpi_owner_guest; 340 UINT32 num_of_guests; 341 GUEST_CPU_HANDLE initial_gcpu = NULL; 342 VMM_POLICY policy; 343 BOOLEAN debug_port_params_error; 344 REPORT_INITIALIZATION_DATA initialization_data; 345 GUEST_HANDLE guest; 346 GUEST_ECONTEXT guest_ctx; 347 UINT32 i = 0; 348 349 #ifdef USE_ACPI 350 HVA fadt_hva = 0; 351 #ifdef ENABLE_VTD 352 HVA dmar_hva = 0; 353 #endif 354 #endif 355 356 #ifdef JLMDEBUG 357 bprint("evmm bsp_main\n"); 358 #endif 359 360 // save number of CPUs 361 g_num_of_cpus = num_of_cpus; 362 363 // get post launch status 364 #if 1 365 g_is_post_launch = (BITMAP_GET(startup_struct->flags, VMM_STARTUP_POST_OS_LAUNCH_MODE) != 0); 366 #else 367 g_is_post_launch = 0; 368 #endif 369 hw_calibrate_tsc_ticks_per_second(); 370 371 // Init the debug port. If the version is too low, there's no debug parameters. 372 // Use the defaults and later on assert. 373 if (startup_struct->version_of_this_struct >= VMM_STARTUP_STRUCT_MIN_VERSION_WITH_DEBUG) { 374 debug_port_params_error = vmm_debug_port_init_params(&startup_struct->debug_params.port); 375 g_debug_gpa = startup_struct->debug_params.debug_data; 376 } else { 377 debug_port_params_error = vmm_debug_port_init_params(NULL); 378 } 379 380 // init the LIBC library 381 vmm_libc_init(); 382 // Now we have a functional debug output 383 #ifdef JLMDEBUG 384 bprint("evmm: past vmm_libc_init()\n"); 385 #endif 386 if (debug_port_params_error) { 387 VMM_LOG(mask_uvmm, level_error, 388 "\nFAILURE: Loader-VMM version mismatch (no debug port parameters)\n"); 389 VMM_DEADLOOP(); 390 }; 391 392 if(g_is_post_launch) { 393 if(application_params_struct) { 394 if (application_params_struct->size_of_this_struct != 395 sizeof(VMM_APPLICATION_PARAMS_STRUCT)) { 396 VMM_LOG(mask_uvmm, level_error, 397 "\nFAILURE: application params structure size mismatch)\n"); 398 VMM_DEADLOOP(); 399 }; 400 g_session_id = application_params_struct->session_id; 401 g_heap_pa_num = (UINT32)(application_params_struct->entry_number); 402 g_additional_heap_pa = application_params_struct->address_entry_list; 403 } 404 else 405 g_session_id = 0; 406 } 407 408 // Print global version message 409 vmm_version_print(); 410 VMM_LOG(mask_uvmm, level_trace,"\nBSP: uVMM image base address = %P, entry point address = %P\n", 411 startup_struct->vmm_memory_layout[0].base_address, 412 startup_struct->vmm_memory_layout[0].entry_point); 413 414 // check input structure 415 if (startup_struct->version_of_this_struct != VMM_STARTUP_STRUCT_VERSION) { 416 VMM_LOG(mask_uvmm, level_error, 417 "\nFAILURE: Loader-VMM version mismatch (init structure version mismatch)\n"); 418 VMM_DEADLOOP(); 419 #ifdef JLMDEBUG 420 bprint("startup struct wrong version\n"); 421 LOOP_FOREVER 422 #endif 423 }; 424 if (startup_struct->size_of_this_struct != sizeof(VMM_STARTUP_STRUCT)) { 425 VMM_LOG(mask_uvmm, level_error, 426 "\nFAILURE: Loader-VMM version mismatch (init structure size mismatch)\n"); 427 VMM_DEADLOOP(); 428 #ifdef JLMDEBUG 429 bprint("startup struct wrong size %lu %d\n", sizeof(VMM_STARTUP_STRUCT), 430 startup_struct->size_of_this_struct); 431 #endif 432 }; 433 434 // setup address space 435 addr_setup_address_space(); 436 // Initialize stack 437 if (!vmm_stack_initialize(startup_struct)) { 438 VMM_LOG(mask_uvmm, level_error, 439 "\nFAILURE: Stack initialization failed\n"); 440 VMM_DEADLOOP(); 441 #ifdef JLMDEBUG 442 bprint("Cant initialize stack\n"); 443 LOOP_FOREVER 444 #endif 445 } 446 447 VMM_ASSERT(vmm_stack_is_initialized()); 448 vmm_stacks_get_details(&lowest_stacks_addr, &stacks_size); 449 VMM_LOG(mask_uvmm, level_trace,"\nBSP:Stacks are successfully initialized:\n"); 450 VMM_LOG(mask_uvmm, level_trace,"\tlowest address of all stacks area = %P\n", 451 lowest_stacks_addr); 452 VMM_LOG(mask_uvmm, level_trace,"\tsize of whole stacks area = %P\n", 453 stacks_size); 454 VMM_DEBUG_CODE(vmm_stacks_print()); 455 456 // Initialize Heap 457 heap_address = lowest_stacks_addr + stacks_size; 458 heap_size = (UINT32) ((startup_struct->vmm_memory_layout[0].base_address + 459 startup_struct->vmm_memory_layout[0].total_size) - heap_address); 460 heap_last_occupied_address = vmm_heap_initialize(heap_address, heap_size); 461 #ifdef JLMDEBUG 462 bprint("stack initialized %d\n", vmm_stack_is_initialized()); 463 bprint("heap_address, heap_size, heap_last_occupied_address: 0x%llx, %u, 0x%llx\n", 464 heap_address, heap_size, heap_last_occupied_address); 465 #endif 466 VMM_LOG(mask_uvmm, level_trace,"\nBSP:Heap is successfully initialized: \n"); 467 VMM_LOG(mask_uvmm, level_trace,"\theap base address = %P \n", heap_address); 468 VMM_LOG(mask_uvmm, level_trace,"\theap last occupied address = %P \n", 469 heap_last_occupied_address); 470 VMM_ASSERT(heap_last_occupied_address<=(startup_struct->vmm_memory_layout[0].base_address + startup_struct->vmm_memory_layout[0].total_size)); 471 #if 0 // Debug print 472 VMM_LOG(mask_uvmm, level_trace,"\tactual size is %P, when requested size was %P\n", 473 heap_last_occupied_address-heap_address, heap_size); 474 #endif 475 476 // Initialize CLI monitor 477 CliMonitorInit(); // must be called after heap initialization. 478 479 vmdb_initialize(); 480 vmm_serial_cli_init(); 481 482 #ifdef DEBUG 483 CLI_AddCommand( 484 cli_show_memory_layout, 485 "debug memory layout", 486 "Print overall memory layout", "", 487 CLI_ACCESS_LEVEL_USER); 488 #endif 489 VMM_LOG(mask_uvmm, level_trace,"BSP: Original VMM_STARTUP_STRUCT dump\n"); 490 VMM_DEBUG_CODE( 491 print_startup_struct( startup_struct ); 492 ) 493 494 // Copy the startup data to heap. 495 // After this point all pointers points to the same structure in the heap. 496 startup_struct_heap = vmm_create_startup_struct_copy(startup_struct); 497 startup_struct = startup_struct_heap; // overwrite the parameter; 498 if (startup_struct_heap == NULL) { 499 VMM_DEADLOOP(); 500 } 501 VMM_LOG(mask_uvmm, level_trace,"BSP: Copied VMM_STARTUP_STRUCT dump\n"); 502 VMM_DEBUG_CODE( print_startup_struct( startup_struct ); ) 503 504 application_params_heap = vmm_create_application_params_struct_copy(application_params_struct); 505 if ((application_params_struct != NULL) && (application_params_heap == NULL)) { 506 VMM_DEADLOOP(); 507 } 508 application_params_struct = application_params_heap; // overwrite the parameter 509 510 #ifdef JLMDEBUG 511 bprint("evmm after vmm_create_application_params_struct_copy,num of cpus: %d\n", num_of_cpus); 512 uint16_t cpuid= hw_cpu_id(); 513 bprint("BSP hw_cpu_id: %04x\n", cpuid); 514 #endif 515 516 // Initialize GDT for all cpus 517 hw_gdt_setup(num_of_cpus); 518 VMM_LOG(mask_uvmm, level_trace,"\nBSP: GDT setup is finished.\n"); 519 520 // Load GDT for BSP 521 hw_gdt_load(cpu_id); 522 VMM_LOG(mask_uvmm, level_trace,"BSP: GDT is loaded.\n"); 523 524 // Initialize IDT for all cpus 525 isr_setup(); 526 VMM_LOG(mask_uvmm, level_trace,"\nBSP: ISR setup is finished. \n"); 527 528 // Load IDT for BSP 529 isr_handling_start(); 530 VMM_LOG(mask_uvmm, level_trace,"BSP: ISR handling started. \n"); 531 532 #ifdef JLMDEBUG 533 bprint("evmm: GDT, IDT loaded for BSP \n"); 534 #endif 535 536 // Store information about e820 537 if (!e820_abstraction_initialize((const INT15_E820_MEMORY_MAP*)startup_struct->physical_memory_layout_E820)) { 538 VMM_LOG(mask_uvmm, level_error, "BSP FAILURE: there is no proper e820 map\n"); 539 VMM_DEADLOOP(); 540 } 541 542 if (!mtrrs_abstraction_bsp_initialize()) { 543 VMM_LOG(mask_uvmm, level_error, "BSP FAILURE: failed to cache mtrrs\n"); 544 VMM_DEADLOOP(); 545 } 546 VMM_LOG(mask_uvmm, level_trace,"\nBSP: MTRRs were successfully cached.\n"); 547 548 #if 0 // No longer needed 549 // Executable info will now be in vmm_memory_map 550 // init uVMM image parser. TODO: mark executable areas 551 exec_image_initialize(); 552 #endif 553 554 #ifdef JLMDEBUG 555 bprint("evmm: about to call hmm_initialize()\n"); 556 #endif 557 // Initialize Host Memory Manager 558 if (!hmm_initialize(startup_struct)) { 559 VMM_LOG(mask_uvmm, level_error, 560 "\nBSP FAILURE: Initialization of Host Memory Manager has failed\n"); 561 VMM_DEADLOOP(); 562 #ifdef JLMDEBUG 563 bprint("hmm_initialize failed\n"); 564 LOOP_FOREVER 565 #endif 566 } 567 VMM_LOG(mask_uvmm, level_trace, 568 "\nBSP: Host Memory Manager was successfully initialized.\n"); 569 570 #ifdef JLMDEBUG 571 bprint("evmm: host memory manager intialized \n"); 572 #endif 573 hmm_set_required_values_to_control_registers(); 574 575 new_cr3 = hmm_get_vmm_page_tables(); // PCD and PWT bits will be 0; 576 #ifdef JLMDEBUG1 577 UINT64 old_cr3= hw_read_cr3(); 578 UINT64 old_cr4= hw_read_cr4(); 579 bprint("evmm position about to change memory mapping new cr3: 0x%016x, old cr3: 0x%016x\n", 580 new_cr3, old_cr3); 581 bprint("old cr4: 0x%llx\n", old_cr4); 582 HexDump((UINT8*)new_cr3, (UINT8*)new_cr3+40); 583 bprint("resetting cr3\n"); 584 hw_write_cr3(old_cr3); 585 bprint("that worked\n"); 586 bprint("new map\n"); 587 UINT64 tvirt= 0x70000000ULL; 588 UINT64 tphys= 0ULL; 589 tphys= getphysical(new_cr3, tvirt); 590 bprint("virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 591 tvirt= (UINT64) vmm_bsp_proc_main; 592 tphys= getphysical(new_cr3, tvirt); 593 bprint("(bsp)virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 594 tvirt= (UINT64) bprint; 595 tphys= getphysical(new_cr3, tvirt); 596 bprint("(bprint)virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 597 bprint("old map\n"); 598 tvirt= 0x70000000ULL; 599 tphys= 0ULL; 600 tphys= getphysical(old_cr3, tvirt); 601 bprint("virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 602 tvirt= (UINT64) vmm_bsp_proc_main; 603 tphys= getphysical(old_cr3, tvirt); 604 bprint("(bsp)virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 605 tvirt= (UINT64) bprint; 606 tphys= getphysical(old_cr3, tvirt); 607 bprint("(bprint)virt: 0x%llx, phys: 0x%llx\n", tvirt, tphys); 608 #endif 609 610 VMM_ASSERT(new_cr3 != HMM_INVALID_VMM_PAGE_TABLES); 611 VMM_LOG(mask_uvmm, level_trace,"BSP: New cr3=%P. \n", new_cr3); 612 613 // enable new memory map 614 hw_write_cr3(new_cr3); 615 #ifdef JLMDEBUG 616 bprint("evmm: new memory map installed\n"); 617 #endif 618 VMM_LOG(mask_uvmm, level_trace,"BSP: Successfully updated CR3 to new value\n"); 619 VMM_ASSERT(hw_read_cr3() == new_cr3); 620 621 #if 0 // S3 support (may depend on thunk? 622 // Allocates memory from heap for s3 resume structure on AP's 623 // This should be called before calling vmm_heap_extend() in order to 624 // ensure identity mapped memory within 4GB for post-OS launch. 625 // Upon heap extending, the memory allocated may be arbitrary mapped. 626 #ifdef ENABLE_PM_S3 627 setup_data_for_s3(); 628 #endif 629 #endif 630 if (g_is_post_launch) { 631 #ifdef JLMDEBUG 632 bprint("evmm is post launch (should never happen)\n"); 633 #endif 634 // To create [0~4G] identity mapping on NO UG machines (NHM), 635 // FPT will be used to handle guest non-paged protected mode. 636 // aka. CR0.PE = 1, CR0.PG = 0 637 // make sure the 32bit FPT pagetables located below 4G physical memory. 638 // assume that GPA-HPA mapping won't be changed. 639 // those page tables are cached. 640 if( !is_unrestricted_guest_supported()){ 641 BOOLEAN fpt_32bit_ok = 642 fpt_create_32_bit_flat_page_tables_under_4G((UINT64) 4 GIGABYTES - 1 ); 643 VMM_ASSERT(fpt_32bit_ok); 644 VMM_LOG(mask_uvmm, level_trace,"BSP: Successfully created 32bit FPT tables and cached them\n"); 645 } 646 init_teardown_lock(); 647 VMM_LOG(mask_uvmm, level_trace,"VMM: Image and stack used %dKB memory.\n", 648 ((UINT64)heap_address - startup_struct->vmm_memory_layout[uvmm_image].base_address)/(1024)); 649 VMM_ASSERT(g_additional_heap_base != 0); 650 heap_last_occupied_address = vmm_heap_extend( g_additional_heap_base, 651 g_heap_pa_num * PAGE_4KB_SIZE); 652 if (g_additional_heap_pa) 653 build_extend_heap_hpa_to_hva(); 654 } 655 VMM_DEBUG_CODE(vmm_trace_init(VMM_MAX_GUESTS_SUPPORTED, num_of_cpus)); 656 657 #ifdef PCI_SCAN 658 host_pci_initialize(); 659 #endif 660 661 // init vmcs hw 662 vmcs_hw_init(); 663 664 // init CR0/CR4 to the VMX compatible values 665 UINT64 old_cr0= hw_read_cr0(); 666 UINT64 new_cr0= vmcs_hw_make_compliant_cr0(old_cr0); 667 #ifdef JLMDEBUG 668 bprint("evmm: make cr0 vmx compatible. old_cr0: 0x%llx, new_cr0: 0x%llx\n", 669 old_cr0, new_cr0); 670 #endif 671 hw_write_cr0(new_cr0); 672 if(g_is_post_launch) { 673 // clear TS bit, since we need to operate on XMM registers. 674 enable_fx_ops(); 675 } 676 hw_write_cr4(vmcs_hw_make_compliant_cr4(hw_read_cr4())); 677 num_of_guests = startup_struct->number_of_secondary_guests + 1; 678 #ifdef JLMDEBUG 679 bprint("evmm: control registers are vmx compatible\n"); 680 #endif 681 682 // TODO: remove the compile time policy 683 clear_policy(&policy); 684 #ifdef VTLB_IS_SUPPORTED 685 set_paging_policy(&policy, ept_is_ept_supported() ? POL_PG_EPT: POL_PG_VTLB); 686 #else 687 if (ept_is_ept_supported()) { 688 set_paging_policy(&policy, POL_PG_EPT); 689 } 690 else { 691 VMM_LOG(mask_uvmm, level_error,"BSP: EPT is not supported\n"); 692 VMM_DEADLOOP(); 693 } 694 #endif 695 vmm_setup_cpu_specific_policies( &policy ); 696 global_policy_setup(&policy); 697 698 scheduler_init( (UINT16)num_of_cpus ); 699 #ifdef JLMDEBUG 700 bprint("evmm: policy and scheduler initialized\n"); 701 #endif 702 703 // init cpu manager, vmexit, host cpu, local apic 704 host_cpu_manager_init( num_of_cpus ); 705 guest_manager_init( (UINT16)num_of_cpus, (UINT16)num_of_cpus ); 706 local_apic_init( (UINT16)num_of_cpus ); 707 TMSL_PROFILING_INIT((UINT16)num_of_cpus ); 708 vmexit_initialize(); 709 host_cpu_init(); 710 local_apic_cpu_init(); 711 #ifdef JLMDEBUG 712 bprint("evmm: host, vmexit, local apic initialized\n"); 713 #endif 714 715 #ifdef ENABLE_PREEMPTION_TIMER 716 vmx_timer_hw_setup(); // called on every CPU 717 #endif 718 719 #ifdef INCLUDE_UNUSED_CODE 720 // init device drivers manager 721 ddm_initialize(); 722 #endif 723 724 // create guests 725 VMM_LOG(mask_uvmm, level_trace,"BSP: Create guests\n"); 726 primary_guest_startup = 727 (const VMM_GUEST_STARTUP*)startup_struct->primary_guest_startup_state; 728 VMM_ASSERT(primary_guest_startup); 729 730 secondary_guests_array = 731 (const VMM_GUEST_STARTUP*)startup_struct->secondary_guests_startup_state_array; 732 VMM_ASSERT((num_of_guests == 1) || (secondary_guests_array != 0)); 733 734 if (!initialize_all_guests(num_of_cpus, 735 #if 0 // Further memory exclusion support 736 // vmm_memory map will be changed to exclude multiple regions 737 (int) startup_struct->num_excluded_regions, 738 startup_struct->vmm_memory_layout, 739 #else 740 &(startup_struct->vmm_memory_layout[0]), 741 #endif 742 primary_guest_startup, num_of_guests - 1, 743 secondary_guests_array, application_params_heap)) { 744 VMM_LOG(mask_uvmm, level_error,"BSP: Error initializing guests. Halt.\n"); 745 VMM_DEADLOOP(); 746 } 747 #ifdef JLMDEBUG 748 bprint("evmm: guests initialized \n"); 749 bprint("nmi owner: %d\n", startup_struct->nmi_owner); 750 #endif 751 VMM_LOG(mask_uvmm, level_trace, 752 "BSP: Guests created succefully. Number of guests: %d\n", 753 guest_count()); 754 755 // should be set only after guests initialized 756 vmm_set_state(VMM_STATE_BOOT); 757 #ifdef JLMDEBUG 758 bprint("evmm: vmm_set_state done\n"); 759 #endif 760 761 // get important guest ids 762 nmi_owner_guest = guest_handle_by_magic_number(startup_struct->nmi_owner); 763 acpi_owner_guest = guest_handle_by_magic_number(startup_struct->acpi_owner); 764 device_default_owner_guest = guest_handle_by_magic_number( 765 startup_struct->default_device_owner); 766 #ifdef JLMDEBUG 767 bprint("evmm: nmi_owner, acpi owner, defaut device owner: %p %p %p\n", (void*)nmi_owner_guest, (void*)acpi_owner_guest, (void*)device_default_owner_guest); 768 #endif 769 VMM_ASSERT(nmi_owner_guest); 770 VMM_ASSERT(acpi_owner_guest); 771 VMM_ASSERT(device_default_owner_guest); 772 guest_set_nmi_owner(nmi_owner_guest); 773 guest_set_acpi_owner(acpi_owner_guest); 774 guest_set_default_device_owner(device_default_owner_guest); 775 VMM_LOG(mask_uvmm, level_trace, 776 "BSP: NMI owning guest ID=%d\tMagic Number= %#x\n", 777 guest_get_id(nmi_owner_guest), guest_magic_number(nmi_owner_guest)); 778 VMM_LOG(mask_uvmm, level_trace, 779 "BSP: ACPI owning guest ID=%d \tMagic Number = %#x\n", 780 guest_get_id(acpi_owner_guest), guest_magic_number(acpi_owner_guest)); 781 VMM_LOG(mask_uvmm, level_trace, 782 "BSP: Default device owning guest ID=%d \tMagic Number = %#x\n", 783 guest_get_id(device_default_owner_guest), 784 guest_magic_number(device_default_owner_guest)); 785 #ifdef JLMDEBUG 786 bprint("evmm: about to initialize guest manager\n"); 787 #endif 788 // Initialize Event Manager 789 // must be called after heap and CLI initialization 790 event_manager_initialize(num_of_cpus); 791 #ifdef PCI_SCAN 792 gpci_initialize(); 793 #endif 794 // init IPC engine 795 #ifdef OLD_IPC 796 if (!ipc_initialize(num_of_cpus)) 797 #else 798 if (!nmi_manager_initialize(num_of_cpus)) 799 #endif 800 { 801 VMM_LOG(mask_uvmm, level_trace,"\nFAILURE: IPC initialization failed\n"); 802 VMM_DEADLOOP(); 803 } 804 for(i=0; i < VMM_MAX_CPU_SUPPORTED; i++) 805 vmcs_sw_shadow_disable[i] = FALSE; 806 #ifdef JLMDEBUG 807 bprint("evmm: done with event manager, ipc, nmi intialize\n"); 808 #endif 809 810 if(g_is_post_launch) { 811 #ifdef USE_ACPI 812 if (INVALID_PHYSICAL_ADDRESS == application_params_struct->fadt_gpa || 813 !gpm_gpa_to_hva(gcpu_get_current_gpm(acpi_owner_guest), 814 (GPA)(application_params_struct->fadt_gpa), &fadt_hva)) 815 fadt_hva = 0; 816 #ifdef ENABLE_VTD 817 if (INVALID_PHYSICAL_ADDRESS == application_params_struct->dmar_gpa || 818 !gpm_gpa_to_hva(gcpu_get_current_gpm(acpi_owner_guest), 819 (GPA)(application_params_struct->dmar_gpa), &dmar_hva)) 820 dmar_hva = 0; 821 #endif 822 #endif 823 } 824 825 #ifdef USE_ACPI 826 vmm_acpi_init(fadt_hva); 827 #endif 828 829 #ifdef ENABLE_VTD 830 vtd_initialize( &(startup_struct->vmm_memory_layout[uvmm_image]),application_params_heap, dmar_hva); 831 #endif //ENABLE_VTD 832 833 // init all addon packages 834 start_addons(num_of_cpus, startup_struct_heap, application_params_heap); 835 #ifdef JLMDEBUG 836 bprint("evmm: done with add-ons\n"); 837 #endif 838 839 // Destroy startup structures, which reside in heap 840 vmm_destroy_startup_struct(startup_struct_heap); 841 startup_struct = NULL; 842 startup_struct_heap = NULL; 843 vmm_destroy_application_params_struct(application_params_heap); 844 application_params_struct = NULL; 845 application_params_heap = NULL; 846 847 // TODO: global var - init finished 848 vmcs_hw_allocate_vmxon_regions(num_of_cpus); 849 #ifdef JLMDEBUG 850 bprint("evmm: vmx allocate regions done\n"); 851 #endif 852 853 // Initialize guest data 854 initialization_data.num_of_cpus = (UINT16) num_of_cpus; 855 for (i = 0; i < VMM_MAX_GUESTS_SUPPORTED; i++) { 856 initialization_data.guest_data[i].guest_id = INVALID_GUEST_ID; 857 initialization_data.guest_data[i].primary_guest = FALSE; 858 } 859 if (num_of_guests>VMM_MAX_GUESTS_SUPPORTED) { 860 VMM_LOG(mask_uvmm, level_error, 861 "%s: %d guests not supported by VMM.\n", 862 __FUNCTION__, num_of_guests); 863 } else { 864 for (guest = guest_first(&guest_ctx), i = 0; guest; 865 guest = guest_next(&guest_ctx), i++) { 866 initialization_data.guest_data[i].guest_id = guest_get_id(guest); 867 if (guest_is_primary(guest)) { 868 initialization_data.guest_data[i].primary_guest = TRUE; 869 } 870 } 871 } 872 #ifdef JLMDEBUG 873 bprint("evmm: initialized guest data\n"); 874 #endif 875 if (!report_uvmm_event(UVMM_EVENT_INITIALIZATION_BEFORE_APS_STARTED, NULL, NULL, 876 (void *)&initialization_data)) { 877 VMM_LOG(mask_uvmm, level_trace, 878 "report_initialization failed before the APs have started\n"); 879 } 880 VMM_LOG(mask_uvmm, level_trace, 881 "BSP: Successfully finished single-core initializations\n"); 882 883 #ifdef JLMDEBUG 884 bprint("evmm: about to set state\n"); 885 #endif 886 vmm_set_state(VMM_STATE_WAIT_FOR_APs); 887 LAUNCH_APPLICATION_PROCS(); 888 #ifdef JLMDEBUG 889 bprint("evmm: about to initialize_host_vmcs_region\n"); 890 #endif 891 initialize_host_vmcs_regions(cpu_id); 892 VMM_LOG(mask_uvmm, level_trace,"BSP: Successfully finished initializations\n"); 893 894 #ifdef JLMDEBUG 895 bprint("evmm: about to turn on vmx\n"); 896 #endif 897 898 vmcs_hw_vmx_on(); 899 VMM_LOG(mask_uvmm, level_trace,"BSP: VMXON\n"); 900 #ifdef JLMDEBUG 901 bprint("evmm: vmx on\n"); 902 #endif 903 904 // schedule first gcpu 905 initial_gcpu = scheduler_select_initial_gcpu(); 906 if(initial_gcpu ==NULL) { 907 #ifdef JLMDEBUG 908 bprint("initial_gpu is NULL\n"); 909 LOOP_FOREVER 910 #endif 911 } 912 #ifdef JLMDEBUG 913 bprint("evmm: gcpu active, %p\n", (void*)initial_gcpu); 914 #endif 915 VMM_ASSERT(initial_gcpu != NULL); 916 VMM_LOG(mask_uvmm, level_trace, 917 "BSP: initial guest selected: GUEST_ID: %d GUEST_CPU_ID: %d\n", 918 guest_vcpu(initial_gcpu)->guest_id, 919 guest_vcpu(initial_gcpu)->guest_cpu_id); 920 ipc_change_state_to_active(initial_gcpu); 921 vmm_print_test(local_apic_id); 922 VMM_LOG(mask_uvmm, level_trace,"BSP: Wait for APs to launch the first Guest CPU\n"); 923 924 WAIT_FOR_APPLICATION_PROCS_LAUNCHED_THE_GUEST(num_of_cpus-1); 925 926 // Assumption: initialization_data was not changed 927 if (!report_uvmm_event(UVMM_EVENT_INITIALIZATION_AFTER_APS_STARTED, 928 (VMM_IDENTIFICATION_DATA)initial_gcpu, 929 (const GUEST_VCPU*)guest_vcpu(initial_gcpu), 930 (void *)&initialization_data)) { 931 VMM_LOG(mask_uvmm, level_trace, 932 "report_initialization failed after the APs have launched the guest\n"); 933 } 934 935 vmm_set_state(VMM_STATE_RUN); 936 VMM_LOG(mask_uvmm, level_trace,"BSP: Resuming the first Guest CPU\n"); 937 event_raise(EVENT_GUEST_LAUNCH, initial_gcpu, &local_apic_id); 938 #ifdef JLMDEBUG 939 bprint("evmm: raised initial event\n"); 940 #endif 941 942 // enable unrestricted guest support in early boot 943 // make guest state compliant for code execution 944 // On systems w/o UG, emulator takes care of it 945 if(is_unrestricted_guest_supported()) { 946 make_guest_state_compliant(initial_gcpu); 947 unrestricted_guest_enable(initial_gcpu); 948 #ifdef JLMDEBUG1 949 bprint("evmm: unrestricted_guest_enable complete, bsp\n"); 950 #endif 951 } 952 else { 953 #ifdef JLMDEBUG 954 bprint("evmm: unrestricted guest NOT supported\n"); 955 #endif 956 // For non-UG systems enable EPT, if guest is in paging mode 957 EM64T_CR0 guest_cr0; 958 guest_cr0.Uint64 = gcpu_get_guest_visible_control_reg(initial_gcpu, 959 IA32_CTRL_CR0); 960 if (guest_cr0.Bits.PG) { 961 #ifdef JLMDEBUG 962 bprint("evmm: about to call enable_ept_during_launch\n"); 963 #endif 964 enable_ept_during_launch(initial_gcpu); 965 } 966 #ifdef JLMDEBUG 967 bprint("evmm: enable_ept_during_launch not called\n"); 968 #endif 969 } 970 #ifdef FAST_VIEW_SWITCH 971 if(fvs_is_eptp_switching_supported()) { 972 #ifdef JLMDEBUG 973 bprint("evmm: about to call fvs_guest_vmfunc_enable\n"); 974 LOOP_FOREVER 975 #endif 976 fvs_guest_vmfunc_enable(initial_gcpu); 977 fvs_vmfunc_vmcs_init(initial_gcpu); 978 } 979 #endif // FAST_VIEW_SWITCH 980 981 #ifdef JLMDEBUG1 982 bprint("evmm: about to call vmcs_store_initial, bsp\n"); 983 #endif 984 vmcs_store_initial(initial_gcpu, cpu_id); 985 #ifdef JLMDEBUG 986 bprint("evmm: about to guest resume, bsp\n"); 987 #endif 988 gcpu_resume(initial_gcpu); 989 VMM_LOG(mask_uvmm, level_error,"BSP: Resume initial guest cpu failed\n", cpu_id); 990 VMM_DEADLOOP(); 991 } 992 993 994 // The Application Processor main routine 995 // Should never return! 996 void vmm_application_procs_main(UINT32 local_apic_id) 997 { 998 #ifdef JLMDEBUG 999 bprint("evmm: ap_main %d\n", local_apic_id); 1000 #endif 1001 CPU_ID cpu_id = (CPU_ID)local_apic_id; 1002 HPA new_cr3 = 0; 1003 GUEST_CPU_HANDLE initial_gcpu = NULL; 1004 1005 WAIT_FOR_APPLICATION_PROCS_LAUNCH(); 1006 VMM_LOG(mask_uvmm, level_trace,"\n\nAP%d: Alive. Local APIC ID=%P\n", 1007 cpu_id, lapic_id()); 1008 1009 // Load GDT/IDT 1010 hw_gdt_load(cpu_id); 1011 VMM_LOG(mask_uvmm, level_trace,"AP%d: GDT is loaded.\n", cpu_id); 1012 isr_handling_start(); 1013 VMM_LOG(mask_uvmm, level_trace,"AP%d: ISR handling started.\n", cpu_id); 1014 1015 if (!mtrrs_abstraction_ap_initialize()) { 1016 VMM_LOG(mask_uvmm, level_error,"AP%d FAILURE: Failed to cache MTRRs\n", 1017 cpu_id); 1018 VMM_DEADLOOP(); 1019 } 1020 VMM_LOG(mask_uvmm, level_trace,"AP%d: MTRRs were successfully cached\n", cpu_id); 1021 1022 // Set new CR3 to VMM page tables 1023 hmm_set_required_values_to_control_registers(); 1024 new_cr3 = hmm_get_vmm_page_tables(); 1025 VMM_ASSERT(new_cr3 != HMM_INVALID_VMM_PAGE_TABLES); 1026 VMM_LOG(mask_uvmm, level_trace,"AP%d: New cr3=%P. \n", cpu_id, new_cr3); 1027 hw_write_cr3(new_cr3); 1028 VMM_LOG(mask_uvmm, level_trace,"AP%d: Successfully updated CR3 to new value\n", 1029 cpu_id); 1030 VMM_ASSERT(hw_read_cr3() == new_cr3); 1031 VMM_ASSERT(vmcs_hw_is_cpu_vmx_capable()); 1032 1033 // init CR0/CR4 to the VMX compatible values 1034 hw_write_cr0(vmcs_hw_make_compliant_cr0(hw_read_cr0())); 1035 if(g_is_post_launch) { 1036 // clear TS bit, since we need to operate on XMM registers. 1037 enable_fx_ops(); 1038 } 1039 hw_write_cr4(vmcs_hw_make_compliant_cr4(hw_read_cr4())); 1040 1041 // init current host CPU 1042 host_cpu_init(); 1043 local_apic_cpu_init(); 1044 1045 initialize_host_vmcs_regions( cpu_id ); 1046 VMM_LOG(mask_uvmm, level_trace,"AP%d: Successfully finished initializations\n", cpu_id); 1047 1048 vmcs_hw_vmx_on(); 1049 VMM_LOG(mask_uvmm, level_trace,"AP%d: VMXON\n", cpu_id); 1050 1051 // schedule first gcpu 1052 initial_gcpu = scheduler_select_initial_gcpu(); 1053 VMM_ASSERT( initial_gcpu != NULL ); 1054 VMM_LOG(mask_uvmm, level_trace, 1055 "AP%d: initial guest selected: GUEST_ID: %d GUEST_CPU_ID: %d\n", 1056 cpu_id, guest_vcpu( initial_gcpu )->guest_id, 1057 guest_vcpu( initial_gcpu )->guest_cpu_id ); 1058 1059 ipc_change_state_to_active( initial_gcpu ); 1060 vmm_print_test(local_apic_id); 1061 APPLICATION_PROC_LAUNCHING_THE_GUEST(); 1062 VMM_LOG(mask_uvmm, level_trace,"AP%d: Resuming the first Guest CPU\n", cpu_id); 1063 #ifdef JLMDEBUG1 1064 bprint("called APPLICATION_PROC_LAUNCHING_THE_GUEST %d\n", 1065 g_application_procs_launch_the_guest); 1066 #endif 1067 1068 event_raise(EVENT_GUEST_LAUNCH, initial_gcpu, &local_apic_id); 1069 1070 // enable unrestricted guest support in early boot 1071 // make guest state compliant for code execution 1072 // On systems w/o UG, emulator takes care of it 1073 if(is_unrestricted_guest_supported()) { 1074 make_guest_state_compliant(initial_gcpu); 1075 unrestricted_guest_enable(initial_gcpu); 1076 #ifdef JLMDEBUG1 1077 bprint("evmm: unrestricted_guest_enable complete, ap %d\n", local_apic_id); 1078 #endif 1079 } else { 1080 // For non-UG systems enable EPT, if guest is in paging mode 1081 EM64T_CR0 guest_cr0; 1082 guest_cr0.Uint64 = gcpu_get_guest_visible_control_reg(initial_gcpu,IA32_CTRL_CR0); 1083 if (guest_cr0.Bits.PG) { 1084 enable_ept_during_launch(initial_gcpu); 1085 } 1086 } 1087 #ifdef FAST_VIEW_SWITCH 1088 if (fvs_is_eptp_switching_supported()) { 1089 fvs_guest_vmfunc_enable(initial_gcpu); 1090 fvs_vmfunc_vmcs_init(initial_gcpu); 1091 } 1092 #endif 1093 1094 vmcs_store_initial(initial_gcpu, cpu_id); 1095 #ifdef JLMDEBUG 1096 bprint("ap proc %d at gp_resume\n", local_apic_id); 1097 #endif 1098 gcpu_resume(initial_gcpu); 1099 VMM_LOG(mask_uvmm, level_error, 1100 "AP%d: Resume initial guest cpu failed\n", cpu_id); 1101 VMM_DEADLOOP(); 1102 } 1103 1104 void make_guest_state_compliant(GUEST_CPU_HANDLE initial_gcpu) 1105 { 1106 UINT16 selector; 1107 UINT64 base; 1108 UINT32 limit; 1109 UINT32 attr; 1110 UINT32 idx; 1111 UINT64 cr0; 1112 1113 cr0 = gcpu_get_guest_visible_control_reg(initial_gcpu, IA32_CTRL_CR0); 1114 if (!(cr0 & CR0_PE)) { 1115 // for guest to execute real mode code 1116 // its state needs to be in certain way 1117 // this code enforces it 1118 for (idx = IA32_SEG_CS; idx < IA32_SEG_COUNT; ++idx) { 1119 gcpu_get_segment_reg(initial_gcpu, (VMM_IA32_SEGMENT_REGISTERS)idx, 1120 &selector, &base, &limit, &attr); 1121 make_segreg_hw_real_mode_compliant(initial_gcpu, selector, base, 1122 limit, attr, (VMM_IA32_SEGMENT_REGISTERS)idx); 1123 } 1124 VMM_LOG(mask_uvmm, level_info,"BSP: guest compliant in real mode for UG early boot.\n"); 1125 } 1126 } 1127 1128 #ifdef DEBUG 1129 int cli_show_memory_layout(unsigned argc UNUSED, char *args[] UNUSED) 1130 { 1131 CLI_PRINT(" Memory Layout : uVMM : Thunk\n"); 1132 CLI_PRINT("---------------:------------------:-----------------\n"); 1133 CLI_PRINT(" Base Address : %16P : %16P\n", 1134 vmm_startup_data.vmm_memory_layout[uvmm_image].base_address, 1135 vmm_startup_data.vmm_memory_layout[thunk_image].base_address); 1136 CLI_PRINT(" Entry Point : %16P : %16P\n", 1137 vmm_startup_data.vmm_memory_layout[uvmm_image].entry_point, 1138 vmm_startup_data.vmm_memory_layout[thunk_image].entry_point); 1139 CLI_PRINT(" Image Size : %16P : %16P\n", 1140 vmm_startup_data.vmm_memory_layout[uvmm_image].image_size, 1141 vmm_startup_data.vmm_memory_layout[thunk_image].image_size); 1142 CLI_PRINT(" Total Size : %16P : %16P\n", 1143 vmm_startup_data.vmm_memory_layout[uvmm_image].total_size, 1144 vmm_startup_data.vmm_memory_layout[thunk_image].total_size); 1145 return 0; 1146 } 1147 #endif