Reactos

[HAL:APIC] Fix interrupt assignment

This is probably not how it is supposed to work, but the results are somewhat similar to what Windows has.

+139 -98
+4 -19
hal/halx86/acpi/busemul.c
··· 85 85 return TRUE; 86 86 } 87 87 88 - ULONG 89 - NTAPI 90 - HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber, 91 - IN ULONG BusInterruptLevel, 92 - IN ULONG BusInterruptVector, 93 - OUT PKIRQL Irql, 94 - OUT PKAFFINITY Affinity) 95 - { 96 - UCHAR Vector = IRQ2VECTOR((UCHAR)BusInterruptLevel); 97 - *Irql = VECTOR2IRQL(Vector); 98 - *Affinity = 0xFFFFFFFF; 99 - return Vector; 100 - } 101 - 102 88 BOOLEAN 103 89 NTAPI 104 90 HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress, ··· 254 240 OUT PKAFFINITY Affinity) 255 241 { 256 242 /* Call the system bus translator */ 257 - return HalpGetSystemInterruptVector_Acpi(BusNumber, 258 - BusInterruptLevel, 259 - BusInterruptVector, 260 - Irql, 261 - Affinity); 243 + return HalpGetRootInterruptVector(BusInterruptLevel, 244 + BusInterruptVector, 245 + Irql, 246 + Affinity); 262 247 } 263 248 264 249 /*
+70 -30
hal/halx86/apic/apic.c
··· 4 4 * FILE: hal/halx86/apic/apic.c 5 5 * PURPOSE: HAL APIC Management and Control Code 6 6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 7 - * REFERENCES: http://www.joseflores.com/docs/ExploringIrql.html 7 + * REFERENCES: https://web.archive.org/web/20190407074221/http://www.joseflores.com/docs/ExploringIrql.html 8 8 * http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx 9 9 * http://bbs.unixmap.net/thread-2022-1-1.html 10 + * https://www.codemachine.com/article_interruptdispatching.html 11 + * https://www.osronline.com/article.cfm%5Earticle=211.htm 10 12 */ 11 13 12 14 /* INCLUDES *******************************************************************/ ··· 17 19 #include <debug.h> 18 20 19 21 #ifndef _M_AMD64 20 - //#define APIC_LAZY_IRQL //FIXME: Disabled due to bug. 22 + #define APIC_LAZY_IRQL 21 23 #endif 22 24 23 25 /* GLOBALS ********************************************************************/ ··· 329 331 UCHAR 330 332 NTAPI 331 333 HalpAllocateSystemInterrupt( 332 - IN UCHAR Irq, 333 - IN KIRQL Irql) 334 + _In_ UCHAR Irq, 335 + _In_ UCHAR Vector) 334 336 { 335 337 IOAPIC_REDIRECTION_REGISTER ReDirReg; 336 - IN UCHAR Vector; 337 338 338 - /* Start with lowest vector */ 339 - Vector = IrqlToTpr(Irql) & 0xF0; 340 - 341 - /* Find an empty vector */ 342 - while (HalpVectorToIndex[Vector] != APIC_FREE_VECTOR) 343 - { 344 - Vector++; 345 - 346 - /* Check if we went over the edge */ 347 - if (TprToIrql(Vector) > Irql) 348 - { 349 - /* Nothing free, return failure */ 350 - return 0; 351 - } 352 - } 353 - 354 - /* Save irq in the table */ 355 - HalpVectorToIndex[Vector] = Irq; 339 + ASSERT(Irq < 24); 340 + ASSERT(HalpVectorToIndex[Vector] == APIC_FREE_VECTOR); 356 341 357 342 /* Setup a redirection entry */ 358 343 ReDirReg.Vector = Vector; ··· 369 354 /* Initialize entry */ 370 355 ApicWriteIORedirectionEntry(Irq, ReDirReg); 371 356 357 + /* Save irq in the table */ 358 + HalpVectorToIndex[Vector] = Irq; 359 + 360 + return Vector; 361 + } 362 + 363 + ULONG 364 + NTAPI 365 + HalpGetRootInterruptVector( 366 + _In_ ULONG BusInterruptLevel, 367 + _In_ ULONG BusInterruptVector, 368 + _Out_ PKIRQL OutIrql, 369 + _Out_ PKAFFINITY OutAffinity) 370 + { 371 + UCHAR Vector; 372 + KIRQL Irql; 373 + 374 + /* Get the vector currently registered */ 375 + Vector = HalpIrqToVector(BusInterruptLevel); 376 + 377 + /* Check if it's used */ 378 + if (Vector != 0xFF) 379 + { 380 + /* Calculate IRQL */ 381 + NT_ASSERT(HalpVectorToIndex[Vector] == BusInterruptLevel); 382 + *OutIrql = HalpVectorToIrql(Vector); 383 + } 384 + else 385 + { 386 + ULONG Offset; 387 + 388 + /* Outer loop to find alternative slots, when all IRQLs are in use */ 389 + for (Offset = 0; Offset < 15; Offset++) 390 + { 391 + /* Loop allowed IRQL range */ 392 + for (Irql = CLOCK_LEVEL - 1; Irql >= CMCI_LEVEL; Irql--) 393 + { 394 + /* Calculate the vactor */ 395 + Vector = IrqlToTpr(Irql) + Offset; 396 + 397 + /* Check if the vector is free */ 398 + if (HalpVectorToIrq(Vector) == APIC_FREE_VECTOR) 399 + { 400 + /* Found one, allocate the interrupt */ 401 + Vector = HalpAllocateSystemInterrupt(BusInterruptLevel, Vector); 402 + *OutIrql = Irql; 403 + goto Exit; 404 + } 405 + } 406 + } 407 + 408 + DPRINT1("Failed to get an interrupt vector for IRQ %lu\n", BusInterruptLevel); 409 + *OutAffinity = 0; 410 + *OutIrql = 0; 411 + return 0; 412 + } 413 + 414 + Exit: 415 + 416 + *OutAffinity = HalpDefaultInterruptAffinity; 417 + ASSERT(HalpDefaultInterruptAffinity); 418 + 372 419 return Vector; 373 420 } 374 421 ··· 414 461 for (Vector = 0; Vector <= 255; Vector++) 415 462 { 416 463 HalpVectorToIndex[Vector] = APIC_FREE_VECTOR; 417 - } 418 - 419 - // HACK: Allocate all IRQs, should rather do that on demand 420 - for (Index = 0; Index <= 15; Index++) 421 - { 422 - /* Map the IRQs to IRQLs like with the PIC */ 423 - HalpAllocateSystemInterrupt(Index, 27 - Index); 424 464 } 425 465 426 466 /* Enable the timer interrupt */
+31 -13
hal/halx86/apic/apicp.h
··· 11 11 #ifdef _M_AMD64 12 12 #define LOCAL_APIC_BASE 0xFFFFFFFFFFFE0000ULL 13 13 #define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL 14 - #define APIC_SPURIOUS_VECTOR 0x3f 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 + 15 31 #define IrqlToTpr(Irql) (Irql << 4) 16 32 #define IrqlToSoftVector(Irql) ((Irql << 4)|0xf) 17 33 #define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4)) ··· 19 35 #else 20 36 #define LOCAL_APIC_BASE 0xFFFE0000 21 37 #define IOAPIC_BASE 0xFFFE1000 38 + 39 + /* Vectors */ 22 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 + 23 53 #define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql]) 24 54 #define IrqlToSoftVector(Irql) IrqlToTpr(Irql) 25 55 #define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) ··· 42 72 #define IMCR_PIC_DIRECT 0x00 43 73 #define IMCR_PIC_VIA_APIC 0x01 44 74 45 - #define ZERO_VECTOR 0x00 // IRQL 00 46 - #define APC_VECTOR 0x3D // IRQL 01 47 - #define DISPATCH_VECTOR 0x41 // IRQL 02 48 - #define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 49 - #define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 50 - #define APIC_SYNCH_VECTOR 0xD1 // IRQL 28 51 - #define APIC_IPI_VECTOR 0xE1 // IRQL 29 52 - #define APIC_ERROR_VECTOR 0xE3 53 - #define POWERFAIL_VECTOR 0xEF // IRQL 30 54 - #define APIC_PROFILE_VECTOR 0xFD // IRQL 31 55 - #define APIC_PERF_VECTOR 0xFE 56 - #define APIC_NMI_VECTOR 0xFF 57 75 58 76 /* APIC Register Address Map */ 59 77 #define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
+5 -7
hal/halx86/include/bus.h
··· 400 400 401 401 ULONG 402 402 NTAPI 403 - HalpGetSystemInterruptVector_Acpi( 404 - ULONG BusNumber, 405 - ULONG BusInterruptLevel, 406 - ULONG BusInterruptVector, 407 - PKIRQL Irql, 408 - PKAFFINITY Affinity 409 - ); 403 + HalpGetRootInterruptVector( 404 + _In_ ULONG BusInterruptLevel, 405 + _In_ ULONG BusInterruptVector, 406 + _Out_ PKIRQL Irql, 407 + _Out_ PKAFFINITY Affinity); 410 408 411 409 ULONG 412 410 NTAPI
-29
hal/halx86/legacy/bus/sysbus.c
··· 112 112 113 113 ULONG 114 114 NTAPI 115 - HalpGetRootInterruptVector(IN ULONG BusInterruptLevel, 116 - IN ULONG BusInterruptVector, 117 - OUT PKIRQL Irql, 118 - OUT PKAFFINITY Affinity) 119 - { 120 - UCHAR SystemVector; 121 - 122 - /* Validate the IRQ */ 123 - if (BusInterruptLevel > 23) 124 - { 125 - /* Invalid vector */ 126 - DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel); 127 - return 0; 128 - } 129 - 130 - /* Get the system vector */ 131 - SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel); 132 - 133 - /* Return the IRQL and affinity */ 134 - *Irql = HalpVectorToIrql(SystemVector); 135 - *Affinity = HalpDefaultInterruptAffinity; 136 - ASSERT(HalpDefaultInterruptAffinity); 137 - 138 - /* Return the vector */ 139 - return SystemVector; 140 - } 141 - 142 - ULONG 143 - NTAPI 144 115 HalpGetSystemInterruptVector(IN PBUS_HANDLER BusHandler, 145 116 IN PBUS_HANDLER RootHandler, 146 117 IN ULONG BusInterruptLevel,
+29
hal/halx86/pic/pic.c
··· 1233 1233 return NULL; 1234 1234 } 1235 1235 1236 + ULONG 1237 + NTAPI 1238 + HalpGetRootInterruptVector(IN ULONG BusInterruptLevel, 1239 + IN ULONG BusInterruptVector, 1240 + OUT PKIRQL Irql, 1241 + OUT PKAFFINITY Affinity) 1242 + { 1243 + UCHAR SystemVector; 1244 + 1245 + /* Validate the IRQ */ 1246 + if (BusInterruptLevel > 23) 1247 + { 1248 + /* Invalid vector */ 1249 + DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel); 1250 + return 0; 1251 + } 1252 + 1253 + /* Get the system vector */ 1254 + SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel); 1255 + 1256 + /* Return the IRQL and affinity */ 1257 + *Irql = HalpVectorToIrql(SystemVector); 1258 + *Affinity = HalpDefaultInterruptAffinity; 1259 + ASSERT(HalpDefaultInterruptAffinity); 1260 + 1261 + /* Return the vector */ 1262 + return SystemVector; 1263 + } 1264 + 1236 1265 #else /* _MINIHAL_ */ 1237 1266 1238 1267 KIRQL