4 This local APIC library instance supports x2APIC capable processors
5 which have xAPIC and x2APIC modes.
7 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Register/LocalApic.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/LocalApicLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/TimerLib.h>
25 #include <Library/PcdLib.h>
28 // Library internal functions
32 Determine if the CPU supports the Local APIC Base Address MSR.
34 @retval TRUE The CPU supports the Local APIC Base Address MSR.
35 @retval FALSE The CPU does not support the Local APIC Base Address MSR.
39 LocalApicBaseAddressMsrSupported (
46 AsmCpuid (1, &RegEax
, NULL
, NULL
, NULL
);
47 FamilyId
= BitFieldRead32 (RegEax
, 8, 11);
48 if (FamilyId
== 0x04 || FamilyId
== 0x05) {
50 // CPUs with a FamilyId of 0x04 or 0x05 do not support the
51 // Local APIC Base Address MSR
59 Retrieve the base address of local APIC.
61 @return The base address of local APIC.
66 GetLocalApicBaseAddress (
70 MSR_IA32_APIC_BASE ApicBaseMsr
;
72 if (!LocalApicBaseAddressMsrSupported ()) {
74 // If CPU does not support Local APIC Base Address MSR, then retrieve
75 // Local APIC Base Address from PCD
77 return PcdGet32 (PcdCpuLocalApicBaseAddress
);
80 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
82 return (UINTN
)(LShiftU64 ((UINT64
) ApicBaseMsr
.Bits
.ApicBaseHigh
, 32)) +
83 (((UINTN
)ApicBaseMsr
.Bits
.ApicBaseLow
) << 12);
87 Set the base address of local APIC.
89 If BaseAddress is not aligned on a 4KB boundary, then ASSERT().
91 @param[in] BaseAddress Local APIC base address to be set.
96 SetLocalApicBaseAddress (
100 MSR_IA32_APIC_BASE ApicBaseMsr
;
102 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
104 if (!LocalApicBaseAddressMsrSupported ()) {
106 // Ignore set request of the CPU does not support APIC Base Address MSR
111 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
113 ApicBaseMsr
.Bits
.ApicBaseLow
= (UINT32
) (BaseAddress
>> 12);
114 ApicBaseMsr
.Bits
.ApicBaseHigh
= (UINT32
) (RShiftU64((UINT64
) BaseAddress
, 32));
116 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
120 Read from a local APIC register.
122 This function reads from a local APIC register either in xAPIC or x2APIC mode.
123 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
124 accessed using multiple 32-bit loads or stores, so this function only performs
127 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
128 It must be 16-byte aligned.
130 @return 32-bit Value read from the register.
140 ASSERT ((MmioOffset
& 0xf) == 0);
142 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
143 return MmioRead32 (GetLocalApicBaseAddress() + MmioOffset
);
146 // DFR is not supported in x2APIC mode.
148 ASSERT (MmioOffset
!= XAPIC_ICR_DFR_OFFSET
);
150 // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
151 // is not supported in this function for simplicity.
153 ASSERT (MmioOffset
!= XAPIC_ICR_HIGH_OFFSET
);
155 MsrIndex
= (UINT32
)(MmioOffset
>> 4) + X2APIC_MSR_BASE_ADDRESS
;
156 return AsmReadMsr32 (MsrIndex
);
161 Write to a local APIC register.
163 This function writes to a local APIC register either in xAPIC or x2APIC mode.
164 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
165 accessed using multiple 32-bit loads or stores, so this function only performs
168 if the register index is invalid or unsupported in current APIC mode, then ASSERT.
170 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
171 It must be 16-byte aligned.
172 @param Value Value to be written to the register.
183 ASSERT ((MmioOffset
& 0xf) == 0);
185 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
186 MmioWrite32 (GetLocalApicBaseAddress() + MmioOffset
, Value
);
189 // DFR is not supported in x2APIC mode.
191 ASSERT (MmioOffset
!= XAPIC_ICR_DFR_OFFSET
);
193 // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
194 // is not supported in this function for simplicity.
196 ASSERT (MmioOffset
!= XAPIC_ICR_HIGH_OFFSET
);
197 ASSERT (MmioOffset
!= XAPIC_ICR_LOW_OFFSET
);
199 MsrIndex
= (UINT32
)(MmioOffset
>> 4) + X2APIC_MSR_BASE_ADDRESS
;
201 // The serializing semantics of WRMSR are relaxed when writing to the APIC registers.
202 // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
205 AsmWriteMsr32 (MsrIndex
, Value
);
210 Send an IPI by writing to ICR.
212 This function returns after the IPI has been accepted by the target processor.
214 @param IcrLow 32-bit value to be written to the low half of ICR.
215 @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
224 LOCAL_APIC_ICR_LOW IcrLowReg
;
225 UINTN LocalApciBaseAddress
;
227 BOOLEAN InterruptState
;
230 // Legacy APIC or X2APIC?
232 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
233 ASSERT (ApicId
<= 0xff);
235 InterruptState
= SaveAndDisableInterrupts ();
238 // Get base address of this LAPIC
240 LocalApciBaseAddress
= GetLocalApicBaseAddress();
243 // Save existing contents of ICR high 32 bits
245 IcrHigh
= MmioRead32 (LocalApciBaseAddress
+ XAPIC_ICR_HIGH_OFFSET
);
248 // Wait for DeliveryStatus clear in case a previous IPI
249 // is still being sent
252 IcrLowReg
.Uint32
= MmioRead32 (LocalApciBaseAddress
+ XAPIC_ICR_LOW_OFFSET
);
253 } while (IcrLowReg
.Bits
.DeliveryStatus
!= 0);
256 // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
258 MmioWrite32 (LocalApciBaseAddress
+ XAPIC_ICR_HIGH_OFFSET
, ApicId
<< 24);
259 MmioWrite32 (LocalApciBaseAddress
+ XAPIC_ICR_LOW_OFFSET
, IcrLow
);
262 // Wait for DeliveryStatus clear again
265 IcrLowReg
.Uint32
= MmioRead32 (LocalApciBaseAddress
+ XAPIC_ICR_LOW_OFFSET
);
266 } while (IcrLowReg
.Bits
.DeliveryStatus
!= 0);
269 // And restore old contents of ICR high
271 MmioWrite32 (LocalApciBaseAddress
+ XAPIC_ICR_HIGH_OFFSET
, IcrHigh
);
273 SetInterruptState (InterruptState
);
277 // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an
278 // interrupt in x2APIC mode.
280 MsrValue
= LShiftU64 ((UINT64
) ApicId
, 32) | IcrLow
;
281 AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS
, MsrValue
);
286 // Library API implementation functions
290 Get the current local APIC mode.
292 If local APIC is disabled, then ASSERT.
294 @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
295 @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
303 MSR_IA32_APIC_BASE ApicBaseMsr
;
305 if (!LocalApicBaseAddressMsrSupported ()) {
307 // If CPU does not support APIC Base Address MSR, then return XAPIC mode
309 return LOCAL_APIC_MODE_XAPIC
;
312 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
314 // Local APIC should have been enabled
316 ASSERT (ApicBaseMsr
.Bits
.En
!= 0);
317 if (ApicBaseMsr
.Bits
.Extd
!= 0) {
318 return LOCAL_APIC_MODE_X2APIC
;
320 return LOCAL_APIC_MODE_XAPIC
;
325 Set the current local APIC mode.
327 If the specified local APIC mode is not valid, then ASSERT.
328 If the specified local APIC mode can't be set as current, then ASSERT.
330 @param ApicMode APIC mode to be set.
332 @note This API must not be called from an interrupt handler or SMI handler.
333 It may result in unpredictable behavior.
342 MSR_IA32_APIC_BASE ApicBaseMsr
;
344 if (!LocalApicBaseAddressMsrSupported ()) {
346 // Ignore set request if the CPU does not support APIC Base Address MSR
351 CurrentMode
= GetApicMode ();
352 if (CurrentMode
== LOCAL_APIC_MODE_XAPIC
) {
354 case LOCAL_APIC_MODE_XAPIC
:
356 case LOCAL_APIC_MODE_X2APIC
:
357 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
358 ApicBaseMsr
.Bits
.Extd
= 1;
359 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
366 case LOCAL_APIC_MODE_XAPIC
:
368 // Transition from x2APIC mode to xAPIC mode is a two-step process:
369 // x2APIC -> Local APIC disabled -> xAPIC
371 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
372 ApicBaseMsr
.Bits
.Extd
= 0;
373 ApicBaseMsr
.Bits
.En
= 0;
374 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
375 ApicBaseMsr
.Bits
.En
= 1;
376 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
378 case LOCAL_APIC_MODE_X2APIC
:
387 Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
389 In xAPIC mode, the initial local APIC ID may be different from current APIC ID.
390 In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
391 the 32-bit local APIC ID is returned as initial APIC ID.
393 @return 32-bit initial local APIC ID of the executing processor.
402 UINT32 MaxCpuIdIndex
;
405 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
407 // Get the max index of basic CPUID
409 AsmCpuid (CPUID_SIGNATURE
, &MaxCpuIdIndex
, NULL
, NULL
, NULL
);
411 // If CPUID Leaf B is supported,
412 // Then the initial 32-bit APIC ID = CPUID.0BH:EDX
413 // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24]
415 if (MaxCpuIdIndex
>= CPUID_EXTENDED_TOPOLOGY
) {
416 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY
, 0, NULL
, NULL
, NULL
, &ApicId
);
419 AsmCpuid (CPUID_VERSION_INFO
, NULL
, &RegEbx
, NULL
, NULL
);
427 Get the local APIC ID of the executing processor.
429 @return 32-bit local APIC ID of the executing processor.
440 ApicId
= ReadLocalApicReg (XAPIC_ID_OFFSET
);
441 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
442 ApicId
= ((InitApicId
= GetInitialApicId ()) < 0x100) ? (ApicId
>> 24) : InitApicId
;
449 Get the value of the local APIC version register.
451 @return the value of the local APIC version register.
459 return ReadLocalApicReg (XAPIC_VERSION_OFFSET
);
463 Send a Fixed IPI to a specified target processor.
465 This function returns after the IPI has been accepted by the target processor.
467 @param ApicId The local APIC ID of the target processor.
468 @param Vector The vector number of the interrupt being sent.
477 LOCAL_APIC_ICR_LOW IcrLow
;
480 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
481 IcrLow
.Bits
.Level
= 1;
482 IcrLow
.Bits
.Vector
= Vector
;
483 SendIpi (IcrLow
.Uint32
, ApicId
);
487 Send a Fixed IPI to all processors excluding self.
489 This function returns after the IPI has been accepted by the target processors.
491 @param Vector The vector number of the interrupt being sent.
495 SendFixedIpiAllExcludingSelf (
499 LOCAL_APIC_ICR_LOW IcrLow
;
502 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
503 IcrLow
.Bits
.Level
= 1;
504 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
505 IcrLow
.Bits
.Vector
= Vector
;
506 SendIpi (IcrLow
.Uint32
, 0);
510 Send a SMI IPI to a specified target processor.
512 This function returns after the IPI has been accepted by the target processor.
514 @param ApicId Specify the local APIC ID of the target processor.
522 LOCAL_APIC_ICR_LOW IcrLow
;
525 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
526 IcrLow
.Bits
.Level
= 1;
527 SendIpi (IcrLow
.Uint32
, ApicId
);
531 Send a SMI IPI to all processors excluding self.
533 This function returns after the IPI has been accepted by the target processors.
537 SendSmiIpiAllExcludingSelf (
541 LOCAL_APIC_ICR_LOW IcrLow
;
544 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
545 IcrLow
.Bits
.Level
= 1;
546 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
547 SendIpi (IcrLow
.Uint32
, 0);
551 Send an INIT IPI to a specified target processor.
553 This function returns after the IPI has been accepted by the target processor.
555 @param ApicId Specify the local APIC ID of the target processor.
563 LOCAL_APIC_ICR_LOW IcrLow
;
566 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
567 IcrLow
.Bits
.Level
= 1;
568 SendIpi (IcrLow
.Uint32
, ApicId
);
572 Send an INIT IPI to all processors excluding self.
574 This function returns after the IPI has been accepted by the target processors.
578 SendInitIpiAllExcludingSelf (
582 LOCAL_APIC_ICR_LOW IcrLow
;
585 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
586 IcrLow
.Bits
.Level
= 1;
587 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
588 SendIpi (IcrLow
.Uint32
, 0);
592 Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
594 This function returns after the IPI has been accepted by the target processor.
596 if StartupRoutine >= 1M, then ASSERT.
597 if StartupRoutine is not multiple of 4K, then ASSERT.
599 @param ApicId Specify the local APIC ID of the target processor.
600 @param StartupRoutine Points to a start-up routine which is below 1M physical
601 address and 4K aligned.
607 IN UINT32 StartupRoutine
610 LOCAL_APIC_ICR_LOW IcrLow
;
612 ASSERT (StartupRoutine
< 0x100000);
613 ASSERT ((StartupRoutine
& 0xfff) == 0);
615 SendInitIpi (ApicId
);
616 MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds
));
618 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
619 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
620 IcrLow
.Bits
.Level
= 1;
621 SendIpi (IcrLow
.Uint32
, ApicId
);
622 MicroSecondDelay (200);
623 SendIpi (IcrLow
.Uint32
, ApicId
);
627 Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
629 This function returns after the IPI has been accepted by the target processors.
631 if StartupRoutine >= 1M, then ASSERT.
632 if StartupRoutine is not multiple of 4K, then ASSERT.
634 @param StartupRoutine Points to a start-up routine which is below 1M physical
635 address and 4K aligned.
639 SendInitSipiSipiAllExcludingSelf (
640 IN UINT32 StartupRoutine
643 LOCAL_APIC_ICR_LOW IcrLow
;
645 ASSERT (StartupRoutine
< 0x100000);
646 ASSERT ((StartupRoutine
& 0xfff) == 0);
648 SendInitIpiAllExcludingSelf ();
649 MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds
));
651 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
652 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
653 IcrLow
.Bits
.Level
= 1;
654 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
655 SendIpi (IcrLow
.Uint32
, 0);
656 MicroSecondDelay (200);
657 SendIpi (IcrLow
.Uint32
, 0);
661 Programming Virtual Wire Mode.
663 This function programs the local APIC for virtual wire mode following
664 the example described in chapter A.3 of the MP 1.4 spec.
666 IOxAPIC is not involved in this type of virtual wire mode.
670 ProgramVirtualWireMode (
675 LOCAL_APIC_LVT_LINT Lint
;
678 // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
680 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
681 Svr
.Bits
.SpuriousVector
= 0xf;
682 Svr
.Bits
.SoftwareEnable
= 1;
683 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
686 // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
688 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
689 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_EXTINT
;
690 Lint
.Bits
.InputPinPolarity
= 0;
691 Lint
.Bits
.TriggerMode
= 0;
693 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, Lint
.Uint32
);
696 // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
698 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
699 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_NMI
;
700 Lint
.Bits
.InputPinPolarity
= 0;
701 Lint
.Bits
.TriggerMode
= 0;
703 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, Lint
.Uint32
);
707 Disable LINT0 & LINT1 interrupts.
709 This function sets the mask flag in the LVT LINT0 & LINT1 registers.
713 DisableLvtInterrupts (
717 LOCAL_APIC_LVT_LINT LvtLint
;
719 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
720 LvtLint
.Bits
.Mask
= 1;
721 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, LvtLint
.Uint32
);
723 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
724 LvtLint
.Bits
.Mask
= 1;
725 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, LvtLint
.Uint32
);
729 Read the initial count value from the init-count register.
731 @return The initial count value read from the init-count register.
735 GetApicTimerInitCount (
739 return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
);
743 Read the current count value from the current-count register.
745 @return The current count value read from the current-count register.
749 GetApicTimerCurrentCount (
753 return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET
);
757 Initialize the local APIC timer.
759 The local APIC timer is initialized and enabled.
761 @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
762 If it is 0, then use the current divide value in the DCR.
763 @param InitCount The initial count value.
764 @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
765 @param Vector The timer interrupt vector number.
769 InitializeApicTimer (
770 IN UINTN DivideValue
,
772 IN BOOLEAN PeriodicMode
,
778 LOCAL_APIC_LVT_TIMER LvtTimer
;
782 // Ensure local APIC is in software-enabled state.
784 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
785 Svr
.Bits
.SoftwareEnable
= 1;
786 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
789 // Program init-count register.
791 WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
, InitCount
);
793 if (DivideValue
!= 0) {
794 ASSERT (DivideValue
<= 128);
795 ASSERT (DivideValue
== GetPowerOfTwo32((UINT32
)DivideValue
));
796 Divisor
= (UINT32
)((HighBitSet32 ((UINT32
)DivideValue
) - 1) & 0x7);
798 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
799 Dcr
.Bits
.DivideValue1
= (Divisor
& 0x3);
800 Dcr
.Bits
.DivideValue2
= (Divisor
>> 2);
801 WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
, Dcr
.Uint32
);
805 // Enable APIC timer interrupt with specified timer mode.
807 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
809 LvtTimer
.Bits
.TimerMode
= 1;
811 LvtTimer
.Bits
.TimerMode
= 0;
813 LvtTimer
.Bits
.Mask
= 0;
814 LvtTimer
.Bits
.Vector
= Vector
;
815 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
819 Get the state of the local APIC timer.
821 @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
822 @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
823 @param Vector Return the timer interrupt vector number.
828 OUT UINTN
*DivideValue OPTIONAL
,
829 OUT BOOLEAN
*PeriodicMode OPTIONAL
,
830 OUT UINT8
*Vector OPTIONAL
835 LOCAL_APIC_LVT_TIMER LvtTimer
;
837 if (DivideValue
!= NULL
) {
838 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
839 Divisor
= Dcr
.Bits
.DivideValue1
| (Dcr
.Bits
.DivideValue2
<< 2);
840 Divisor
= (Divisor
+ 1) & 0x7;
841 *DivideValue
= ((UINTN
)1) << Divisor
;
844 if (PeriodicMode
!= NULL
|| Vector
!= NULL
) {
845 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
846 if (PeriodicMode
!= NULL
) {
847 if (LvtTimer
.Bits
.TimerMode
== 1) {
848 *PeriodicMode
= TRUE
;
850 *PeriodicMode
= FALSE
;
853 if (Vector
!= NULL
) {
854 *Vector
= (UINT8
) LvtTimer
.Bits
.Vector
;
860 Enable the local APIC timer interrupt.
864 EnableApicTimerInterrupt (
868 LOCAL_APIC_LVT_TIMER LvtTimer
;
870 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
871 LvtTimer
.Bits
.Mask
= 0;
872 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
876 Disable the local APIC timer interrupt.
880 DisableApicTimerInterrupt (
884 LOCAL_APIC_LVT_TIMER LvtTimer
;
886 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
887 LvtTimer
.Bits
.Mask
= 1;
888 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
892 Get the local APIC timer interrupt state.
894 @retval TRUE The local APIC timer interrupt is enabled.
895 @retval FALSE The local APIC timer interrupt is disabled.
899 GetApicTimerInterruptState (
903 LOCAL_APIC_LVT_TIMER LvtTimer
;
905 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
906 return (BOOLEAN
)(LvtTimer
.Bits
.Mask
== 0);
910 Send EOI to the local APIC.
918 WriteLocalApicReg (XAPIC_EOI_OFFSET
, 0);
922 Get the 32-bit address that a device should use to send a Message Signaled
923 Interrupt (MSI) to the Local APIC of the currently executing processor.
925 @return 32-bit address used to send an MSI to the Local APIC.
933 LOCAL_APIC_MSI_ADDRESS MsiAddress
;
936 // Return address for an MSI interrupt to be delivered only to the APIC ID
937 // of the currently executing processor.
939 MsiAddress
.Uint32
= 0;
940 MsiAddress
.Bits
.BaseAddress
= 0xFEE;
941 MsiAddress
.Bits
.DestinationId
= GetApicId ();
942 return MsiAddress
.Uint32
;
946 Get the 64-bit data value that a device should use to send a Message Signaled
947 Interrupt (MSI) to the Local APIC of the currently executing processor.
949 If Vector is not in range 0x10..0xFE, then ASSERT().
950 If DeliveryMode is not supported, then ASSERT().
952 @param Vector The 8-bit interrupt vector associated with the MSI.
953 Must be in the range 0x10..0xFE
954 @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
955 is handled. The only supported values are:
956 0: LOCAL_APIC_DELIVERY_MODE_FIXED
957 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
958 2: LOCAL_APIC_DELIVERY_MODE_SMI
959 4: LOCAL_APIC_DELIVERY_MODE_NMI
960 5: LOCAL_APIC_DELIVERY_MODE_INIT
961 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
963 @param LevelTriggered TRUE specifies a level triggered interrupt.
964 FALSE specifies an edge triggered interrupt.
965 @param AssertionLevel Ignored if LevelTriggered is FALSE.
966 TRUE specifies a level triggered interrupt that active
967 when the interrupt line is asserted.
968 FALSE specifies a level triggered interrupt that active
969 when the interrupt line is deasserted.
971 @return 64-bit data value used to send an MSI to the Local APIC.
977 IN UINTN DeliveryMode
,
978 IN BOOLEAN LevelTriggered
,
979 IN BOOLEAN AssertionLevel
982 LOCAL_APIC_MSI_DATA MsiData
;
984 ASSERT (Vector
>= 0x10 && Vector
<= 0xFE);
985 ASSERT (DeliveryMode
< 8 && DeliveryMode
!= 6 && DeliveryMode
!= 3);
988 MsiData
.Bits
.Vector
= Vector
;
989 MsiData
.Bits
.DeliveryMode
= (UINT32
)DeliveryMode
;
990 if (LevelTriggered
) {
991 MsiData
.Bits
.TriggerMode
= 1;
992 if (AssertionLevel
) {
993 MsiData
.Bits
.Level
= 1;
996 return MsiData
.Uint64
;