ReactOS 0.4.15-dev-8102-g108db8f
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 232 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 206 of file apic.c.

207{
208#ifdef _M_AMD64
209 return (KIRQL)__readcr8();
210#elif defined(APIC_LAZY_IRQL)
211 /* Return the field in the PCR */
213#else
214 /* Read the TPR and convert it to an IRQL */
215 return TprToIrql(ApicRead(APIC_TPR));
216#endif
217}
FORCEINLINE ULONG ApicRead(APIC_REGISTER Register)
Definition: apicp.h:316
#define TprToIrql(Tpr)
Definition: apicp.h:56
@ APIC_TPR
Definition: apicp.h:82
_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 198 of file apic.c.

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

Referenced by HalpApcInterruptHandler(), and HalpDispatchInterruptHandler().

◆ ApicInitializeIOApic()

VOID NTAPI ApicInitializeIOApic ( VOID  )

Definition at line 459 of file apic.c.

460{
461 PHARDWARE_PTE Pte;
463 UCHAR Index;
465
466 /* Map the I/O Apic page */
469 Pte->Valid = 1;
470 Pte->Write = 1;
471 Pte->Owner = 1;
472 Pte->CacheDisable = 1;
473 Pte->Global = 1;
475
476 /* Setup a redirection entry */
477 ReDirReg.Vector = APIC_FREE_VECTOR;
478 ReDirReg.MessageType = APIC_MT_Fixed;
480 ReDirReg.DeliveryStatus = 0;
481 ReDirReg.Polarity = 0;
482 ReDirReg.RemoteIRR = 0;
483 ReDirReg.TriggerMode = APIC_TGM_Edge;
484 ReDirReg.Mask = 1;
485 ReDirReg.Reserved = 0;
486 ReDirReg.Destination = 0;
487
488 /* Loop all table entries */
489 for (Index = 0; Index < APIC_MAX_IRQ; Index++)
490 {
491 /* Initialize entry */
493 }
494
495 /* Init the vactor to index table */
496 for (Vector = 0; Vector <= 255; Vector++)
497 {
499 }
500
501 /* Enable the timer interrupt (but keep it masked) */
502 ReDirReg.Vector = APIC_CLOCK_VECTOR;
503 ReDirReg.MessageType = APIC_MT_Fixed;
505 ReDirReg.TriggerMode = APIC_TGM_Edge;
506 ReDirReg.Mask = 1;
507 ReDirReg.Destination = ApicRead(APIC_ID);
509}
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:145
#define IOAPIC_BASE
Definition: apicp.h:37
#define APIC_CLOCK_VECTOR
Definition: apicp.h:44
#define APIC_MAX_IRQ
Definition: apicp.h:59
#define APIC_FREE_VECTOR
Definition: apicp.h:60
@ APIC_MT_Fixed
Definition: apicp.h:125
#define APIC_CLOCK_INDEX
Definition: apicp.h:116
@ APIC_ID
Definition: apicp.h:80
@ APIC_TGM_Edge
Definition: apicp.h:138
#define IOAPIC_PHYS_BASE
Definition: apicp.h:115
#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 291 of file apic.c.

292{
293 APIC_BASE_ADDRESS_REGISTER BaseRegister;
295 LVT_REGISTER LvtEntry;
296
297 /* Enable the APIC if it wasn't yet */
298 BaseRegister.LongLong = __readmsr(MSR_APIC_BASE);
299 BaseRegister.Enable = 1;
300 BaseRegister.BootStrapCPUCore = (Cpu == 0);
301 __writemsr(MSR_APIC_BASE, BaseRegister.LongLong);
302
303 /* Set spurious vector and SoftwareEnable to 1 */
304 SpIntRegister.Long = ApicRead(APIC_SIVR);
305 SpIntRegister.Vector = APIC_SPURIOUS_VECTOR;
306 SpIntRegister.SoftwareEnable = 1;
307 SpIntRegister.FocusCPUCoreChecking = 0;
308 ApicWrite(APIC_SIVR, SpIntRegister.Long);
309
310 /* Read the version and save it globally */
311 if (Cpu == 0) ApicVersion = ApicRead(APIC_VER);
312
313 /* Set the mode to flat (max 8 CPUs supported!) */
315
316 /* Set logical apic ID */
317 ApicWrite(APIC_LDR, ApicLogicalId(Cpu) << 24);
318
319 /* Set the spurious ISR */
321
322 /* Create a template LVT */
323 LvtEntry.Long = 0;
324 LvtEntry.Vector = APIC_FREE_VECTOR;
325 LvtEntry.MessageType = APIC_MT_Fixed;
326 LvtEntry.DeliveryStatus = 0;
327 LvtEntry.RemoteIRR = 0;
328 LvtEntry.TriggerMode = APIC_TGM_Edge;
329 LvtEntry.Mask = 1;
330 LvtEntry.TimerMode = 0;
331
332 /* Initialize and mask LVTs */
333 ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
334 ApicWrite(APIC_THRMLVTR, LvtEntry.Long);
335 ApicWrite(APIC_PCLVTR, LvtEntry.Long);
336 ApicWrite(APIC_EXT0LVTR, LvtEntry.Long);
337 ApicWrite(APIC_EXT1LVTR, LvtEntry.Long);
338 ApicWrite(APIC_EXT2LVTR, LvtEntry.Long);
339 ApicWrite(APIC_EXT3LVTR, LvtEntry.Long);
340
341 /* LINT0 */
342 LvtEntry.Vector = APIC_SPURIOUS_VECTOR;
343 LvtEntry.MessageType = APIC_MT_ExtInt;
344 ApicWrite(APIC_LINT0, LvtEntry.Long);
345
346 /* Enable LINT1 (NMI) */
347 LvtEntry.Mask = 0;
348 LvtEntry.Vector = APIC_NMI_VECTOR;
349 LvtEntry.MessageType = APIC_MT_NMI;
350 LvtEntry.TriggerMode = APIC_TGM_Level;
351 ApicWrite(APIC_LINT1, LvtEntry.Long);
352
353 /* Enable error LVTR */
354 LvtEntry.Vector = APIC_ERROR_VECTOR;
355 LvtEntry.MessageType = APIC_MT_Fixed;
356 ApicWrite(APIC_ERRLVTR, LvtEntry.Long);
357
358 /* Set the IRQL from the PCR */
360#ifdef APIC_LAZY_IRQL
361 /* Save the new hard IRQL in the IRR field */
362 KeGetPcr()->IRR = KeGetPcr()->Irql;
363#endif
364}
ULONG ApicVersion
Definition: apic.c:27
FORCEINLINE VOID ApicSetIrql(KIRQL Irql)
Definition: apic.c:221
#define MSR_APIC_BASE
Definition: apicp.h:114
@ APIC_DF_Flat
Definition: apicp.h:161
#define APIC_NMI_VECTOR
Definition: apicp.h:52
@ APIC_MT_NMI
Definition: apicp.h:129
@ APIC_MT_ExtInt
Definition: apicp.h:132
#define APIC_SPURIOUS_VECTOR
Definition: apicp.h:40
#define APIC_ERROR_VECTOR
Definition: apicp.h:48
#define ApicLogicalId(Cpu)
Definition: apicp.h:117
VOID __cdecl ApicSpuriousService(VOID)
FORCEINLINE VOID ApicWrite(APIC_REGISTER Register, ULONG Value)
Definition: apicp.h:323
@ APIC_LINT1
Definition: apicp.h:100
@ APIC_EXT3LVTR
Definition: apicp.h:111
@ APIC_EXT1LVTR
Definition: apicp.h:109
@ APIC_VER
Definition: apicp.h:81
@ APIC_LDR
Definition: apicp.h:87
@ APIC_ERRLVTR
Definition: apicp.h:101
@ APIC_PCLVTR
Definition: apicp.h:98
@ APIC_EXT2LVTR
Definition: apicp.h:110
@ APIC_THRMLVTR
Definition: apicp.h:97
@ APIC_TMRLVTR
Definition: apicp.h:96
@ APIC_DFR
Definition: apicp.h:88
@ APIC_LINT0
Definition: apicp.h:99
@ APIC_SIVR
Definition: apicp.h:89
@ APIC_EXT0LVTR
Definition: apicp.h:108
@ APIC_TGM_Level
Definition: apicp.h:139
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:272
UINT32 MessageType
Definition: apicp.h:268
UINT32 TimerMode
Definition: apicp.h:275
UINT32 Long
Definition: apicp.h:264
UINT32 Vector
Definition: apicp.h:267
UINT32 Mask
Definition: apicp.h:274
UINT32 TriggerMode
Definition: apicp.h:273
UINT32 DeliveryStatus
Definition: apicp.h:270

Referenced by HalpInitProcessor().

◆ ApicLowerIrql()

FORCEINLINE VOID ApicLowerIrql ( KIRQL  Irql)

Definition at line 237 of file apic.c.

238{
240
241 /* Is the new Irql lower than set in the TPR? */
242 if (Irql < KeGetPcr()->IRR)
243 {
244 /* Save the new hard IRQL in the IRR field */
245 KeGetPcr()->IRR = Irql;
246
247 /* Need to lower it back */
249 }
250}
#define IrqlToTpr(Irql)
Definition: apicp.h:54
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:288
#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.Long0 = 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 the low dword to send the interrupt */
173
174 /* Wait until we see the interrupt request.
175 * It will stay in requested state until we re-enable interrupts.
176 */
177 while (!(ApicRead(Irr) & IrrBit))
178 {
179 NOTHING;
180 }
181
182 /* Finally, restore the original interrupt state */
184 {
185 _enable();
186 }
187}
#define EFLAGS_INTERRUPT_MASK
Definition: SystemCall.c:11
@ APIC_DSH_Self
Definition: apicp.h:153
@ APIC_ICR0
Definition: apicp.h:94
@ APIC_IRR
Definition: apicp.h:92
#define NOTHING
Definition: input_list.c:10
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:1674
_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 221 of file apic.c.

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

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 749 of file apic.c.

753{
754 KIRQL CurrentIrql;
755
756 /* Get the current IRQL */
757 CurrentIrql = ApicGetCurrentIrql();
758
759#ifdef APIC_LAZY_IRQL
760 /* Check if this interrupt is allowed */
761 if (CurrentIrql >= Irql)
762 {
764 UCHAR Index;
765
766 /* It is not, set the real Irql in the TPR! */
767 ApicWrite(APIC_TPR, IrqlToTpr(CurrentIrql));
768
769 /* Save the new hard IRQL in the IRR field */
770 KeGetPcr()->IRR = CurrentIrql;
771
772 /* End this interrupt */
773 ApicSendEOI();
774
775 /* Get the irq for this vector */
777
778 /* Check if it's valid */
779 if (Index < APIC_MAX_IRQ)
780 {
781 /* Read the I/O redirection entry */
783
784 /* Re-request the interrupt to be handled later */
786 }
787 else
788 {
789 /* This should be a reserved vector! */
791
792 /* Re-request the interrupt to be handled later */
794 }
795
796 /* Pretend it was a spurious interrupt */
797 return FALSE;
798 }
799#endif
800 /* Save the current IRQL */
801 *OldIrql = CurrentIrql;
802
803 /* Set the new IRQL */
805
806 /* Turn on interrupts */
807 _enable();
808
809 /* Success */
810 return TRUE;
811}
#define ApicRaiseIrql
Definition: apic.c:232
FORCEINLINE VOID ApicRequestSelfInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
Definition: apic.c:139
FORCEINLINE VOID ApicSendEOI(void)
Definition: apic.c:191
FORCEINLINE IOAPIC_REDIRECTION_REGISTER ApicReadIORedirectionEntry(UCHAR Index)
Definition: apic.c:125
FORCEINLINE KIRQL ApicGetCurrentIrql(VOID)
Definition: apic.c:206
#define APIC_RESERVED_VECTOR
Definition: apicp.h:61
#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 660 of file apic.c.

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

◆ HalDisableSystemInterrupt()

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

Definition at line 725 of file apic.c.

728{
730 UCHAR Index;
733
735
736 /* Read lower dword of redirection entry */
737 ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
738
739 /* Mask it */
740 ReDirReg.Mask = 1;
741
742 /* Write back lower dword */
743 IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
744}
#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 671 of file apic.c.

675{
677 PKPRCB Prcb = KeGetCurrentPrcb();
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 was unused */
696 if (ReDirReg.Vector != Vector)
697 {
698 ReDirReg.Vector = Vector;
701 ReDirReg.Destination = 0;
702 }
703
704 /* Check if the destination is logical */
705 if (ReDirReg.DestinationMode == APIC_DM_Logical)
706 {
707 /* Set the bit for this cpu */
708 ReDirReg.Destination |= ApicLogicalId(Prcb->Number);
709 }
710
711 /* Set the trigger mode */
712 ReDirReg.TriggerMode = 1 - InterruptMode;
713
714 /* Now unmask it */
715 ReDirReg.Mask = FALSE;
716
717 /* Write back the entry */
719
720 return TRUE;
721}
@ APIC_DM_Logical
Definition: apicp.h:146
@ APIC_MT_LowestPriority
Definition: apicp.h:126
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
USHORT Number
Definition: ketypes.h:643
_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 815 of file apic.c.

818{
819 /* Send an EOI */
820 ApicSendEOI();
821
822 /* Restore the old IRQL */
824}
FORCEINLINE VOID ApicLowerIrql(KIRQL Irql)
Definition: apic.c:237

Referenced by MpsTimerHandler().

◆ HalpAllocateSystemInterrupt()

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

Definition at line 368 of file apic.c.

371{
373
374 ASSERT(Irq < APIC_MAX_IRQ);
376
377 /* Setup a redirection entry */
378 ReDirReg.Vector = Vector;
381 ReDirReg.DeliveryStatus = 0;
382 ReDirReg.Polarity = 0;
383 ReDirReg.RemoteIRR = 0;
384 ReDirReg.TriggerMode = APIC_TGM_Edge;
385 ReDirReg.Mask = 1;
386 ReDirReg.Reserved = 0;
387 ReDirReg.Destination = 0;
388
389 /* Initialize entry */
390 ApicWriteIORedirectionEntry(Irq, ReDirReg);
391
392 /* Save irq in the table */
394
395 return Vector;
396}

Referenced by HalpGetRootInterruptVector().

◆ HalpApcInterruptHandler()

VOID DECLSPEC_NORETURN FASTCALL HalpApcInterruptHandler ( IN PKTRAP_FRAME  TrapFrame)

Definition at line 558 of file apic.c.

559{
560 KPROCESSOR_MODE ProcessorMode;
563
564 /* Enter trap */
565 KiEnterInterruptTrap(TrapFrame);
566
567#ifdef APIC_LAZY_IRQL
569 {
570 /* "Spurious" interrupt, exit the interrupt */
571 KiEoiHelper(TrapFrame);
572 }
573#else
574 /* Save the old IRQL */
577#endif
578
579 /* Raise to APC_LEVEL */
581
582 /* End the interrupt */
583 ApicSendEOI();
584
585 /* Kernel or user APC? */
586 if (KiUserTrap(TrapFrame)) ProcessorMode = UserMode;
587 else if (TrapFrame->EFlags & EFLAGS_V86_MASK) ProcessorMode = UserMode;
588 else ProcessorMode = KernelMode;
589
590 /* Enable interrupts and call the kernel's APC interrupt handler */
591 _enable();
592 KiDeliverApc(ProcessorMode, NULL, TrapFrame);
593
594 /* Disable interrupts */
595 _disable();
596
597 /* Restore the old IRQL */
599
600 /* Exit the interrupt */
601 KiEoiHelper(TrapFrame);
602}
BOOLEAN NTAPI HalBeginSystemInterrupt(IN KIRQL Irql, IN ULONG Vector, OUT PKIRQL OldIrql)
Definition: apic.c:749
FORCEINLINE KIRQL ApicGetProcessorIrql(VOID)
Definition: apic.c:198
#define APC_VECTOR
Definition: apicp.h:41
#define NULL
Definition: types.h:112
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define EFLAGS_V86_MASK
Definition: ketypes.h:193
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: ke.h:364
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 607 of file apic.c.

608{
611
612 /* Enter trap */
613 KiEnterInterruptTrap(TrapFrame);
614
615#ifdef APIC_LAZY_IRQL
617 {
618 /* "Spurious" interrupt, exit the interrupt */
619 KiEoiHelper(TrapFrame);
620 }
621#else
622 /* Get the current IRQL */
625#endif
626
627 /* Raise to DISPATCH_LEVEL */
629
630 /* End the interrupt */
631 ApicSendEOI();
632
633 /* Enable interrupts and call the kernel's DPC interrupt handler */
634 _enable();
636 _disable();
637
638 /* Restore the old IRQL */
640
641 /* Exit the interrupt */
642 KiEoiHelper(TrapFrame);
643}
#define DISPATCH_VECTOR
Definition: apicp.h:42
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 400 of file apic.c.

405{
407 KIRQL Irql;
408
409 /* Get the vector currently registered */
411
412 /* Check if it's used */
414 {
415 /* Calculate IRQL */
417 *OutIrql = HalpVectorToIrql(Vector);
418 }
419 else
420 {
422
423 /* Outer loop to find alternative slots, when all IRQLs are in use */
424 for (Offset = 0; Offset < 15; Offset++)
425 {
426 /* Loop allowed IRQL range */
427 for (Irql = CLOCK_LEVEL - 1; Irql >= CMCI_LEVEL; Irql--)
428 {
429 /* Calculate the vactor */
431
432 /* Check if the vector is free */
434 {
435 /* Found one, allocate the interrupt */
437 *OutIrql = Irql;
438 goto Exit;
439 }
440 }
441 }
442
443 DPRINT1("Failed to get an interrupt vector for IRQ %lu\n", BusInterruptLevel);
444 *OutAffinity = 0;
445 *OutIrql = 0;
446 return 0;
447 }
448
449Exit:
450
451 *OutAffinity = HalpDefaultInterruptAffinity;
453
454 return Vector;
455}
UCHAR FASTCALL HalpIrqToVector(UCHAR Irq)
Definition: apic.c:257
KIRQL FASTCALL HalpVectorToIrql(UCHAR Vector)
Definition: apic.c:270
UCHAR NTAPI HalpAllocateSystemInterrupt(_In_ UCHAR Irq, _In_ UCHAR Vector)
Definition: apic.c:368
UCHAR FASTCALL HalpVectorToIrq(UCHAR Vector)
Definition: apic.c:277
#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:3310

Referenced by HalGetInterruptVector(), and HalpGetSystemInterruptVector().

◆ HalpInitializePICs()

VOID NTAPI HalpInitializePICs ( IN BOOLEAN  EnableInterrupts)

Definition at line 513 of file apic.c.

514{
515 ULONG_PTR EFlags;
516
517 /* Save EFlags and disable interrupts */
518 EFlags = __readeflags();
519 _disable();
520
521 /* Initialize and mask the PIC */
523
524 /* Initialize the I/O APIC */
526
527 /* Manually reserve some vectors */
533
534 /* Set interrupt handlers in the IDT */
537#ifndef _M_AMD64
540#endif
541
542 /* Register the vectors for APC and dispatch interrupts */
545
546 /* Restore interrupt state */
548 __writeeflags(EFlags);
549}
VOID NTAPI ApicInitializeIOApic(VOID)
Definition: apic.c:459
#define CLOCK_IPI_VECTOR
Definition: apicp.h:46
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:1669
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by HalInitSystem().

◆ HalpIrqToVector()

UCHAR FASTCALL HalpIrqToVector ( UCHAR  Irq)

Definition at line 257 of file apic.c.

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

Referenced by HalpGetRootInterruptVector().

◆ HalpSendEOI()

VOID NTAPI HalpSendEOI ( VOID  )

Definition at line 284 of file apic.c.

285{
286 ApicSendEOI();
287}

◆ HalpVectorToIrq()

UCHAR FASTCALL HalpVectorToIrq ( UCHAR  Vector)

Definition at line 277 of file apic.c.

278{
280}

Referenced by HalpGetRootInterruptVector().

◆ HalpVectorToIrql()

KIRQL FASTCALL HalpVectorToIrql ( UCHAR  Vector)

Definition at line 270 of file apic.c.

271{
272 return TprToIrql(Vector);
273}

Referenced by HalpGetRootInterruptVector().

◆ HalRequestSoftwareInterrupt()

VOID FASTCALL HalRequestSoftwareInterrupt ( IN KIRQL  Irql)

Definition at line 652 of file apic.c.

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

◆ 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:282
#define IOAPIC_IOREGSEL
Definition: apicp.h:281
#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 831 of file apic.c.

832{
833 /* Read the current TPR and convert it to an IRQL */
834 return ApicGetCurrentIrql();
835}

◆ KeRaiseIrqlToDpcLevel()

KIRQL NTAPI KeRaiseIrqlToDpcLevel ( VOID  )

Definition at line 880 of file apic.c.

881{
883}
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: apic.c:856

◆ KeRaiseIrqlToSynchLevel()

KIRQL NTAPI KeRaiseIrqlToSynchLevel ( VOID  )

Definition at line 887 of file apic.c.

888{
889 return KfRaiseIrql(SYNCH_LEVEL);
890}
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704

◆ KfLowerIrql()

VOID FASTCALL KfLowerIrql ( IN KIRQL  OldIrql)

Definition at line 839 of file apic.c.

841{
842#if DBG
843 /* Validate correct lower */
845 {
846 /* Crash system */
847 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
848 }
849#endif
850 /* Set the new IRQL */
852}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430

◆ KfRaiseIrql()

KIRQL FASTCALL KfRaiseIrql ( IN KIRQL  NewIrql)

Definition at line 856 of file apic.c.

858{
860
861 /* Read the current IRQL */
863#if DBG
864 /* Validate correct raise */
865 if (OldIrql > NewIrql)
866 {
867 /* Crash system */
868 KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL);
869 }
870#endif
871 /* Convert the new IRQL to a TPR value and write the register */
873
874 /* Return old IRQL */
875 return OldIrql;
876}
_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.