4 This local APIC library instance supports xAPIC mode only.
6 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Register/LocalApic.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/LocalApicLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/TimerLib.h>
26 // Library internal functions
30 Retrieve the base address of local APIC.
32 @return The base address of local APIC.
37 GetLocalApicBaseAddress (
41 MSR_IA32_APIC_BASE ApicBaseMsr
;
43 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
45 return (UINTN
)(LShiftU64 ((UINT64
) ApicBaseMsr
.Bits
.ApicBaseHigh
, 32)) +
46 (((UINTN
)ApicBaseMsr
.Bits
.ApicBaseLow
) << 12);
50 Set the base address of local APIC.
52 If BaseAddress is not aligned on a 4KB boundary, then ASSERT().
54 @param[in] BaseAddress Local APIC base address to be set.
59 SetLocalApicBaseAddress (
63 MSR_IA32_APIC_BASE ApicBaseMsr
;
65 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
67 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
69 ApicBaseMsr
.Bits
.ApicBaseLow
= (UINT32
) (BaseAddress
>> 12);
70 ApicBaseMsr
.Bits
.ApicBaseHigh
= (UINT32
) (RShiftU64((UINT64
) BaseAddress
, 32));
72 AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS
, ApicBaseMsr
.Uint64
);
76 Read from a local APIC register.
78 This function reads from a local APIC register either in xAPIC or x2APIC mode.
79 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
80 accessed using multiple 32-bit loads or stores, so this function only performs
83 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
84 It must be 16-byte aligned.
86 @return 32-bit Value read from the register.
94 ASSERT ((MmioOffset
& 0xf) == 0);
95 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
97 return MmioRead32 (GetLocalApicBaseAddress() + MmioOffset
);
101 Write to a local APIC register.
103 This function writes to a local APIC register either in xAPIC or x2APIC mode.
104 It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be
105 accessed using multiple 32-bit loads or stores, so this function only performs
108 if the register index is invalid or unsupported in current APIC mode, then ASSERT.
110 @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode.
111 It must be 16-byte aligned.
112 @param Value Value to be written to the register.
121 ASSERT ((MmioOffset
& 0xf) == 0);
122 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
124 MmioWrite32 (GetLocalApicBaseAddress() + MmioOffset
, Value
);
128 Send an IPI by writing to ICR.
130 This function returns after the IPI has been accepted by the target processor.
132 @param IcrLow 32-bit value to be written to the low half of ICR.
133 @param ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.
141 LOCAL_APIC_ICR_LOW IcrLowReg
;
143 BOOLEAN InterruptState
;
145 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
146 ASSERT (ApicId
<= 0xff);
148 InterruptState
= SaveAndDisableInterrupts ();
151 // Save existing contents of ICR high 32 bits
153 IcrHigh
= ReadLocalApicReg (XAPIC_ICR_HIGH_OFFSET
);
156 // Wait for DeliveryStatus clear in case a previous IPI
157 // is still being sent
160 IcrLowReg
.Uint32
= ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET
);
161 } while (IcrLowReg
.Bits
.DeliveryStatus
!= 0);
164 // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.
166 WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET
, ApicId
<< 24);
167 WriteLocalApicReg (XAPIC_ICR_LOW_OFFSET
, IcrLow
);
170 // Wait for DeliveryStatus clear again
173 IcrLowReg
.Uint32
= ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET
);
174 } while (IcrLowReg
.Bits
.DeliveryStatus
!= 0);
177 // And restore old contents of ICR high
179 WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET
, IcrHigh
);
181 SetInterruptState (InterruptState
);
186 // Library API implementation functions
190 Get the current local APIC mode.
192 If local APIC is disabled, then ASSERT.
194 @retval LOCAL_APIC_MODE_XAPIC current APIC mode is xAPIC.
195 @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.
205 MSR_IA32_APIC_BASE ApicBaseMsr
;
207 ApicBaseMsr
.Uint64
= AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS
);
209 // Local APIC should have been enabled
211 ASSERT (ApicBaseMsr
.Bits
.En
!= 0);
212 ASSERT (ApicBaseMsr
.Bits
.Extd
== 0);
215 return LOCAL_APIC_MODE_XAPIC
;
219 Set the current local APIC mode.
221 If the specified local APIC mode is not valid, then ASSERT.
222 If the specified local APIC mode can't be set as current, then ASSERT.
224 @param ApicMode APIC mode to be set.
226 @note This API must not be called from an interrupt handler or SMI handler.
227 It may result in unpredictable behavior.
235 ASSERT (ApicMode
== LOCAL_APIC_MODE_XAPIC
);
236 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
240 Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.
242 In xAPIC mode, the initial local APIC ID may be different from current APIC ID.
243 In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case,
244 the 32-bit local APIC ID is returned as initial APIC ID.
246 @return 32-bit initial local APIC ID of the executing processor.
255 UINT32 MaxCpuIdIndex
;
258 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
261 // Get the max index of basic CPUID
263 AsmCpuid (CPUID_SIGNATURE
, &MaxCpuIdIndex
, NULL
, NULL
, NULL
);
266 // If CPUID Leaf B is supported,
267 // Then the initial 32-bit APIC ID = CPUID.0BH:EDX
268 // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24]
270 if (MaxCpuIdIndex
>= CPUID_EXTENDED_TOPOLOGY
) {
271 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY
, 0, NULL
, NULL
, NULL
, &ApicId
);
275 AsmCpuid (CPUID_VERSION_INFO
, NULL
, &RegEbx
, NULL
, NULL
);
280 Get the local APIC ID of the executing processor.
282 @return 32-bit local APIC ID of the executing processor.
292 ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC
);
294 if ((ApicId
= GetInitialApicId ()) < 0x100) {
296 // If the initial local APIC ID is less 0x100, read APIC ID from
297 // XAPIC_ID_OFFSET, otherwise return the initial local APIC ID.
299 ApicId
= ReadLocalApicReg (XAPIC_ID_OFFSET
);
306 Get the value of the local APIC version register.
308 @return the value of the local APIC version register.
316 return ReadLocalApicReg (XAPIC_VERSION_OFFSET
);
320 Send a Fixed IPI to a specified target processor.
322 This function returns after the IPI has been accepted by the target processor.
324 @param ApicId The local APIC ID of the target processor.
325 @param Vector The vector number of the interrupt being sent.
334 LOCAL_APIC_ICR_LOW IcrLow
;
337 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
338 IcrLow
.Bits
.Level
= 1;
339 IcrLow
.Bits
.Vector
= Vector
;
340 SendIpi (IcrLow
.Uint32
, ApicId
);
344 Send a Fixed IPI to all processors excluding self.
346 This function returns after the IPI has been accepted by the target processors.
348 @param Vector The vector number of the interrupt being sent.
352 SendFixedIpiAllExcludingSelf (
356 LOCAL_APIC_ICR_LOW IcrLow
;
359 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_FIXED
;
360 IcrLow
.Bits
.Level
= 1;
361 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
362 IcrLow
.Bits
.Vector
= Vector
;
363 SendIpi (IcrLow
.Uint32
, 0);
367 Send a SMI IPI to a specified target processor.
369 This function returns after the IPI has been accepted by the target processor.
371 @param ApicId Specify the local APIC ID of the target processor.
379 LOCAL_APIC_ICR_LOW IcrLow
;
382 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
383 IcrLow
.Bits
.Level
= 1;
384 SendIpi (IcrLow
.Uint32
, ApicId
);
388 Send a SMI IPI to all processors excluding self.
390 This function returns after the IPI has been accepted by the target processors.
394 SendSmiIpiAllExcludingSelf (
398 LOCAL_APIC_ICR_LOW IcrLow
;
401 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_SMI
;
402 IcrLow
.Bits
.Level
= 1;
403 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
404 SendIpi (IcrLow
.Uint32
, 0);
408 Send an INIT IPI to a specified target processor.
410 This function returns after the IPI has been accepted by the target processor.
412 @param ApicId Specify the local APIC ID of the target processor.
420 LOCAL_APIC_ICR_LOW IcrLow
;
423 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
424 IcrLow
.Bits
.Level
= 1;
425 SendIpi (IcrLow
.Uint32
, ApicId
);
429 Send an INIT IPI to all processors excluding self.
431 This function returns after the IPI has been accepted by the target processors.
435 SendInitIpiAllExcludingSelf (
439 LOCAL_APIC_ICR_LOW IcrLow
;
442 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_INIT
;
443 IcrLow
.Bits
.Level
= 1;
444 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
445 SendIpi (IcrLow
.Uint32
, 0);
449 Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.
451 This function returns after the IPI has been accepted by the target processor.
453 if StartupRoutine >= 1M, then ASSERT.
454 if StartupRoutine is not multiple of 4K, then ASSERT.
456 @param ApicId Specify the local APIC ID of the target processor.
457 @param StartupRoutine Points to a start-up routine which is below 1M physical
458 address and 4K aligned.
464 IN UINT32 StartupRoutine
467 LOCAL_APIC_ICR_LOW IcrLow
;
469 ASSERT (StartupRoutine
< 0x100000);
470 ASSERT ((StartupRoutine
& 0xfff) == 0);
472 SendInitIpi (ApicId
);
473 MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds
));
475 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
476 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
477 IcrLow
.Bits
.Level
= 1;
478 SendIpi (IcrLow
.Uint32
, ApicId
);
479 MicroSecondDelay (200);
480 SendIpi (IcrLow
.Uint32
, ApicId
);
484 Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.
486 This function returns after the IPI has been accepted by the target processors.
488 if StartupRoutine >= 1M, then ASSERT.
489 if StartupRoutine is not multiple of 4K, then ASSERT.
491 @param StartupRoutine Points to a start-up routine which is below 1M physical
492 address and 4K aligned.
496 SendInitSipiSipiAllExcludingSelf (
497 IN UINT32 StartupRoutine
500 LOCAL_APIC_ICR_LOW IcrLow
;
502 ASSERT (StartupRoutine
< 0x100000);
503 ASSERT ((StartupRoutine
& 0xfff) == 0);
505 SendInitIpiAllExcludingSelf ();
506 MicroSecondDelay (PcdGet32(PcdCpuInitIpiDelayInMicroSeconds
));
508 IcrLow
.Bits
.Vector
= (StartupRoutine
>> 12);
509 IcrLow
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_STARTUP
;
510 IcrLow
.Bits
.Level
= 1;
511 IcrLow
.Bits
.DestinationShorthand
= LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF
;
512 SendIpi (IcrLow
.Uint32
, 0);
513 MicroSecondDelay (200);
514 SendIpi (IcrLow
.Uint32
, 0);
518 Programming Virtual Wire Mode.
520 This function programs the local APIC for virtual wire mode following
521 the example described in chapter A.3 of the MP 1.4 spec.
523 IOxAPIC is not involved in this type of virtual wire mode.
527 ProgramVirtualWireMode (
532 LOCAL_APIC_LVT_LINT Lint
;
535 // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.
537 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
538 Svr
.Bits
.SpuriousVector
= 0xf;
539 Svr
.Bits
.SoftwareEnable
= 1;
540 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
543 // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.
545 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
546 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_EXTINT
;
547 Lint
.Bits
.InputPinPolarity
= 0;
548 Lint
.Bits
.TriggerMode
= 0;
550 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, Lint
.Uint32
);
553 // Program the LINT0 vector entry as NMI. Not masked, edge, active high.
555 Lint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
556 Lint
.Bits
.DeliveryMode
= LOCAL_APIC_DELIVERY_MODE_NMI
;
557 Lint
.Bits
.InputPinPolarity
= 0;
558 Lint
.Bits
.TriggerMode
= 0;
560 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, Lint
.Uint32
);
564 Disable LINT0 & LINT1 interrupts.
566 This function sets the mask flag in the LVT LINT0 & LINT1 registers.
570 DisableLvtInterrupts (
574 LOCAL_APIC_LVT_LINT LvtLint
;
576 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET
);
577 LvtLint
.Bits
.Mask
= 1;
578 WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET
, LvtLint
.Uint32
);
580 LvtLint
.Uint32
= ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET
);
581 LvtLint
.Bits
.Mask
= 1;
582 WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET
, LvtLint
.Uint32
);
586 Read the initial count value from the init-count register.
588 @return The initial count value read from the init-count register.
592 GetApicTimerInitCount (
596 return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
);
600 Read the current count value from the current-count register.
602 @return The current count value read from the current-count register.
606 GetApicTimerCurrentCount (
610 return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET
);
614 Initialize the local APIC timer.
616 The local APIC timer is initialized and enabled.
618 @param DivideValue The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
619 If it is 0, then use the current divide value in the DCR.
620 @param InitCount The initial count value.
621 @param PeriodicMode If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
622 @param Vector The timer interrupt vector number.
626 InitializeApicTimer (
627 IN UINTN DivideValue
,
629 IN BOOLEAN PeriodicMode
,
635 LOCAL_APIC_LVT_TIMER LvtTimer
;
639 // Ensure local APIC is in software-enabled state.
641 Svr
.Uint32
= ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
);
642 Svr
.Bits
.SoftwareEnable
= 1;
643 WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET
, Svr
.Uint32
);
646 // Program init-count register.
648 WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET
, InitCount
);
650 if (DivideValue
!= 0) {
651 ASSERT (DivideValue
<= 128);
652 ASSERT (DivideValue
== GetPowerOfTwo32((UINT32
)DivideValue
));
653 Divisor
= (UINT32
)((HighBitSet32 ((UINT32
)DivideValue
) - 1) & 0x7);
655 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
656 Dcr
.Bits
.DivideValue1
= (Divisor
& 0x3);
657 Dcr
.Bits
.DivideValue2
= (Divisor
>> 2);
658 WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
, Dcr
.Uint32
);
662 // Enable APIC timer interrupt with specified timer mode.
664 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
666 LvtTimer
.Bits
.TimerMode
= 1;
668 LvtTimer
.Bits
.TimerMode
= 0;
670 LvtTimer
.Bits
.Mask
= 0;
671 LvtTimer
.Bits
.Vector
= Vector
;
672 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
676 Get the state of the local APIC timer.
678 @param DivideValue Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.
679 @param PeriodicMode Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.
680 @param Vector Return the timer interrupt vector number.
685 OUT UINTN
*DivideValue OPTIONAL
,
686 OUT BOOLEAN
*PeriodicMode OPTIONAL
,
687 OUT UINT8
*Vector OPTIONAL
692 LOCAL_APIC_LVT_TIMER LvtTimer
;
694 if (DivideValue
!= NULL
) {
695 Dcr
.Uint32
= ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET
);
696 Divisor
= Dcr
.Bits
.DivideValue1
| (Dcr
.Bits
.DivideValue2
<< 2);
697 Divisor
= (Divisor
+ 1) & 0x7;
698 *DivideValue
= ((UINTN
)1) << Divisor
;
701 if (PeriodicMode
!= NULL
|| Vector
!= NULL
) {
702 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
703 if (PeriodicMode
!= NULL
) {
704 if (LvtTimer
.Bits
.TimerMode
== 1) {
705 *PeriodicMode
= TRUE
;
707 *PeriodicMode
= FALSE
;
710 if (Vector
!= NULL
) {
711 *Vector
= (UINT8
) LvtTimer
.Bits
.Vector
;
717 Enable the local APIC timer interrupt.
721 EnableApicTimerInterrupt (
725 LOCAL_APIC_LVT_TIMER LvtTimer
;
727 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
728 LvtTimer
.Bits
.Mask
= 0;
729 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
733 Disable the local APIC timer interrupt.
737 DisableApicTimerInterrupt (
741 LOCAL_APIC_LVT_TIMER LvtTimer
;
743 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
744 LvtTimer
.Bits
.Mask
= 1;
745 WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET
, LvtTimer
.Uint32
);
749 Get the local APIC timer interrupt state.
751 @retval TRUE The local APIC timer interrupt is enabled.
752 @retval FALSE The local APIC timer interrupt is disabled.
756 GetApicTimerInterruptState (
760 LOCAL_APIC_LVT_TIMER LvtTimer
;
762 LvtTimer
.Uint32
= ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET
);
763 return (BOOLEAN
)(LvtTimer
.Bits
.Mask
== 0);
767 Send EOI to the local APIC.
775 WriteLocalApicReg (XAPIC_EOI_OFFSET
, 0);
779 Get the 32-bit address that a device should use to send a Message Signaled
780 Interrupt (MSI) to the Local APIC of the currently executing processor.
782 @return 32-bit address used to send an MSI to the Local APIC.
790 LOCAL_APIC_MSI_ADDRESS MsiAddress
;
793 // Return address for an MSI interrupt to be delivered only to the APIC ID
794 // of the currently executing processor.
796 MsiAddress
.Uint32
= 0;
797 MsiAddress
.Bits
.BaseAddress
= 0xFEE;
798 MsiAddress
.Bits
.DestinationId
= GetApicId ();
799 return MsiAddress
.Uint32
;
803 Get the 64-bit data value that a device should use to send a Message Signaled
804 Interrupt (MSI) to the Local APIC of the currently executing processor.
806 If Vector is not in range 0x10..0xFE, then ASSERT().
807 If DeliveryMode is not supported, then ASSERT().
809 @param Vector The 8-bit interrupt vector associated with the MSI.
810 Must be in the range 0x10..0xFE
811 @param DeliveryMode A 3-bit value that specifies how the recept of the MSI
812 is handled. The only supported values are:
813 0: LOCAL_APIC_DELIVERY_MODE_FIXED
814 1: LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY
815 2: LOCAL_APIC_DELIVERY_MODE_SMI
816 4: LOCAL_APIC_DELIVERY_MODE_NMI
817 5: LOCAL_APIC_DELIVERY_MODE_INIT
818 7: LOCAL_APIC_DELIVERY_MODE_EXTINT
820 @param LevelTriggered TRUE specifies a level triggered interrupt.
821 FALSE specifies an edge triggered interrupt.
822 @param AssertionLevel Ignored if LevelTriggered is FALSE.
823 TRUE specifies a level triggered interrupt that active
824 when the interrupt line is asserted.
825 FALSE specifies a level triggered interrupt that active
826 when the interrupt line is deasserted.
828 @return 64-bit data value used to send an MSI to the Local APIC.
834 IN UINTN DeliveryMode
,
835 IN BOOLEAN LevelTriggered
,
836 IN BOOLEAN AssertionLevel
839 LOCAL_APIC_MSI_DATA MsiData
;
841 ASSERT (Vector
>= 0x10 && Vector
<= 0xFE);
842 ASSERT (DeliveryMode
< 8 && DeliveryMode
!= 6 && DeliveryMode
!= 3);
845 MsiData
.Bits
.Vector
= Vector
;
846 MsiData
.Bits
.DeliveryMode
= (UINT32
)DeliveryMode
;
847 if (LevelTriggered
) {
848 MsiData
.Bits
.TriggerMode
= 1;
849 if (AssertionLevel
) {
850 MsiData
.Bits
.Level
= 1;
853 return MsiData
.Uint64
;