/**
  Searches the performance measurement log from the beginning of the log
  for the first matching record that contains a zero end time and fills in a valid end time.

  Searches the performance measurement log from the beginning of the log
  for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
  If the record can not be found then return EFI_NOT_FOUND.
  If the record is found and TimeStamp is not zero,
  then the end time in the record is filled in with the value specified by TimeStamp.
  If the record is found and TimeStamp is zero, then the end time in the matching record
  is filled in with the current time stamp value.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the found record
                                  is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.

  @retval EFI_SUCCESS             The end of  the measurement was recorded.
  @retval EFI_NOT_FOUND           The specified measurement record could not be found.

**/
EFI_STATUS
EFIAPI
EndGaugeEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
  UINT32              Index;

  AcquireSpinLock (&mSmmPerfLock);

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }

  Index = SmmSearchForGaugeEntry (Handle, Token, Module, Identifier);
  if (Index >= mGaugeData->NumberOfEntries) {
    ReleaseSpinLock (&mSmmPerfLock);
    return EFI_NOT_FOUND;
  }
  GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
  GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;

  ReleaseSpinLock (&mSmmPerfLock);

  return EFI_SUCCESS;
}
예제 #2
0
파일: DebugLib.c 프로젝트: 0xDEC0DE8/STM
/**
  Prints an assert message containing a filename, line number, and description.  
  This may be followed by a breakpoint or a dead loop.

  Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
  to the debug output device.  If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of 
  PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if 
  DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then 
  CpuDeadLoop() is called.  If neither of these bits are set, then this function 
  returns immediately after the message is printed to the debug output device.
  DebugAssert() must actively prevent recursion.  If DebugAssert() is called while
  processing another DebugAssert(), then DebugAssert() must return immediately.

  If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
  If Description is NULL, then a <Description> string of "(NULL) Description" is printed.

  @param  FileName     The pointer to the name of the source file that generated the assert condition.
  @param  LineNumber   The line number in the source file that generated the assert condition
  @param  Description  The pointer to the description of the assert condition.

**/
VOID
EFIAPI
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  CHAR8  Buffer[MAX_DEBUG_MESSAGE_LENGTH];

  //
  // Generate the ASSERT() message in Ascii format
  //
  AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT %a(%d): %a\n", FileName, LineNumber, Description);

  //
  // Send the print string to the Console Output device
  //
  AcquireSpinLock (&mInternalDebugLock);
  SerialPortWrite ((UINT8 *) Buffer, AsciiStrLen(Buffer));
  ReleaseSpinLock (&mInternalDebugLock);

  //
  // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
  //
  if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
    CpuBreakpoint ();
  } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
    CpuDeadLoop ();
  }
}
예제 #3
0
/**
  The page fault handler that on-demand read PI CpuSaveStates for framework use. If the fault
  is not targeted to mFrameworkSmst->CpuSaveState range, the function will return FALSE to let
  PageFaultHandlerHook know it needs to pass the fault over to original page fault handler.
  
  @retval TRUE     The page fault is correctly handled.
  @retval FALSE    The page fault is not handled and is passed through to original handler.

**/
BOOLEAN
PageFaultHandler (
  VOID
  )
{
  BOOLEAN        IsHandled;
  UINT64         *PageTable;
  UINT64         PFAddress;
  UINTN          NumCpuStatePages;
  
  ASSERT (mPageTableHookEnabled);
  AcquireSpinLock (&mPFLock);

  PageTable = (UINT64*)(UINTN)(AsmReadCr3 () & mPhyMask);
  PFAddress = AsmReadCr2 ();
  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));
  IsHandled = FALSE;
  if (((UINTN)mFrameworkSmst->CpuSaveState & ~(SIZE_2MB-1)) == (PFAddress & ~(SIZE_2MB-1))) {
    if ((UINTN)mFrameworkSmst->CpuSaveState <= PFAddress &&
        PFAddress < (UINTN)mFrameworkSmst->CpuSaveState + EFI_PAGES_TO_SIZE (NumCpuStatePages)
        ) {
      mCpuStatePageTable[BitFieldRead64 (PFAddress, 12, 20)] |= BIT0 | BIT1; // present and rw
      CpuFlushTlb ();
      ReadWriteCpuStatePage (PFAddress & ~(SIZE_4KB-1), TRUE);
      IsHandled = TRUE;
    } else {
      ASSERT (FALSE);
    }
  }

  ReleaseSpinLock (&mPFLock);
  return IsHandled;
}
static
FORCEINLINE
VOID
ReleaseTimerListLock (
    __inout PTIMER_LIST TimerList
    )
{
    ReleaseSpinLock(&TimerList->Lock);
}
예제 #5
0
파일: CpuMpPei.c 프로젝트: thselvam/edk2
/**
  This function will be called from AP reset code if BSP uses WakeUpAP.

  @param ExchangeInfo     Pointer to the MP exchange info buffer
  @param NumApsExecuting  Number of curret executing AP
**/
VOID
EFIAPI
ApCFunction (
  IN MP_CPU_EXCHANGE_INFO      *ExchangeInfo,
  IN UINTN                     NumApsExecuting
  )
{
  PEI_CPU_MP_DATA            *PeiCpuMpData;
  UINTN                      ProcessorNumber;
  EFI_AP_PROCEDURE           Procedure;
  UINTN                      BistData;

  PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
  if (PeiCpuMpData->InitFlag) {
    //
    // This is first time AP wakeup, get BIST information from AP stack
    //
    BistData = *(UINTN *) (PeiCpuMpData->Buffer + NumApsExecuting * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
    PeiCpuMpData->CpuData[NumApsExecuting].Health.Uint32 = (UINT32) BistData;
    PeiCpuMpData->CpuData[NumApsExecuting].ApicId = GetInitialApicId ();
    if (PeiCpuMpData->CpuData[NumApsExecuting].ApicId >= 0xFF) {
      //
      // Set x2APIC mode if there are any logical processor reporting
      // an APIC ID of 255 or greater.
      //
      AcquireSpinLock(&PeiCpuMpData->MpLock);
      PeiCpuMpData->X2ApicEnable = TRUE;
      ReleaseSpinLock(&PeiCpuMpData->MpLock);
    }
    //
    // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
    //
    MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
    MicrocodeDetect ();
  } else {
    //
    // Execute AP function if AP is not disabled
    //
    GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
    if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
        (PeiCpuMpData->ApFunction != 0)) {
      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
      Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
      Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
    }
  }

  //
  // AP finished executing C code
  //
  InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);

  AsmCliHltLoop ();
}
예제 #6
0
파일: DebugMp.c 프로젝트: baranee/edk2
/**
  Release a spin lock when Multi-processor supported.

  @param[in, out] MpSpinLock      A pointer to the spin lock.

**/
VOID
ReleaseMpSpinLock (
  IN OUT SPIN_LOCK           *MpSpinLock
  )
{
  if (!MultiProcessorDebugSupport()) {
    return;
  }

  ReleaseSpinLock (MpSpinLock);
}
예제 #7
0
/**

  This function is NMI handler.

  @param Index CPU index

**/
VOID
ExceptionNMIHandler (
  IN UINT32 Index
  )
{
  VM_EXIT_INFO_INTERRUPTION                    InterruptionInformation;

  InterruptionInformation.Uint32 = VmRead32 (VMCS_32_RO_VMEXIT_INTERRUPTION_INFO_INDEX);

  AcquireSpinLock (&mHostContextCommon.DebugLock);
  DEBUG ((EFI_D_INFO, "(FRM) !!!ExceptionNmiHandler %d!!!\n", Index));
  DEBUG ((EFI_D_INFO, "(FRM) InterruptType  %d, Vector %x\n", InterruptionInformation.Bits.InterruptType, InterruptionInformation.Bits.Vector));

  DumpVmcsAllField ();
  ReleaseSpinLock (&mHostContextCommon.DebugLock);
  CpuDeadLoop();
}
예제 #8
0
/**

  This function is interrupt windows handler.

  @param Index CPU index

**/
VOID
InterruptWindowHandler (
  UINT32 Index
  )
{
  VM_ENTRY_CONTROL_INTERRUPT                   InterruptControl;
  VM_EXEC_PROCESSOR_BASES_VMEXIT_CONTROLS      ProcessorBasedCtrls;
  VM_EXEC_PIN_BASES_VMEXIT_CONTROLS            PinBasedCtls;

  DEBUG ((EFI_D_INFO, "W"));

  InterruptControl.Uint32 = mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterrupt[mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop];

  if (InterruptControl.Bits.Valid == 0) {
    AcquireSpinLock (&mHostContextCommon.DebugLock);
    DEBUG ((EFI_D_ERROR, "(FRM) !!!InterruptWindowHandler Invalid Information - %d!!!\n", Index));
    DumpVmcsAllField ();
    ReleaseSpinLock (&mHostContextCommon.DebugLock);
    CpuDeadLoop ();
  }

  VmWrite32 (VMCS_32_CONTROL_VMENTRY_INTERRUPTION_INFO_INDEX, InterruptControl.Uint32);
  mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop--;

  //
  // Disable InterruptWindows, if LastPendingInterrupt
  //
  ProcessorBasedCtrls.Uint32 = VmRead32 (VMCS_32_CONTROL_PROCESSOR_BASED_VM_EXECUTION_INDEX);
  if (mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop == 0) {
    ProcessorBasedCtrls.Bits.InterruptWindow = 0;
  } else {
    ProcessorBasedCtrls.Bits.InterruptWindow = 1;
  }
  VmWrite32 (VMCS_32_CONTROL_PROCESSOR_BASED_VM_EXECUTION_INDEX,     ProcessorBasedCtrls.Uint32);
  PinBasedCtls.Uint32 = VmRead32 (VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX);
  PinBasedCtls.Bits.ExternalInterrupt = 1;
  VmWrite32 (VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX,           PinBasedCtls.Uint32);

  return ;
}
예제 #9
0
파일: FrmInit.c 프로젝트: 0xDEC0DE8/STM
/**

  This function launch guest BSP.

**/
VOID
LaunchGuestBsp (
  VOID
  )
{
  UINTN             Flag;
  UINTN             Rflags;

  Flag = SetJump (&mGuestJumpBuffer);
  if (Flag != 0) {
    DEBUG ((EFI_D_INFO, "(FRM) !!!Guest JumpBack to EFI!!!\n"));
    // Run successfully
    return ;
  }

  AsmVmPtrLoad (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Vmcs);

  //
  // Launch STM
  //
  LaunchStm (mBspIndex);

  AsmVmPtrLoad (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Vmcs);

  AcquireSpinLock (&mHostContextCommon.DebugLock);
  DumpVmcsAllField ();
  ReleaseSpinLock (&mHostContextCommon.DebugLock);

  AsmWbinvd ();

  Rflags = AsmVmLaunch (&mGuestContextCommon.GuestContextPerCpu[mBspIndex].Register);
  DEBUG ((EFI_D_ERROR, "(FRM) !!!LaunchGuestBsp FAIL!!!\n"));
  DEBUG ((EFI_D_ERROR, "(FRM) Rflags: %08x\n", Rflags));
  DEBUG ((EFI_D_ERROR, "(FRM) VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
 
  CpuDeadLoop ();
}
예제 #10
0
파일: DebugLib.c 프로젝트: 0xDEC0DE8/STM
/**
  Prints a debug message to the debug output device if the specified error level is enabled.

  If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print 
  the message specified by Format and the associated variable argument list to 
  the debug output device.

  If Format is NULL, then ASSERT().

  @param  ErrorLevel  The error level of the debug message.
  @param  Format      Format string for the debug message to print.
  @param  ...         Variable argument list whose contents are accessed 
                      based on the format string specified by Format.

**/
VOID
EFIAPI
DebugPrint (
  IN  UINTN        ErrorLevel,
  IN  CONST CHAR8  *Format,
  ...
  )
{
  CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
  VA_LIST  Marker;

  //
  // If Format is NULL, then ASSERT().
  //
  ASSERT (Format != NULL);

  //
  // Check driver debug mask value and global mask
  //
  if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
    return;
  }

  //
  // Convert the DEBUG() message to an ASCII String
  //
  VA_START (Marker, Format);
  AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
  VA_END (Marker);

  //
  // Send the print string to a Serial Port 
  //
  AcquireSpinLock (&mInternalDebugLock);
  SerialPortWrite ((UINT8 *) Buffer, AsciiStrLen(Buffer));
  ReleaseSpinLock (&mInternalDebugLock);
}
예제 #11
0
/**
  Internal worker function for common exception handler.

  @param ExceptionType         Exception type.
  @param SystemContext         Pointer to EFI_SYSTEM_CONTEXT.
  @param ExceptionHandlerData  Pointer to exception handler data.
**/
VOID
CommonExceptionHandlerWorker (
  IN EFI_EXCEPTION_TYPE          ExceptionType, 
  IN EFI_SYSTEM_CONTEXT          SystemContext,
  IN EXCEPTION_HANDLER_DATA      *ExceptionHandlerData
  )
{
  EXCEPTION_HANDLER_CONTEXT      *ExceptionHandlerContext;
  RESERVED_VECTORS_DATA          *ReservedVectors;
  EFI_CPU_INTERRUPT_HANDLER      *ExternalInterruptHandler;

  ExceptionHandlerContext  = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
  ReservedVectors          = ExceptionHandlerData->ReservedVectors;
  ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;

  switch (ReservedVectors[ExceptionType].Attribute) {
  case EFI_VECTOR_HANDOFF_HOOK_BEFORE:
    //
    // Need to jmp to old IDT handler after this exception handler
    //
    ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
    ExceptionHandlerContext->OldIdtHandler     = ReservedVectors[ExceptionType].ExceptonHandler;
    break;
  case EFI_VECTOR_HANDOFF_HOOK_AFTER:
    while (TRUE) {
      //
      // If if anyone has gotten SPIN_LOCK for owner running hook after
      //
      if (AcquireSpinLockOrFail (&ReservedVectors[ExceptionType].SpinLock)) {
        //
        // Need to execute old IDT handler before running this exception handler
        //
        ReservedVectors[ExceptionType].ApicId = GetApicId ();
        ArchSaveExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData);
        ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE;
        ExceptionHandlerContext->OldIdtHandler     = ReservedVectors[ExceptionType].ExceptonHandler;
        return;
      }
      //
      // If failed to acquire SPIN_LOCK, check if it was locked by processor itself
      //
      if (ReservedVectors[ExceptionType].ApicId == GetApicId ()) {
        //
        // Old IDT handler has been executed, then restore CPU exception content to
        // run new exception handler.
        //
        ArchRestoreExceptionContext (ExceptionType, SystemContext, ExceptionHandlerData);
        //
        // Rlease spin lock for ApicId
        //
        ReleaseSpinLock (&ReservedVectors[ExceptionType].SpinLock);
        break;
      }
      CpuPause ();
    }
    break;
  case 0xffffffff:
    break;
  default:
    //
    // It should never reach here
    //
    CpuDeadLoop ();
    break;
  }
  
  if (ExternalInterruptHandler != NULL &&
      ExternalInterruptHandler[ExceptionType] != NULL) {
    (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext);
  } else if (ExceptionType < CPU_EXCEPTION_NUM) {
    //
    // Get Spinlock to display CPU information
    //
    while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) {
      CpuPause ();
    }
    //
    // Display ExceptionType, CPU information and Image information
    //  
    DumpCpuContent (ExceptionType, SystemContext);
    //
    // Release Spinlock of output message
    //
    ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock);
    //
    // Enter a dead loop if needn't to execute old IDT handler further
    //
    if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) {
      CpuDeadLoop ();
    }
  }
}
예제 #12
0
/**
  This function will be called from AP reset code if BSP uses WakeUpAP.

  @param ExchangeInfo     Pointer to the MP exchange info buffer
  @param NumApsExecuting  Number of current executing AP
**/
VOID
EFIAPI
ApCFunction (
  IN MP_CPU_EXCHANGE_INFO      *ExchangeInfo,
  IN UINTN                     NumApsExecuting
  )
{
  PEI_CPU_MP_DATA            *PeiCpuMpData;
  UINTN                      ProcessorNumber;
  EFI_AP_PROCEDURE           Procedure;
  UINTN                      BistData;
  volatile UINT32            *ApStartupSignalBuffer;

  PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
  while (TRUE) {
    if (PeiCpuMpData->InitFlag) {
      ProcessorNumber = NumApsExecuting;
      //
      // Sync BSP's Control registers to APs
      //
      RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters, FALSE);
      //
      // This is first time AP wakeup, get BIST information from AP stack
      //
      BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
      PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;
      PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();
      if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {
        //
        // Set x2APIC mode if there are any logical processor reporting
        // an APIC ID of 255 or greater.
        //
        AcquireSpinLock(&PeiCpuMpData->MpLock);
        PeiCpuMpData->X2ApicEnable = TRUE;
        ReleaseSpinLock(&PeiCpuMpData->MpLock);
      }
      //
      // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
      //
      MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
      MicrocodeDetect ();
      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
    } else {
      //
      // Execute AP function if AP is not disabled
      //
      GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
      if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
        //
        // Restore AP's volatile registers saved
        //
        RestoreVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
      }

      if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
          (PeiCpuMpData->ApFunction != 0)) {
        PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
        Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
        //
        // Invoke AP function here
        //
        Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
        //
        // Re-get the processor number due to BSP/AP maybe exchange in AP function
        //
        GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
        PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
      }
    }

    //
    // AP finished executing C code
    //
    InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);

    //
    // Place AP is specified loop mode
    //
    if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
      //
      // Save AP volatile registers
      //
      SaveVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
      //
      // Place AP in Hlt-loop
      //
      while (TRUE) {
        DisableInterrupts ();
        CpuSleep ();
        CpuPause ();
      }
    }
    ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;
    //
    // Clear AP start-up signal
    //
    *ApStartupSignalBuffer = 0;
    while (TRUE) {
      DisableInterrupts ();
      if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {
        //
        // Place AP in Mwait-loop
        //
        AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);
        if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
          //
          // If AP start-up signal is not set, place AP into
          // the maximum C-state
          //
          AsmMwait (PeiCpuMpData->ApTargetCState << 4, 0);
        }
      } else if (PeiCpuMpData->ApLoopMode == ApInRunLoop) {
        //
        // Place AP in Run-loop
        //
        CpuPause ();
      } else {
        ASSERT (FALSE);
      }

      //
      // If AP start-up signal is written, AP is waken up
      // otherwise place AP in loop again
      //
      if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
        break;
      }
    }
  }
}
예제 #13
0
파일: CpuS3.c 프로젝트: lgao4/edk2
/**
  Programs registers for the calling processor.

  This function programs registers for the calling processor.

  @param  RegisterTable Pointer to register table of the running processor.

**/
VOID
SetProcessorRegister (
  IN CPU_REGISTER_TABLE        *RegisterTable
  )
{
  CPU_REGISTER_TABLE_ENTRY  *RegisterTableEntry;
  UINTN                     Index;
  UINTN                     Value;
  SPIN_LOCK                 *MsrSpinLock;

  //
  // Traverse Register Table of this logical processor
  //
  RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
  for (Index = 0; Index < RegisterTable->TableLength; Index++, RegisterTableEntry++) {
    //
    // Check the type of specified register
    //
    switch (RegisterTableEntry->RegisterType) {
    //
    // The specified register is Control Register
    //
    case ControlRegister:
      switch (RegisterTableEntry->Index) {
      case 0:
        Value = AsmReadCr0 ();
        Value = (UINTN) BitFieldWrite64 (
                          Value,
                          RegisterTableEntry->ValidBitStart,
                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
                          (UINTN) RegisterTableEntry->Value
                          );
        AsmWriteCr0 (Value);
        break;
      case 2:
        Value = AsmReadCr2 ();
        Value = (UINTN) BitFieldWrite64 (
                          Value,
                          RegisterTableEntry->ValidBitStart,
                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
                          (UINTN) RegisterTableEntry->Value
                          );
        AsmWriteCr2 (Value);
        break;
      case 3:
        Value = AsmReadCr3 ();
        Value = (UINTN) BitFieldWrite64 (
                          Value,
                          RegisterTableEntry->ValidBitStart,
                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
                          (UINTN) RegisterTableEntry->Value
                          );
        AsmWriteCr3 (Value);
        break;
      case 4:
        Value = AsmReadCr4 ();
        Value = (UINTN) BitFieldWrite64 (
                          Value,
                          RegisterTableEntry->ValidBitStart,
                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
                          (UINTN) RegisterTableEntry->Value
                          );
        AsmWriteCr4 (Value);
        break;
      default:
        break;
      }
      break;
    //
    // The specified register is Model Specific Register
    //
    case Msr:
      //
      // If this function is called to restore register setting after INIT signal,
      // there is no need to restore MSRs in register table.
      //
      if (RegisterTableEntry->ValidBitLength >= 64) {
        //
        // If length is not less than 64 bits, then directly write without reading
        //
        AsmWriteMsr64 (
          RegisterTableEntry->Index,
          RegisterTableEntry->Value
          );
      } else {
        //
        // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
        // to make sure MSR read/write operation is atomic.
        //
        MsrSpinLock = GetMsrSpinLockByIndex (RegisterTableEntry->Index);
        AcquireSpinLock (MsrSpinLock);
        //
        // Set the bit section according to bit start and length
        //
        AsmMsrBitFieldWrite64 (
          RegisterTableEntry->Index,
          RegisterTableEntry->ValidBitStart,
          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
          RegisterTableEntry->Value
          );
        ReleaseSpinLock (MsrSpinLock);
      }
      break;
    //
    // Enable or disable cache
    //
    case CacheControl:
      //
      // If value of the entry is 0, then disable cache.  Otherwise, enable cache.
      //
      if (RegisterTableEntry->Value == 0) {
        AsmDisableCache ();
      } else {
        AsmEnableCache ();
      }
      break;

    default:
      break;
    }
  }
}
예제 #14
0
/**

  This function is external interrupt handler.

  @param Index CPU index

**/
VOID
ExternalInterruptHandler (
  UINT32 Index
  )
{
  VM_EXIT_INFO_INTERRUPTION                    InterruptionInformation;
//  VM_EXIT_INFO_IDT_VECTORING                   IdtVectoring;
  VM_ENTRY_CONTROL_INTERRUPT                   InterruptControl;
  VM_EXEC_PROCESSOR_BASES_VMEXIT_CONTROLS      ProcessorBasedCtrls;
  VM_EXEC_PIN_BASES_VMEXIT_CONTROLS            PinBasedCtls;

  DEBUG ((EFI_D_INFO, "I"));

  InterruptControl.Uint32 = 0;
#if 1
  InterruptionInformation.Uint32 = VmRead32 (VMCS_32_RO_VMEXIT_INTERRUPTION_INFO_INDEX);

  if (InterruptionInformation.Bits.Valid == 0) {
    AcquireSpinLock (&mHostContextCommon.DebugLock);
    DEBUG ((EFI_D_ERROR, "(FRM) !!!ExternalInterruptHandler Invaid Information - %d!!!\n", Index));
    DumpVmcsAllField ();
    ReleaseSpinLock (&mHostContextCommon.DebugLock);
    CpuDeadLoop ();
  }

  InterruptControl.Bits.Vector = InterruptionInformation.Bits.Vector;
  InterruptControl.Bits.InterruptType = InterruptionInformation.Bits.InterruptType;
  InterruptControl.Bits.DeliverErrorCode = InterruptionInformation.Bits.ErrorCodeValid;
  InterruptControl.Bits.Valid = InterruptionInformation.Bits.Valid;

  if (InterruptControl.Bits.DeliverErrorCode) {
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_EXCEPTION_ERROR_CODE_INDEX, VmRead32 (VMCS_32_RO_VMEXIT_INTERRUPTION_ERROR_CODE_INDEX));
  }
#else
  IdtVectoring.Uint32 = VmRead32 (VMCS_32_RO_IDT_VECTORING_INFO_INDEX);

  InterruptControl.Bits.Vector = IdtVectoring.Bits.Vector;
  InterruptControl.Bits.InterruptType = IdtVectoring.Bits.InterruptType;
  InterruptControl.Bits.DeliverErrorCode = IdtVectoring.Bits.ErrorCodeValid;
  InterruptControl.Bits.Valid = IdtVectoring.Bits.Valid;

  if (InterruptControl.Bits.DeliverErrorCode) {
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_EXCEPTION_ERROR_CODE_INDEX, VmRead32 (VMCS_32_RO_IDT_VECTORING_ERROR_CODE_INDEX));
  }
#endif

  if ((InterruptControl.Bits.InterruptType == INTERRUPT_TYPE_EXTERNAL_SOFTWARE_INTERRUPT) ||
      (InterruptControl.Bits.InterruptType == INTERRUPT_TYPE_EXTERNAL_PRIVILEDGED_SOFTWARE_EXCEPTION) ||
      (InterruptControl.Bits.InterruptType == INTERRUPT_TYPE_EXTERNAL_SOFTWARE_EXCEPTIONT)) {
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_INSTRUCTION_LENGTH_INDEX, VmRead32 (VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
  } else {
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_INSTRUCTION_LENGTH_INDEX, 0);
  }

  if (((VmReadN (VMCS_N_GUEST_RFLAGS_INDEX) & RFLAGS_IF) == 0) &&
      (InterruptControl.Bits.InterruptType == INTERRUPT_TYPE_EXTERNAL_EXTERNAL_INTERRUPT)) {
    //
    // Enable InterruptWindows, and pending ...
    //
//    DEBUG ((EFI_D_INFO, "P"));
    if (mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop != 0) {
      //
      // NOTE: The reason for code running here is:
      //   When ISR is set, the lower or equal IRQ will be masked, but higher IRQ will arrive to set IRR no matter EOI issued or not.
      //   When EOI is issued, only highest ISR will be cleared.
      //
      // The PIC/8259 IRQ priority is: 0 1 (8 9 10 11 12 13 14 15) 3 4 5 6 7
      // The IO-APIC IRQ priority is:
      //
//      AcquireSpinLock (&mHostContextCommon.DebugLock);
//      DEBUG ((EFI_D_INFO, "(FRM) !!!ExternalInterruptHandler Already Pending - %d!!!\n", Index));
//      DEBUG ((EFI_D_INFO, "(FRM) InterruptControl - %x\n", InterruptControl.Uint32));
//      DEBUG ((EFI_D_INFO, "(FRM) LastPendingInterrupt - %x\n", mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterrupt[mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop]));
//      DumpVmcsAllField ();
//      ReleaseSpinLock (&mHostContextCommon.DebugLock);
      DEBUG ((EFI_D_INFO, "D"));
    }
    mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop++;
    mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterrupt[mGuestContextCommon.GuestContextPerCpu[Index].LastPendingInterruptTop] = InterruptControl.Uint32;
    ProcessorBasedCtrls.Uint32 = VmRead32 (VMCS_32_CONTROL_PROCESSOR_BASED_VM_EXECUTION_INDEX);
    ProcessorBasedCtrls.Bits.InterruptWindow = 1;
    VmWrite32 (VMCS_32_CONTROL_PROCESSOR_BASED_VM_EXECUTION_INDEX,     ProcessorBasedCtrls.Uint32);
    PinBasedCtls.Uint32 = VmRead32 (VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX);
    PinBasedCtls.Bits.ExternalInterrupt = 0;
    VmWrite32 (VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX,           PinBasedCtls.Uint32);
  } else {
//    DEBUG ((EFI_D_INFO, "J"));
    //
    // Inject interrupt to guest
    //
    VmWrite32 (VMCS_32_CONTROL_VMENTRY_INTERRUPTION_INFO_INDEX, InterruptControl.Uint32);
  }

  return ;
}
예제 #15
0
파일: MpService.c 프로젝트: PaulSelles/edk2
/**
  SMI handler for BSP.

  @param     CpuIndex         BSP processor Index
  @param     SyncMode         SMM MP sync mode

**/
VOID
BSPHandler (
  IN      UINTN                     CpuIndex,
  IN      SMM_CPU_SYNC_MODE         SyncMode
  )
{
  UINTN                             Index;
  MTRR_SETTINGS                     Mtrrs;
  UINTN                             ApCount;
  BOOLEAN                           ClearTopLevelSmiResult;
  UINTN                             PresentCount;

  ASSERT (CpuIndex == mSmmMpSyncData->BspIndex);
  ApCount = 0;

  //
  // Flag BSP's presence
  //
  mSmmMpSyncData->InsideSmm = TRUE;

  //
  // Initialize Debug Agent to start source level debug in BSP handler
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_ENTER_SMI, NULL, NULL);

  //
  // Mark this processor's presence
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;

  //
  // Clear platform top level SMI status bit before calling SMI handlers. If
  // we cleared it after SMI handlers are run, we would miss the SMI that
  // occurs after SMI handlers are done and before SMI status bit is cleared.
  //
  ClearTopLevelSmiResult = ClearTopLevelSmiStatus();
  ASSERT (ClearTopLevelSmiResult == TRUE);

  //
  // Set running processor index
  //
  gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu = CpuIndex;

  //
  // If Traditional Sync Mode or need to configure MTRRs: gather all available APs.
  //
  if (SyncMode == SmmCpuSyncModeTradition || SmmCpuFeaturesNeedConfigureMtrrs()) {

    //
    // Wait for APs to arrive
    //
    SmmWaitForApArrival();

    //
    // Lock the counter down and retrieve the number of APs
    //
    mSmmMpSyncData->AllCpusInSync = TRUE;
    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;

    //
    // Wait for all APs to get ready for programming MTRRs
    //
    WaitForAllAPs (ApCount);

    if (SmmCpuFeaturesNeedConfigureMtrrs()) {
      //
      // Signal all APs it's time for backup MTRRs
      //
      ReleaseAllAPs ();

      //
      // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
      // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
      // to a large enough value to avoid this situation.
      // Note: For HT capable CPUs, threads within a core share the same set of MTRRs.
      // We do the backup first and then set MTRR to avoid race condition for threads
      // in the same core.
      //
      MtrrGetAllMtrrs(&Mtrrs);

      //
      // Wait for all APs to complete their MTRR saving
      //
      WaitForAllAPs (ApCount);

      //
      // Let all processors program SMM MTRRs together
      //
      ReleaseAllAPs ();

      //
      // WaitForSemaphore() may wait for ever if an AP happens to enter SMM at
      // exactly this point. Please make sure PcdCpuSmmMaxSyncLoops has been set
      // to a large enough value to avoid this situation.
      //
      ReplaceOSMtrrs (CpuIndex);

      //
      // Wait for all APs to complete their MTRR programming
      //
      WaitForAllAPs (ApCount);
    }
  }

  //
  // The BUSY lock is initialized to Acquired state
  //
  AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy);

  //
  // Restore SMM Configuration in S3 boot path.
  //
  if (mRestoreSmmConfigurationInS3) {
    //
    // Configure SMM Code Access Check feature if available.
    //
    ConfigSmmCodeAccessCheck ();
    mRestoreSmmConfigurationInS3 = FALSE;
  }

  //
  // Invoke SMM Foundation EntryPoint with the processor information context.
  //
  gSmmCpuPrivate->SmmCoreEntry (&gSmmCpuPrivate->SmmCoreEntryContext);

  //
  // Make sure all APs have completed their pending none-block tasks
  //
  for (Index = mMaxNumberOfCpus; Index-- > 0;) {
    if (Index != CpuIndex && mSmmMpSyncData->CpuData[Index].Present) {
      AcquireSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);
      ReleaseSpinLock (&mSmmMpSyncData->CpuData[Index].Busy);;
    }
  }

  //
  // Perform the remaining tasks
  //
  PerformRemainingTasks ();

  //
  // If Relaxed-AP Sync Mode: gather all available APs after BSP SMM handlers are done, and
  // make those APs to exit SMI synchronously. APs which arrive later will be excluded and
  // will run through freely.
  //
  if (SyncMode != SmmCpuSyncModeTradition && !SmmCpuFeaturesNeedConfigureMtrrs()) {

    //
    // Lock the counter down and retrieve the number of APs
    //
    mSmmMpSyncData->AllCpusInSync = TRUE;
    ApCount = LockdownSemaphore (&mSmmMpSyncData->Counter) - 1;
    //
    // Make sure all APs have their Present flag set
    //
    while (TRUE) {
      PresentCount = 0;
      for (Index = mMaxNumberOfCpus; Index-- > 0;) {
        if (mSmmMpSyncData->CpuData[Index].Present) {
          PresentCount ++;
        }
      }
      if (PresentCount > ApCount) {
        break;
      }
    }
  }

  //
  // Notify all APs to exit
  //
  mSmmMpSyncData->InsideSmm = FALSE;
  ReleaseAllAPs ();

  //
  // Wait for all APs to complete their pending tasks
  //
  WaitForAllAPs (ApCount);

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Signal APs to restore MTRRs
    //
    ReleaseAllAPs ();

    //
    // Restore OS MTRRs
    //
    SmmCpuFeaturesReenableSmrr ();
    MtrrSetAllMtrrs(&Mtrrs);

    //
    // Wait for all APs to complete MTRR programming
    //
    WaitForAllAPs (ApCount);
  }

  //
  // Stop source level debug in BSP handler, the code below will not be
  // debugged.
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_EXIT_SMI, NULL, NULL);

  //
  // Signal APs to Reset states/semaphore for this processor
  //
  ReleaseAllAPs ();

  //
  // Perform pending operations for hot-plug
  //
  SmmCpuUpdate ();

  //
  // Clear the Present flag of BSP
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;

  //
  // Gather APs to exit SMM synchronously. Note the Present flag is cleared by now but
  // WaitForAllAps does not depend on the Present flag.
  //
  WaitForAllAPs (ApCount);

  //
  // Reset BspIndex to -1, meaning BSP has not been elected.
  //
  if (FeaturePcdGet (PcdCpuSmmEnableBspElection)) {
    mSmmMpSyncData->BspIndex = (UINT32)-1;
  }

  //
  // Allow APs to check in from this point on
  //
  mSmmMpSyncData->Counter = 0;
  mSmmMpSyncData->AllCpusInSync = FALSE;
}
예제 #16
0
/**
  Report status code listener for SMM. This is used to record the performance
  data for S3 Suspend Start and S3 Suspend End in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerSmm (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS                           Status;
  UINT64                               CurrentTime;
  EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  S3SuspendRecord;
  UINT8                                *NewRecordBuffer;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }
  
  //
  // Collect one or more Boot records in boot time
  //
  if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    AcquireSpinLock (&mSmmFpdtLock);
    
    if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
      //
      // Try to allocate big SMRAM data to store Boot record. 
      //
      if (mSmramIsOutOfResource) {
        ReleaseSpinLock (&mSmmFpdtLock);
        return EFI_OUT_OF_RESOURCES;
      }
      NewRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer); 
      if (NewRecordBuffer == NULL) {
        ReleaseSpinLock (&mSmmFpdtLock);
        mSmramIsOutOfResource = TRUE;
        return EFI_OUT_OF_RESOURCES;
      }
      mBootRecordBuffer  = NewRecordBuffer;
      mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
    }
    //
    // Save boot record into the temp memory space.
    //
    CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
    mBootRecordSize += Data->Size;
    
    ReleaseSpinLock (&mSmmFpdtLock);
    return EFI_SUCCESS;
  }

  if ((Value != PcdGet32 (PcdProgressCodeS3SuspendStart)) &&
      (Value != PcdGet32 (PcdProgressCodeS3SuspendEnd))) {
    return EFI_UNSUPPORTED;
  }

  //
  // Retrieve current time.
  //
  CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());

  if (Value == PcdGet32 (PcdProgressCodeS3SuspendStart)) {
    //
    // S3 Suspend started, record the performance data and return.
    //
    mSuspendStartTime = CurrentTime;
    return EFI_SUCCESS;
  }

  //
  // We are going to S3 sleep, record S3 Suspend End performance data.
  //
  S3SuspendRecord.SuspendStart = mSuspendStartTime;
  S3SuspendRecord.SuspendEnd   = CurrentTime;

  //
  // Save S3 suspend performance data to lock box, it will be used by Firmware Performance PEIM.
  //
  if (!mS3SuspendLockBoxSaved) {
    Status = SaveLockBox (
               &gEfiFirmwarePerformanceGuid,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);

    mS3SuspendLockBoxSaved = TRUE;
  } else {
    Status = UpdateLockBox (
               &gEfiFirmwarePerformanceGuid,
               0,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);
  }

  return EFI_SUCCESS;
}
예제 #17
0
파일: MpService.c 프로젝트: PaulSelles/edk2
/**
  SMI handler for AP.

  @param     CpuIndex         AP processor Index.
  @param     ValidSmi         Indicates that current SMI is a valid SMI or not.
  @param     SyncMode         SMM MP sync mode.

**/
VOID
APHandler (
  IN      UINTN                     CpuIndex,
  IN      BOOLEAN                   ValidSmi,
  IN      SMM_CPU_SYNC_MODE         SyncMode
  )
{
  UINT64                            Timer;
  UINTN                             BspIndex;
  MTRR_SETTINGS                     Mtrrs;

  //
  // Timeout BSP
  //
  for (Timer = StartSyncTimer ();
       !IsSyncTimerTimeout (Timer) &&
       !mSmmMpSyncData->InsideSmm;
       ) {
    CpuPause ();
  }

  if (!mSmmMpSyncData->InsideSmm) {
    //
    // BSP timeout in the first round
    //
    if (mSmmMpSyncData->BspIndex != -1) {
      //
      // BSP Index is known
      //
      BspIndex = mSmmMpSyncData->BspIndex;
      ASSERT (CpuIndex != BspIndex);

      //
      // Send SMI IPI to bring BSP in
      //
      SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[BspIndex].ProcessorId);

      //
      // Now clock BSP for the 2nd time
      //
      for (Timer = StartSyncTimer ();
           !IsSyncTimerTimeout (Timer) &&
           !mSmmMpSyncData->InsideSmm;
           ) {
        CpuPause ();
      }

      if (!mSmmMpSyncData->InsideSmm) {
        //
        // Give up since BSP is unable to enter SMM
        // and signal the completion of this AP
        WaitForSemaphore (&mSmmMpSyncData->Counter);
        return;
      }
    } else {
      //
      // Don't know BSP index. Give up without sending IPI to BSP.
      //
      WaitForSemaphore (&mSmmMpSyncData->Counter);
      return;
    }
  }

  //
  // BSP is available
  //
  BspIndex = mSmmMpSyncData->BspIndex;
  ASSERT (CpuIndex != BspIndex);

  //
  // Mark this processor's presence
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = TRUE;

  if (SyncMode == SmmCpuSyncModeTradition || SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Notify BSP of arrival at this point
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
  }

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Wait for the signal from BSP to backup MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Backup OS MTRRs
    //
    MtrrGetAllMtrrs(&Mtrrs);

    //
    // Signal BSP the completion of this AP
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

    //
    // Wait for BSP's signal to program MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Replace OS MTRRs with SMI MTRRs
    //
    ReplaceOSMtrrs (CpuIndex);

    //
    // Signal BSP the completion of this AP
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);
  }

  while (TRUE) {
    //
    // Wait for something to happen
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Check if BSP wants to exit SMM
    //
    if (!mSmmMpSyncData->InsideSmm) {
      break;
    }

    //
    // BUSY should be acquired by SmmStartupThisAp()
    //
    ASSERT (
      !AcquireSpinLockOrFail (&mSmmMpSyncData->CpuData[CpuIndex].Busy)
      );

    //
    // Invoke the scheduled procedure
    //
    (*mSmmMpSyncData->CpuData[CpuIndex].Procedure) (
      (VOID*)mSmmMpSyncData->CpuData[CpuIndex].Parameter
      );

    //
    // Release BUSY
    //
    ReleaseSpinLock (&mSmmMpSyncData->CpuData[CpuIndex].Busy);
  }

  if (SmmCpuFeaturesNeedConfigureMtrrs()) {
    //
    // Notify BSP the readiness of this AP to program MTRRs
    //
    ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

    //
    // Wait for the signal from BSP to program MTRRs
    //
    WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

    //
    // Restore OS MTRRs
    //
    SmmCpuFeaturesReenableSmrr ();
    MtrrSetAllMtrrs(&Mtrrs);
  }

  //
  // Notify BSP the readiness of this AP to Reset states/semaphore for this processor
  //
  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

  //
  // Wait for the signal from BSP to Reset states/semaphore for this processor
  //
  WaitForSemaphore (&mSmmMpSyncData->CpuData[CpuIndex].Run);

  //
  // Reset states/semaphore for this processor
  //
  mSmmMpSyncData->CpuData[CpuIndex].Present = FALSE;

  //
  // Notify BSP the readiness of this AP to exit SMM
  //
  ReleaseSemaphore (&mSmmMpSyncData->CpuData[BspIndex].Run);

}
예제 #18
0
/**
  Adds a record at the end of the performance measurement log
  that records the start time of a performance measurement.

  Adds a record to the end of the performance measurement log
  that contains the Handle, Token, Module and Identifier.
  The end time of the new record must be set to zero.
  If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
  If TimeStamp is zero, the start time in the record is filled in with the value
  read from the current time stamp.

  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  TimeStamp               64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the created record
                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.

  @retval EFI_SUCCESS             The data was read correctly from the device.
  @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.

**/
EFI_STATUS
EFIAPI
StartGaugeEx (
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       TimeStamp,
  IN UINT32       Identifier
  )
{
  GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
  UINTN                     GaugeDataSize;
  GAUGE_DATA_HEADER         *NewGaugeData;
  UINTN                     OldGaugeDataSize;
  GAUGE_DATA_HEADER         *OldGaugeData;
  UINT32                    Index;

  AcquireSpinLock (&mSmmPerfLock);

  Index = mGaugeData->NumberOfEntries;
  if (Index >= mMaxGaugeRecords) {
    //
    // Try to enlarge the scale of gauge array.
    //
    OldGaugeData      = mGaugeData;
    OldGaugeDataSize  = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;

    GaugeDataSize     = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;

    NewGaugeData = AllocateZeroPool (GaugeDataSize);
    if (NewGaugeData == NULL) {
      ReleaseSpinLock (&mSmmPerfLock);
      return EFI_OUT_OF_RESOURCES;
    }

    mGaugeData = NewGaugeData;
    mMaxGaugeRecords *= 2;

    //
    // Initialize new data array and migrate old data one.
    //
    mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);

    FreePool (OldGaugeData);
  }

  GaugeEntryExArray               = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
  GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;

  if (Token != NULL) {
    AsciiStrnCpyS (GaugeEntryExArray[Index].Token, SMM_PERFORMANCE_STRING_SIZE, Token, SMM_PERFORMANCE_STRING_LENGTH);
  }
  if (Module != NULL) {
    AsciiStrnCpyS (GaugeEntryExArray[Index].Module, SMM_PERFORMANCE_STRING_SIZE, Module, SMM_PERFORMANCE_STRING_LENGTH);
  }

  GaugeEntryExArray[Index].EndTimeStamp = 0;
  GaugeEntryExArray[Index].Identifier = Identifier;

  if (TimeStamp == 0) {
    TimeStamp = GetPerformanceCounter ();
  }
  GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;

  mGaugeData->NumberOfEntries++;

  ReleaseSpinLock (&mSmmPerfLock);

  return EFI_SUCCESS;
}
예제 #19
0
/**

  This function is IO instruction handler for SMM.

  @param Index CPU index

**/
VOID
SmmIoHandler (
  IN UINT32 Index
  )
{
  VM_EXIT_QUALIFICATION   Qualification;
  UINT16                  Port;
  UINTN                   *DataPtr;
  UINTN                   LinearAddr;
  X86_REGISTER            *Reg;
  STM_RSC_IO_DESC         *IoDesc;
  STM_RSC_PCI_CFG_DESC    *PciCfgDesc;
  UINT32                  PciAddress;
  STM_RSC_IO_DESC         LocalIoDesc;
  STM_RSC_PCI_CFG_DESC    *LocalPciCfgDescPtr;
  UINT8                   LocalPciCfgDescBuf[STM_LOG_ENTRY_SIZE];

  Reg = &mGuestContextCommonSmm.GuestContextPerCpu[Index].Register;

  Qualification.UintN = VmReadN (VMCS_N_RO_EXIT_QUALIFICATION_INDEX);

  if (Qualification.IoInstruction.Operand != 0) {
    Port = (UINT16)Qualification.IoInstruction.PortNum;
  } else {
    Port = (UINT16)Reg->Rdx;
  }
  DataPtr = (UINTN *)&Reg->Rax;

  //
  // We need handle case that CF9 is protected, but CF8, CFC need to be pass-through.
  // But DWORD CF8 programming will be caught here.
  // So add check here. CF8 will be bypassed, because it does not in CF9 scope.
  //
  IoDesc = GetStmResourceIo (mHostContextCommon.MleProtectedResource.Base, Port);
  if (IoDesc != NULL) {
    DEBUG ((EFI_D_ERROR, "IO violation!\n"));
    AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)IoDesc);
    SmmExceptionHandler (Index);
    CpuDeadLoop ();
  }

  IoDesc = GetStmResourceIo ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, Port);
  if (IoDesc == NULL) {
    ZeroMem (&LocalIoDesc, sizeof(LocalIoDesc));
    LocalIoDesc.Hdr.RscType = IO_RANGE;
    LocalIoDesc.Hdr.Length = sizeof(LocalIoDesc);
    LocalIoDesc.Base = Port;
    LocalIoDesc.Length = (UINT16)(Qualification.IoInstruction.Size + 1);
    AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalIoDesc);
  }

  //
  // Check PCI - 0xCF8, 0xCFC~0xCFF access
  //
  if (Port == 0xCF8) {
    // Access PciAddress

    //
    // We need make sure PciAddress access and PciData access is atomic.
    //
    AcquireSpinLock (&mHostContextCommon.PciLock);
  }
  if ((Port >= 0xCFC) && (Port <= 0xCFF)) {
    // Access PciData

    //
    // AcquireLock to prevent 0xCF8 access
    //
    AcquireSpinLock (&mHostContextCommon.PciLock);
    PciAddress = IoRead32 (0xCF8);
    PciCfgDesc = GetStmResourcePci (
                   mHostContextCommon.MleProtectedResource.Base,
                   BUS_FROM_CF8_ADDRESS(PciAddress),
                   DEVICE_FROM_CF8_ADDRESS(PciAddress),
                   FUNCTION_FROM_CF8_ADDRESS(PciAddress),
                   REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3),
                   (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W
                   );
    if (PciCfgDesc != NULL) {
      DEBUG ((EFI_D_ERROR, "IO (PCI) violation!\n"));
      AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)PciCfgDesc);
      ReleaseSpinLock (&mHostContextCommon.PciLock);
      SmmExceptionHandler (Index);
      CpuDeadLoop ();
    }

    PciCfgDesc = GetStmResourcePci (
                   (STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr,
                   BUS_FROM_CF8_ADDRESS(PciAddress),
                   DEVICE_FROM_CF8_ADDRESS(PciAddress),
                   FUNCTION_FROM_CF8_ADDRESS(PciAddress),
                   REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3),
                   (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W
                   );
    if (PciCfgDesc == NULL) {
      DEBUG((EFI_D_ERROR, "Add unclaimed PCI_RSC!\n"));
      LocalPciCfgDescPtr = (STM_RSC_PCI_CFG_DESC *)LocalPciCfgDescBuf;
      ZeroMem (LocalPciCfgDescBuf, sizeof(LocalPciCfgDescBuf));
      LocalPciCfgDescPtr->Hdr.RscType = PCI_CFG_RANGE;
      LocalPciCfgDescPtr->Hdr.Length = sizeof(STM_RSC_PCI_CFG_DESC); // BUGBUG: Just report this PCI device, it is hard to create PCI hierachy here.
      LocalPciCfgDescPtr->RWAttributes = (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W;
      LocalPciCfgDescPtr->Base = REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3);
      LocalPciCfgDescPtr->Length = (UINT16)(Qualification.IoInstruction.Size + 1);
      LocalPciCfgDescPtr->OriginatingBusNumber = BUS_FROM_CF8_ADDRESS(PciAddress);
      LocalPciCfgDescPtr->LastNodeIndex = 0;
      LocalPciCfgDescPtr->PciDevicePath[0].Type = 1;
      LocalPciCfgDescPtr->PciDevicePath[0].Subtype = 1;
      LocalPciCfgDescPtr->PciDevicePath[0].Length = sizeof(STM_PCI_DEVICE_PATH_NODE);
      LocalPciCfgDescPtr->PciDevicePath[0].PciFunction = FUNCTION_FROM_CF8_ADDRESS(PciAddress);
      LocalPciCfgDescPtr->PciDevicePath[0].PciDevice = DEVICE_FROM_CF8_ADDRESS(PciAddress);
      AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)LocalPciCfgDescPtr);
    }
  }

  if (Qualification.IoInstruction.Rep != 0) {
    UINT64 RcxMask;

    RcxMask = 0xFFFFFFFFFFFFFFFFull;
    if ((mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer & IA32_EFER_MSR_MLA) == 0) {
      RcxMask = 0xFFFFFFFFull;
    }
    if ((Reg->Rcx & RcxMask) == 0) {
      // Skip
      if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
        ReleaseSpinLock (&mHostContextCommon.PciLock);
      }
      VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
      return ;
    }
  }

  if (Qualification.IoInstruction.String != 0) {
    LinearAddr = VmReadN (VMCS_N_RO_GUEST_LINEAR_ADDR_INDEX);
    if (VmReadN (VMCS_N_GUEST_CR0_INDEX) & CR0_PG) {
      DataPtr = (UINTN *)(UINTN)GuestLinearToHostPhysical (Index, LinearAddr);
    } else {
      DataPtr = (UINTN *)LinearAddr;
    }

    if ((VmReadN (VMCS_N_GUEST_RFLAGS_INDEX) & RFLAGS_DF) != 0) {
      if (Qualification.IoInstruction.Direction != 0) {
        Reg->Rdi -= Qualification.IoInstruction.Size + 1;
      } else {
        Reg->Rsi -= Qualification.IoInstruction.Size + 1;
      }
    } else {
      if (Qualification.IoInstruction.Direction != 0) {
        Reg->Rdi += Qualification.IoInstruction.Size + 1;
      } else {
        Reg->Rsi += Qualification.IoInstruction.Size + 1;
      }
    }
  }

  if (Qualification.IoInstruction.Direction != 0) { // IN
    switch (Qualification.IoInstruction.Size) {
    case 0:
      *(UINT8 *)DataPtr = IoRead8 (Port);
      goto Ret;
      break;
    case 1:
      *(UINT16 *)DataPtr = IoRead16 (Port);
      goto Ret;
      break;
    case 3:
      *(UINT32 *)DataPtr = IoRead32 (Port);
      goto Ret;
      break;
    default:
      break;
    }
  } else { // OUT
    switch (Qualification.IoInstruction.Size) {
    case 0:
      IoWrite8 (Port, (UINT8)*DataPtr);
      goto Ret;
      break;
    case 1:
      IoWrite16 (Port, (UINT16)*DataPtr);
      goto Ret;
      break;
    case 3:
      IoWrite32 (Port, (UINT32)*DataPtr);
      goto Ret;
      break;
    default:
      break;
    }
  }

  if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
    ReleaseSpinLock (&mHostContextCommon.PciLock);
  }
  DEBUG ((EFI_D_INFO, "!!!IoHandler!!!\n"));
  DumpVmcsAllField ();

  CpuDeadLoop ();

Ret:
  if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
    ReleaseSpinLock (&mHostContextCommon.PciLock);
  }
  if (Qualification.IoInstruction.Rep != 0) {
    // replay
    Reg->Rcx --;
    return ;
  }

  VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
  return ;
}
예제 #20
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 ;
}