Пример #1
0
/**

  This function is WRMSR handler for SMM.

  @param Index CPU index

**/
VOID
SmmWriteMsrHandler (
  IN UINT32 Index
  )
{
  UINT64            Data64;
  UINT32            MsrIndex;
  VM_ENTRY_CONTROLS VmEntryControls;
  X86_REGISTER      *Reg;
  STM_RSC_MSR_DESC  *MsrDesc;
  STM_RSC_MSR_DESC  LocalMsrDesc;

  Reg = &mGuestContextCommonSmm.GuestContextPerCpu[Index].Register;
  MsrIndex = ReadUnaligned32 ((UINT32 *)&Reg->Rcx);

  MsrDesc = GetStmResourceMsr (mHostContextCommon.MleProtectedResource.Base, MsrIndex);
  if ((MsrDesc != NULL) && (MsrDesc->WriteMask != 0)) {
    DEBUG ((EFI_D_ERROR, "WRMSR (%x) violation!\n", MsrIndex));
    AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)MsrDesc);
    SmmExceptionHandler (Index);
    CpuDeadLoop ();
  }

  MsrDesc = GetStmResourceMsr ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, MsrIndex);
  if ((MsrDesc == NULL) || (MsrDesc->WriteMask == 0) || (MsrDesc->KernelModeProcessing == 0)) {
    ZeroMem (&LocalMsrDesc, sizeof(LocalMsrDesc));
    LocalMsrDesc.Hdr.RscType = MACHINE_SPECIFIC_REG;
    LocalMsrDesc.Hdr.Length = sizeof(LocalMsrDesc);
    LocalMsrDesc.MsrIndex = MsrIndex;
    LocalMsrDesc.ReadMask = 0;
    LocalMsrDesc.WriteMask = (UINT64)-1;
    AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalMsrDesc);
  }

//  DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler!!!\n"));
  Data64 = LShiftU64 ((UINT64)ReadUnaligned32 ((UINT32 *)&Reg->Rdx), 32) | (UINT64)ReadUnaligned32 ((UINT32 *)&Reg->Rax);

  switch (MsrIndex) {
  case IA32_EFER_MSR_INDEX:
#if 0
  AcquireSpinLock (&mHostContextCommon.DebugLock);
    if ((Data64 & IA32_EFER_MSR_SCE) != 0) {
      DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler - SCE!!!\n"));
    }
    if ((Data64 & IA32_EFER_MSR_XDE) != 0) {
      DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler - XDE!!!\n"));
    }
  ReleaseSpinLock (&mHostContextCommon.DebugLock);
#endif
    mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer = Data64;
    //
    // Check IA32e mode switch
    //
    VmEntryControls.Uint32 = VmRead32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX);
    if ((Data64 & IA32_EFER_MSR_MLE) != 0) {
      mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer |= IA32_EFER_MSR_MLE;
    } else {
      mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer &= ~IA32_EFER_MSR_MLE;
    }
    if (((mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer & IA32_EFER_MSR_MLE) != 0) && 
        ((VmReadN (VMCS_N_GUEST_CR0_INDEX) & CR0_PG) != 0)) {
      mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer |= IA32_EFER_MSR_MLA;
      VmEntryControls.Bits.Ia32eGuest = 1;
    } else {
      mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer &= ~IA32_EFER_MSR_MLA;
      VmEntryControls.Bits.Ia32eGuest = 0;
    }
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryControls.Uint32);
    VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX,          mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer);

    break;

  case IA32_SYSENTER_CS_MSR_INDEX:
    VmWrite32 (VMCS_32_GUEST_IA32_SYSENTER_CS_INDEX, (UINT32)Data64);
    break;
  case IA32_SYSENTER_ESP_MSR_INDEX:
    VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_ESP_INDEX, (UINTN)Data64);
    break;
  case IA32_SYSENTER_EIP_MSR_INDEX:
    VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_EIP_INDEX, (UINTN)Data64);
    break;

  case IA32_FS_BASE_MSR_INDEX:
    VmWriteN (VMCS_N_GUEST_FS_BASE_INDEX, (UINTN)Data64);
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use FS
    break;
  case IA32_GS_BASE_MSR_INDEX:
    VmWriteN (VMCS_N_GUEST_GS_BASE_INDEX, (UINTN)Data64);
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use GS
    break;
#if 0
  case IA32_KERNAL_GS_BASE_MSR_INDEX:
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this
    break;
  case IA32_STAR_MSR_INDEX:
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this
    break;
  case IA32_LSTAR_MSR_INDEX:
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this
    break;
  case IA32_FMASK_MSR_INDEX:
    AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this
    break;
#endif

  case IA32_SMM_MONITOR_CTL_MSR_INDEX:
    break;

  case EFI_MSR_NEHALEM_SMRR_PHYS_BASE:
  case EFI_MSR_NEHALEM_SMRR_PHYS_MASK:
    // Ignore the write
    break;
    
  case IA32_BIOS_UPDT_TRIG_MSR_INDEX:
    // Only write it when BIOS request MicrocodeUpdate
    MsrDesc = GetStmResourceMsr ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, IA32_BIOS_UPDT_TRIG_MSR_INDEX);
    if (MsrDesc != NULL) {
      AsmWriteMsr64 (MsrIndex, Data64);
    }
    break;

  default:
    //
    // For rest one, we need pass back to BIOS
    //

    //
    // Need mask write item
    //
    if (MsrDesc != NULL) {
      Data64 |= MsrDesc->WriteMask;
    }

    AsmWriteMsr64 (MsrIndex, Data64);
    break;
  }

  VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
  return ;
}
Пример #2
0
/**

  This function set VMCS guest AP wakeup field.

  @param Index  CPU index
  @param Vector AP wakeup vector

**/
VOID
SetVmcsGuestApWakeupField (
  IN UINT32 Index,
  IN UINT8  Vector
  )
{
  VM_ENTRY_CONTROLS       VmEntryControls;

  //
  // AP state:
  // eax: 0
  // ebx: 0
  // ecx: 0
  // edx: CPUID_EAX (1)
  // esi: 0
  // edi: 0
  // ebp: 0
  // esp: 0
  // esp: 0
  // cr0: 00000010
  // cr2: 00000000
  // cr3: 00000000
  // cr4: 00000000
  // dr0: 00000000
  // dr1: 00000000
  // dr2: 00000000
  // dr3: 00000000
  // dr6: ffff0ff0
  // dr7: 00000400
  //
  // eip: 0
  // eflags: 00010002
  //
  // idtbase: 00000000
  // gdtbase: 00000000
  // ldtbase: 00000000
  // tssbase: 00000000
  // idtlim: 0000ffff
  // gdtlim: 0000ffff
  // ldtlim: 0000ffff
  // tsslim: 0000ffff
  // ldtar: 0082
  // tssar: 008b
  // ldtr: 0000
  // tr: 0000
  //
  // csbase: vector << 12
  // dsbase: 0
  // ssbase: 0
  // esbase: 0
  // fsbase: 0
  // gsbase: 0
  // cslim: 0000ffff
  // dslim: 0000ffff
  // sslim: 0000ffff
  // eslim: 0000ffff
  // fslim: 0000ffff
  // gslim: 0000ffff
  // csar: 0093
  // dsar: 0093
  // ssar: 0093
  // esar: 0093
  // fsar: 0093
  // gsar: 0093
  // cs: vector << 8
  // ds: 0
  // ss: 0
  // es: 0
  // fs: 0
  // gs: 0
  //

  VmWrite32 (VMCS_32_GUEST_ACTIVITY_STATE_INDEX, GUEST_ACTIVITY_STATE_ACTIVE);
  VmWrite16 (VMCS_16_GUEST_CS_INDEX, (UINT16)Vector << 8);
  VmWriteN (VMCS_N_GUEST_CS_BASE_INDEX, (UINTN)Vector << 12);
  VmWriteN (VMCS_N_GUEST_RIP_INDEX, 0);
  VmWriteN (VMCS_N_GUEST_SS_BASE_INDEX, 0);
  VmWriteN (VMCS_N_GUEST_RSP_INDEX, 0);

  VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, 0x00010002);

  VmWrite16 (VMCS_16_GUEST_ES_INDEX, 0);
  VmWrite16 (VMCS_16_GUEST_SS_INDEX, 0);
  VmWrite16 (VMCS_16_GUEST_DS_INDEX, 0);
  VmWrite16 (VMCS_16_GUEST_FS_INDEX, 0);
  VmWrite16 (VMCS_16_GUEST_GS_INDEX, 0);
  VmWrite16 (VMCS_16_GUEST_TR_INDEX, 0);

  VmWriteN (VMCS_N_GUEST_ES_BASE_INDEX,                  0);
  VmWriteN (VMCS_N_GUEST_DS_BASE_INDEX,                  0);
  VmWriteN (VMCS_N_GUEST_FS_BASE_INDEX,                  0);
  VmWriteN (VMCS_N_GUEST_GS_BASE_INDEX,                  0);

  VmWrite32 (VMCS_32_GUEST_ES_ACCESS_RIGHT_INDEX,        0x0093);
  VmWrite32 (VMCS_32_GUEST_CS_ACCESS_RIGHT_INDEX,        0x0093);
  VmWrite32 (VMCS_32_GUEST_SS_ACCESS_RIGHT_INDEX,        0x0093);
  VmWrite32 (VMCS_32_GUEST_DS_ACCESS_RIGHT_INDEX,        0x0093);
  VmWrite32 (VMCS_32_GUEST_FS_ACCESS_RIGHT_INDEX,        0x0093);
  VmWrite32 (VMCS_32_GUEST_GS_ACCESS_RIGHT_INDEX,        0x0093);

  VmWrite32 (VMCS_32_GUEST_ES_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_CS_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_SS_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_DS_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_FS_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_GS_LIMIT_INDEX,               0x0000ffff);

  VmWriteN (VMCS_N_GUEST_DR7_INDEX,                      0x00000400);
  VmWriteN (VMCS_N_GUEST_LDTR_BASE_INDEX,                0);
  VmWriteN (VMCS_N_GUEST_TR_BASE_INDEX,                  0);
  VmWriteN (VMCS_N_GUEST_GDTR_BASE_INDEX,                0);
  VmWriteN (VMCS_N_GUEST_IDTR_BASE_INDEX,                0);
  VmWrite32 (VMCS_32_GUEST_LDTR_LIMIT_INDEX,             0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_TR_LIMIT_INDEX,               0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_GDTR_LIMIT_INDEX,             0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_IDTR_LIMIT_INDEX,             0x0000ffff);
  VmWrite32 (VMCS_32_GUEST_LDTR_ACCESS_RIGHT_INDEX,      0x0082);
  VmWrite32 (VMCS_32_GUEST_TR_ACCESS_RIGHT_INDEX,        0x008b);
  VmWrite32 (VMCS_32_GUEST_INTERRUPTIBILITY_STATE_INDEX, 0);

  VmEntryControls.Uint32 = VmRead32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX);
  VmEntryControls.Bits.Ia32eGuest = 0;
  VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryControls.Uint32);

  mGuestContextCommon.GuestContextPerCpu[Index].Cr0 = (UINTN)(AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX) & ~CR0_PE & ~CR0_PG);
  mGuestContextCommon.GuestContextPerCpu[Index].Cr4 = (UINTN)(AsmReadMsr64 (IA32_VMX_CR4_FIXED0_MSR_INDEX) & AsmReadMsr64 (IA32_VMX_CR4_FIXED1_MSR_INDEX));
  mGuestContextCommon.GuestContextPerCpu[Index].EFER = 0;

  VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, 0);

  VmWriteN (VMCS_N_GUEST_CR0_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr0);
  VmWriteN (VMCS_N_GUEST_CR4_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr4);
  VmWriteN (VMCS_N_GUEST_CR3_INDEX, 0);

  VmWriteN (VMCS_N_CONTROL_CR0_READ_SHADOW_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr0);
  VmWriteN (VMCS_N_CONTROL_CR4_READ_SHADOW_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr4 & ~CR4_VMXE & ~CR4_SMXE);

  VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX,       mGuestContextCommon.GuestContextPerCpu[Index].EFER);

  ZeroMem (&mGuestContextCommon.GuestContextPerCpu[Index].Register, sizeof(X86_REGISTER));
  AsmCpuidEx (
    CPUID_FEATURE_INFORMATION,
    0,
    (UINT32 *)&mGuestContextCommon.GuestContextPerCpu[Index].Register.Rax,
    (UINT32 *)&mGuestContextCommon.GuestContextPerCpu[Index].Register.Rbx,
    (UINT32 *)&mGuestContextCommon.GuestContextPerCpu[Index].Register.Rcx,
    (UINT32 *)&mGuestContextCommon.GuestContextPerCpu[Index].Register.Rdx
    );
  mGuestContextCommon.GuestContextPerCpu[Index].Register.Rdx = mGuestContextCommon.GuestContextPerCpu[Index].Register.Rax;
  mGuestContextCommon.GuestContextPerCpu[Index].Register.Rax = 0;
  mGuestContextCommon.GuestContextPerCpu[Index].Register.Rbx = 0;
  mGuestContextCommon.GuestContextPerCpu[Index].Register.Rcx = 0;

  if (!mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest) {
    mGuestContextCommon.GuestContextPerCpu[Index].Cr0 |= CR0_PE | CR0_PG;
    VmWriteN (VMCS_N_GUEST_CR0_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr0);
    VmWriteN (VMCS_N_CONTROL_CR0_READ_SHADOW_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr0);
    // BUGBUG: Start emulator...
    CpuDeadLoop ();
  }
}