ReactOS 0.4.16-dev-1067-ge98bba2
apic.c File Reference
#include <hal.h>
#include "apicp.h"
#include <debug.h>
Include dependency graph for apic.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define APIC_LAZY_IRQL
 
#define ApicRaiseIrql   ApicSetIrql
 

Functions

FORCEINLINE ULONG IOApicRead (UCHAR Register)
 
FORCEINLINE VOID IOApicWrite (UCHAR Register, ULONG Value)
 
FORCEINLINE VOID ApicWriteIORedirectionEntry (UCHAR Index, IOAPIC_REDIRECTION_REGISTER ReDirReg)
 
FORCEINLINE IOAPIC_REDIRECTION_REGISTER ApicReadIORedirectionEntry (UCHAR Index)
 
FORCEINLINE VOID ApicRequestSelfInterrupt (IN UCHAR Vector, UCHAR TriggerMode)
 
FORCEINLINE VOID ApicSendEOI (void)
 
FORCEINLINE KIRQL ApicGetProcessorIrql (VOID)
 
FORCEINLINE KIRQL ApicGetCurrentIrql (VOID)
 
FORCEINLINE VOID ApicSetIrql (KIRQL Irql)
 
FORCEINLINE VOID ApicLowerIrql (KIRQL Irql)
 
UCHAR FASTCALL HalpIrqToVector (UCHAR Irq)
 
KIRQL FASTCALL HalpVectorToIrql (UCHAR Vector)
 
UCHAR FASTCALL HalpVectorToIrq (UCHAR Vector)
 
VOID NTAPI HalpSendEOI (VOID)
 
VOID NTAPI ApicInitializeLocalApic (ULONG Cpu)
 
UCHAR NTAPI HalpAllocateSystemInterrupt (_In_ UCHAR Irq, _In_ UCHAR Vector)
 
ULONG NTAPI HalpGetRootInterruptVector (_In_ ULONG BusInterruptLevel, _In_ ULONG BusInterruptVector, _Out_ PKIRQL OutIrql, _Out_ PKAFFINITY OutAffinity)
 
VOID NTAPI ApicInitializeIOApic (VOID)
 
VOID NTAPI HalpInitializePICs (IN BOOLEAN EnableInterrupts)
 
VOID DECLSPEC_NORETURN FASTCALL HalpApcInterruptHandler (IN PKTRAP_FRAME TrapFrame)
 
VOID DECLSPEC_NORETURN FASTCALL HalpDispatchInterruptHandler (IN PKTRAP_FRAME TrapFrame)
 
VOID FASTCALL HalRequestSoftwareInterrupt (IN KIRQL Irql)
 
VOID FASTCALL HalClearSoftwareInterrupt (IN KIRQL Irql)
 
BOOLEAN NTAPI HalEnableSystemInterrupt (IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode)
 
VOID NTAPI HalDisableSystemInterrupt (IN ULONG Vector, IN KIRQL Irql)
 
BOOLEAN NTAPI HalBeginSystemInterrupt (IN KIRQL Irql, IN ULONG Vector, OUT PKIRQL OldIrql)
 
VOID NTAPI HalEndSystemInterrupt (IN KIRQL OldIrql, IN PKTRAP_FRAME TrapFrame)
 
KIRQL NTAPI KeGetCurrentIrql (VOID)
 
VOID FASTCALL KfLowerIrql (IN KIRQL OldIrql)
 
KIRQL FASTCALL KfRaiseIrql (IN KIRQL NewIrql)
 
KIRQL NTAPI KeRaiseIrqlToDpcLevel (VOID)
 
KIRQL NTAPI KeRaiseIrqlToSynchLevel (VOID)
 

Variables

ULONG ApicVersion
 
UCHAR HalpVectorToIndex [256]
 
const UCHAR HalpIRQLtoTPR [32]
 
const KIRQL HalVectorToIRQL [16]
 

Macro Definition Documentation

◆ APIC_LAZY_IRQL

#define APIC_LAZY_IRQL

Definition at line 22 of file apic.c.

◆ ApicRaiseIrql

#define ApicRaiseIrql   ApicSetIrql

Definition at line 233 of file apic.c.

◆ NDEBUG

#define NDEBUG

Definition at line 18 of file apic.c.

Function Documentation

◆ ApicGetCurrentIrql()

FORCEINLINE KIRQL ApicGetCurrentIrql ( VOID  )

Definition at line 207 of file apic.c.

208{
209#ifdef _M_AMD64
210 return (KIRQL)__readcr8();
211#elif defined(APIC_LAZY_IRQL)
212 /* Return the field in the PCR */
214#else
215 /* Read the TPR and convert it to an IRQL */
216 return TprToIrql(ApicRead(APIC_TPR));
217#endif
218}
FORCEINLINE ULONG ApicRead(APIC_REGISTER Register)
Definition: apicp.h:318
#define TprToIrql(Tpr)
Definition: apicp.h:57
@ APIC_TPR
Definition: apicp.h:84
_Out_ PKIRQL Irql
Definition: csq.h:179
UCHAR KIRQL
Definition: env_spec_w32.h:591
PPC_QUAL unsigned char __readfsbyte(const unsigned long Offset)
Definition: intrin_ppc.h:360
Definition: ke.h:294
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by HalBeginSystemInterrupt(), HalpApcInterruptHandler(), HalpDispatchInterruptHandler(), KeGetCurrentIrql(), KfLowerIrql(), and KfRaiseIrql().

◆ ApicGetProcessorIrql()

FORCEINLINE KIRQL ApicGetProcessorIrql ( VOID  )

Definition at line 199 of file apic.c.

200{
201 /* Read the TPR and convert it to an IRQL */
202 return TprToIrql(ApicRead(APIC_PPR));
203}
@ APIC_PPR
Definition: apicp.h:86

Referenced by HalpApcInterruptHandler(), and HalpDispatchInterruptHandler().

◆ ApicInitializeIOApic()

VOID NTAPI ApicInitializeIOApic ( VOID  )

Definition at line 460 of file apic.c.

461{
462 PHARDWARE_PTE Pte;
464 UCHAR Index;
466
467 /* Map the I/O Apic page */
470 Pte->Valid = 1;
471 Pte->Write = 1;
472 Pte->Owner = 1;
473 Pte->CacheDisable = 1;
474 Pte->Global = 1;
476
477 /* Setup a redirection entry */
478 ReDirReg.Vector = APIC_FREE_VECTOR;
479 ReDirReg.MessageType = APIC_MT_Fixed;
481 ReDirReg.DeliveryStatus = 0;
482 ReDirReg.Polarity = 0;
483 ReDirReg.RemoteIRR = 0;
484 ReDirReg.TriggerMode = APIC_TGM_Edge;
485 ReDirReg.Mask = 1;
486 ReDirReg.Reserved = 0;
487 ReDirReg.Destination = ApicRead(APIC_ID) >> 24;
488
489 /* Loop all table entries */
490 for (Index = 0; Index < APIC_MAX_IRQ; Index++)
491 {
492 /* Initialize entry */
494 }
495
496 /* Init the vactor to index table */
497 for (Vector = 0; Vector <= 255; Vector++)
498 {
500 }
501
502 /* Enable the timer interrupt (but keep it masked) */
503 ReDirReg.Vector = APIC_CLOCK_VECTOR;
504 ReDirReg.MessageType = APIC_MT_Fixed;
506 ReDirReg.TriggerMode = APIC_TGM_Level;
507 ReDirReg.Mask = 1;
508 ReDirReg.Destination = ApicRead(APIC_ID) >> 24;
510}
UCHAR HalpVectorToIndex[256]
Definition: apic.c:28
FORCEINLINE VOID ApicWriteIORedirectionEntry(UCHAR Index, IOAPIC_REDIRECTION_REGISTER ReDirReg)
Definition: apic.c:114
@ APIC_DM_Physical
Definition: apicp.h:147
#define IOAPIC_BASE
Definition: apicp.h:38
#define APIC_CLOCK_VECTOR
Definition: apicp.h:45
#define APIC_MAX_IRQ
Definition: apicp.h:61
#define APIC_FREE_VECTOR
Definition: apicp.h:62
@ APIC_MT_Fixed
Definition: apicp.h:127
#define APIC_CLOCK_INDEX
Definition: apicp.h:118
@ APIC_ID
Definition: apicp.h:82
@ APIC_TGM_Level
Definition: apicp.h:141
@ APIC_TGM_Edge
Definition: apicp.h:140
#define IOAPIC_PHYS_BASE
Definition: apicp.h:117
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define HalAddressToPte(x)
Definition: halp.h:177
#define _ReadWriteBarrier()
Definition: intrin_arm.h:36
ULONG64 Owner
Definition: mmtypes.h:68
ULONG64 PageFrameNumber
Definition: mmtypes.h:78
ULONG64 Write
Definition: mmtypes.h:67
ULONG64 Valid
Definition: mmtypes.h:66
ULONG64 CacheDisable
Definition: mmtypes.h:70
ULONG64 Global
Definition: mmtypes.h:74
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by HalpInitializePICs().

◆ ApicInitializeLocalApic()

VOID NTAPI ApicInitializeLocalApic ( ULONG  Cpu)

Definition at line 292 of file apic.c.

293{
294 APIC_BASE_ADDRESS_REGISTER BaseRegister;
296 LVT_REGISTER LvtEntry;
297
298 /* Enable the APIC if it wasn't yet */
299 BaseRegister.LongLong = __readmsr(MSR_APIC_BASE);
300 BaseRegister.Enable = 1;
301 BaseRegister.BootStrapCPUCore = (Cpu == 0);
302 __writemsr(MSR_APIC_BASE, BaseRegister.LongLong);
303
304 /* Set spurious vector and SoftwareEnable to 1 */
305 SpIntRegister.Long = ApicRead(APIC_SIVR);
306 SpIntRegister.Vector = APIC_SPURIOUS_VECTOR;
307 SpIntRegister.SoftwareEnable = 1;
308 SpIntRegister.FocusCPUCoreChecking = 0;
309 ApicWrite(APIC_SIVR, SpIntRegister.Long);
310
311 /* Read the version and save it globally */
312 if (Cpu == 0) ApicVersion = ApicRead(APIC_VER);
313
314 /* Set the mode to flat (max 8 CPUs supported!) */
316
317 /* Set logical apic ID */
318 ApicWrite(APIC_LDR, ApicLogicalId(Cpu) << 24);
319
320 /* Set the spurious ISR */
322
323 /* Create a template LVT */
324 LvtEntry.Long = 0;
325 LvtEntry.Vector = APIC_FREE_VECTOR;
326 LvtEntry.MessageType = APIC_MT_Fixed;
327 LvtEntry.DeliveryStatus = 0;
328 LvtEntry.RemoteIRR = 0;
329 LvtEntry.TriggerMode = APIC_TGM_Edge;
330 LvtEntry.Mask = 1;
331 LvtEntry.TimerMode = 0;
332
333 /* Initialize and mask LVTs */
334 ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
335 ApicWrite(APIC_THRMLVTR, LvtEntry.Long);
336 ApicWrite(APIC_PCLVTR, LvtEntry.Long);
337 ApicWrite(APIC_EXT0LVTR, LvtEntry.Long);
338 ApicWrite(APIC_EXT1LVTR, LvtEntry.Long);
339 ApicWrite(APIC_EXT2LVTR, LvtEntry.Long);
340 ApicWrite(APIC_EXT3LVTR, LvtEntry.Long);
341
342 /* LINT0 */
343 LvtEntry.Vector = APIC_SPURIOUS_VECTOR;
344 LvtEntry.MessageType = APIC_MT_ExtInt;
345 ApicWrite(APIC_LINT0, LvtEntry.Long);
346
347 /* Enable LINT1 (NMI) */
348 LvtEntry.Mask = 0;
349 LvtEntry.Vector = APIC_NMI_VECTOR;
350 LvtEntry.MessageType = APIC_MT_NMI;
351 LvtEntry.TriggerMode = APIC_TGM_Level;
352 ApicWrite(APIC_LINT1, LvtEntry.Long);
353
354 /* Enable error LVTR */
355 LvtEntry.Vector = APIC_ERROR_VECTOR;
356 LvtEntry.MessageType = APIC_MT_Fixed;
357 ApicWrite(APIC_ERRLVTR, LvtEntry.Long);
358
359 /* Set the IRQL from the PCR */
361#ifdef APIC_LAZY_IRQL
362 /* Save the new hard IRQL in the IRR field */
363 KeGetPcr()->IRR = KeGetPcr()->Irql;
364#endif
365}
ULONG ApicVersion
Definition: apic.c:27
FORCEINLINE VOID ApicSetIrql(KIRQL Irql)
Definition: apic.c:222
#define MSR_APIC_BASE
Definition: apicp.h:116
@ APIC_DF_Flat
Definition: apicp.h:163
#define APIC_NMI_VECTOR
Definition: apicp.h:53
@ APIC_MT_NMI
Definition: apicp.h:131
@ APIC_MT_ExtInt
Definition: apicp.h:134
#define APIC_SPURIOUS_VECTOR
Definition: apicp.h:41
#define APIC_ERROR_VECTOR
Definition: apicp.h:49
#define ApicLogicalId(Cpu)
Definition: apicp.h:119
VOID __cdecl ApicSpuriousService(VOID)
FORCEINLINE VOID ApicWrite(APIC_REGISTER Register, ULONG Value)
Definition: apicp.h:325
@ APIC_LINT1
Definition: apicp.h:102
@ APIC_EXT3LVTR
Definition: apicp.h:113
@ APIC_EXT1LVTR
Definition: apicp.h:111
@ APIC_VER
Definition: apicp.h:83
@ APIC_LDR
Definition: apicp.h:89
@ APIC_ERRLVTR
Definition: apicp.h:103
@ APIC_PCLVTR
Definition: apicp.h:100
@ APIC_EXT2LVTR
Definition: apicp.h:112
@ APIC_THRMLVTR
Definition: apicp.h:99
@ APIC_TMRLVTR
Definition: apicp.h:98
@ APIC_DFR
Definition: apicp.h:90
@ APIC_LINT0
Definition: apicp.h:101
@ APIC_SIVR
Definition: apicp.h:91
@ APIC_EXT0LVTR
Definition: apicp.h:110
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
#define KeGetPcr()
Definition: ketypes.h:81
FORCEINLINE VOID KeRegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler)
Definition: ke.h:301
UINT32 RemoteIRR
Definition: apicp.h:274
UINT32 MessageType
Definition: apicp.h:270
UINT32 TimerMode
Definition: apicp.h:277
UINT32 Long
Definition: apicp.h:266
UINT32 Vector
Definition: apicp.h:269
UINT32 Mask
Definition: apicp.h:276
UINT32 TriggerMode
Definition: apicp.h:275
UINT32 DeliveryStatus
Definition: apicp.h:272

Referenced by HalpInitProcessor().

◆ ApicLowerIrql()

FORCEINLINE VOID ApicLowerIrql ( KIRQL  Irql)

Definition at line 238 of file apic.c.

239{
241
242 /* Is the new Irql lower than set in the TPR? */
243 if (Irql < KeGetPcr()->IRR)
244 {
245 /* Save the new hard IRQL in the IRR field */
246 KeGetPcr()->IRR = Irql;
247
248 /* Need to lower it back */
250 }
251}
#define IrqlToTpr(Irql)
Definition: apicp.h:55
PPC_QUAL void __writefsbyte(const unsigned long Offset, const unsigned char Data)
Definition: intrin_ppc.h:342

Referenced by HalEndSystemInterrupt(), HalpApcInterruptHandler(), HalpDispatchInterruptHandler(), and KfLowerIrql().

◆ ApicReadIORedirectionEntry()

FORCEINLINE IOAPIC_REDIRECTION_REGISTER ApicReadIORedirectionEntry ( UCHAR  Index)

Definition at line 125 of file apic.c.

127{
129
131 ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
132 ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);
133
134 return ReDirReg;
135}
FORCEINLINE ULONG IOApicRead(UCHAR Register)
Definition: apic.c:94
#define IOAPIC_REDTBL
Definition: apicp.h:290
#define ASSERT(a)
Definition: mode.c:44

Referenced by HalBeginSystemInterrupt(), and HalEnableSystemInterrupt().

◆ ApicRequestSelfInterrupt()

FORCEINLINE VOID ApicRequestSelfInterrupt ( IN UCHAR  Vector,
UCHAR  TriggerMode 
)

Definition at line 139 of file apic.c.

140{
141 ULONG Flags;
144
145 /*
146 * The IRR registers are spaced 16 bytes apart and hold 32 status bits each.
147 * Pre-compute the register and bit that match our vector.
148 */
149 ULONG VectorHigh = Vector / 32;
150 ULONG VectorLow = Vector % 32;
151 ULONG Irr = APIC_IRR + 0x10 * VectorHigh;
152 ULONG IrrBit = 1UL << VectorLow;
153
154 /* Setup the command register */
155 Icr.LongLong = 0;
156 Icr.Vector = Vector;
158 Icr.TriggerMode = TriggerMode;
160
161 /* Disable interrupts so that we can change IRR without being interrupted */
163 _disable();
164
165 /* Wait for the APIC to be idle */
166 do
167 {
168 IcrStatus.Long0 = ApicRead(APIC_ICR0);
169 } while (IcrStatus.DeliveryStatus);
170
171 /* Write high dword first, then low dword to send the interrupt */
174
175 /* Wait until we see the interrupt request.
176 * It will stay in requested state until we re-enable interrupts.
177 */
178 while (!(ApicRead(Irr) & IrrBit))
179 {
181 }
182
183 /* Finally, restore the original interrupt state */
185 {
186 _enable();
187 }
188}
#define EFLAGS_INTERRUPT_MASK
Definition: SystemCall.c:11
@ APIC_DSH_Self
Definition: apicp.h:155
@ APIC_ICR0
Definition: apicp.h:96
@ APIC_IRR
Definition: apicp.h:94
@ APIC_ICR1
Definition: apicp.h:97
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1688
#define YieldProcessor
Definition: ke.h:48
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by HalBeginSystemInterrupt(), and HalRequestSoftwareInterrupt().

◆ ApicSendEOI()

FORCEINLINE VOID ApicSendEOI ( void  )

◆ ApicSetIrql()

FORCEINLINE VOID ApicSetIrql ( KIRQL  Irql)

Definition at line 222 of file apic.c.

223{
224#ifdef _M_AMD64
225 __writecr8(Irql);
226#elif defined(APIC_LAZY_IRQL)
228#else
229 /* Convert IRQL and write the TPR */
231#endif
232}

Referenced by ApicInitializeLocalApic().

◆ ApicWriteIORedirectionEntry()

FORCEINLINE VOID ApicWriteIORedirectionEntry ( UCHAR  Index,
IOAPIC_REDIRECTION_REGISTER  ReDirReg 
)

Definition at line 114 of file apic.c.

117{
119 IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
120 IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
121}
FORCEINLINE VOID IOApicWrite(UCHAR Register, ULONG Value)
Definition: apic.c:104

Referenced by ApicInitializeIOApic(), HalEnableSystemInterrupt(), and HalpAllocateSystemInterrupt().

◆ HalBeginSystemInterrupt()

BOOLEAN NTAPI HalBeginSystemInterrupt ( IN KIRQL  Irql,
IN ULONG  Vector,
OUT PKIRQL  OldIrql 
)

Definition at line 743 of file apic.c.

747{
748 KIRQL CurrentIrql;
749
750 /* Get the current IRQL */
751 CurrentIrql = ApicGetCurrentIrql();
752
753#ifdef APIC_LAZY_IRQL
754 /* Check if this interrupt is allowed */
755 if (CurrentIrql >= Irql)
756 {
758 UCHAR Index;
759
760 /* It is not, set the real Irql in the TPR! */
761 ApicWrite(APIC_TPR, IrqlToTpr(CurrentIrql));
762
763 /* Save the new hard IRQL in the IRR field */
764 KeGetPcr()->IRR = CurrentIrql;
765
766 /* End this interrupt */
767 ApicSendEOI();
768
769 /* Get the irq for this vector */
771
772 /* Check if it's valid */
773 if (Index < APIC_MAX_IRQ)
774 {
775 /* Read the I/O redirection entry */
777
778 /* Re-request the interrupt to be handled later */
780 }
781 else
782 {
783 /* This should be a reserved vector! */
785
786 /* Re-request the interrupt to be handled later */
788 }
789
790 /* Pretend it was a spurious interrupt */
791 return FALSE;
792 }
793#endif
794 /* Save the current IRQL */
795 *OldIrql = CurrentIrql;
796
797 /* Set the new IRQL */
799
800 /* Turn on interrupts */
801 _enable();
802
803 /* Success */
804 return TRUE;
805}
#define ApicRaiseIrql
Definition: apic.c:233
FORCEINLINE VOID ApicRequestSelfInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
Definition: apic.c:139
FORCEINLINE VOID ApicSendEOI(void)
Definition: apic.c:192
FORCEINLINE IOAPIC_REDIRECTION_REGISTER ApicReadIORedirectionEntry(UCHAR Index)
Definition: apic.c:125
FORCEINLINE KIRQL ApicGetCurrentIrql(VOID)
Definition: apic.c:207
#define APIC_RESERVED_VECTOR
Definition: apicp.h:63
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by HalpApcInterruptHandler(), HalpDispatchInterruptHandler(), and MpsTimerHandler().

◆ HalClearSoftwareInterrupt()

VOID FASTCALL HalClearSoftwareInterrupt ( IN KIRQL  Irql)

Definition at line 661 of file apic.c.

663{
664 /* Nothing to do */
665}

◆ HalDisableSystemInterrupt()

VOID NTAPI HalDisableSystemInterrupt ( IN ULONG  Vector,
IN KIRQL  Irql 
)

Definition at line 720 of file apic.c.

723{
725 UCHAR Index;
728
730
731 /* Read lower dword of redirection entry */
732 ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
733
734 /* Mask it */
735 ReDirReg.Mask = 1;
736
737 /* Write back lower dword */
738 IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
739}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define HIGH_LEVEL
Definition: env_spec_w32.h:703

◆ HalEnableSystemInterrupt()

BOOLEAN NTAPI HalEnableSystemInterrupt ( IN ULONG  Vector,
IN KIRQL  Irql,
IN KINTERRUPT_MODE  InterruptMode 
)

Definition at line 672 of file apic.c.

676{
678 UCHAR Index;
680 ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0));
681
682 /* Get the irq for this vector */
684
685 /* Check if its valid */
686 if (Index == APIC_FREE_VECTOR)
687 {
688 /* Interrupt is not in use */
689 return FALSE;
690 }
691
692 /* Read the redirection entry */
694
695 /* Check if the interrupt is already enabled */
696 if (ReDirReg.Mask == FALSE)
697 {
698 /* If the vector matches, there is nothing more to do,
699 otherwise something is wrong. */
700 return (ReDirReg.Vector == Vector);
701 }
702
703 /* Set up the redirection entry */
704 ReDirReg.Vector = Vector;
705 ReDirReg.MessageType = APIC_MT_Fixed;
707 ReDirReg.Destination = ApicRead(APIC_ID) >> 24;
710 ReDirReg.Mask = FALSE;
711
712 /* Write back the entry */
714
715 return TRUE;
716}
@ LevelSensitive
Definition: miniport.h:80
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE InterruptMode
Definition: iofuncs.h:806

◆ HalEndSystemInterrupt()

VOID NTAPI HalEndSystemInterrupt ( IN KIRQL  OldIrql,
IN PKTRAP_FRAME  TrapFrame 
)

Definition at line 809 of file apic.c.

812{
813 /* Send an EOI */
814 ApicSendEOI();
815
816 /* Restore the old IRQL */
818}
FORCEINLINE VOID ApicLowerIrql(KIRQL Irql)
Definition: apic.c:238

Referenced by MpsTimerHandler().

◆ HalpAllocateSystemInterrupt()

UCHAR NTAPI HalpAllocateSystemInterrupt ( _In_ UCHAR  Irq,
_In_ UCHAR  Vector 
)

Definition at line 369 of file apic.c.

372{
374
375 ASSERT(Irq < APIC_MAX_IRQ);
377
378 /* Setup a redirection entry */
379 ReDirReg.Vector = Vector;
382 ReDirReg.DeliveryStatus = 0;
383 ReDirReg.Polarity = 0;
384 ReDirReg.RemoteIRR = 0;
385 ReDirReg.TriggerMode = APIC_TGM_Edge;
386 ReDirReg.Mask = 1;
387 ReDirReg.Reserved = 0;
388 ReDirReg.Destination = ApicRead(APIC_ID) >> 24;
389
390 /* Initialize entry */
391 ApicWriteIORedirectionEntry(Irq, ReDirReg);
392
393 /* Save irq in the table */
395
396 return Vector;
397}
@ APIC_DM_Logical
Definition: apicp.h:148
@ APIC_MT_LowestPriority
Definition: apicp.h:128

Referenced by HalpGetRootInterruptVector().

◆ HalpApcInterruptHandler()

VOID DECLSPEC_NORETURN FASTCALL HalpApcInterruptHandler ( IN PKTRAP_FRAME  TrapFrame)

Definition at line 559 of file apic.c.

560{
561 KPROCESSOR_MODE ProcessorMode;
564
565 /* Enter trap */
566 KiEnterInterruptTrap(TrapFrame);
567
568#ifdef APIC_LAZY_IRQL
570 {
571 /* "Spurious" interrupt, exit the interrupt */
572 KiEoiHelper(TrapFrame);
573 }
574#else
575 /* Save the old IRQL */
578#endif
579
580 /* Raise to APC_LEVEL */
582
583 /* End the interrupt */
584 ApicSendEOI();
585
586 /* Kernel or user APC? */
587 if (KiUserTrap(TrapFrame)) ProcessorMode = UserMode;
588 else if (TrapFrame->EFlags & EFLAGS_V86_MASK) ProcessorMode = UserMode;
589 else ProcessorMode = KernelMode;
590
591 /* Enable interrupts and call the kernel's APC interrupt handler */
592 _enable();
593 KiDeliverApc(ProcessorMode, NULL, TrapFrame);
594
595 /* Disable interrupts */
596 _disable();
597
598 /* Restore the old IRQL */
600
601 /* Exit the interrupt */
602 KiEoiHelper(TrapFrame);
603}
BOOLEAN NTAPI HalBeginSystemInterrupt(IN KIRQL Irql, IN ULONG Vector, OUT PKIRQL OldIrql)
Definition: apic.c:743
FORCEINLINE KIRQL ApicGetProcessorIrql(VOID)
Definition: apic.c:199
#define APC_VECTOR
Definition: apicp.h:42
#define NULL
Definition: types.h:112
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define EFLAGS_V86_MASK
Definition: ketypes.h:197
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: ke.h:367
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
VOID NTAPI KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: apc.c:302
FORCEINLINE VOID KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:368
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7

◆ HalpDispatchInterruptHandler()

VOID DECLSPEC_NORETURN FASTCALL HalpDispatchInterruptHandler ( IN PKTRAP_FRAME  TrapFrame)

Definition at line 608 of file apic.c.

609{
612
613 /* Enter trap */
614 KiEnterInterruptTrap(TrapFrame);
615
616#ifdef APIC_LAZY_IRQL
618 {
619 /* "Spurious" interrupt, exit the interrupt */
620 KiEoiHelper(TrapFrame);
621 }
622#else
623 /* Get the current IRQL */
626#endif
627
628 /* Raise to DISPATCH_LEVEL */
630
631 /* End the interrupt */
632 ApicSendEOI();
633
634 /* Enable interrupts and call the kernel's DPC interrupt handler */
635 _enable();
637 _disable();
638
639 /* Restore the old IRQL */
641
642 /* Exit the interrupt */
643 KiEoiHelper(TrapFrame);
644}
#define DISPATCH_VECTOR
Definition: apicp.h:43
VOID NTAPI KiDispatchInterrupt(VOID)
Definition: thrdini.c:305
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696

◆ HalpGetRootInterruptVector()

ULONG NTAPI HalpGetRootInterruptVector ( _In_ ULONG  BusInterruptLevel,
_In_ ULONG  BusInterruptVector,
_Out_ PKIRQL  OutIrql,
_Out_ PKAFFINITY  OutAffinity 
)

Definition at line 401 of file apic.c.

406{
408 KIRQL Irql;
409
410 /* Get the vector currently registered */
412
413 /* Check if it's used */
415 {
416 /* Calculate IRQL */
418 *OutIrql = HalpVectorToIrql(Vector);
419 }
420 else
421 {
423
424 /* Outer loop to find alternative slots, when all IRQLs are in use */
425 for (Offset = 0; Offset < 15; Offset++)
426 {
427 /* Loop allowed IRQL range */
428 for (Irql = CLOCK_LEVEL - 1; Irql >= CMCI_LEVEL; Irql--)
429 {
430 /* Calculate the vactor */
432
433 /* Check if the vector is free */
435 {
436 /* Found one, allocate the interrupt */
438 *OutIrql = Irql;
439 goto Exit;
440 }
441 }
442 }
443
444 DPRINT1("Failed to get an interrupt vector for IRQ %lu\n", BusInterruptLevel);
445 *OutAffinity = 0;
446 *OutIrql = 0;
447 return 0;
448 }
449
450Exit:
451
452 *OutAffinity = HalpDefaultInterruptAffinity;
454
455 return Vector;
456}
UCHAR FASTCALL HalpIrqToVector(UCHAR Irq)
Definition: apic.c:258
KIRQL FASTCALL HalpVectorToIrql(UCHAR Vector)
Definition: apic.c:271
UCHAR NTAPI HalpAllocateSystemInterrupt(_In_ UCHAR Irq, _In_ UCHAR Vector)
Definition: apic.c:369
UCHAR FASTCALL HalpVectorToIrq(UCHAR Vector)
Definition: apic.c:278
#define DPRINT1
Definition: precomp.h:8
KAFFINITY HalpDefaultInterruptAffinity
Definition: processor.c:18
#define CMCI_LEVEL
Definition: ketypes.h:15
#define CLOCK_LEVEL
Definition: ketypes.h:16
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
static void Exit(void)
Definition: sock.c:1330
_In_ ULONG _In_ ULONG BusInterruptLevel
Definition: halfuncs.h:171
#define NT_ASSERT
Definition: rtlfuncs.h:3327

Referenced by HalGetInterruptVector(), and HalpGetSystemInterruptVector().

◆ HalpInitializePICs()

VOID NTAPI HalpInitializePICs ( IN BOOLEAN  EnableInterrupts)

Definition at line 514 of file apic.c.

515{
516 ULONG_PTR EFlags;
517
518 /* Save EFlags and disable interrupts */
519 EFlags = __readeflags();
520 _disable();
521
522 /* Initialize and mask the PIC */
524
525 /* Initialize the I/O APIC */
527
528 /* Manually reserve some vectors */
534
535 /* Set interrupt handlers in the IDT */
538#ifndef _M_AMD64
541#endif
542
543 /* Register the vectors for APC and dispatch interrupts */
546
547 /* Restore interrupt state */
549 __writeeflags(EFlags);
550}
VOID NTAPI ApicInitializeIOApic(VOID)
Definition: apic.c:460
#define CLOCK_IPI_VECTOR
Definition: apicp.h:47
static NTSTATUS EnableInterrupts(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR FlagsToDisable, IN UCHAR FlagsToEnable)
Definition: pnp.c:380
VOID HalpClockInterrupt(VOID)
Definition: timer.c:30
VOID NTAPI HalpRegisterVector(IN UCHAR Flags, IN ULONG BusVector, IN ULONG SystemVector, IN KIRQL Irql)
Definition: usage.c:34
VOID NTAPI HalpInitializeLegacyPICs(VOID)
Definition: pic.c:18
#define IDT_INTERNAL
Definition: halp.h:21
VOID __cdecl HalpDispatchInterrupt(VOID)
VOID __cdecl HalpApcInterrupt(VOID)
VOID __cdecl HalpClockIpi(VOID)
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1683
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by HalInitSystem().

◆ HalpIrqToVector()

UCHAR FASTCALL HalpIrqToVector ( UCHAR  Irq)

Definition at line 258 of file apic.c.

259{
261
262 /* Read low dword of the redirection entry */
263 ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Irq);
264
265 /* Return the vector */
266 return (UCHAR)ReDirReg.Vector;
267}

Referenced by HalpGetRootInterruptVector().

◆ HalpSendEOI()

VOID NTAPI HalpSendEOI ( VOID  )

Definition at line 285 of file apic.c.

286{
287 ApicSendEOI();
288}

◆ HalpVectorToIrq()

UCHAR FASTCALL HalpVectorToIrq ( UCHAR  Vector)

Definition at line 278 of file apic.c.

279{
281}

Referenced by HalpGetRootInterruptVector().

◆ HalpVectorToIrql()

KIRQL FASTCALL HalpVectorToIrql ( UCHAR  Vector)

Definition at line 271 of file apic.c.

272{
273 return TprToIrql(Vector);
274}

Referenced by HalpGetRootInterruptVector().

◆ HalRequestSoftwareInterrupt()

VOID FASTCALL HalRequestSoftwareInterrupt ( IN KIRQL  Irql)

Definition at line 653 of file apic.c.

654{
655 /* Convert irql to vector and request an interrupt */
657}
#define IrqlToSoftVector(Irql)
Definition: apicp.h:56

◆ IOApicRead()

FORCEINLINE ULONG IOApicRead ( UCHAR  Register)

Definition at line 94 of file apic.c.

95{
96 /* Select the register, then do the read */
97 ASSERT(Register <= 0x3F);
100}
#define IOAPIC_IOWIN
Definition: apicp.h:284
#define IOAPIC_IOREGSEL
Definition: apicp.h:283
#define WRITE_REGISTER_ULONG(r, v)
Definition: arm.h:27
#define READ_REGISTER_ULONG(r)
Definition: arm.h:26
uint32_t * PULONG
Definition: typedefs.h:59

Referenced by ApicReadIORedirectionEntry(), HalDisableSystemInterrupt(), and HalpIrqToVector().

◆ IOApicWrite()

FORCEINLINE VOID IOApicWrite ( UCHAR  Register,
ULONG  Value 
)

Definition at line 104 of file apic.c.

105{
106 /* Select the register, then do the write */
107 ASSERT(Register <= 0x3F);
110}
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by ApicWriteIORedirectionEntry(), and HalDisableSystemInterrupt().

◆ KeGetCurrentIrql()

KIRQL NTAPI KeGetCurrentIrql ( VOID  )

Definition at line 826 of file apic.c.

827{
828 /* Read the current TPR and convert it to an IRQL */
829 return ApicGetCurrentIrql();
830}

◆ KeRaiseIrqlToDpcLevel()

KIRQL NTAPI KeRaiseIrqlToDpcLevel ( VOID  )

Definition at line 875 of file apic.c.

876{
878}
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: apic.c:851

◆ KeRaiseIrqlToSynchLevel()

KIRQL NTAPI KeRaiseIrqlToSynchLevel ( VOID  )

Definition at line 882 of file apic.c.

883{
884 return KfRaiseIrql(SYNCH_LEVEL);
885}
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704

◆ KfLowerIrql()

VOID FASTCALL KfLowerIrql ( IN KIRQL  OldIrql)

Definition at line 834 of file apic.c.

836{
837#if DBG
838 /* Validate correct lower */
840 {
841 /* Crash system */
842 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
843 }
844#endif
845 /* Set the new IRQL */
847}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434

◆ KfRaiseIrql()

KIRQL FASTCALL KfRaiseIrql ( IN KIRQL  NewIrql)

Definition at line 851 of file apic.c.

853{
855
856 /* Read the current IRQL */
858#if DBG
859 /* Validate correct raise */
860 if (OldIrql > NewIrql)
861 {
862 /* Crash system */
863 KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
864 }
865#endif
866 /* Convert the new IRQL to a TPR value and write the register */
868
869 /* Return old IRQL */
870 return OldIrql;
871}
_Requires_lock_held_ SpinLock _Releases_lock_ SpinLock _In_ _IRQL_restores_ KIRQL NewIrql
Definition: ke.h:114

Referenced by KeRaiseIrqlToDpcLevel(), and KeRaiseIrqlToSynchLevel().

Variable Documentation

◆ ApicVersion

ULONG ApicVersion

Definition at line 27 of file apic.c.

Referenced by ApicInitializeLocalApic().

◆ HalpIRQLtoTPR

const UCHAR HalpIRQLtoTPR[32]

Definition at line 32 of file apic.c.

◆ HalpVectorToIndex

◆ HalVectorToIRQL

const KIRQL HalVectorToIRQL[16]
Initial value:
=
{
0,
0xff,
0xff,
1,
2,
4,
5,
6,
7,
8,
9,
10,
27,
28,
29,
31,
}

Definition at line 69 of file apic.c.