github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/vmexit/vmexit_sipi.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 "vmm_defs.h"
    16  #include "hw_utils.h"
    17  #include "vmcs_api.h"
    18  #include "guest_cpu.h"
    19  #include "ipc.h"
    20  #include "vmm_events_data.h"
    21  #include "vmx_trace.h"
    22  #include "pat_manager.h"
    23  #include "hw_interlocked.h"
    24  #ifdef JLMDEBUG
    25  #include "jlmdebug.h"
    26  #endif
    27  
    28  UINT32 g_guest_num_of_cpus=1; //BSP Core
    29  extern UINT32 g_s3_resume_flag;
    30  
    31  
    32  // FUNCTION : vmexit_sipi_event()
    33  // PURPOSE  : Configure VMCS register-state with CPU Real Mode state.
    34  //          : and launch emulator.
    35  // ARGUMENTS: GUEST_CPU_HANDLE gcpu
    36  // RETURNS  : void
    37  // NOTE     : The hard-coded values used for VMCS-registers initialization
    38  //          : are the values CPU sets its registers with after RESET.
    39  //          : See Intel® 64 and IA-32 Architectures Software Developer’s Manual
    40  //          : Volume 3A: System Programming Guide, Part 1
    41  //          : Table 9-1. IA-32 Processor States Following Power-up, Reset, or INIT
    42  VMEXIT_HANDLING_STATUS vmexit_sipi_event(GUEST_CPU_HANDLE gcpu)
    43  {
    44      VMCS_OBJECT                *vmcs = gcpu_get_vmcs(gcpu);
    45      IA32_VMX_EXIT_QUALIFICATION qualification;
    46      UINT16                      real_mode_segment;
    47      VMEXIT_HANDLING_STATUS      ret_status = VMEXIT_NOT_HANDLED;
    48  
    49  #ifdef JLMDEBUG1
    50      bprint("vmexit_sipi_event(%p)\n", gcpu);
    51  #endif
    52      do {    // single-execution loop
    53          // Check if this is IPC SIPI signal.
    54          if (ipc_sipi_vmexit_handler(gcpu)) {
    55              // We're already in Wait for SIPI state. Nothing to do
    56              ret_status = VMEXIT_HANDLED;
    57              break;
    58          }
    59  
    60  #ifdef SIPI_LAYERED_IS_SUPPORTED
    61          if (gcpu_is_vmcs_layered(gcpu)) {
    62              break;  // level-1 must handle
    63          }
    64  #endif
    65          // AP currently is in Wait for SIPI state,
    66          // gets guest SIPI(vector not 0xff) and activates the AP
    67  #ifdef ENABLE_PM_S3
    68          if (g_s3_resume_flag==0) {
    69  #else
    70          {
    71  #endif
    72              // No S3 resume, count guest AP cores
    73              hw_interlocked_increment((INT32*)&(g_guest_num_of_cpus)); 
    74          }
    75  
    76          VMM_LOG(mask_anonymous, level_trace,
    77              "CPU-%d Leave SIPI State: Guest Core Count is %d.\n", hw_cpu_id(),
    78              g_guest_num_of_cpus);
    79          VMM_DEBUG_CODE(vmm_trace(gcpu, "[sipi] Leave SIPI State\n"));
    80  #ifdef JLMDEBUG1
    81          bprint("%D guest cpus\n", g_guest_num_of_cpus);
    82  #endif
    83  
    84          // emulator configures guest with host state, and setup emulator 
    85          // context to real mode,
    86          // thus we have to configure the guest with the values of Real Mode, i.e.
    87          // those values, CPU sets to registers after RESET, 
    88          // though we never launch guest in that way
    89          gcpu_set_guest_visible_control_reg(gcpu, IA32_CTRL_CR0, 0x60000010);
    90          gcpu_set_control_reg(gcpu, IA32_CTRL_CR0, 0x60000010);
    91          gcpu_set_guest_visible_control_reg(gcpu, IA32_CTRL_CR3, 0);
    92          gcpu_set_control_reg(gcpu, IA32_CTRL_CR3, 0);
    93          gcpu_set_guest_visible_control_reg(gcpu, IA32_CTRL_CR4, 0);
    94          gcpu_set_control_reg(gcpu, IA32_CTRL_CR4, 0);
    95          gcpu_set_control_reg(gcpu, IA32_CTRL_CR2, 0);
    96          gcpu_set_control_reg(gcpu, IA32_CTRL_CR8, 0);
    97          qualification.Uint64 = vmcs_read(vmcs, VMCS_EXIT_INFO_QUALIFICATION);
    98          real_mode_segment = (UINT16) qualification.Sipi.Vector << 8;
    99          gcpu_set_segment_reg(gcpu, IA32_SEG_CS, real_mode_segment,
   100                              real_mode_segment << 4, 0xFFFF, 0x9B);
   101          // Attribute set bits: Present, R/W, Accessed
   102          gcpu_set_segment_reg(gcpu, IA32_SEG_DS, 0, 0, 0xFFFF, 0x93);
   103          gcpu_set_segment_reg(gcpu, IA32_SEG_ES, 0, 0, 0xFFFF, 0x93);
   104          gcpu_set_segment_reg(gcpu, IA32_SEG_FS, 0, 0, 0xFFFF, 0x93);
   105          gcpu_set_segment_reg(gcpu, IA32_SEG_GS, 0, 0, 0xFFFF, 0x93);
   106          gcpu_set_segment_reg(gcpu, IA32_SEG_SS, 0, 0, 0xFFFF, 0x93);
   107  	/* IA Manual 3B: 23.3.1.2 
   108  	  For TR Bits 3:0 (Type).
   109  	  — If the guest will not be IA-32e mode, the Type must be 3 or 11
   110  	  — If the guest will be IA-32e mode, the Type must be 11 
   111  	  Using Type 11 here
   112  	*/
   113          gcpu_set_segment_reg(gcpu, IA32_SEG_TR  , 0, 0, 0xFFFF, 0x8B); // CIRT uses 8Bh
   114          gcpu_set_segment_reg(gcpu, IA32_SEG_LDTR, 0, 0, 0xFFFF, 0x82); // CIRT uses 10082h
   115          gcpu_set_gdt_reg(gcpu, 0, 0xFFFF);
   116          gcpu_set_idt_reg(gcpu, 0, 0xFFFF);
   117          gcpu_set_debug_reg(gcpu, IA32_REG_DR0, 0);
   118          gcpu_set_debug_reg(gcpu, IA32_REG_DR1, 0);
   119          gcpu_set_debug_reg(gcpu, IA32_REG_DR2, 0);
   120          gcpu_set_debug_reg(gcpu, IA32_REG_DR3, 0);
   121          gcpu_set_debug_reg(gcpu, IA32_REG_DR6, 0xFFFF0FF0);
   122          gcpu_set_debug_reg(gcpu, IA32_REG_DR7, 0x00000400);
   123          gcpu_set_gp_reg(gcpu, IA32_REG_RAX, 0);
   124          gcpu_set_gp_reg(gcpu, IA32_REG_RBX, 0);
   125          gcpu_set_gp_reg(gcpu, IA32_REG_RCX, 0);
   126          gcpu_set_gp_reg(gcpu, IA32_REG_RDX, 0xF00);
   127          gcpu_set_gp_reg(gcpu, IA32_REG_RDI, 0);
   128          gcpu_set_gp_reg(gcpu, IA32_REG_RSI, 0);
   129          gcpu_set_gp_reg(gcpu, IA32_REG_RBP, 0);
   130          gcpu_set_gp_reg(gcpu, IA32_REG_RSP, 0); // CIRT uses FFFCh ??
   131          gcpu_set_gp_reg(gcpu, IA32_REG_RIP, 0);
   132          gcpu_set_gp_reg(gcpu, IA32_REG_RFLAGS, 2);  // CIRT uses 46h ??
   133          gcpu_set_msr_reg(gcpu, IA32_VMM_MSR_EFER, 0);
   134          gcpu_set_activity_state(gcpu, Ia32VmxVmcsGuestSleepStateActive);
   135  	// set state in vmenter control fields
   136  	gcpu_set_vmenter_control( gcpu );
   137          ret_status = VMEXIT_HANDLED;
   138      } while (0);
   139      return ret_status;
   140  }
   141  
   142  
   143