4 This local APIC library instance supports x2APIC capable processors
5 which have xAPIC and x2APIC modes.
7 Copyright (c) 2010 - 2012, 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>
27 // Library internal functions
31 Retrieve the base address of local APIC.
33 @return The base address of local APIC.
38 GetLocalApicBaseAddress (
42 MSR_IA32_APIC_BASE ApicBaseMsr
;
44 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
46 return (UINTN
)(LShiftU64 ((UINT64
) ApicBaseMsr
.Bits
.ApicBaseHigh
, 32)) +
47 (((UINTN
)ApicBaseMsr
.Bits
.ApicBaseLow
) << 12);
51 Set the base address of local APIC.
53 If BaseAddress is not aligned on a 4KB boundary, then ASSERT().
55 @param[in] BaseAddress Local APIC base address to be set.
60 SetLocalApicBaseAddress (
64 MSR_IA32_APIC_BASE ApicBaseMsr
;
66 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
68 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
70 ApicBaseMsr
.Bits
.ApicBaseLow
= (UINT32
) (BaseAddress
>> 12);
71 ApicBaseMsr
.Bits
.ApicBaseHigh
= (UINT32
) (RShiftU64((UINT64
) BaseAddress
, 32));
73 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
77 Read from a local APIC register.
79 This function reads from a local APIC register either in xAPIC or x2APIC mode.
80 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
81 accessed using multiple 32-bit loads or stores, so this function only performs
84 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
85 It must be 16-byte aligned.
87 @return 32-bit Value read from the register.
97 ASSERT ((MmioOffset
& 0xf) == 0);
99 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
100 return MmioRead32 (GetLocalApicBaseAddress() + MmioOffset
);
103 // DFR is not supported in x2APIC mode.
105 ASSERT (MmioOffset
!= XAPIC_ICR_DFR_OFFSET
);
107 // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It
108 // is not supported in this function for simplicity.
110 ASSERT (MmioOffset
!= XAPIC_ICR_HIGH_OFFSET
);
112 MsrIndex
= (UINT32
)(MmioOffset
>> 4) + X2APIC_MSR_BASE_ADDRESS
;
113 return AsmReadMsr32 (MsrIndex
);
118 Write to a local APIC register.
120 This function writes to a local APIC register either in xAPIC or x2APIC mode.
121 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
122 accessed using multiple 32-bit loads or stores, so this function only performs
125 if the register index is invalid or unsupported in current APIC mode, then ASSERT.
127 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
128 It must be 16-byte aligned.
129 @param Value Value to be written to the register.
140 ASSERT ((MmioOffset
& 0xf) == 0);
142 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
143 MmioWrite32 (GetLocalApicBaseAddress() + MmioOffset
, Value
);
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
);
154 ASSERT (MmioOffset
!= XAPIC_ICR_LOW_OFFSET
);
156 MsrIndex
= (UINT32
)(MmioOffset
>> 4) + X2APIC_MSR_BASE_ADDRESS
;
158 // The serializing semantics of WRMSR are relaxed when writing to the APIC registers.
159 // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
162 AsmWriteMsr32 (MsrIndex
, Value
);
167 Send an IPI by writing to ICR.
169 This function returns after the IPI has been accepted by the target processor.
171 @param IcrLow 32-bit value to be written to the low half of ICR.
172 @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
181 LOCAL_APIC_ICR_LOW IcrLowReg
;
182 UINTN LocalApciBaseAddress
;
184 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
185 ASSERT (ApicId
<= 0xff);
188 // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
190 LocalApciBaseAddress
= GetLocalApicBaseAddress();
191 MmioWrite32 (LocalApciBaseAddress
+ XAPIC_ICR_HIGH_OFFSET
, ApicId
<< 24);
192 MmioWrite32 (LocalApciBaseAddress
+ XAPIC_ICR_LOW_OFFSET
, IcrLow
);
194 IcrLowReg
.Uint32
= MmioRead32 (LocalApciBaseAddress
+ XAPIC_ICR_LOW_OFFSET
);
195 } while (IcrLowReg
.Bits
.DeliveryStatus
!= 0);
198 // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an
199 // interrupt in x2APIC mode.
201 MsrValue
= LShiftU64 ((UINT64
) ApicId
, 32) | IcrLow
;
202 AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS
, MsrValue
);
207 // Library API implementation functions
211 Get the current local APIC mode.
213 If local APIC is disabled, then ASSERT.
215 @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
216 @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
224 MSR_IA32_APIC_BASE ApicBaseMsr
;
226 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
228 // Local APIC should have been enabled
230 ASSERT (ApicBaseMsr
.Bits
.En
!= 0);
231 if (ApicBaseMsr
.Bits
.Extd
!= 0) {
232 return LOCAL_APIC_MODE_X2APIC
;
234 return LOCAL_APIC_MODE_XAPIC
;
239 Set the current local APIC mode.
241 If the specified local APIC mode is not valid, then ASSERT.
242 If the specified local APIC mode can't be set as current, then ASSERT.
244 @param ApicMode APIC mode to be set.
253 MSR_IA32_APIC_BASE ApicBaseMsr
;
255 CurrentMode
= GetApicMode ();
256 if (CurrentMode
== LOCAL_APIC_MODE_XAPIC
) {
258 case LOCAL_APIC_MODE_XAPIC
:
260 case LOCAL_APIC_MODE_X2APIC
:
261 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
262 ApicBaseMsr
.Bits
.Extd
= 1;
263 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
270 case LOCAL_APIC_MODE_XAPIC
:
272 // Transition from x2APIC mode to xAPIC mode is a two-step process:
273 // x2APIC -> Local APIC disabled -> xAPIC
275 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
276 ApicBaseMsr
.Bits
.Extd
= 0;
277 ApicBaseMsr
.Bits
.En
= 0;
278 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
279 ApicBaseMsr
.Bits
.En
= 1;
280 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
282 case LOCAL_APIC_MODE_X2APIC
:
291 Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
293 In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.
294 In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
295 the 32-bit local APIC ID is returned as initial APIC ID.
297 @return 32-bit initial local APIC ID of the executing processor.
307 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
308 AsmCpuid (CPUID_VERSION_INFO
, NULL
, &RegEbx
, NULL
, NULL
);
316 Get the local APIC ID of the executing processor.
318 @return 32-bit local APIC ID of the executing processor.
328 ApicId
= ReadLocalApicReg (XAPIC_ID_OFFSET
);
329 if (GetApicMode () == LOCAL_APIC_MODE_XAPIC
) {
336 Get the value of the local APIC version register.
338 @return the value of the local APIC version register.
346 return ReadLocalApicReg (XAPIC_VERSION_OFFSET
);
350 Send a Fixed IPI to a specified target processor.
352 This function returns after the IPI has been accepted by the target processor.
354 @param ApicId The local APIC ID of the target processor.
355 @param Vector The vector number of the interrupt being sent.
364 LOCAL_APIC_ICR_LOW IcrLow
;
367 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
368 IcrLow
.Bits
.Level
= 1;
369 IcrLow
.Bits
.Vector
= Vector
;
370 SendIpi (IcrLow
.Uint32
, ApicId
);
374 Send a Fixed IPI to all processors excluding self.
376 This function returns after the IPI has been accepted by the target processors.
378 @param Vector The vector number of the interrupt being sent.
382 SendFixedIpiAllExcludingSelf (
386 LOCAL_APIC_ICR_LOW IcrLow
;
389 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
390 IcrLow
.Bits
.Level
= 1;
391 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
392 IcrLow
.Bits
.Vector
= Vector
;
393 SendIpi (IcrLow
.Uint32
, 0);
397 Send a SMI IPI to a specified target processor.
399 This function returns after the IPI has been accepted by the target processor.
401 @param ApicId Specify the local APIC ID of the target processor.
409 LOCAL_APIC_ICR_LOW IcrLow
;
412 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
413 IcrLow
.Bits
.Level
= 1;
414 SendIpi (IcrLow
.Uint32
, ApicId
);
418 Send a SMI IPI to all processors excluding self.
420 This function returns after the IPI has been accepted by the target processors.
424 SendSmiIpiAllExcludingSelf (
428 LOCAL_APIC_ICR_LOW IcrLow
;
431 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
432 IcrLow
.Bits
.Level
= 1;
433 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
434 SendIpi (IcrLow
.Uint32
, 0);
438 Send an INIT IPI to a specified target processor.
440 This function returns after the IPI has been accepted by the target processor.
442 @param ApicId Specify the local APIC ID of the target processor.
450 LOCAL_APIC_ICR_LOW IcrLow
;
453 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
454 IcrLow
.Bits
.Level
= 1;
455 SendIpi (IcrLow
.Uint32
, ApicId
);
459 Send an INIT IPI to all processors excluding self.
461 This function returns after the IPI has been accepted by the target processors.
465 SendInitIpiAllExcludingSelf (
469 LOCAL_APIC_ICR_LOW IcrLow
;
472 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
473 IcrLow
.Bits
.Level
= 1;
474 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
475 SendIpi (IcrLow
.Uint32
, 0);
479 Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
481 This function returns after the IPI has been accepted by the target processor.
483 if StartupRoutine >= 1M, then ASSERT.
484 if StartupRoutine is not multiple of 4K, then ASSERT.
486 @param ApicId Specify the local APIC ID of the target processor.
487 @param StartupRoutine Points to a start-up routine which is below 1M physical
488 address and 4K aligned.
494 IN UINT32 StartupRoutine
497 LOCAL_APIC_ICR_LOW IcrLow
;
499 ASSERT (StartupRoutine
< 0x100000);
500 ASSERT ((StartupRoutine
& 0xfff) == 0);
502 SendInitIpi (ApicId
);
503 MicroSecondDelay (10);
505 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
506 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
507 IcrLow
.Bits
.Level
= 1;
508 SendIpi (IcrLow
.Uint32
, ApicId
);
509 MicroSecondDelay (200);
510 SendIpi (IcrLow
.Uint32
, ApicId
);
514 Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
516 This function returns after the IPI has been accepted by the target processors.
518 if StartupRoutine >= 1M, then ASSERT.
519 if StartupRoutine is not multiple of 4K, then ASSERT.
521 @param StartupRoutine Points to a start-up routine which is below 1M physical
522 address and 4K aligned.
526 SendInitSipiSipiAllExcludingSelf (
527 IN UINT32 StartupRoutine
530 LOCAL_APIC_ICR_LOW IcrLow
;
532 ASSERT (StartupRoutine
< 0x100000);
533 ASSERT ((StartupRoutine
& 0xfff) == 0);
535 SendInitIpiAllExcludingSelf ();
536 MicroSecondDelay (10);
538 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
539 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
540 IcrLow
.Bits
.Level
= 1;
541 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
542 SendIpi (IcrLow
.Uint32
, 0);
543 MicroSecondDelay (200);
544 SendIpi (IcrLow
.Uint32
, 0);
548 Programming Virtual Wire Mode.
550 This function programs the local APIC for virtual wire mode following
551 the example described in chapter A.3 of the MP 1.4 spec.
553 IOxAPIC is not involved in this type of virtual wire mode.
557 ProgramVirtualWireMode (
562 LOCAL_APIC_LVT_LINT Lint
;
565 // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
567 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
568 Svr
.Bits
.SpuriousVector
= 0xf;
569 Svr
.Bits
.SoftwareEnable
= 1;
570 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
573 // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
575 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
576 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_EXTINT
;
577 Lint
.Bits
.InputPinPolarity
= 0;
578 Lint
.Bits
.TriggerMode
= 0;
580 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, Lint
.Uint32
);
583 // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
585 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
586 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_NMI
;
587 Lint
.Bits
.InputPinPolarity
= 0;
588 Lint
.Bits
.TriggerMode
= 0;
590 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, Lint
.Uint32
);
594 Disable LINT0 & LINT1 interrupts.
596 This function sets the mask flag in the LVT LINT0 & LINT1 registers.
600 DisableLvtInterrupts (
604 LOCAL_APIC_LVT_LINT LvtLint
;
606 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
607 LvtLint
.Bits
.Mask
= 1;
608 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, LvtLint
.Uint32
);
610 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
611 LvtLint
.Bits
.Mask
= 1;
612 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, LvtLint
.Uint32
);
616 Read the initial count value from the init-count register.
618 @return The initial count value read from the init-count register.
622 GetApicTimerInitCount (
626 return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
);
630 Read the current count value from the current-count register.
632 @return The current count value read from the current-count register.
636 GetApicTimerCurrentCount (
640 return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET
);
644 Initialize the local APIC timer.
646 The local APIC timer is initialized and enabled.
648 @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
649 If it is 0, then use the current divide value in the DCR.
650 @param InitCount The initial count value.
651 @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
652 @param Vector The timer interrupt vector number.
656 InitializeApicTimer (
657 IN UINTN DivideValue
,
659 IN BOOLEAN PeriodicMode
,
665 LOCAL_APIC_LVT_TIMER LvtTimer
;
669 // Ensure local APIC is in software-enabled state.
671 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
672 Svr
.Bits
.SoftwareEnable
= 1;
673 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
676 // Program init-count register.
678 WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
, InitCount
);
680 if (DivideValue
!= 0) {
681 ASSERT (DivideValue
<= 128);
682 ASSERT (DivideValue
== GetPowerOfTwo32((UINT32
)DivideValue
));
683 Divisor
= (UINT32
)((HighBitSet32 ((UINT32
)DivideValue
) - 1) & 0x7);
685 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
686 Dcr
.Bits
.DivideValue1
= (Divisor
& 0x3);
687 Dcr
.Bits
.DivideValue2
= (Divisor
>> 2);
688 WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
, Dcr
.Uint32
);
692 // Enable APIC timer interrupt with specified timer mode.
694 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
696 LvtTimer
.Bits
.TimerMode
= 1;
698 LvtTimer
.Bits
.TimerMode
= 0;
700 LvtTimer
.Bits
.Mask
= 0;
701 LvtTimer
.Bits
.Vector
= Vector
;
702 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
706 Get the state of the local APIC timer.
708 @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
709 @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
710 @param Vector Return the timer interrupt vector number.
715 OUT UINTN
*DivideValue OPTIONAL
,
716 OUT BOOLEAN
*PeriodicMode OPTIONAL
,
717 OUT UINT8
*Vector OPTIONAL
722 LOCAL_APIC_LVT_TIMER LvtTimer
;
724 if (DivideValue
!= NULL
) {
725 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
726 Divisor
= Dcr
.Bits
.DivideValue1
| (Dcr
.Bits
.DivideValue2
<< 2);
727 Divisor
= (Divisor
+ 1) & 0x7;
728 *DivideValue
= ((UINTN
)1) << Divisor
;
731 if (PeriodicMode
!= NULL
|| Vector
!= NULL
) {
732 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
733 if (PeriodicMode
!= NULL
) {
734 if (LvtTimer
.Bits
.TimerMode
== 1) {
735 *PeriodicMode
= TRUE
;
737 *PeriodicMode
= FALSE
;
740 if (Vector
!= NULL
) {
741 *Vector
= (UINT8
) LvtTimer
.Bits
.Vector
;
747 Enable the local APIC timer interrupt.
751 EnableApicTimerInterrupt (
755 LOCAL_APIC_LVT_TIMER LvtTimer
;
757 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
758 LvtTimer
.Bits
.Mask
= 0;
759 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
763 Disable the local APIC timer interrupt.
767 DisableApicTimerInterrupt (
771 LOCAL_APIC_LVT_TIMER LvtTimer
;
773 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
774 LvtTimer
.Bits
.Mask
= 1;
775 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
779 Get the local APIC timer interrupt state.
781 @retval TRUE The local APIC timer interrupt is enabled.
782 @retval FALSE The local APIC timer interrupt is disabled.
786 GetApicTimerInterruptState (
790 LOCAL_APIC_LVT_TIMER LvtTimer
;
792 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
793 return (BOOLEAN
)(LvtTimer
.Bits
.Mask
== 0);
797 Send EOI to the local APIC.
805 WriteLocalApicReg (XAPIC_EOI_OFFSET
, 0);
809 Get the 32-bit address that a device should use to send a Message Signaled
810 Interrupt (MSI) to the Local APIC of the currently executing processor.
812 @return 32-bit address used to send an MSI to the Local APIC.
820 LOCAL_APIC_MSI_ADDRESS MsiAddress
;
823 // Return address for an MSI interrupt to be delivered only to the APIC ID
824 // of the currently executing processor.
826 MsiAddress
.Uint32
= 0;
827 MsiAddress
.Bits
.BaseAddress
= 0xFEE;
828 MsiAddress
.Bits
.DestinationId
= GetApicId ();
829 return MsiAddress
.Uint32
;
833 Get the 64-bit data value that a device should use to send a Message Signaled
834 Interrupt (MSI) to the Local APIC of the currently executing processor.
836 If Vector is not in range 0x10..0xFE, then ASSERT().
837 If DeliveryMode is not supported, then ASSERT().
839 @param Vector The 8-bit interrupt vector associated with the MSI.
840 Must be in the range 0x10..0xFE
841 @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
842 is handled. The only supported values are:
843 0: LOCAL_APIC_DELIVERY_MODE_FIXED
844 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
845 2: LOCAL_APIC_DELIVERY_MODE_SMI
846 4: LOCAL_APIC_DELIVERY_MODE_NMI
847 5: LOCAL_APIC_DELIVERY_MODE_INIT
848 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
850 @param LevelTriggered TRUE specifies a level triggered interrupt.
851 FALSE specifies an edge triggered interrupt.
852 @param AssertionLevel Ignored if LevelTriggered is FALSE.
853 TRUE specifies a level triggered interrupt that active
854 when the interrupt line is asserted.
855 FALSE specifies a level triggered interrupt that active
856 when the interrupt line is deasserted.
858 @return 64-bit data value used to send an MSI to the Local APIC.
864 IN UINTN DeliveryMode
,
865 IN BOOLEAN LevelTriggered
,
866 IN BOOLEAN AssertionLevel
869 LOCAL_APIC_MSI_DATA MsiData
;
871 ASSERT (Vector
>= 0x10 && Vector
<= 0xFE);
872 ASSERT (DeliveryMode
< 8 && DeliveryMode
!= 6 && DeliveryMode
!= 3);
875 MsiData
.Bits
.Vector
= Vector
;
876 MsiData
.Bits
.DeliveryMode
= (UINT32
)DeliveryMode
;
877 if (LevelTriggered
) {
878 MsiData
.Bits
.TriggerMode
= 1;
879 if (AssertionLevel
) {
880 MsiData
.Bits
.Level
= 1;
883 return MsiData
.Uint64
;