1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Header file for APIC hal 5 * COPYRIGHT: Copyright 2011 Timo Kreuzer <timo.kreuzer@reactos.org> 6 * Copyright 2021 Justin Miller <justinmiller100@gmail.com> 7 */ 8 9 #pragma once 10 11 #ifdef _M_AMD64 12 #define LOCAL_APIC_BASE 0xFFFFFFFFFFFE0000ULL 13 #define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL 14 15 /* Vectors */ 16 #define APC_VECTOR 0x1F // IRQL 01 (APC_LEVEL) - KiApcInterrupt 17 #define DISPATCH_VECTOR 0x2F // IRQL 02 (DISPATCH_LEVEL) - KiDpcInterrupt 18 #define CMCI_VECTOR 0x35 // IRQL 05 (CMCI_LEVEL) - HalpInterruptCmciService 19 #define APIC_CLOCK_VECTOR 0xD1 // IRQL 13 (CLOCK_LEVEL), IRQ 8 - HalpTimerClockInterrupt 20 #define CLOCK_IPI_VECTOR 0xD2 // IRQL 13 (CLOCK_LEVEL) - HalpTimerClockIpiRoutine 21 #define REBOOT_VECTOR 0xD7 // IRQL 15 (PROFILE_LEVEL) - HalpInterruptRebootService 22 #define STUB_VECTOR 0xD8 // IRQL 15 (PROFILE_LEVEL) - HalpInterruptStubService 23 #define APIC_SPURIOUS_VECTOR 0xDF // IRQL 13 (CLOCK_LEVEL) - HalpInterruptSpuriousService 24 #define APIC_IPI_VECTOR 0xE1 // IRQL 14 (IPI_LEVEL) - KiIpiInterrupt 25 #define APIC_ERROR_VECTOR 0xE2 // IRQL 14 (IPI_LEVEL) - HalpInterruptLocalErrorService 26 #define POWERFAIL_VECTOR 0xE3 // IRQL 14 (POWER_LEVEL) : HalpInterruptDeferredRecoveryService 27 #define APIC_PROFILE_VECTOR 0xFD // IRQL 15 (PROFILE_LEVEL) - HalpTimerProfileInterrupt 28 #define APIC_PERF_VECTOR 0xFE // IRQL 15 (PROFILE_LEVEL) - HalpPerfInterrupt 29 #define APIC_NMI_VECTOR 0xFF 30 31 #define IrqlToTpr(Irql) (Irql << 4) 32 #define IrqlToSoftVector(Irql) ((Irql << 4)|0xf) 33 #define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4)) 34 #define CLOCK2_LEVEL CLOCK_LEVEL 35 #else 36 #define LOCAL_APIC_BASE 0xFFFE0000 37 #define IOAPIC_BASE 0xFFFE1000 38 39 /* Vectors */ 40 #define APIC_SPURIOUS_VECTOR 0x1f 41 #define APC_VECTOR 0x3D // IRQL 01 42 #define DISPATCH_VECTOR 0x41 // IRQL 02 43 #define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 44 #define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 45 #define APIC_SYNCH_VECTOR 0xD1 // IRQL 28 46 #define APIC_IPI_VECTOR 0xE1 // IRQL 29 47 #define APIC_ERROR_VECTOR 0xE3 48 #define POWERFAIL_VECTOR 0xEF // IRQL 30 49 #define APIC_PROFILE_VECTOR 0xFD // IRQL 31 50 #define APIC_PERF_VECTOR 0xFE 51 #define APIC_NMI_VECTOR 0xFF 52 53 #define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql]) 54 #define IrqlToSoftVector(Irql) IrqlToTpr(Irql) 55 #define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) 56 #endif 57 58 #define APIC_MAX_IRQ 24 59 #define APIC_FREE_VECTOR 0xFF 60 #define APIC_RESERVED_VECTOR 0xFE 61 62 /* The IMCR is supported by two read/writable or write-only I/O ports, 63 22h and 23h, which receive address and data respectively. 64 To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR. 65 Then write the data to I/O port 23h. The power-on default value is zero, 66 which connects the NMI and 8259 INTR lines directly to the BSP. 67 Writing a value of 01h forces the NMI and 8259 INTR signals to pass through the APIC. 68 */ 69 #define IMCR_ADDRESS_PORT (PUCHAR)0x0022 70 #define IMCR_DATA_PORT (PUCHAR)0x0023 71 #define IMCR_SELECT 0x70 72 #define IMCR_PIC_DIRECT 0x00 73 #define IMCR_PIC_VIA_APIC 0x01 74 75 76 /* APIC Register Address Map */ 77 typedef enum _APIC_REGISTER 78 { 79 APIC_ID = 0x0020, /* Local APIC ID Register (R/W) */ 80 APIC_VER = 0x0030, /* Local APIC Version Register (R) */ 81 APIC_TPR = 0x0080, /* Task Priority Register (R/W) */ 82 APIC_APR = 0x0090, /* Arbitration Priority Register (R) */ 83 APIC_PPR = 0x00A0, /* Processor Priority Register (R) */ 84 APIC_EOI = 0x00B0, /* EOI Register (W) */ 85 APIC_RRR = 0x00C0, /* Remote Read Register () */ 86 APIC_LDR = 0x00D0, /* Logical Destination Register (R/W) */ 87 APIC_DFR = 0x00E0, /* Destination Format Register (0-27 R, 28-31 R/W) */ 88 APIC_SIVR = 0x00F0, /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */ 89 APIC_ISR = 0x0100, /* Interrupt Service Register 0-255 (R) */ 90 APIC_TMR = 0x0180, /* Trigger Mode Register 0-255 (R) */ 91 APIC_IRR = 0x0200, /* Interrupt Request Register 0-255 (r) */ 92 APIC_ESR = 0x0280, /* Error Status Register (R) */ 93 APIC_ICR0 = 0x0300, /* Interrupt Command Register 0-31 (R/W) */ 94 APIC_ICR1 = 0x0310, /* Interrupt Command Register 32-63 (R/W) */ 95 APIC_TMRLVTR = 0x0320, /* Timer Local Vector Table (R/W) */ 96 APIC_THRMLVTR = 0x0330, /* Thermal Local Vector Table */ 97 APIC_PCLVTR = 0x0340, /* Performance Counter Local Vector Table (R/W) */ 98 APIC_LINT0 = 0x0350, /* LINT0 Local Vector Table (R/W) */ 99 APIC_LINT1 = 0x0360, /* LINT1 Local Vector Table (R/W) */ 100 APIC_ERRLVTR = 0x0370, /* Error Local Vector Table (R/W) */ 101 APIC_TICR = 0x0380, /* Initial Count Register for Timer (R/W) */ 102 APIC_TCCR = 0x0390, /* Current Count Register for Timer (R) */ 103 APIC_TDCR = 0x03E0, /* Timer Divide Configuration Register (R/W) */ 104 APIC_EAFR = 0x0400, /* extended APIC Feature register (R/W) */ 105 APIC_EACR = 0x0410, /* Extended APIC Control Register (R/W) */ 106 APIC_SEOI = 0x0420, /* Specific End Of Interrupt Register (W) */ 107 APIC_EXT0LVTR = 0x0500, /* Extended Interrupt 0 Local Vector Table */ 108 APIC_EXT1LVTR = 0x0510, /* Extended Interrupt 1 Local Vector Table */ 109 APIC_EXT2LVTR = 0x0520, /* Extended Interrupt 2 Local Vector Table */ 110 APIC_EXT3LVTR = 0x0530 /* Extended Interrupt 3 Local Vector Table */ 111 } APIC_REGISTER; 112 113 #define MSR_APIC_BASE 0x0000001B 114 #define IOAPIC_PHYS_BASE 0xFEC00000 115 #define APIC_CLOCK_INDEX 8 116 #define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu)) 117 118 /* The following definitions are based on AMD documentation. 119 They differ slightly in Intel documentation. */ 120 121 /* Message Type (Intel: "Delivery Mode") */ 122 typedef enum _APIC_MT 123 { 124 APIC_MT_Fixed = 0, 125 APIC_MT_LowestPriority = 1, 126 APIC_MT_SMI = 2, 127 APIC_MT_RemoteRead = 3, 128 APIC_MT_NMI = 4, 129 APIC_MT_INIT = 5, 130 APIC_MT_Startup = 6, 131 APIC_MT_ExtInt = 7, 132 } APIC_MT; 133 134 /* Trigger Mode */ 135 typedef enum _APIC_TGM 136 { 137 APIC_TGM_Edge, 138 APIC_TGM_Level 139 } APIC_TGM; 140 141 /* Destination Mode */ 142 typedef enum _APIC_DM 143 { 144 APIC_DM_Physical, 145 APIC_DM_Logical 146 } APIC_DM; 147 148 /* Destination Short Hand */ 149 typedef enum _APIC_DSH 150 { 151 APIC_DSH_Destination, 152 APIC_DSH_Self, 153 APIC_DSH_AllIncludingSelf, 154 APIC_DSH_AllExclusingSelf 155 } APIC_DSH; 156 157 /* Write Constants */ 158 typedef enum _APIC_DF 159 { 160 APIC_DF_Flat = 0xFFFFFFFF, 161 APIC_DF_Cluster = 0x0FFFFFFF 162 } APIC_DF; 163 164 /* Remote Read Status */ 165 typedef enum _APIC_RRS 166 { 167 APIC_RRS_Invalid = 0, 168 APIC_RRS_Pending = 1, 169 APIC_RRS_Done = 2 170 } APIC_RRS; 171 172 /* Timer Constants */ 173 enum _TIMER_DV 174 { 175 TIMER_DV_DivideBy2 = 0, 176 TIMER_DV_DivideBy4 = 1, 177 TIMER_DV_DivideBy8 = 2, 178 TIMER_DV_DivideBy16 = 3, 179 TIMER_DV_DivideBy32 = 8, 180 TIMER_DV_DivideBy64 = 9, 181 TIMER_DV_DivideBy128 = 10, 182 TIMER_DV_DivideBy1 = 11, 183 } TIMER_DV; 184 185 #include <pshpack1.h> 186 typedef union _APIC_BASE_ADRESS_REGISTER 187 { 188 UINT64 LongLong; 189 struct 190 { 191 UINT64 Reserved1:8; 192 UINT64 BootStrapCPUCore:1; 193 UINT64 Reserved2:2; 194 UINT64 Enable:1; 195 UINT64 BaseAddress:40; 196 UINT64 ReservedMBZ:12; 197 }; 198 } APIC_BASE_ADRESS_REGISTER; 199 200 typedef union _APIC_SPURIOUS_INERRUPT_REGISTER 201 { 202 UINT32 Long; 203 struct 204 { 205 UINT32 Vector:8; 206 UINT32 SoftwareEnable:1; 207 UINT32 FocusCPUCoreChecking:1; 208 UINT32 ReservedMBZ:22; 209 }; 210 } APIC_SPURIOUS_INERRUPT_REGISTER; 211 212 typedef union _APIC_VERSION_REGISTER 213 { 214 UINT32 Long; 215 struct 216 { 217 UINT32 Version:8; 218 UINT32 ReservedMBZ:8; 219 UINT32 MaxLVT:8; 220 UINT32 ReservedMBZ1:7; 221 UINT32 ExtRegSpacePresent:1; 222 }; 223 } APIC_VERSION_REGISTER; 224 225 typedef union _APIC_EXTENDED_CONTROL_REGISTER 226 { 227 UINT32 Long; 228 struct 229 { 230 UINT32 Version:1; 231 UINT32 SEOIEnable:1; 232 UINT32 ExtApicIdEnable:1; 233 UINT32 ReservedMBZ:29; 234 }; 235 } APIC_EXTENDED_CONTROL_REGISTER; 236 237 typedef union _APIC_INTERRUPT_COMMAND_REGISTER 238 { 239 UINT64 LongLong; 240 struct 241 { 242 UINT32 Long0; 243 UINT32 Long1; 244 }; 245 struct 246 { 247 UINT64 Vector:8; 248 UINT64 MessageType:3; 249 UINT64 DestinationMode:1; 250 UINT64 DeliveryStatus:1; 251 UINT64 ReservedMBZ:1; 252 UINT64 Level:1; 253 UINT64 TriggerMode:1; 254 UINT64 RemoteReadStatus:2; /* Intel: Reserved */ 255 UINT64 DestinationShortHand:2; 256 UINT64 Reserved2MBZ:36; 257 UINT64 Destination:8; 258 }; 259 } APIC_INTERRUPT_COMMAND_REGISTER; 260 261 typedef union _LVT_REGISTER 262 { 263 UINT32 Long; 264 struct 265 { 266 UINT32 Vector:8; 267 UINT32 MessageType:3; 268 UINT32 ReservedMBZ:1; 269 UINT32 DeliveryStatus:1; 270 UINT32 Reserved1MBZ:1; 271 UINT32 RemoteIRR:1; 272 UINT32 TriggerMode:1; 273 UINT32 Mask:1; 274 UINT32 TimerMode:1; 275 UINT32 Reserved2MBZ:13; 276 }; 277 } LVT_REGISTER; 278 279 /* IOAPIC offsets */ 280 enum 281 { 282 IOAPIC_IOREGSEL = 0x00, 283 IOAPIC_IOWIN = 0x10 284 }; 285 286 /* IOAPIC Constants */ 287 enum 288 { 289 IOAPIC_ID = 0x00, 290 IOAPIC_VER = 0x01, 291 IOAPIC_ARB = 0x02, 292 IOAPIC_REDTBL = 0x10 293 }; 294 295 typedef union _IOAPIC_REDIRECTION_REGISTER 296 { 297 UINT64 LongLong; 298 struct 299 { 300 UINT32 Long0; 301 UINT32 Long1; 302 }; 303 struct 304 { 305 UINT64 Vector:8; 306 UINT64 DeliveryMode:3; 307 UINT64 DestinationMode:1; 308 UINT64 DeliveryStatus:1; 309 UINT64 Polarity:1; 310 UINT64 RemoteIRR:1; 311 UINT64 TriggerMode:1; 312 UINT64 Mask:1; 313 UINT64 Reserved:39; 314 UINT64 Destination:8; 315 }; 316 } IOAPIC_REDIRECTION_REGISTER; 317 #include <poppack.h> 318 319 FORCEINLINE 320 ULONG 321 ApicRead(APIC_REGISTER Register) 322 { 323 return READ_REGISTER_ULONG((PULONG)(APIC_BASE + Register)); 324 } 325 326 FORCEINLINE 327 VOID 328 ApicWrite(APIC_REGISTER Register, ULONG Value) 329 { 330 WRITE_REGISTER_ULONG((PULONG)(APIC_BASE + Register), Value); 331 } 332 333 VOID 334 NTAPI 335 ApicInitializeTimer(ULONG Cpu); 336 337 VOID 338 NTAPI 339 HalInitializeProfiling(VOID); 340 341 VOID 342 NTAPI 343 HalpInitApicInfo(IN PLOADER_PARAMETER_BLOCK KeLoaderBlock); 344 345 VOID __cdecl ApicSpuriousService(VOID); 346