1bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** @file 2bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Local APIC Library. 3bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 4bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This local APIC library instance supports x2APIC capable processors 5bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun which have xAPIC and x2APIC modes. 6bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 7a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR> 8bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This program and the accompanying materials 9bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun are licensed and made available under the terms and conditions of the BSD License 10bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun which accompanies this distribution. The full text of the license may be found at 11bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun http://opensource.org/licenses/bsd-license.php 12bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 13bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 16bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 17bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 1828a7ddf0311f8557360b4f8d042e558b938f6e8cMichael Kinney#include <Register/Cpuid.h> 19a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan#include <Register/Msr.h> 20bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Register/LocalApic.h> 21bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 22bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Library/BaseLib.h> 23bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Library/DebugLib.h> 24bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Library/LocalApicLib.h> 25bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Library/IoLib.h> 26bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun#include <Library/TimerLib.h> 27e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney#include <Library/PcdLib.h> 28bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 29bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// 30bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// Library internal functions 31bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// 32bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 33bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 34e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney Determine if the CPU supports the Local APIC Base Address MSR. 35e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 36e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney @retval TRUE The CPU supports the Local APIC Base Address MSR. 37e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney @retval FALSE The CPU does not support the Local APIC Base Address MSR. 38e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 39e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney**/ 40e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael KinneyBOOLEAN 41e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael KinneyLocalApicBaseAddressMsrSupported ( 42e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney VOID 43e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney ) 44e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney{ 45e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney UINT32 RegEax; 46e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney UINTN FamilyId; 47e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 48e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney AsmCpuid (1, &RegEax, NULL, NULL, NULL); 49e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney FamilyId = BitFieldRead32 (RegEax, 8, 11); 50e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney if (FamilyId == 0x04 || FamilyId == 0x05) { 51e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 52e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // CPUs with a FamilyId of 0x04 or 0x05 do not support the 53e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // Local APIC Base Address MSR 54e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 55e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return FALSE; 56e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney } 57e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return TRUE; 58e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney} 59e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 60e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney/** 61a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff Retrieve the base address of local APIC. 62a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 63a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff @return The base address of local APIC. 64a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 65a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff**/ 66a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffUINTN 67a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffEFIAPI 68a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffGetLocalApicBaseAddress ( 69a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff VOID 70a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff ) 71a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff{ 72a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; 73e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 74e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney if (!LocalApicBaseAddressMsrSupported ()) { 75e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 76e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // If CPU does not support Local APIC Base Address MSR, then retrieve 77e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // Local APIC Base Address from PCD 78e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 79e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return PcdGet32 (PcdCpuLocalApicBaseAddress); 80e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney } 81e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 82a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); 83a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 84a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan return (UINTN)(LShiftU64 ((UINT64) ApicBaseMsr.Bits.ApicBaseHi, 32)) + 85a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan (((UINTN)ApicBaseMsr.Bits.ApicBase) << 12); 86a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff} 87a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 88a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff/** 89a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff Set the base address of local APIC. 90a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 91a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff If BaseAddress is not aligned on a 4KB boundary, then ASSERT(). 92a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 93a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff @param[in] BaseAddress Local APIC base address to be set. 94a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 95a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff**/ 96a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffVOID 97a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffEFIAPI 98a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeffSetLocalApicBaseAddress ( 99a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff IN UINTN BaseAddress 100a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff ) 101a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff{ 102a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; 103a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 104a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0); 105a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 106e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney if (!LocalApicBaseAddressMsrSupported ()) { 107e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 108e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // Ignore set request of the CPU does not support APIC Base Address MSR 109e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 110e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return; 111e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney } 112e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 113a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); 114a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 115a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.ApicBase = (UINT32) (BaseAddress >> 12); 116a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.ApicBaseHi = (UINT32) (RShiftU64((UINT64) BaseAddress, 32)); 117a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 118a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); 119a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff} 120a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff 121a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff/** 122bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Read from a local APIC register. 123bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 124bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function reads from a local APIC register either in xAPIC or x2APIC mode. 125bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be 126bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun accessed using multiple 32-bit loads or stores, so this function only performs 127bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 32-bit read. 128bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 129bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode. 130bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun It must be 16-byte aligned. 131bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 132bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @return 32-bit Value read from the register. 133bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 134bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINT32 135bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 136bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunReadLocalApicReg ( 137bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINTN MmioOffset 138bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 139bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 140bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT32 MsrIndex; 141bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 142bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT ((MmioOffset & 0xf) == 0); 143bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 144bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { 145a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff return MmioRead32 (GetLocalApicBaseAddress() + MmioOffset); 146bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 147bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 148bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // DFR is not supported in x2APIC mode. 149bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 150bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET); 151bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 152bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It 153bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // is not supported in this function for simplicity. 154bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 155bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET); 156bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 157bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS; 158bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return AsmReadMsr32 (MsrIndex); 159bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 160bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 161bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 162bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 163bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Write to a local APIC register. 164bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 165bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function writes to a local APIC register either in xAPIC or x2APIC mode. 166bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be 167bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun accessed using multiple 32-bit loads or stores, so this function only performs 168bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 32-bit write. 169bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 170bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if the register index is invalid or unsupported in current APIC mode, then ASSERT. 171bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 172bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode. 173bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun It must be 16-byte aligned. 174bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param Value Value to be written to the register. 175bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 176bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 177bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 178bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunWriteLocalApicReg ( 179bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINTN MmioOffset, 180bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 Value 181bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 182bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 183bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT32 MsrIndex; 184bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 185bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT ((MmioOffset & 0xf) == 0); 186bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 187bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { 188a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff MmioWrite32 (GetLocalApicBaseAddress() + MmioOffset, Value); 189bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 190bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 191bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // DFR is not supported in x2APIC mode. 192bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 193bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET); 194bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 195bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It 196bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // is not supported in this function for simplicity. 197bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 198bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET); 199bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (MmioOffset != XAPIC_ICR_LOW_OFFSET); 200bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 201bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS; 202bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 203bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // The serializing semantics of WRMSR are relaxed when writing to the APIC registers. 204bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode. 205bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 206bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun MemoryFence (); 207bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun AsmWriteMsr32 (MsrIndex, Value); 208bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 209bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 210bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 211bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 212bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send an IPI by writing to ICR. 213bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 214bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processor. 215bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 216bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param IcrLow 32-bit value to be written to the low half of ICR. 217bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor. 218bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 219bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 220bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendIpi ( 221bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 IcrLow, 222bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 ApicId 223bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 224bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 225bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT64 MsrValue; 226bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLowReg; 227a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff UINTN LocalApciBaseAddress; 2289c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan UINT32 IcrHigh; 2299c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan BOOLEAN InterruptState; 230bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 2319c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2329c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // Legacy APIC or X2APIC? 2339c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 234bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { 235bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (ApicId <= 0xff); 236bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 2379c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan InterruptState = SaveAndDisableInterrupts (); 2389c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 239bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 2409c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // Get base address of this LAPIC 241bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 242a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff LocalApciBaseAddress = GetLocalApicBaseAddress(); 2439c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2449c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2459c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // Save existing contents of ICR high 32 bits 2469c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2479c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan IcrHigh = MmioRead32 (LocalApciBaseAddress + XAPIC_ICR_HIGH_OFFSET); 2489c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2499c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2509c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // Wait for DeliveryStatus clear in case a previous IPI 2519c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // is still being sent 2529c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2539c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan do { 2549c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan IcrLowReg.Uint32 = MmioRead32 (LocalApciBaseAddress + XAPIC_ICR_LOW_OFFSET); 2559c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan } while (IcrLowReg.Bits.DeliveryStatus != 0); 2569c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2579c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2589c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent. 2599c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 260a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff MmioWrite32 (LocalApciBaseAddress + XAPIC_ICR_HIGH_OFFSET, ApicId << 24); 261a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff MmioWrite32 (LocalApciBaseAddress + XAPIC_ICR_LOW_OFFSET, IcrLow); 2629c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2639c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2649c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // Wait for DeliveryStatus clear again 2659c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 266bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun do { 267a66e0c7da759ce41b2615529f9d69627e23e5b08vanjeff IcrLowReg.Uint32 = MmioRead32 (LocalApciBaseAddress + XAPIC_ICR_LOW_OFFSET); 268bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } while (IcrLowReg.Bits.DeliveryStatus != 0); 2699c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2709c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2719c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // And restore old contents of ICR high 2729c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan // 2739c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan MmioWrite32 (LocalApciBaseAddress + XAPIC_ICR_HIGH_OFFSET, IcrHigh); 2749c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 2759c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan SetInterruptState (InterruptState); 2769c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 277bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 278bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 279bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an 280bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // interrupt in x2APIC mode. 281bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 28223394428fdfe351ae9382576cdeee2834a2c637drsun MsrValue = LShiftU64 ((UINT64) ApicId, 32) | IcrLow; 283bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS, MsrValue); 284bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 285bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 286bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 287bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// 288bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// Library API implementation functions 289bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun// 290bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 291bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 292bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Get the current local APIC mode. 293bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 294bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun If local APIC is disabled, then ASSERT. 295bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 296bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC. 297bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC. 298bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 299bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINTN 300bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 301bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetApicMode ( 302bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 303bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 304bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 305a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; 306e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 307e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney if (!LocalApicBaseAddressMsrSupported ()) { 308e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 309e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // If CPU does not support APIC Base Address MSR, then return XAPIC mode 310e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 311e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return LOCAL_APIC_MODE_XAPIC; 312e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney } 313bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 314a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); 315bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 316bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Local APIC should have been enabled 317bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 318a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ASSERT (ApicBaseMsr.Bits.EN != 0); 319a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan if (ApicBaseMsr.Bits.EXTD != 0) { 320bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return LOCAL_APIC_MODE_X2APIC; 321bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 322bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return LOCAL_APIC_MODE_XAPIC; 323bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 324bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 325bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 326bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 327bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Set the current local APIC mode. 328bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 329bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun If the specified local APIC mode is not valid, then ASSERT. 330bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun If the specified local APIC mode can't be set as current, then ASSERT. 331bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 332bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param ApicMode APIC mode to be set. 3339c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan 3349c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan @note This API must not be called from an interrupt handler or SMI handler. 3359c71e1e05666d274a760e45866f65fafc2ccfbc6Jeff Fan It may result in unpredictable behavior. 336bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 337bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 338bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 339bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSetApicMode ( 340bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINTN ApicMode 341bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 342bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 343a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan UINTN CurrentMode; 344a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; 345e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney 346e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney if (!LocalApicBaseAddressMsrSupported ()) { 347e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 348e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // Ignore set request if the CPU does not support APIC Base Address MSR 349e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney // 350e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney return; 351e9cd66d0859f63ec6aab2b1ac863fe72b65fe474Michael Kinney } 352bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 353bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun CurrentMode = GetApicMode (); 354bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (CurrentMode == LOCAL_APIC_MODE_XAPIC) { 355bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun switch (ApicMode) { 356bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun case LOCAL_APIC_MODE_XAPIC: 357bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun break; 358bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun case LOCAL_APIC_MODE_X2APIC: 359a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); 360a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.EXTD = 1; 361a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); 362bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun break; 363bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun default: 364bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (FALSE); 365bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 366bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 367bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun switch (ApicMode) { 368bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun case LOCAL_APIC_MODE_XAPIC: 369bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 370bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Transition from x2APIC mode to xAPIC mode is a two-step process: 371bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // x2APIC -> Local APIC disabled -> xAPIC 372bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 373a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); 374a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.EXTD = 0; 375a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.EN = 0; 376a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); 377a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan ApicBaseMsr.Bits.EN = 1; 378a742e1865de889d73372b984e5e53d5d3afa29c4Jeff Fan AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); 379bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun break; 380bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun case LOCAL_APIC_MODE_X2APIC: 381bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun break; 382bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun default: 383bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (FALSE); 384bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 385bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 386bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 387bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 388bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 389bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset. 390bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 3916e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan In xAPIC mode, the initial local APIC ID may be different from current APIC ID. 392bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case, 393bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun the 32-bit local APIC ID is returned as initial APIC ID. 394bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 395bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @return 32-bit initial local APIC ID of the executing processor. 396bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 397bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINT32 398bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 399bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetInitialApicId ( 400bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 401bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 402bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 4036e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan UINT32 ApicId; 4046e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan UINT32 MaxCpuIdIndex; 405bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT32 RegEbx; 406bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 407bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { 4086e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // 4096e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // Get the max index of basic CPUID 4106e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // 4116e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL); 4126e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // 4136e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // If CPUID Leaf B is supported, 4144af3ae1463796ef7b2ecf2bfe8b390e72817212cLaszlo Ersek // And CPUID.0BH:EBX[15:0] reports a non-zero value, 4156e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // Then the initial 32-bit APIC ID = CPUID.0BH:EDX 4166e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24] 4176e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan // 4186e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) { 4194af3ae1463796ef7b2ecf2bfe8b390e72817212cLaszlo Ersek AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &RegEbx, NULL, &ApicId); 4204af3ae1463796ef7b2ecf2bfe8b390e72817212cLaszlo Ersek if ((RegEbx & (BIT16 - 1)) != 0) { 4214af3ae1463796ef7b2ecf2bfe8b390e72817212cLaszlo Ersek return ApicId; 4224af3ae1463796ef7b2ecf2bfe8b390e72817212cLaszlo Ersek } 4236e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan } 424bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL); 425bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return RegEbx >> 24; 426bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 427bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return GetApicId (); 428bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 429bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 430bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 431bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 432bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Get the local APIC ID of the executing processor. 433bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 434bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @return 32-bit local APIC ID of the executing processor. 435bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 436bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINT32 437bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 438bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetApicId ( 439bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 440bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 441bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 442bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT32 ApicId; 4436e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan UINT32 InitApicId; 444bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 445bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET); 446bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) { 4476e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan ApicId = ((InitApicId = GetInitialApicId ()) < 0x100) ? (ApicId >> 24) : InitApicId; 448bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 4496e3e4d70d47a8beb7d7e1ac10be69cc2924b9e8dJeff Fan 450bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return ApicId; 451bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 452bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 453bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 454ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Get the value of the local APIC version register. 455ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 456ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @return the value of the local APIC version register. 457ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun**/ 458ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunUINT32 459ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunEFIAPI 460ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunGetApicVersion ( 461ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun VOID 462ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun ) 463ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun{ 464ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun return ReadLocalApicReg (XAPIC_VERSION_OFFSET); 465ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun} 466ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 467ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun/** 468ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Send a Fixed IPI to a specified target processor. 469ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 470ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun This function returns after the IPI has been accepted by the target processor. 471ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 472ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param ApicId The local APIC ID of the target processor. 473ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param Vector The vector number of the interrupt being sent. 474ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun**/ 475ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunVOID 476ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunEFIAPI 477ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunSendFixedIpi ( 478ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IN UINT32 ApicId, 479ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IN UINT8 Vector 480ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun ) 481ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun{ 482ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun LOCAL_APIC_ICR_LOW IcrLow; 483ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 484ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Uint32 = 0; 485ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED; 486ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.Level = 1; 487ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.Vector = Vector; 488ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun SendIpi (IcrLow.Uint32, ApicId); 489ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun} 490ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 491ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun/** 492ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Send a Fixed IPI to all processors excluding self. 493ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 494ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun This function returns after the IPI has been accepted by the target processors. 495ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 496ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param Vector The vector number of the interrupt being sent. 497ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun**/ 498ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunVOID 499ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunEFIAPI 500ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunSendFixedIpiAllExcludingSelf ( 501ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IN UINT8 Vector 502ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun ) 503ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun{ 504ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun LOCAL_APIC_ICR_LOW IcrLow; 505ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 506ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Uint32 = 0; 507ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED; 508ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.Level = 1; 509ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 510ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun IcrLow.Bits.Vector = Vector; 511ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun SendIpi (IcrLow.Uint32, 0); 512ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun} 513ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 514ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun/** 515bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send a SMI IPI to a specified target processor. 516bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 517bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processor. 518bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 519bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param ApicId Specify the local APIC ID of the target processor. 520bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 521bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 522bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 523bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendSmiIpi ( 524bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 ApicId 525bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 526bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 527bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 528bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 529bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 530bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI; 531bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 532bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, ApicId); 533bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 534bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 535bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 536bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send a SMI IPI to all processors excluding self. 537bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 538bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processors. 539bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 540bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 541bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 542bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendSmiIpiAllExcludingSelf ( 543bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 544bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 545bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 546bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 547bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 548bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 549bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI; 550bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 551bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 552bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, 0); 553bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 554bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 555bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 556bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send an INIT IPI to a specified target processor. 557bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 558bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processor. 559bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 560bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param ApicId Specify the local APIC ID of the target processor. 561bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 562bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 563bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 564bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendInitIpi ( 565bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 ApicId 566bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 567bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 568bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 569bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 570bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 571bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT; 572bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 573bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, ApicId); 574bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 575bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 576bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 577bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send an INIT IPI to all processors excluding self. 578bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 579bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processors. 580bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 581bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 582bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 583bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendInitIpiAllExcludingSelf ( 584bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 585bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 586bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 587bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 588bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 589bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 590bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT; 591bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 592bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 593bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, 0); 594bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 595bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 596bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 597bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send an INIT-Start-up-Start-up IPI sequence to a specified target processor. 598bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 599bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processor. 600bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 601bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if StartupRoutine >= 1M, then ASSERT. 602bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if StartupRoutine is not multiple of 4K, then ASSERT. 603bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 604bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param ApicId Specify the local APIC ID of the target processor. 605bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param StartupRoutine Points to a start-up routine which is below 1M physical 606bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun address and 4K aligned. 607bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 608bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 609bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 610bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendInitSipiSipi ( 611bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 ApicId, 612bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 StartupRoutine 613bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 614bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 615bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 616bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 617bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (StartupRoutine < 0x100000); 618bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT ((StartupRoutine & 0xfff) == 0); 619bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 620bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendInitIpi (ApicId); 621cf1eb6e6f85952b0fad82b937054f611cf148d57Jeff Fan MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds)); 622bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 623bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Vector = (StartupRoutine >> 12); 624bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 625bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 626bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, ApicId); 627bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun MicroSecondDelay (200); 628bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, ApicId); 629bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 630bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 631bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 632bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self. 633bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 634bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function returns after the IPI has been accepted by the target processors. 635bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 636bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if StartupRoutine >= 1M, then ASSERT. 637bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if StartupRoutine is not multiple of 4K, then ASSERT. 638bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 639bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param StartupRoutine Points to a start-up routine which is below 1M physical 640bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun address and 4K aligned. 641bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 642bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 643bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 644bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendInitSipiSipiAllExcludingSelf ( 645bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 StartupRoutine 646bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 647bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 648bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_ICR_LOW IcrLow; 649bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 650bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (StartupRoutine < 0x100000); 651bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT ((StartupRoutine & 0xfff) == 0); 652bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 653bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendInitIpiAllExcludingSelf (); 654cf1eb6e6f85952b0fad82b937054f611cf148d57Jeff Fan MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds)); 655bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Uint32 = 0; 656bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Vector = (StartupRoutine >> 12); 657bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; 658bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.Level = 1; 659bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; 660bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, 0); 661bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun MicroSecondDelay (200); 662bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun SendIpi (IcrLow.Uint32, 0); 663bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 664bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 665bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 66614e4ca25c6199fa29bda7066f31d919197840664Michael Kinney Initialize the state of the SoftwareEnable bit in the Local APIC 66714e4ca25c6199fa29bda7066f31d919197840664Michael Kinney Spurious Interrupt Vector register. 66814e4ca25c6199fa29bda7066f31d919197840664Michael Kinney 66914e4ca25c6199fa29bda7066f31d919197840664Michael Kinney @param Enable If TRUE, then set SoftwareEnable to 1 67014e4ca25c6199fa29bda7066f31d919197840664Michael Kinney If FALSE, then set SoftwareEnable to 0. 67114e4ca25c6199fa29bda7066f31d919197840664Michael Kinney 67214e4ca25c6199fa29bda7066f31d919197840664Michael Kinney**/ 67314e4ca25c6199fa29bda7066f31d919197840664Michael KinneyVOID 67414e4ca25c6199fa29bda7066f31d919197840664Michael KinneyEFIAPI 67514e4ca25c6199fa29bda7066f31d919197840664Michael KinneyInitializeLocalApicSoftwareEnable ( 67614e4ca25c6199fa29bda7066f31d919197840664Michael Kinney IN BOOLEAN Enable 67714e4ca25c6199fa29bda7066f31d919197840664Michael Kinney ) 67814e4ca25c6199fa29bda7066f31d919197840664Michael Kinney{ 67914e4ca25c6199fa29bda7066f31d919197840664Michael Kinney LOCAL_APIC_SVR Svr; 68014e4ca25c6199fa29bda7066f31d919197840664Michael Kinney 68114e4ca25c6199fa29bda7066f31d919197840664Michael Kinney // 68214e4ca25c6199fa29bda7066f31d919197840664Michael Kinney // Set local APIC software-enabled bit. 68314e4ca25c6199fa29bda7066f31d919197840664Michael Kinney // 68414e4ca25c6199fa29bda7066f31d919197840664Michael Kinney Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET); 68514e4ca25c6199fa29bda7066f31d919197840664Michael Kinney if (Enable) { 68614e4ca25c6199fa29bda7066f31d919197840664Michael Kinney if (Svr.Bits.SoftwareEnable == 0) { 68714e4ca25c6199fa29bda7066f31d919197840664Michael Kinney Svr.Bits.SoftwareEnable = 1; 68814e4ca25c6199fa29bda7066f31d919197840664Michael Kinney WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32); 68914e4ca25c6199fa29bda7066f31d919197840664Michael Kinney } 69014e4ca25c6199fa29bda7066f31d919197840664Michael Kinney } else { 69114e4ca25c6199fa29bda7066f31d919197840664Michael Kinney if (Svr.Bits.SoftwareEnable == 1) { 69214e4ca25c6199fa29bda7066f31d919197840664Michael Kinney Svr.Bits.SoftwareEnable = 0; 69314e4ca25c6199fa29bda7066f31d919197840664Michael Kinney WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32); 69414e4ca25c6199fa29bda7066f31d919197840664Michael Kinney } 69514e4ca25c6199fa29bda7066f31d919197840664Michael Kinney } 69614e4ca25c6199fa29bda7066f31d919197840664Michael Kinney} 69714e4ca25c6199fa29bda7066f31d919197840664Michael Kinney 69814e4ca25c6199fa29bda7066f31d919197840664Michael Kinney/** 699bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Programming Virtual Wire Mode. 700bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 701bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun This function programs the local APIC for virtual wire mode following 702bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun the example described in chapter A.3 of the MP 1.4 spec. 703bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 704bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IOxAPIC is not involved in this type of virtual wire mode. 705bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 706bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 707bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 708bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunProgramVirtualWireMode ( 709bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 710bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 711bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 712bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_SVR Svr; 713bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_LVT_LINT Lint; 714bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 715bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 716bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Enable the APIC via SVR and set the spurious interrupt to use Int 00F. 717bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 718bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET); 719bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Svr.Bits.SpuriousVector = 0xf; 720bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Svr.Bits.SoftwareEnable = 1; 721bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32); 722bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 723bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 724bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high. 725bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 726ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET); 727bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT; 728bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.InputPinPolarity = 0; 729bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.TriggerMode = 0; 730bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.Mask = 0; 731ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32); 732bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 733bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 734bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Program the LINT0 vector entry as NMI. Not masked, edge, active high. 735bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 736ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET); 737bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI; 738bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.InputPinPolarity = 0; 739bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.TriggerMode = 0; 740bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Lint.Bits.Mask = 0; 741ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32); 742bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 743bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 744bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 745b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun Disable LINT0 & LINT1 interrupts. 746b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun 747b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun This function sets the mask flag in the LVT LINT0 & LINT1 registers. 748b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun**/ 749b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsunVOID 750b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsunEFIAPI 751b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsunDisableLvtInterrupts ( 752b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun VOID 753b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun ) 754b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun{ 755b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun LOCAL_APIC_LVT_LINT LvtLint; 756b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun 757b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET); 758b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun LvtLint.Bits.Mask = 1; 759b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32); 760b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun 761b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET); 762b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun LvtLint.Bits.Mask = 1; 763b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32); 764b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun} 765b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun 766b1b8c631f613084d43d64d0b9e1d27337d4d8b5arsun/** 767bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Read the initial count value from the init-count register. 768bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 769bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @return The initial count value read from the init-count register. 770bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 771bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINT32 772bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 773bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetApicTimerInitCount ( 774bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 775bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 776bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 777bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET); 778bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 779bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 780bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 781bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Read the current count value from the current-count register. 782bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 783bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @return The current count value read from the current-count register. 784bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 785bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunUINT32 786bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 787bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetApicTimerCurrentCount ( 788bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 789bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 790bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 791bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET); 792bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 793bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 794bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 795bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Initialize the local APIC timer. 796bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 797bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun The local APIC timer is initialized and enabled. 798bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 799bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128. 800bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun If it is 0, then use the current divide value in the DCR. 801bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param InitCount The initial count value. 802bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot. 803bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @param Vector The timer interrupt vector number. 804bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 805bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 806bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 807bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunInitializeApicTimer ( 808bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINTN DivideValue, 809bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT32 InitCount, 810bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN BOOLEAN PeriodicMode, 811bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun IN UINT8 Vector 812bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 813bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 814bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_DCR Dcr; 815bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_LVT_TIMER LvtTimer; 816bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun UINT32 Divisor; 817bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 818bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 819bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Ensure local APIC is in software-enabled state. 820bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 82114e4ca25c6199fa29bda7066f31d919197840664Michael Kinney InitializeLocalApicSoftwareEnable (TRUE); 822bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 823bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 824bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Program init-count register. 825bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 826bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount); 827bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 828bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (DivideValue != 0) { 829bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (DivideValue <= 128); 830bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue)); 831bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7); 832bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 833bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET); 834bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Dcr.Bits.DivideValue1 = (Divisor & 0x3); 835bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Dcr.Bits.DivideValue2 = (Divisor >> 2); 836bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32); 837bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 838bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 839bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 840bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // Enable APIC timer interrupt with specified timer mode. 841bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun // 842bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET); 843bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun if (PeriodicMode) { 844bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.TimerMode = 1; 845bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } else { 846bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.TimerMode = 0; 847bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun } 848bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.Mask = 0; 849bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.Vector = Vector; 850bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32); 851bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 852bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 853bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 854ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Get the state of the local APIC timer. 855ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 8566d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu This function will ASSERT if the local APIC is not software enabled. 8576d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu 858ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128. 859ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot. 860ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun @param Vector Return the timer interrupt vector number. 861ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun**/ 862ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunVOID 863ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunEFIAPI 864ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsunGetApicTimerState ( 865ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun OUT UINTN *DivideValue OPTIONAL, 866ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun OUT BOOLEAN *PeriodicMode OPTIONAL, 867ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun OUT UINT8 *Vector OPTIONAL 868ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun ) 869ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun{ 870ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun UINT32 Divisor; 871ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun LOCAL_APIC_DCR Dcr; 872ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun LOCAL_APIC_LVT_TIMER LvtTimer; 873ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 8746d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu // 8756d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu // Check the APIC Software Enable/Disable bit (bit 8) in Spurious-Interrupt 8766d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu // Vector Register. 8776d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu // This bit will be 1, if local APIC is software enabled. 8786d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu // 8796d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu ASSERT ((ReadLocalApicReg(XAPIC_SPURIOUS_VECTOR_OFFSET) & BIT8) != 0); 8806d72ff7d9daf7efae5243e9c00a281b350fc0f95Hao Wu 881ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun if (DivideValue != NULL) { 882ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET); 883ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2); 884ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun Divisor = (Divisor + 1) & 0x7; 885ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun *DivideValue = ((UINTN)1) << Divisor; 886ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } 887ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 888ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun if (PeriodicMode != NULL || Vector != NULL) { 889ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET); 890ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun if (PeriodicMode != NULL) { 891ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun if (LvtTimer.Bits.TimerMode == 1) { 892ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun *PeriodicMode = TRUE; 893ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } else { 894ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun *PeriodicMode = FALSE; 895ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } 896ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } 897ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun if (Vector != NULL) { 898ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun *Vector = (UINT8) LvtTimer.Bits.Vector; 899ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } 900ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun } 901ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun} 902ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun 903ae40aef1fb4f5f34e5273b6fd5d4103bf6c7dd2drsun/** 904bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Enable the local APIC timer interrupt. 905bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 906bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 907bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 908bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEnableApicTimerInterrupt ( 909bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 910bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 911bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 912bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_LVT_TIMER LvtTimer; 913bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 914bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET); 915bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.Mask = 0; 916bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32); 917bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 918bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 919bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 920bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Disable the local APIC timer interrupt. 921bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 922bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 923bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 924bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunDisableApicTimerInterrupt ( 925bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 926bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 927bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 928bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_LVT_TIMER LvtTimer; 929bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 930bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET); 931bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Bits.Mask = 1; 932bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32); 933bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 934bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 935bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 936bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Get the local APIC timer interrupt state. 937bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 938bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @retval TRUE The local APIC timer interrupt is enabled. 939bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun @retval FALSE The local APIC timer interrupt is disabled. 940bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 941bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunBOOLEAN 942bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 943bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunGetApicTimerInterruptState ( 944bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 945bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 946bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 947bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LOCAL_APIC_LVT_TIMER LvtTimer; 948bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 949bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET); 950bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun return (BOOLEAN)(LvtTimer.Bits.Mask == 0); 951bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 952bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 953bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun/** 954bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun Send EOI to the local APIC. 955bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun**/ 956bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunVOID 957bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunEFIAPI 958bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsunSendApicEoi ( 959bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun VOID 960bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun ) 961bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun{ 962bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun WriteLocalApicReg (XAPIC_EOI_OFFSET, 0); 963bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun} 964bf73cc4bbcdaa76bad31875bce6ff9dd0d91eb09rsun 9655f867ad00d499debbf22dee044b22e01b63e1ademdkinney/** 9665f867ad00d499debbf22dee044b22e01b63e1ademdkinney Get the 32-bit address that a device should use to send a Message Signaled 9675f867ad00d499debbf22dee044b22e01b63e1ademdkinney Interrupt (MSI) to the Local APIC of the currently executing processor. 9685f867ad00d499debbf22dee044b22e01b63e1ademdkinney 9695f867ad00d499debbf22dee044b22e01b63e1ademdkinney @return 32-bit address used to send an MSI to the Local APIC. 9705f867ad00d499debbf22dee044b22e01b63e1ademdkinney**/ 9715f867ad00d499debbf22dee044b22e01b63e1ademdkinneyUINT32 9725f867ad00d499debbf22dee044b22e01b63e1ademdkinneyEFIAPI 9735f867ad00d499debbf22dee044b22e01b63e1ademdkinneyGetApicMsiAddress ( 9745f867ad00d499debbf22dee044b22e01b63e1ademdkinney VOID 9755f867ad00d499debbf22dee044b22e01b63e1ademdkinney ) 9765f867ad00d499debbf22dee044b22e01b63e1ademdkinney{ 9775f867ad00d499debbf22dee044b22e01b63e1ademdkinney LOCAL_APIC_MSI_ADDRESS MsiAddress; 9785f867ad00d499debbf22dee044b22e01b63e1ademdkinney 9795f867ad00d499debbf22dee044b22e01b63e1ademdkinney // 9805f867ad00d499debbf22dee044b22e01b63e1ademdkinney // Return address for an MSI interrupt to be delivered only to the APIC ID 9815f867ad00d499debbf22dee044b22e01b63e1ademdkinney // of the currently executing processor. 9825f867ad00d499debbf22dee044b22e01b63e1ademdkinney // 9835f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiAddress.Uint32 = 0; 9845f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiAddress.Bits.BaseAddress = 0xFEE; 9855f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiAddress.Bits.DestinationId = GetApicId (); 9865f867ad00d499debbf22dee044b22e01b63e1ademdkinney return MsiAddress.Uint32; 9875f867ad00d499debbf22dee044b22e01b63e1ademdkinney} 9885f867ad00d499debbf22dee044b22e01b63e1ademdkinney 9895f867ad00d499debbf22dee044b22e01b63e1ademdkinney/** 9905f867ad00d499debbf22dee044b22e01b63e1ademdkinney Get the 64-bit data value that a device should use to send a Message Signaled 9915f867ad00d499debbf22dee044b22e01b63e1ademdkinney Interrupt (MSI) to the Local APIC of the currently executing processor. 9925f867ad00d499debbf22dee044b22e01b63e1ademdkinney 9935f867ad00d499debbf22dee044b22e01b63e1ademdkinney If Vector is not in range 0x10..0xFE, then ASSERT(). 9945f867ad00d499debbf22dee044b22e01b63e1ademdkinney If DeliveryMode is not supported, then ASSERT(). 9955f867ad00d499debbf22dee044b22e01b63e1ademdkinney 9965f867ad00d499debbf22dee044b22e01b63e1ademdkinney @param Vector The 8-bit interrupt vector associated with the MSI. 9975f867ad00d499debbf22dee044b22e01b63e1ademdkinney Must be in the range 0x10..0xFE 9985f867ad00d499debbf22dee044b22e01b63e1ademdkinney @param DeliveryMode A 3-bit value that specifies how the recept of the MSI 9995f867ad00d499debbf22dee044b22e01b63e1ademdkinney is handled. The only supported values are: 10005f867ad00d499debbf22dee044b22e01b63e1ademdkinney 0: LOCAL_APIC_DELIVERY_MODE_FIXED 10015f867ad00d499debbf22dee044b22e01b63e1ademdkinney 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY 10025f867ad00d499debbf22dee044b22e01b63e1ademdkinney 2: LOCAL_APIC_DELIVERY_MODE_SMI 10035f867ad00d499debbf22dee044b22e01b63e1ademdkinney 4: LOCAL_APIC_DELIVERY_MODE_NMI 10045f867ad00d499debbf22dee044b22e01b63e1ademdkinney 5: LOCAL_APIC_DELIVERY_MODE_INIT 10055f867ad00d499debbf22dee044b22e01b63e1ademdkinney 7: LOCAL_APIC_DELIVERY_MODE_EXTINT 10065f867ad00d499debbf22dee044b22e01b63e1ademdkinney 10075f867ad00d499debbf22dee044b22e01b63e1ademdkinney @param LevelTriggered TRUE specifies a level triggered interrupt. 10085f867ad00d499debbf22dee044b22e01b63e1ademdkinney FALSE specifies an edge triggered interrupt. 10095f867ad00d499debbf22dee044b22e01b63e1ademdkinney @param AssertionLevel Ignored if LevelTriggered is FALSE. 10105f867ad00d499debbf22dee044b22e01b63e1ademdkinney TRUE specifies a level triggered interrupt that active 10115f867ad00d499debbf22dee044b22e01b63e1ademdkinney when the interrupt line is asserted. 10125f867ad00d499debbf22dee044b22e01b63e1ademdkinney FALSE specifies a level triggered interrupt that active 10135f867ad00d499debbf22dee044b22e01b63e1ademdkinney when the interrupt line is deasserted. 10145f867ad00d499debbf22dee044b22e01b63e1ademdkinney 10155f867ad00d499debbf22dee044b22e01b63e1ademdkinney @return 64-bit data value used to send an MSI to the Local APIC. 10165f867ad00d499debbf22dee044b22e01b63e1ademdkinney**/ 10175f867ad00d499debbf22dee044b22e01b63e1ademdkinneyUINT64 10185f867ad00d499debbf22dee044b22e01b63e1ademdkinneyEFIAPI 10195f867ad00d499debbf22dee044b22e01b63e1ademdkinneyGetApicMsiValue ( 10205f867ad00d499debbf22dee044b22e01b63e1ademdkinney IN UINT8 Vector, 10215f867ad00d499debbf22dee044b22e01b63e1ademdkinney IN UINTN DeliveryMode, 10225f867ad00d499debbf22dee044b22e01b63e1ademdkinney IN BOOLEAN LevelTriggered, 10235f867ad00d499debbf22dee044b22e01b63e1ademdkinney IN BOOLEAN AssertionLevel 10245f867ad00d499debbf22dee044b22e01b63e1ademdkinney ) 10255f867ad00d499debbf22dee044b22e01b63e1ademdkinney{ 10265f867ad00d499debbf22dee044b22e01b63e1ademdkinney LOCAL_APIC_MSI_DATA MsiData; 10275f867ad00d499debbf22dee044b22e01b63e1ademdkinney 10285f867ad00d499debbf22dee044b22e01b63e1ademdkinney ASSERT (Vector >= 0x10 && Vector <= 0xFE); 10295f867ad00d499debbf22dee044b22e01b63e1ademdkinney ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3); 10305f867ad00d499debbf22dee044b22e01b63e1ademdkinney 10315f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiData.Uint64 = 0; 10325f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiData.Bits.Vector = Vector; 10335f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiData.Bits.DeliveryMode = (UINT32)DeliveryMode; 10345f867ad00d499debbf22dee044b22e01b63e1ademdkinney if (LevelTriggered) { 10355f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiData.Bits.TriggerMode = 1; 10365f867ad00d499debbf22dee044b22e01b63e1ademdkinney if (AssertionLevel) { 10375f867ad00d499debbf22dee044b22e01b63e1ademdkinney MsiData.Bits.Level = 1; 10385f867ad00d499debbf22dee044b22e01b63e1ademdkinney } 10395f867ad00d499debbf22dee044b22e01b63e1ademdkinney } 10405f867ad00d499debbf22dee044b22e01b63e1ademdkinney return MsiData.Uint64; 10415f867ad00d499debbf22dee044b22e01b63e1ademdkinney} 104273152f19c0be7f31ee05f32878b515a296c487faLeo Duran 104373152f19c0be7f31ee05f32878b515a296c487faLeo Duran/** 104473152f19c0be7f31ee05f32878b515a296c487faLeo Duran Get Package ID/Core ID/Thread ID of a processor. 104573152f19c0be7f31ee05f32878b515a296c487faLeo Duran 104673152f19c0be7f31ee05f32878b515a296c487faLeo Duran The algorithm assumes the target system has symmetry across physical 104773152f19c0be7f31ee05f32878b515a296c487faLeo Duran package boundaries with respect to the number of logical processors 104873152f19c0be7f31ee05f32878b515a296c487faLeo Duran per package, number of cores per package. 104973152f19c0be7f31ee05f32878b515a296c487faLeo Duran 105073152f19c0be7f31ee05f32878b515a296c487faLeo Duran @param[in] InitialApicId Initial APIC ID of the target logical processor. 105173152f19c0be7f31ee05f32878b515a296c487faLeo Duran @param[out] Package Returns the processor package ID. 105273152f19c0be7f31ee05f32878b515a296c487faLeo Duran @param[out] Core Returns the processor core ID. 105373152f19c0be7f31ee05f32878b515a296c487faLeo Duran @param[out] Thread Returns the processor thread ID. 105473152f19c0be7f31ee05f32878b515a296c487faLeo Duran**/ 105573152f19c0be7f31ee05f32878b515a296c487faLeo DuranVOID 10561c8ca9a012ce19a1096625ef9e810036e8346827Jeff FanEFIAPI 1057262128e5ab9edda666586c7dda3f2b0f53c0c557Jeff FanGetProcessorLocationByApicId ( 105873152f19c0be7f31ee05f32878b515a296c487faLeo Duran IN UINT32 InitialApicId, 105973152f19c0be7f31ee05f32878b515a296c487faLeo Duran OUT UINT32 *Package OPTIONAL, 106073152f19c0be7f31ee05f32878b515a296c487faLeo Duran OUT UINT32 *Core OPTIONAL, 106173152f19c0be7f31ee05f32878b515a296c487faLeo Duran OUT UINT32 *Thread OPTIONAL 106273152f19c0be7f31ee05f32878b515a296c487faLeo Duran ) 106373152f19c0be7f31ee05f32878b515a296c487faLeo Duran{ 106473152f19c0be7f31ee05f32878b515a296c487faLeo Duran BOOLEAN TopologyLeafSupported; 106573152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINTN ThreadBits; 106673152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINTN CoreBits; 106773152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_VERSION_INFO_EBX VersionInfoEbx; 106873152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_VERSION_INFO_EDX VersionInfoEdx; 106973152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_CACHE_PARAMS_EAX CacheParamsEax; 107073152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_EXTENDED_TOPOLOGY_EAX ExtendedTopologyEax; 107173152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx; 107273152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx; 107373152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINT32 MaxCpuIdIndex; 107473152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINT32 SubIndex; 107573152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINTN LevelType; 107673152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINT32 MaxLogicProcessorsPerPackage; 107773152f19c0be7f31ee05f32878b515a296c487faLeo Duran UINT32 MaxCoresPerPackage; 107873152f19c0be7f31ee05f32878b515a296c487faLeo Duran 107973152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 108073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Check if the processor is capable of supporting more than one logical processor. 108173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 108273152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuid(CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32); 108373152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (VersionInfoEdx.Bits.HTT == 0) { 108473152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Thread != NULL) { 108573152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Thread = 0; 108673152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 108773152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Core != NULL) { 108873152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Core = 0; 108973152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 109073152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Package != NULL) { 109173152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Package = 0; 109273152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 109373152f19c0be7f31ee05f32878b515a296c487faLeo Duran return; 109473152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 109573152f19c0be7f31ee05f32878b515a296c487faLeo Duran 109673152f19c0be7f31ee05f32878b515a296c487faLeo Duran ThreadBits = 0; 109773152f19c0be7f31ee05f32878b515a296c487faLeo Duran CoreBits = 0; 109873152f19c0be7f31ee05f32878b515a296c487faLeo Duran 109973152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 110073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Assume three-level mapping of APIC ID: Package:Core:SMT. 110173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 110273152f19c0be7f31ee05f32878b515a296c487faLeo Duran TopologyLeafSupported = FALSE; 110373152f19c0be7f31ee05f32878b515a296c487faLeo Duran 110473152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 110573152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Get the max index of basic CPUID 110673152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 110773152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuid(CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL); 110873152f19c0be7f31ee05f32878b515a296c487faLeo Duran 110973152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 111073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // If the extended topology enumeration leaf is available, it 111173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // is the preferred mechanism for enumerating topology. 111273152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 111373152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) { 111473152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuidEx( 111573152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_EXTENDED_TOPOLOGY, 111673152f19c0be7f31ee05f32878b515a296c487faLeo Duran 0, 111773152f19c0be7f31ee05f32878b515a296c487faLeo Duran &ExtendedTopologyEax.Uint32, 111873152f19c0be7f31ee05f32878b515a296c487faLeo Duran &ExtendedTopologyEbx.Uint32, 111973152f19c0be7f31ee05f32878b515a296c487faLeo Duran &ExtendedTopologyEcx.Uint32, 112073152f19c0be7f31ee05f32878b515a296c487faLeo Duran NULL 112173152f19c0be7f31ee05f32878b515a296c487faLeo Duran ); 112273152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 112373152f19c0be7f31ee05f32878b515a296c487faLeo Duran // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for 112473152f19c0be7f31ee05f32878b515a296c487faLeo Duran // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not 112573152f19c0be7f31ee05f32878b515a296c487faLeo Duran // supported on that processor. 112673152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 112773152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (ExtendedTopologyEbx.Uint32 != 0) { 112873152f19c0be7f31ee05f32878b515a296c487faLeo Duran TopologyLeafSupported = TRUE; 112973152f19c0be7f31ee05f32878b515a296c487faLeo Duran 113073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 113173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract 113273152f19c0be7f31ee05f32878b515a296c487faLeo Duran // the SMT sub-field of x2APIC ID. 113373152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 113473152f19c0be7f31ee05f32878b515a296c487faLeo Duran LevelType = ExtendedTopologyEcx.Bits.LevelType; 113573152f19c0be7f31ee05f32878b515a296c487faLeo Duran ASSERT(LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT); 113673152f19c0be7f31ee05f32878b515a296c487faLeo Duran ThreadBits = ExtendedTopologyEax.Bits.ApicIdShift; 113773152f19c0be7f31ee05f32878b515a296c487faLeo Duran 113873152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 113973152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Software must not assume any "level type" encoding 114073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // value to be related to any sub-leaf index, except sub-leaf 0. 114173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 114273152f19c0be7f31ee05f32878b515a296c487faLeo Duran SubIndex = 1; 114373152f19c0be7f31ee05f32878b515a296c487faLeo Duran do { 114473152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuidEx( 114573152f19c0be7f31ee05f32878b515a296c487faLeo Duran CPUID_EXTENDED_TOPOLOGY, 114673152f19c0be7f31ee05f32878b515a296c487faLeo Duran SubIndex, 114773152f19c0be7f31ee05f32878b515a296c487faLeo Duran &ExtendedTopologyEax.Uint32, 114873152f19c0be7f31ee05f32878b515a296c487faLeo Duran NULL, 114973152f19c0be7f31ee05f32878b515a296c487faLeo Duran &ExtendedTopologyEcx.Uint32, 115073152f19c0be7f31ee05f32878b515a296c487faLeo Duran NULL 115173152f19c0be7f31ee05f32878b515a296c487faLeo Duran ); 115273152f19c0be7f31ee05f32878b515a296c487faLeo Duran LevelType = ExtendedTopologyEcx.Bits.LevelType; 115373152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) { 115473152f19c0be7f31ee05f32878b515a296c487faLeo Duran CoreBits = ExtendedTopologyEax.Bits.ApicIdShift - ThreadBits; 115573152f19c0be7f31ee05f32878b515a296c487faLeo Duran break; 115673152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 115773152f19c0be7f31ee05f32878b515a296c487faLeo Duran SubIndex++; 115873152f19c0be7f31ee05f32878b515a296c487faLeo Duran } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID); 115973152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 116073152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 116173152f19c0be7f31ee05f32878b515a296c487faLeo Duran 116273152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (!TopologyLeafSupported) { 116373152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuid(CPUID_VERSION_INFO, NULL, &VersionInfoEbx.Uint32, NULL, NULL); 116473152f19c0be7f31ee05f32878b515a296c487faLeo Duran MaxLogicProcessorsPerPackage = VersionInfoEbx.Bits.MaximumAddressableIdsForLogicalProcessors; 116573152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) { 116673152f19c0be7f31ee05f32878b515a296c487faLeo Duran AsmCpuidEx(CPUID_CACHE_PARAMS, 0, &CacheParamsEax.Uint32, NULL, NULL, NULL); 116773152f19c0be7f31ee05f32878b515a296c487faLeo Duran MaxCoresPerPackage = CacheParamsEax.Bits.MaximumAddressableIdsForLogicalProcessors + 1; 116873152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 116973152f19c0be7f31ee05f32878b515a296c487faLeo Duran else { 117073152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 117173152f19c0be7f31ee05f32878b515a296c487faLeo Duran // Must be a single-core processor. 117273152f19c0be7f31ee05f32878b515a296c487faLeo Duran // 117373152f19c0be7f31ee05f32878b515a296c487faLeo Duran MaxCoresPerPackage = 1; 117473152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 117573152f19c0be7f31ee05f32878b515a296c487faLeo Duran 117673152f19c0be7f31ee05f32878b515a296c487faLeo Duran ThreadBits = (UINTN)(HighBitSet32(MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1); 117773152f19c0be7f31ee05f32878b515a296c487faLeo Duran CoreBits = (UINTN)(HighBitSet32(MaxCoresPerPackage - 1) + 1); } 117873152f19c0be7f31ee05f32878b515a296c487faLeo Duran 117973152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Thread != NULL) { 118073152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Thread = InitialApicId & ((1 << ThreadBits) - 1); 118173152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 118273152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Core != NULL) { 118373152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Core = (InitialApicId >> ThreadBits) & ((1 << CoreBits) - 1); 118473152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 118573152f19c0be7f31ee05f32878b515a296c487faLeo Duran if (Package != NULL) { 118673152f19c0be7f31ee05f32878b515a296c487faLeo Duran *Package = (InitialApicId >> (ThreadBits + CoreBits)); 118773152f19c0be7f31ee05f32878b515a296c487faLeo Duran } 118873152f19c0be7f31ee05f32878b515a296c487faLeo Duran} 1189