Example #1
0
/**

  This function initialize host common context.

**/
VOID
InitHostContextCommon (
  VOID
  )
{
  UINT32                      Index;
  INTERRUPT_GATE_DESCRIPTOR   *IdtGate;

  //
  // PageTable
  //
  mHostContextCommon.PageTable = CreatePageTable ();

  mHostContextCommon.Gdtr.Limit = mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr.Limit;
  mHostContextCommon.Gdtr.Base = (UINTN)AllocatePages (FRM_SIZE_TO_PAGES (mHostContextCommon.Gdtr.Limit + 1));
  CopyMem ((VOID *)mHostContextCommon.Gdtr.Base, (VOID *)mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr.Base, mHostContextCommon.Gdtr.Limit + 1);
  AsmWriteGdtr (&mHostContextCommon.Gdtr);

  mHostContextCommon.Idtr.Limit = 0x100 * sizeof (INTERRUPT_GATE_DESCRIPTOR) - 1;
  mHostContextCommon.Idtr.Base = (UINTN)AllocatePages (FRM_SIZE_TO_PAGES (mHostContextCommon.Idtr.Limit + 1));
  CopyMem ((VOID *)mHostContextCommon.Idtr.Base, (VOID *)mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr.Base, mHostContextCommon.Idtr.Limit + 1);
  IdtGate = (INTERRUPT_GATE_DESCRIPTOR *)mHostContextCommon.Idtr.Base;
  for (Index = 0; Index < 0x100; Index++) {
    IdtGate[Index].Offset15To0 = (UINT16)((UINTN)AsmExceptionHandlers + Index * mExceptionHandlerLength);
    IdtGate[Index].Offset31To16 = (UINT16)(((UINTN)AsmExceptionHandlers + Index * mExceptionHandlerLength) >> 16);
#ifdef MDE_CPU_X64
    IdtGate[Index].Offset63To32 = (UINT32)(((UINTN)AsmExceptionHandlers + Index * mExceptionHandlerLength) >> 32);
#endif
  }
  //
  // Special for NMI
  //
  IdtGate[2].Offset15To0 = (UINT16)((UINTN)AsmNmiExceptionHandler);
  IdtGate[2].Offset31To16 = (UINT16)(((UINTN)AsmNmiExceptionHandler) >> 16);
#ifdef MDE_CPU_X64
  IdtGate[2].Offset63To32 = (UINT32)(((UINTN)AsmNmiExceptionHandler) >> 32);
#endif

  //
  // VmExitHandler
  //
  InitFrmHandler ();
  mTeardownFinished = AllocatePages (FRM_SIZE_TO_PAGES (mHostContextCommon.CpuNum));

  //
  // Init HostContextPerCpu
  //
  mApicIdList = (UINTN)AllocatePages (FRM_SIZE_TO_PAGES (sizeof(UINT32) * mHostContextCommon.CpuNum));
  GetApicIdListFromAcpi ((UINT32 *)mApicIdList);

  for (Index = 0; Index < mHostContextCommon.CpuNum; Index++) {
    mHostContextCommon.HostContextPerCpu[Index].Index = Index;
    mHostContextCommon.HostContextPerCpu[Index].ApicId = *((UINT32 *)mApicIdList + Index);

    mHostContextCommon.HostContextPerCpu[Index].Stack = (UINTN)AllocatePages (32);
    mHostContextCommon.HostContextPerCpu[Index].Stack += FRM_PAGES_TO_SIZE (32);

    InitHostVmcs (Index);
  }
}
Example #2
0
/**
  Initialize Global Descriptor Table.

**/
VOID
InitGlobalDescriptorTable (
  VOID
  )
{
  GDT_ENTRIES *gdt;
  IA32_DESCRIPTOR gdtPtr;

  //
  // Allocate Runtime Data for the GDT
  //
  gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
  ASSERT (gdt != NULL);
  gdt = ALIGN_POINTER (gdt, 8);

  //
  // Initialize all GDT entries
  //
  CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));

  //
  // Write GDT register
  //
  gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
  gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
  AsmWriteGdtr (&gdtPtr);

  //
  // Update selector (segment) registers base on new GDT
  //
  SetCodeSelector ((UINT16)CPU_CODE_SEL);
  SetDataSelectors ((UINT16)CPU_DATA_SEL);
}
Example #3
0
VOID
__lgdt (
    _In_ IA32_DESCRIPTOR* Gdtr
    )
{
    //
    // Use the UEFI framework function
    //
    AsmWriteGdtr(Gdtr);
}
Example #4
0
/**
  Platform specific mechanism to transfer control to 16bit OS waking vector

  @param[in] AcpiWakingVector    The 16bit OS waking vector
  @param[in] AcpiLowMemoryBase   A buffer under 1M which could be used during the transfer

**/
VOID
PlatformTransferControl16 (
    IN UINT32       AcpiWakingVector,
    IN UINT32       AcpiLowMemoryBase
)
{
    UINT32      NewValue;
    UINT64      BaseAddress;
    UINT64      SmramLength;
    UINTN       Index;

    DEBUG (( EFI_D_INFO, "PlatformTransferControl - Entry\r\n"));

    //
    // Need to make sure the GDT is loaded with values that support long mode and real mode.
    //
    AsmWriteGdtr (&mGdt);

    //
    // Disable eSram block (this will also clear/zero eSRAM)
    // We only use eSRAM in the PEI phase. Disable now that we are resuming the OS
    //
    NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK);
    NewValue |= BLOCK_DISABLE_PG;
    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue);

    //
    // Update HMBOUND to top of DDR3 memory and LOCK
    // We disabled eSRAM so now we move HMBOUND down to top of DDR3
    //
    QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength);
    NewValue = (UINT32)(BaseAddress + SmramLength);
    DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue));
    QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK));

    //
    // Lock all IMR regions now that HMBOUND is locked
    //
    for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index += 4) {
        NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);
        NewValue |= IMR_LOCK;
        QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index, NewValue);
    }

    //
    // Call ASM routine to switch to real mode and jump to 16bit OS waking vector
    //
    AsmTransferControl(AcpiWakingVector, 0);

    //
    // Never run to here
    //
    CpuDeadLoop();
}
Example #5
0
/**
  Initialize Global Descriptor Table.

**/
VOID
SetLinuxDescriptorTables (
  VOID
  )
{
  IA32_DESCRIPTOR GdtPtr;
  IA32_DESCRIPTOR IdtPtr;

  //
  // Write GDT register
  //
  GdtPtr.Base = (UINT32)(UINTN)(VOID*) mGdt;
  GdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
  AsmWriteGdtr (&GdtPtr);

  IdtPtr.Base = (UINT32) 0;
  IdtPtr.Limit = (UINT16) 0;
  AsmWriteIdtr (&IdtPtr);
}
Example #6
0
/**
   Transfers control to DxeCore.

   This function performs a CPU architecture specific operations to execute
   the entry point of DxeCore with the parameters of HobList.
   It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.

   @param DxeCoreEntryPoint         The entry point of DxeCore.
   @param HobList                   The start of HobList passed to DxeCore.

**/
VOID
HandOffToDxeCore (
  IN EFI_PHYSICAL_ADDRESS   DxeCoreEntryPoint,
  IN EFI_PEI_HOB_POINTERS   HobList
  )
{
  EFI_STATUS                Status;
  EFI_PHYSICAL_ADDRESS      BaseOfStack;
  EFI_PHYSICAL_ADDRESS      TopOfStack;
  UINTN                     PageTables;
  X64_IDT_GATE_DESCRIPTOR   *IdtTable;
  UINTN                     SizeOfTemplate;
  VOID                      *TemplateBase;
  EFI_PHYSICAL_ADDRESS      VectorAddress;
  UINT32                    Index;
  X64_IDT_TABLE             *IdtTableForX64;
  EFI_VECTOR_HANDOFF_INFO   *VectorInfo;
  EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
  BOOLEAN                   BuildPageTablesIa32Pae;

  if (IsNullDetectionEnabled ()) {
    ClearFirst4KPage (HobList.Raw);
  }

  Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
  ASSERT_EFI_ERROR (Status);

  if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {
    //
    // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
    // Pre-allocate a 32 bytes which confroms to x64 calling convention.
    //
    // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
    // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
    // register parameters is reserved on the stack, in case the called function
    // wants to spill them; this is important if the function is variadic.
    //
    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;

    //
    //  x64 Calling Conventions requires that the stack must be aligned to 16 bytes
    //
    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);

    //
    // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
    // memory, it may be corrupted when copying FV to high-end memory
    //
    AsmWriteGdtr (&gGdt);
    //
    // Create page table and save PageMapLevel4 to CR3
    //
    PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);

    //
    // End of PEI phase signal
    //
    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);
    Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);
    ASSERT_EFI_ERROR (Status);

    //
    // Paging might be already enabled. To avoid conflict configuration,
    // disable paging first anyway.
    //
    AsmWriteCr0 (AsmReadCr0 () & (~BIT31));
    AsmWriteCr3 (PageTables);

    //
    // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
    //
    UpdateStackHob (BaseOfStack, STACK_SIZE);

    SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);

    Status = PeiServicesAllocatePages (
               EfiBootServicesData,
               EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),
               &VectorAddress
               );
    ASSERT_EFI_ERROR (Status);

    //
    // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that
    // it may not be gotten correctly after IDT register is re-written.
    //
    IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress;
    IdtTableForX64->PeiService = GetPeiServicesTablePointer ();

    VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);
    IdtTable      = IdtTableForX64->IdtTable;
    for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {
      IdtTable[Index].Ia32IdtEntry.Bits.GateType    =  0x8e;
      IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0  =  0;
      IdtTable[Index].Ia32IdtEntry.Bits.Selector    =  SYS_CODE64_SEL;

      IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow   = (UINT16) VectorAddress;
      IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh  = (UINT16) (RShiftU64 (VectorAddress, 16));
      IdtTable[Index].Offset32To63                  = (UINT32) (RShiftU64 (VectorAddress, 32));
      IdtTable[Index].Reserved                      = 0;

      CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);
      AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);

      VectorAddress += SizeOfTemplate;
    }

    gLidtDescriptor.Base = (UINTN) IdtTable;

    //
    // Disable interrupt of Debug timer, since new IDT table cannot handle it.
    //
    SaveAndSetDebugTimerInterrupt (FALSE);

    AsmWriteIdtr (&gLidtDescriptor);

    DEBUG ((
      DEBUG_INFO,
      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",
      __FUNCTION__,
      BaseOfStack,
      STACK_SIZE
      ));

    //
    // Go to Long Mode and transfer control to DxeCore.
    // Interrupts will not get turned on until the CPU AP is loaded.
    // Call x64 drivers passing in single argument, a pointer to the HOBs.
    //
    AsmEnablePaging64 (
      SYS_CODE64_SEL,
      DxeCoreEntryPoint,
      (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
      0,
      TopOfStack
      );
  } else {
    //
    // Get Vector Hand-off Info PPI and build Guided HOB
    //
    Status = PeiServicesLocatePpi (
               &gEfiVectorHandoffInfoPpiGuid,
               0,
               NULL,
               (VOID **)&VectorHandoffInfoPpi
               );
    if (Status == EFI_SUCCESS) {
      DEBUG ((EFI_D_INFO, "Vector Hand-off Info PPI is gotten, GUIDed HOB is created!\n"));
      VectorInfo = VectorHandoffInfoPpi->Info;
      Index = 1;
      while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
        VectorInfo ++;
        Index ++;
      }
      BuildGuidDataHob (
        &gEfiVectorHandoffInfoPpiGuid,
        VectorHandoffInfoPpi->Info,
        sizeof (EFI_VECTOR_HANDOFF_INFO) * Index
        );
    }

    //
    // Compute the top of the stack we were allocated. Pre-allocate a UINTN
    // for safety.
    //
    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;
    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);

    PageTables = 0;
    BuildPageTablesIa32Pae = ToBuildPageTable ();
    if (BuildPageTablesIa32Pae) {
      PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
      if (IsEnableNonExecNeeded ()) {
        EnableExecuteDisableBit();
      }
    }

    //
    // End of PEI phase signal
    //
    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);
    Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);
    ASSERT_EFI_ERROR (Status);

    if (BuildPageTablesIa32Pae) {
      //
      // Paging might be already enabled. To avoid conflict configuration,
      // disable paging first anyway.
      //
      AsmWriteCr0 (AsmReadCr0 () & (~BIT31));
      AsmWriteCr3 (PageTables);
      //
      // Set Physical Address Extension (bit 5 of CR4).
      //
      AsmWriteCr4 (AsmReadCr4 () | BIT5);
    }

    //
    // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
    //
    UpdateStackHob (BaseOfStack, STACK_SIZE);

    DEBUG ((
      DEBUG_INFO,
      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",
      __FUNCTION__,
      BaseOfStack,
      STACK_SIZE
      ));

    //
    // Transfer the control to the entry point of DxeCore.
    //
    if (BuildPageTablesIa32Pae) {
      AsmEnablePaging32 (
        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
        HobList.Raw,
        NULL,
        (VOID *) (UINTN) TopOfStack
        );
    } else {
      SwitchStack (
        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
        HobList.Raw,
        NULL,
        (VOID *) (UINTN) TopOfStack
        );
    }
  }
}