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