TianoCore EDK2 master
BaseXApicLib.c
Go to the documentation of this file.
1
14#include <Register/Amd/Cpuid.h>
15#include <Register/Intel/Msr.h>
17
18#include <Library/BaseLib.h>
19#include <Library/DebugLib.h>
21#include <Library/IoLib.h>
22#include <Library/TimerLib.h>
23#include <Library/PcdLib.h>
24#include <Library/CpuLib.h>
25#include <Library/UefiCpuLib.h>
26
27//
28// Library internal functions
29//
30
38BOOLEAN
40 VOID
41 )
42{
43 UINT32 RegEax;
44 UINTN FamilyId;
45
46 AsmCpuid (1, &RegEax, NULL, NULL, NULL);
47 FamilyId = BitFieldRead32 (RegEax, 8, 11);
48 if ((FamilyId == 0x04) || (FamilyId == 0x05)) {
49 //
50 // CPUs with a FamilyId of 0x04 or 0x05 do not support the
51 // Local APIC Base Address MSR
52 //
53 return FALSE;
54 }
55
56 return TRUE;
57}
58
66EFIAPI
68 VOID
69 )
70{
72
74 //
75 // If CPU does not support Local APIC Base Address MSR, then retrieve
76 // Local APIC Base Address from PCD
77 //
78 return PcdGet32 (PcdCpuLocalApicBaseAddress);
79 }
80
82
83 return (UINTN)(LShiftU64 ((UINT64)ApicBaseMsr.Bits.ApicBaseHi, 32)) +
84 (((UINTN)ApicBaseMsr.Bits.ApicBase) << 12);
85}
86
95VOID
96EFIAPI
98 IN UINTN BaseAddress
99 )
100{
101 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
102
103 ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0);
104
106 //
107 // Ignore set request if the CPU does not support APIC Base Address MSR
108 //
109 return;
110 }
111
112 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
113
114 ApicBaseMsr.Bits.ApicBase = (UINT32)(BaseAddress >> 12);
115 ApicBaseMsr.Bits.ApicBaseHi = (UINT32)(RShiftU64 ((UINT64)BaseAddress, 32));
116
118}
119
133UINT32
134EFIAPI
136 IN UINTN MmioOffset
137 )
138{
139 ASSERT ((MmioOffset & 0xf) == 0);
141
142 return MmioRead32 (GetLocalApicBaseAddress () + MmioOffset);
143}
144
159VOID
160EFIAPI
162 IN UINTN MmioOffset,
163 IN UINT32 Value
164 )
165{
166 ASSERT ((MmioOffset & 0xf) == 0);
168
169 MmioWrite32 (GetLocalApicBaseAddress () + MmioOffset, Value);
170}
171
180VOID
182 IN UINT32 IcrLow,
183 IN UINT32 ApicId
184 )
185{
186 LOCAL_APIC_ICR_LOW IcrLowReg;
187 UINT32 IcrHigh;
188 BOOLEAN InterruptState;
189
191 ASSERT (ApicId <= 0xff);
192
193 InterruptState = SaveAndDisableInterrupts ();
194
195 //
196 // Save existing contents of ICR high 32 bits
197 //
198 IcrHigh = ReadLocalApicReg (XAPIC_ICR_HIGH_OFFSET);
199
200 //
201 // Wait for DeliveryStatus clear in case a previous IPI
202 // is still being sent
203 //
204 do {
205 IcrLowReg.Uint32 = ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET);
206 } while (IcrLowReg.Bits.DeliveryStatus != 0);
207
208 //
209 // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
210 //
211 WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET, ApicId << 24);
212 WriteLocalApicReg (XAPIC_ICR_LOW_OFFSET, IcrLow);
213
214 //
215 // Wait for DeliveryStatus clear again
216 //
217 do {
218 IcrLowReg.Uint32 = ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET);
219 } while (IcrLowReg.Bits.DeliveryStatus != 0);
220
221 //
222 // And restore old contents of ICR high
223 //
224 WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET, IcrHigh);
225
226 SetInterruptState (InterruptState);
227}
228
229//
230// Library API implementation functions
231//
232
241UINTN
242EFIAPI
244 VOID
245 )
246{
248 {
249 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
250
251 //
252 // Check to see if the CPU supports the APIC Base Address MSR
253 //
255 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
256 //
257 // Local APIC should have been enabled
258 //
259 ASSERT (ApicBaseMsr.Bits.EN != 0);
260 ASSERT (ApicBaseMsr.Bits.EXTD == 0);
261 }
262 }
265}
266
278VOID
279EFIAPI
281 IN UINTN ApicMode
282 )
283{
284 ASSERT (ApicMode == LOCAL_APIC_MODE_XAPIC);
286}
287
297UINT32
298EFIAPI
300 VOID
301 )
302{
303 UINT32 ApicId;
304 UINT32 MaxCpuIdIndex;
305 UINT32 RegEbx;
306
308
309 //
310 // Get the max index of basic CPUID
311 //
312 AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
313
314 //
315 // If CPUID Leaf B is supported,
316 // And CPUID.0BH:EBX[15:0] reports a non-zero value,
317 // Then the initial 32-bit APIC ID = CPUID.0BH:EDX
318 // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24]
319 //
320 if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
321 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &RegEbx, NULL, &ApicId);
322 if ((RegEbx & (BIT16 - 1)) != 0) {
323 return ApicId;
324 }
325 }
326
328 return RegEbx >> 24;
329}
330
336UINT32
337EFIAPI
339 VOID
340 )
341{
342 UINT32 ApicId;
343
345
346 if ((ApicId = GetInitialApicId ()) < 0x100) {
347 //
348 // If the initial local APIC ID is less 0x100, read APIC ID from
349 // XAPIC_ID_OFFSET, otherwise return the initial local APIC ID.
350 //
351 ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);
352 ApicId >>= 24;
353 }
354
355 return ApicId;
356}
357
363UINT32
364EFIAPI
366 VOID
367 )
368{
369 return ReadLocalApicReg (XAPIC_VERSION_OFFSET);
370}
371
380VOID
381EFIAPI
383 IN UINT32 ApicId,
384 IN UINT8 Vector
385 )
386{
387 LOCAL_APIC_ICR_LOW IcrLow;
388
389 IcrLow.Uint32 = 0;
390 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
391 IcrLow.Bits.Level = 1;
392 IcrLow.Bits.Vector = Vector;
393 SendIpi (IcrLow.Uint32, ApicId);
394}
395
403VOID
404EFIAPI
406 IN UINT8 Vector
407 )
408{
409 LOCAL_APIC_ICR_LOW IcrLow;
410
411 IcrLow.Uint32 = 0;
412 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;
413 IcrLow.Bits.Level = 1;
414 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
415 IcrLow.Bits.Vector = Vector;
416 SendIpi (IcrLow.Uint32, 0);
417}
418
426VOID
427EFIAPI
429 IN UINT32 ApicId
430 )
431{
432 LOCAL_APIC_ICR_LOW IcrLow;
433
434 IcrLow.Uint32 = 0;
435 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
436 IcrLow.Bits.Level = 1;
437 SendIpi (IcrLow.Uint32, ApicId);
438}
439
445VOID
446EFIAPI
448 VOID
449 )
450{
451 LOCAL_APIC_ICR_LOW IcrLow;
452
453 IcrLow.Uint32 = 0;
454 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;
455 IcrLow.Bits.Level = 1;
456 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
457 SendIpi (IcrLow.Uint32, 0);
458}
459
467VOID
468EFIAPI
470 IN UINT32 ApicId
471 )
472{
473 LOCAL_APIC_ICR_LOW IcrLow;
474
475 IcrLow.Uint32 = 0;
476 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
477 IcrLow.Bits.Level = 1;
478 SendIpi (IcrLow.Uint32, ApicId);
479}
480
486VOID
487EFIAPI
489 VOID
490 )
491{
492 LOCAL_APIC_ICR_LOW IcrLow;
493
494 IcrLow.Uint32 = 0;
495 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;
496 IcrLow.Bits.Level = 1;
497 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
498 SendIpi (IcrLow.Uint32, 0);
499}
500
513VOID
514EFIAPI
516 IN UINT32 ApicId,
517 IN UINT32 StartupRoutine
518 )
519{
520 LOCAL_APIC_ICR_LOW IcrLow;
521
522 ASSERT (StartupRoutine < 0x100000);
523 ASSERT ((StartupRoutine & 0xfff) == 0);
524
525 SendInitIpi (ApicId);
526 MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds));
527 IcrLow.Uint32 = 0;
528 IcrLow.Bits.Vector = (StartupRoutine >> 12);
529 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
530 IcrLow.Bits.Level = 1;
531 SendIpi (IcrLow.Uint32, ApicId);
533 MicroSecondDelay (200);
534 SendIpi (IcrLow.Uint32, ApicId);
535 }
536}
537
549VOID
550EFIAPI
552 IN UINT32 StartupRoutine
553 )
554{
555 LOCAL_APIC_ICR_LOW IcrLow;
556
557 ASSERT (StartupRoutine < 0x100000);
558 ASSERT ((StartupRoutine & 0xfff) == 0);
559
561 MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds));
562 IcrLow.Uint32 = 0;
563 IcrLow.Bits.Vector = (StartupRoutine >> 12);
564 IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
565 IcrLow.Bits.Level = 1;
566 IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;
567 SendIpi (IcrLow.Uint32, 0);
569 MicroSecondDelay (200);
570 SendIpi (IcrLow.Uint32, 0);
571 }
572}
573
582VOID
583EFIAPI
585 IN BOOLEAN Enable
586 )
587{
588 LOCAL_APIC_SVR Svr;
589
590 //
591 // Set local APIC software-enabled bit.
592 //
593 Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
594 if (Enable) {
595 if (Svr.Bits.SoftwareEnable == 0) {
596 Svr.Bits.SoftwareEnable = 1;
597 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
598 }
599 } else {
600 if (Svr.Bits.SoftwareEnable == 1) {
601 Svr.Bits.SoftwareEnable = 0;
602 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
603 }
604 }
605}
606
615VOID
616EFIAPI
618 VOID
619 )
620{
621 LOCAL_APIC_SVR Svr;
623
624 //
625 // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
626 //
627 Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);
628 Svr.Bits.SpuriousVector = 0xf;
629 Svr.Bits.SoftwareEnable = 1;
630 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);
631
632 //
633 // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
634 //
635 Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
636 Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;
637 Lint.Bits.InputPinPolarity = 0;
638 Lint.Bits.TriggerMode = 0;
639 Lint.Bits.Mask = 0;
640 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);
641
642 //
643 // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
644 //
645 Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
646 Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;
647 Lint.Bits.InputPinPolarity = 0;
648 Lint.Bits.TriggerMode = 0;
649 Lint.Bits.Mask = 0;
650 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);
651}
652
658VOID
659EFIAPI
661 VOID
662 )
663{
664 LOCAL_APIC_LVT_LINT LvtLint;
665
666 LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);
667 LvtLint.Bits.Mask = 1;
668 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32);
669
670 LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);
671 LvtLint.Bits.Mask = 1;
672 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32);
673}
674
680UINT32
681EFIAPI
683 VOID
684 )
685{
686 return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);
687}
688
694UINT32
695EFIAPI
697 VOID
698 )
699{
700 return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);
701}
702
714VOID
715EFIAPI
717 IN UINTN DivideValue,
718 IN UINT32 InitCount,
719 IN BOOLEAN PeriodicMode,
720 IN UINT8 Vector
721 )
722{
723 LOCAL_APIC_DCR Dcr;
724 LOCAL_APIC_LVT_TIMER LvtTimer;
725 UINT32 Divisor;
726
727 //
728 // Ensure local APIC is in software-enabled state.
729 //
731
732 //
733 // Program init-count register.
734 //
735 WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);
736
737 if (DivideValue != 0) {
738 ASSERT (DivideValue <= 128);
739 ASSERT (DivideValue == GetPowerOfTwo32 ((UINT32)DivideValue));
740 Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);
741
742 Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
743 Dcr.Bits.DivideValue1 = (Divisor & 0x3);
744 Dcr.Bits.DivideValue2 = (Divisor >> 2);
745 WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32);
746 }
747
748 //
749 // Enable APIC timer interrupt with specified timer mode.
750 //
751 LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
752 if (PeriodicMode) {
753 LvtTimer.Bits.TimerMode = 1;
754 } else {
755 LvtTimer.Bits.TimerMode = 0;
756 }
757
758 LvtTimer.Bits.Mask = 0;
759 LvtTimer.Bits.Vector = Vector;
760 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
761}
762
772VOID
773EFIAPI
775 OUT UINTN *DivideValue OPTIONAL,
776 OUT BOOLEAN *PeriodicMode OPTIONAL,
777 OUT UINT8 *Vector OPTIONAL
778 )
779{
780 UINT32 Divisor;
781 LOCAL_APIC_DCR Dcr;
782 LOCAL_APIC_LVT_TIMER LvtTimer;
783
784 //
785 // Check the APIC Software Enable/Disable bit (bit 8) in Spurious-Interrupt
786 // Vector Register.
787 // This bit will be 1, if local APIC is software enabled.
788 //
789 ASSERT ((ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET) & BIT8) != 0);
790
791 if (DivideValue != NULL) {
792 Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);
793 Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);
794 Divisor = (Divisor + 1) & 0x7;
795 *DivideValue = ((UINTN)1) << Divisor;
796 }
797
798 if ((PeriodicMode != NULL) || (Vector != NULL)) {
799 LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
800 if (PeriodicMode != NULL) {
801 if (LvtTimer.Bits.TimerMode == 1) {
802 *PeriodicMode = TRUE;
803 } else {
804 *PeriodicMode = FALSE;
805 }
806 }
807
808 if (Vector != NULL) {
809 *Vector = (UINT8)LvtTimer.Bits.Vector;
810 }
811 }
812}
813
817VOID
818EFIAPI
820 VOID
821 )
822{
823 LOCAL_APIC_LVT_TIMER LvtTimer;
824
825 LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
826 LvtTimer.Bits.Mask = 0;
827 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
828}
829
833VOID
834EFIAPI
836 VOID
837 )
838{
839 LOCAL_APIC_LVT_TIMER LvtTimer;
840
841 LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
842 LvtTimer.Bits.Mask = 1;
843 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);
844}
845
852BOOLEAN
853EFIAPI
855 VOID
856 )
857{
858 LOCAL_APIC_LVT_TIMER LvtTimer;
859
860 LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);
861 return (BOOLEAN)(LvtTimer.Bits.Mask == 0);
862}
863
867VOID
868EFIAPI
870 VOID
871 )
872{
873 WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);
874}
875
882UINT32
883EFIAPI
885 VOID
886 )
887{
888 LOCAL_APIC_MSI_ADDRESS MsiAddress;
889
890 //
891 // Return address for an MSI interrupt to be delivered only to the APIC ID
892 // of the currently executing processor.
893 //
894 MsiAddress.Uint32 = 0;
895 MsiAddress.Bits.BaseAddress = 0xFEE;
896 MsiAddress.Bits.DestinationId = GetApicId ();
897 return MsiAddress.Uint32;
898}
899
928UINT64
929EFIAPI
931 IN UINT8 Vector,
932 IN UINTN DeliveryMode,
933 IN BOOLEAN LevelTriggered,
934 IN BOOLEAN AssertionLevel
935 )
936{
937 LOCAL_APIC_MSI_DATA MsiData;
938
939 ASSERT (Vector >= 0x10 && Vector <= 0xFE);
940 ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3);
941
942 MsiData.Uint64 = 0;
943 MsiData.Bits.Vector = Vector;
944 MsiData.Bits.DeliveryMode = (UINT32)DeliveryMode;
945 if (LevelTriggered) {
946 MsiData.Bits.TriggerMode = 1;
947 if (AssertionLevel) {
948 MsiData.Bits.Level = 1;
949 }
950 }
951
952 return MsiData.Uint64;
953}
954
967VOID
968EFIAPI
970 IN UINT32 InitialApicId,
971 OUT UINT32 *Package OPTIONAL,
972 OUT UINT32 *Core OPTIONAL,
973 OUT UINT32 *Thread OPTIONAL
974 )
975{
976 BOOLEAN TopologyLeafSupported;
977 CPUID_VERSION_INFO_EBX VersionInfoEbx;
978 CPUID_VERSION_INFO_EDX VersionInfoEdx;
979 CPUID_CACHE_PARAMS_EAX CacheParamsEax;
980 CPUID_EXTENDED_TOPOLOGY_EAX ExtendedTopologyEax;
981 CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx;
982 CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx;
983 CPUID_AMD_EXTENDED_CPU_SIG_ECX AmdExtendedCpuSigEcx;
984 CPUID_AMD_PROCESSOR_TOPOLOGY_EBX AmdProcessorTopologyEbx;
985 CPUID_AMD_VIR_PHY_ADDRESS_SIZE_ECX AmdVirPhyAddressSizeEcx;
986 UINT32 MaxStandardCpuIdIndex;
987 UINT32 MaxExtendedCpuIdIndex;
988 UINT32 SubIndex;
989 UINTN LevelType;
990 UINT32 MaxLogicProcessorsPerPackage;
991 UINT32 MaxCoresPerPackage;
992 UINTN ThreadBits;
993 UINTN CoreBits;
994
995 //
996 // Check if the processor is capable of supporting more than one logical processor.
997 //
998 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
999 if (VersionInfoEdx.Bits.HTT == 0) {
1000 if (Thread != NULL) {
1001 *Thread = 0;
1002 }
1003
1004 if (Core != NULL) {
1005 *Core = 0;
1006 }
1007
1008 if (Package != NULL) {
1009 *Package = 0;
1010 }
1011
1012 return;
1013 }
1014
1015 //
1016 // Assume three-level mapping of APIC ID: Package|Core|Thread.
1017 //
1018 ThreadBits = 0;
1019 CoreBits = 0;
1020
1021 //
1022 // Get max index of CPUID
1023 //
1024 AsmCpuid (CPUID_SIGNATURE, &MaxStandardCpuIdIndex, NULL, NULL, NULL);
1025 AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedCpuIdIndex, NULL, NULL, NULL);
1026
1027 //
1028 // If the extended topology enumeration leaf is available, it
1029 // is the preferred mechanism for enumerating topology.
1030 //
1031 TopologyLeafSupported = FALSE;
1032 if (MaxStandardCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
1033 AsmCpuidEx (
1035 0,
1036 &ExtendedTopologyEax.Uint32,
1037 &ExtendedTopologyEbx.Uint32,
1038 &ExtendedTopologyEcx.Uint32,
1039 NULL
1040 );
1041 //
1042 // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
1043 // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
1044 // supported on that processor.
1045 //
1046 if (ExtendedTopologyEbx.Uint32 != 0) {
1047 TopologyLeafSupported = TRUE;
1048
1049 //
1050 // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
1051 // the SMT sub-field of x2APIC ID.
1052 //
1053 LevelType = ExtendedTopologyEcx.Bits.LevelType;
1054 ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
1055 ThreadBits = ExtendedTopologyEax.Bits.ApicIdShift;
1056
1057 //
1058 // Software must not assume any "level type" encoding
1059 // value to be related to any sub-leaf index, except sub-leaf 0.
1060 //
1061 SubIndex = 1;
1062 do {
1063 AsmCpuidEx (
1065 SubIndex,
1066 &ExtendedTopologyEax.Uint32,
1067 NULL,
1068 &ExtendedTopologyEcx.Uint32,
1069 NULL
1070 );
1071 LevelType = ExtendedTopologyEcx.Bits.LevelType;
1072 if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
1073 CoreBits = ExtendedTopologyEax.Bits.ApicIdShift - ThreadBits;
1074 break;
1075 }
1076
1077 SubIndex++;
1078 } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
1079 }
1080 }
1081
1082 if (!TopologyLeafSupported) {
1083 //
1084 // Get logical processor count
1085 //
1086 AsmCpuid (CPUID_VERSION_INFO, NULL, &VersionInfoEbx.Uint32, NULL, NULL);
1087 MaxLogicProcessorsPerPackage = VersionInfoEbx.Bits.MaximumAddressableIdsForLogicalProcessors;
1088
1089 //
1090 // Assume single-core processor
1091 //
1092 MaxCoresPerPackage = 1;
1093
1094 //
1095 // Check for topology extensions on AMD processor
1096 //
1098 if (MaxExtendedCpuIdIndex >= CPUID_AMD_PROCESSOR_TOPOLOGY) {
1099 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, &AmdExtendedCpuSigEcx.Uint32, NULL);
1100 if (AmdExtendedCpuSigEcx.Bits.TopologyExtensions != 0) {
1101 //
1102 // Account for max possible thread count to decode ApicId
1103 //
1104 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, NULL, NULL, &AmdVirPhyAddressSizeEcx.Uint32, NULL);
1105 MaxLogicProcessorsPerPackage = 1 << AmdVirPhyAddressSizeEcx.Bits.ApicIdCoreIdSize;
1106
1107 //
1108 // Get cores per processor package
1109 //
1110 AsmCpuid (CPUID_AMD_PROCESSOR_TOPOLOGY, NULL, &AmdProcessorTopologyEbx.Uint32, NULL, NULL);
1111 MaxCoresPerPackage = MaxLogicProcessorsPerPackage / (AmdProcessorTopologyEbx.Bits.ThreadsPerCore + 1);
1112 }
1113 }
1114 } else {
1115 //
1116 // Extract core count based on CACHE information
1117 //
1118 if (MaxStandardCpuIdIndex >= CPUID_CACHE_PARAMS) {
1119 AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &CacheParamsEax.Uint32, NULL, NULL, NULL);
1120 if (CacheParamsEax.Uint32 != 0) {
1121 MaxCoresPerPackage = CacheParamsEax.Bits.MaximumAddressableIdsForLogicalProcessors + 1;
1122 }
1123 }
1124 }
1125
1126 ThreadBits = (UINTN)(HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
1127 CoreBits = (UINTN)(HighBitSet32 (MaxCoresPerPackage - 1) + 1);
1128 }
1129
1130 if (Thread != NULL) {
1131 *Thread = InitialApicId & ((1 << ThreadBits) - 1);
1132 }
1133
1134 if (Core != NULL) {
1135 *Core = (InitialApicId >> ThreadBits) & ((1 << CoreBits) - 1);
1136 }
1137
1138 if (Package != NULL) {
1139 *Package = (InitialApicId >> (ThreadBits + CoreBits));
1140 }
1141}
1142
1159VOID
1160EFIAPI
1162 IN UINT32 InitialApicId,
1163 OUT UINT32 *Package OPTIONAL,
1164 OUT UINT32 *Die OPTIONAL,
1165 OUT UINT32 *Tile OPTIONAL,
1166 OUT UINT32 *Module OPTIONAL,
1167 OUT UINT32 *Core OPTIONAL,
1168 OUT UINT32 *Thread OPTIONAL
1169 )
1170{
1171 CPUID_EXTENDED_TOPOLOGY_EAX ExtendedTopologyEax;
1172 CPUID_EXTENDED_TOPOLOGY_ECX ExtendedTopologyEcx;
1173 UINT32 MaxStandardCpuIdIndex;
1174 UINT32 Index;
1175 UINTN LevelType;
1176 UINT32 Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
1177 UINT32 *Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 2];
1178
1179 for (LevelType = 0; LevelType < ARRAY_SIZE (Bits); LevelType++) {
1180 Bits[LevelType] = 0;
1181 }
1182
1183 //
1184 // Get max index of CPUID
1185 //
1186 AsmCpuid (CPUID_SIGNATURE, &MaxStandardCpuIdIndex, NULL, NULL, NULL);
1187 if (MaxStandardCpuIdIndex < CPUID_V2_EXTENDED_TOPOLOGY) {
1188 if (Die != NULL) {
1189 *Die = 0;
1190 }
1191
1192 if (Tile != NULL) {
1193 *Tile = 0;
1194 }
1195
1196 if (Module != NULL) {
1197 *Module = 0;
1198 }
1199
1200 GetProcessorLocationByApicId (InitialApicId, Package, Core, Thread);
1201 return;
1202 }
1203
1204 //
1205 // If the V2 extended topology enumeration leaf is available, it
1206 // is the preferred mechanism for enumerating topology.
1207 //
1208 for (Index = 0; ; Index++) {
1209 AsmCpuidEx (
1211 Index,
1212 &ExtendedTopologyEax.Uint32,
1213 NULL,
1214 &ExtendedTopologyEcx.Uint32,
1215 NULL
1216 );
1217
1218 LevelType = ExtendedTopologyEcx.Bits.LevelType;
1219
1220 //
1221 // first level reported should be SMT.
1222 //
1223 ASSERT ((Index != 0) || (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT));
1225 break;
1226 }
1227
1228 ASSERT (LevelType < ARRAY_SIZE (Bits));
1229 Bits[LevelType] = ExtendedTopologyEax.Bits.ApicIdShift;
1230 }
1231
1232 for (LevelType = CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE; LevelType < ARRAY_SIZE (Bits); LevelType++) {
1233 //
1234 // If there are more levels between level-1 (low-level) and level-2 (high-level), the unknown levels will be ignored
1235 // and treated as an extension of the last known level (i.e., level-1 in this case).
1236 //
1237 if (Bits[LevelType] == 0) {
1238 Bits[LevelType] = Bits[LevelType - 1];
1239 }
1240 }
1241
1242 Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 1] = Package;
1243 Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE] = Die;
1244 Location[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_TILE] = Tile;
1246 Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE] = Core;
1247 Location[CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT] = Thread;
1248
1249 Bits[CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 1] = 32;
1250
1251 for ( LevelType = CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT
1252 ; LevelType <= CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE + 1
1253 ; LevelType++
1254 )
1255 {
1256 if (Location[LevelType] != NULL) {
1257 //
1258 // Bits[i] holds the number of bits to shift right on x2APIC ID to get a unique
1259 // topology ID of the next level type.
1260 //
1261 *Location[LevelType] = InitialApicId >> Bits[LevelType - 1];
1262
1263 //
1264 // Bits[i] - Bits[i-1] holds the number of bits for the next ONE level type.
1265 //
1266 *Location[LevelType] &= (1 << (Bits[LevelType] - Bits[LevelType - 1])) - 1;
1267 }
1268 }
1269}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
#define NULL
Definition: Base.h:312
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1279
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
BOOLEAN EFIAPI SetInterruptState(IN BOOLEAN InterruptState)
Definition: Cpu.c:48
BOOLEAN EFIAPI SaveAndDisableInterrupts(VOID)
Definition: Cpu.c:21
UINT32 EFIAPI GetPowerOfTwo32(IN UINT32 Operand)
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
UINT32 EFIAPI BitFieldRead32(IN UINT32 Operand, IN UINTN StartBit, IN UINTN EndBit)
Definition: BitField.c:527
VOID EFIAPI SendInitSipiSipiAllExcludingSelf(IN UINT32 StartupRoutine)
Definition: BaseXApicLib.c:551
VOID EFIAPI SendFixedIpiAllExcludingSelf(IN UINT8 Vector)
Definition: BaseXApicLib.c:405
VOID EFIAPI InitializeLocalApicSoftwareEnable(IN BOOLEAN Enable)
Definition: BaseXApicLib.c:584
UINT32 EFIAPI ReadLocalApicReg(IN UINTN MmioOffset)
Definition: BaseXApicLib.c:135
VOID EFIAPI SendSmiIpi(IN UINT32 ApicId)
Definition: BaseXApicLib.c:428
UINT32 EFIAPI GetApicVersion(VOID)
Definition: BaseXApicLib.c:365
BOOLEAN EFIAPI GetApicTimerInterruptState(VOID)
Definition: BaseXApicLib.c:854
VOID EFIAPI SetLocalApicBaseAddress(IN UINTN BaseAddress)
Definition: BaseXApicLib.c:97
UINT32 EFIAPI GetApicId(VOID)
Definition: BaseXApicLib.c:338
VOID EFIAPI DisableLvtInterrupts(VOID)
Definition: BaseXApicLib.c:660
VOID EFIAPI GetApicTimerState(OUT UINTN *DivideValue OPTIONAL, OUT BOOLEAN *PeriodicMode OPTIONAL, OUT UINT8 *Vector OPTIONAL)
Definition: BaseXApicLib.c:774
VOID EFIAPI SendInitIpi(IN UINT32 ApicId)
Definition: BaseXApicLib.c:469
UINT32 EFIAPI GetInitialApicId(VOID)
Definition: BaseXApicLib.c:299
VOID EFIAPI SendInitIpiAllExcludingSelf(VOID)
Definition: BaseXApicLib.c:488
BOOLEAN LocalApicBaseAddressMsrSupported(VOID)
Definition: BaseXApicLib.c:39
VOID EFIAPI SendSmiIpiAllExcludingSelf(VOID)
Definition: BaseXApicLib.c:447
UINTN EFIAPI GetApicMode(VOID)
Definition: BaseXApicLib.c:243
VOID EFIAPI ProgramVirtualWireMode(VOID)
Definition: BaseXApicLib.c:617
VOID EFIAPI EnableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:819
UINT32 EFIAPI GetApicMsiAddress(VOID)
Definition: BaseXApicLib.c:884
VOID SendIpi(IN UINT32 IcrLow, IN UINT32 ApicId)
Definition: BaseXApicLib.c:181
VOID EFIAPI SendFixedIpi(IN UINT32 ApicId, IN UINT8 Vector)
Definition: BaseXApicLib.c:382
VOID EFIAPI WriteLocalApicReg(IN UINTN MmioOffset, IN UINT32 Value)
Definition: BaseXApicLib.c:161
VOID EFIAPI SetApicMode(IN UINTN ApicMode)
Definition: BaseXApicLib.c:280
UINT32 EFIAPI GetApicTimerInitCount(VOID)
Definition: BaseXApicLib.c:682
UINTN EFIAPI GetLocalApicBaseAddress(VOID)
Definition: BaseXApicLib.c:67
UINT64 EFIAPI GetApicMsiValue(IN UINT8 Vector, IN UINTN DeliveryMode, IN BOOLEAN LevelTriggered, IN BOOLEAN AssertionLevel)
Definition: BaseXApicLib.c:930
VOID EFIAPI GetProcessorLocation2ByApicId(IN UINT32 InitialApicId, OUT UINT32 *Package OPTIONAL, OUT UINT32 *Die OPTIONAL, OUT UINT32 *Tile OPTIONAL, OUT UINT32 *Module OPTIONAL, OUT UINT32 *Core OPTIONAL, OUT UINT32 *Thread OPTIONAL)
VOID EFIAPI GetProcessorLocationByApicId(IN UINT32 InitialApicId, OUT UINT32 *Package OPTIONAL, OUT UINT32 *Core OPTIONAL, OUT UINT32 *Thread OPTIONAL)
Definition: BaseXApicLib.c:969
VOID EFIAPI InitializeApicTimer(IN UINTN DivideValue, IN UINT32 InitCount, IN BOOLEAN PeriodicMode, IN UINT8 Vector)
Definition: BaseXApicLib.c:716
VOID EFIAPI SendApicEoi(VOID)
Definition: BaseXApicLib.c:869
UINT32 EFIAPI GetApicTimerCurrentCount(VOID)
Definition: BaseXApicLib.c:696
VOID EFIAPI SendInitSipiSipi(IN UINT32 ApicId, IN UINT32 StartupRoutine)
Definition: BaseXApicLib.c:515
VOID EFIAPI DisableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:835
UINT32 EFIAPI AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuIdEx.c:43
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:532
#define ASSERT(Expression)
Definition: DebugLib.h:391
#define DEBUG_CODE_END()
Definition: DebugLib.h:543
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
UINT64 EFIAPI AsmWriteMsr64(IN UINT32 Index, IN UINT64 Value)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define LOCAL_APIC_MODE_XAPIC
xAPIC mode.
Definition: LocalApicLib.h:15
#define CPUID_AMD_PROCESSOR_TOPOLOGY
Definition: Cpuid.h:519
#define MSR_IA32_APIC_BASE
#define CPUID_EXTENDED_FUNCTION
Definition: Cpuid.h:3740
#define CPUID_SIGNATURE
Definition: Cpuid.h:45
#define CPUID_VIR_PHY_ADDRESS_SIZE
Definition: Cpuid.h:4047
#define CPUID_CACHE_PARAMS
Definition: Cpuid.h:802
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
#define CPUID_EXTENDED_TOPOLOGY
Definition: Cpuid.h:1810
#define CPUID_V2_EXTENDED_TOPOLOGY
Definition: Cpuid.h:3680
#define CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_MODULE
Definition: Cpuid.h:3687
#define CPUID_EXTENDED_CPU_SIG
Definition: Cpuid.h:3763
#define CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID
Definition: Cpuid.h:1897
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
BOOLEAN EFIAPI StandardSignatureIsAuthenticAMD(VOID)
struct CPUID_AMD_EXTENDED_CPU_SIG_ECX::@513 Bits
struct CPUID_AMD_PROCESSOR_TOPOLOGY_EBX::@519 Bits
struct CPUID_AMD_VIR_PHY_ADDRESS_SIZE_ECX::@517 Bits
UINT32 MaximumAddressableIdsForLogicalProcessors
Definition: Cpuid.h:843
struct CPUID_CACHE_PARAMS_EAX::@609 Bits
struct CPUID_EXTENDED_TOPOLOGY_EAX::@625 Bits
struct CPUID_EXTENDED_TOPOLOGY_ECX::@627 Bits
UINT32 MaximumAddressableIdsForLogicalProcessors
Definition: Cpuid.h:147
struct CPUID_VERSION_INFO_EBX::@605 Bits
struct CPUID_VERSION_INFO_EDX::@607 Bits
UINT32 DivideValue1
Low 2 bits of the divide value.
Definition: LocalApic.h:109
UINT32 DivideValue2
Highest 1 bit of the divide value.
Definition: LocalApic.h:111
UINT32 Vector
The vector number of the interrupt being sent.
Definition: LocalApic.h:64
UINT32 DeliveryMode
Specifies the type of IPI to be sent.
Definition: LocalApic.h:65
UINT32 Level
0 for the INIT level de-assert delivery mode. Otherwise 1.
Definition: LocalApic.h:69
UINT32 DestinationShorthand
A shorthand notation to specify the destination of the interrupt.
Definition: LocalApic.h:72
UINT32 DeliveryStatus
Indicates the IPI delivery status. This field is reserved in x2APIC mode.
Definition: LocalApic.h:67
UINT32 TriggerMode
0:edge, 1:level.
Definition: LocalApic.h:144
UINT32 InputPinPolarity
Interrupt Input Pin Polarity.
Definition: LocalApic.h:142
UINT32 DeliveryMode
Specifies the type of interrupt to be sent.
Definition: LocalApic.h:139
UINT32 Mask
0: Not masked, 1: Masked.
Definition: LocalApic.h:145
UINT32 Vector
The vector number of the interrupt being sent.
Definition: LocalApic.h:122
UINT32 TimerMode
0: One-shot, 1: Periodic.
Definition: LocalApic.h:127
UINT32 Mask
0: Not masked, 1: Masked.
Definition: LocalApic.h:126
UINT32 BaseAddress
Must be 0FEEH.
Definition: LocalApic.h:161
UINT32 DestinationId
Specifies the Destination ID.
Definition: LocalApic.h:160
UINT32 DeliveryMode
Specifies the type of interrupt to be sent.
Definition: LocalApic.h:172
UINT32 Level
0:Deassert, 1:Assert. Ignored for Edge triggered interrupts.
Definition: LocalApic.h:174
UINT32 TriggerMode
0:Edge, 1:Level.
Definition: LocalApic.h:175
UINT32 Vector
Interrupt vector in range 010h..0FEH.
Definition: LocalApic.h:171
UINT32 SpuriousVector
Spurious Vector.
Definition: LocalApic.h:94
UINT32 SoftwareEnable
APIC Software Enable/Disable.
Definition: LocalApic.h:95
struct MSR_IA32_APIC_BASE_REGISTER::@539 Bits