4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Local APIC Library.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This local APIC library instance supports x2APIC capable processors
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which have xAPIC and x2APIC modes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Register/LocalApic.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/BaseLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/DebugLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/LocalApicLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/IoLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/TimerLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/PcdLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Library internal functions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Read from a local APIC register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function reads from a local APIC register either in xAPIC or x2APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync accessed using multiple 32-bit loads or stores, so this function only performs
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 32-bit read.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It must be 16-byte aligned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return 32-bit Value read from the register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncReadLocalApicReg (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN MmioOffset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 MsrIndex;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((MmioOffset & 0xf) == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DFR is not supported in x2APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is not supported in this function for simplicity.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return AsmReadMsr32 (MsrIndex);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Write to a local APIC register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function writes to a local APIC register either in xAPIC or x2APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync accessed using multiple 32-bit loads or stores, so this function only performs
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 32-bit write.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if the register index is invalid or unsupported in current APIC mode, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It must be 16-byte aligned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Value Value to be written to the register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWriteLocalApicReg (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN MmioOffset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 MsrIndex;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((MmioOffset & 0xf) == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DFR is not supported in x2APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is not supported in this function for simplicity.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MmioOffset != XAPIC_ICR_LOW_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The serializing semantics of WRMSR are relaxed when writing to the APIC registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MemoryFence ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteMsr32 (MsrIndex, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an IPI by writing to ICR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param IcrLow 32-bit value to be written to the low half of ICR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendIpi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 IcrLow,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ApicId
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 MsrValue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLowReg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ApicId <= 0xff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_HIGH_OFFSET, ApicId << 24);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET, IcrLow);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLowReg.Uint32 = MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (IcrLowReg.Bits.DeliveryStatus != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // interrupt in x2APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsrValue = LShiftU64 ((UINT64) ApicId, 32) | IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS, MsrValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Library API implementation functions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the current local APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If local APIC is disabled, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicMode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MSR_IA32_APIC_BASE ApicBaseMsr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Local APIC should have been enabled
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ApicBaseMsr.Bits.En != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ApicBaseMsr.Bits.Extd != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return LOCAL_APIC_MODE_X2APIC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return LOCAL_APIC_MODE_XAPIC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Set the current local APIC mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the specified local APIC mode is not valid, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the specified local APIC mode can't be set as current, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicMode APIC mode to be set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSetApicMode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN ApicMode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN CurrentMode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MSR_IA32_APIC_BASE ApicBaseMsr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CurrentMode = GetApicMode ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CurrentMode == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (ApicMode) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case LOCAL_APIC_MODE_XAPIC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case LOCAL_APIC_MODE_X2APIC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Bits.Extd = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (ApicMode) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case LOCAL_APIC_MODE_XAPIC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transition from x2APIC mode to xAPIC mode is a two-step process:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // x2APIC -> Local APIC disabled -> xAPIC
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Bits.Extd = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Bits.En = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicBaseMsr.Bits.En = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case LOCAL_APIC_MODE_X2APIC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the 32-bit local APIC ID is returned as initial APIC ID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return 32-bit initial local APIC ID of the executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetInitialApicId (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 RegEbx;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RegEbx >> 24;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return GetApicId ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the local APIC ID of the executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return 32-bit local APIC ID of the executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicId (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 ApicId;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ApicId >>= 24;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ApicId;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the value of the local APIC version register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return the value of the local APIC version register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicVersion (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a Fixed IPI to a specified target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicId The local APIC ID of the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Vector The vector number of the interrupt being sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendFixedIpi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ApicId,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Vector
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Vector = Vector;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a Fixed IPI to all processors excluding self.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processors.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Vector The vector number of the interrupt being sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendFixedIpiAllExcludingSelf (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Vector
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Vector = Vector;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a SMI IPI to a specified target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicId Specify the local APIC ID of the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendSmiIpi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ApicId
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a SMI IPI to all processors excluding self.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processors.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendSmiIpiAllExcludingSelf (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an INIT IPI to a specified target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicId Specify the local APIC ID of the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendInitIpi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ApicId
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an INIT IPI to all processors excluding self.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processors.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendInitIpiAllExcludingSelf (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if StartupRoutine >= 1M, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if StartupRoutine is not multiple of 4K, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ApicId Specify the local APIC ID of the target processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param StartupRoutine Points to a start-up routine which is below 1M physical
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address and 4K aligned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendInitSipiSipi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ApicId,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 StartupRoutine
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (StartupRoutine < 0x100000);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((StartupRoutine & 0xfff) == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendInitIpi (ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MicroSecondDelay (10);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Vector = (StartupRoutine >> 12);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MicroSecondDelay (200);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, ApicId);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function returns after the IPI has been accepted by the target processors.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if StartupRoutine >= 1M, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if StartupRoutine is not multiple of 4K, then ASSERT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param StartupRoutine Points to a start-up routine which is below 1M physical
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address and 4K aligned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendInitSipiSipiAllExcludingSelf (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 StartupRoutine
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_ICR_LOW IcrLow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (StartupRoutine < 0x100000);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((StartupRoutine & 0xfff) == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendInitIpiAllExcludingSelf ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MicroSecondDelay (10);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Vector = (StartupRoutine >> 12);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MicroSecondDelay (200);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SendIpi (IcrLow.Uint32, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Programming Virtual Wire Mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function programs the local APIC for virtual wire mode following
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the example described in chapter A.3 of the MP 1.4 spec.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IOxAPIC is not involved in this type of virtual wire mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncProgramVirtualWireMode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_SVR Svr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_LINT Lint;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Svr.Bits.SpuriousVector = 0xf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Svr.Bits.SoftwareEnable = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.InputPinPolarity = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.TriggerMode = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.Mask = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.InputPinPolarity = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.TriggerMode = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lint.Bits.Mask = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Disable LINT0 & LINT1 interrupts.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function sets the mask flag in the LVT LINT0 & LINT1 registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDisableLvtInterrupts (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_LINT LvtLint;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtLint.Bits.Mask = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtLint.Bits.Mask = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Read the initial count value from the init-count register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The initial count value read from the init-count register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicTimerInitCount (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Read the current count value from the current-count register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The current count value read from the current-count register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicTimerCurrentCount (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Initialize the local APIC timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The local APIC timer is initialized and enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If it is 0, then use the current divide value in the DCR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param InitCount The initial count value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Vector The timer interrupt vector number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncInitializeApicTimer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN DivideValue,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 InitCount,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN PeriodicMode,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Vector
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_SVR Svr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_DCR Dcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_TIMER LvtTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Divisor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Ensure local APIC is in software-enabled state.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Svr.Bits.SoftwareEnable = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Program init-count register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DivideValue != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (DivideValue <= 128);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dcr.Bits.DivideValue1 = (Divisor & 0x3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dcr.Bits.DivideValue2 = (Divisor >> 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Enable APIC timer interrupt with specified timer mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PeriodicMode) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.TimerMode = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.TimerMode = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.Mask = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.Vector = Vector;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the state of the local APIC timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Vector Return the timer interrupt vector number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicTimerState (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINTN *DivideValue OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT BOOLEAN *PeriodicMode OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINT8 *Vector OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Divisor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_DCR Dcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_TIMER LvtTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DivideValue != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Divisor = (Divisor + 1) & 0x7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *DivideValue = ((UINTN)1) << Divisor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PeriodicMode != NULL || Vector != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PeriodicMode != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LvtTimer.Bits.TimerMode == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *PeriodicMode = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *PeriodicMode = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Vector != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Vector = (UINT8) LvtTimer.Bits.Vector;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Enable the local APIC timer interrupt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEnableApicTimerInterrupt (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_TIMER LvtTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.Mask = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Disable the local APIC timer interrupt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDisableApicTimerInterrupt (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_TIMER LvtTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Bits.Mask = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the local APIC timer interrupt state.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE The local APIC timer interrupt is enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE The local APIC timer interrupt is disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicTimerInterruptState (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_LVT_TIMER LvtTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (BOOLEAN)(LvtTimer.Bits.Mask == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send EOI to the local APIC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendApicEoi (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the 32-bit address that a device should use to send a Message Signaled
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interrupt (MSI) to the Local APIC of the currently executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return 32-bit address used to send an MSI to the Local APIC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicMsiAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_MSI_ADDRESS MsiAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return address for an MSI interrupt to be delivered only to the APIC ID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // of the currently executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiAddress.Uint32 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiAddress.Bits.BaseAddress = 0xFEE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiAddress.Bits.DestinationId = GetApicId ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return MsiAddress.Uint32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the 64-bit data value that a device should use to send a Message Signaled
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interrupt (MSI) to the Local APIC of the currently executing processor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Vector is not in range 0x10..0xFE, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If DeliveryMode is not supported, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Vector The 8-bit interrupt vector associated with the MSI.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Must be in the range 0x10..0xFE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is handled. The only supported values are:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0: LOCAL_APIC_DELIVERY_MODE_FIXED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 2: LOCAL_APIC_DELIVERY_MODE_SMI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 4: LOCAL_APIC_DELIVERY_MODE_NMI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 5: LOCAL_APIC_DELIVERY_MODE_INIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param LevelTriggered TRUE specifies a level triggered interrupt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE specifies an edge triggered interrupt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param AssertionLevel Ignored if LevelTriggered is FALSE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE specifies a level triggered interrupt that active
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync when the interrupt line is asserted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE specifies a level triggered interrupt that active
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync when the interrupt line is deasserted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return 64-bit data value used to send an MSI to the Local APIC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT64
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGetApicMsiValue (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Vector,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN DeliveryMode,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN LevelTriggered,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN AssertionLevel
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LOCAL_APIC_MSI_DATA MsiData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Vector >= 0x10 && Vector <= 0xFE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiData.Uint64 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiData.Bits.Vector = Vector;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiData.Bits.DeliveryMode = (UINT32)DeliveryMode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LevelTriggered) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiData.Bits.TriggerMode = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AssertionLevel) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MsiData.Bits.Level = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return MsiData.Uint64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}