[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.
This commit is contained in:
Timo Kreuzer 2021-06-05 15:41:49 +02:00
parent 235d7472ba
commit 64e52088d1
6 changed files with 139 additions and 98 deletions

View file

@ -85,20 +85,6 @@ HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
return TRUE;
}
ULONG
NTAPI
HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity)
{
UCHAR Vector = IRQ2VECTOR((UCHAR)BusInterruptLevel);
*Irql = VECTOR2IRQL(Vector);
*Affinity = 0xFFFFFFFF;
return Vector;
}
BOOLEAN
NTAPI
HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
@ -254,11 +240,10 @@ HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
OUT PKAFFINITY Affinity)
{
/* Call the system bus translator */
return HalpGetSystemInterruptVector_Acpi(BusNumber,
BusInterruptLevel,
BusInterruptVector,
Irql,
Affinity);
return HalpGetRootInterruptVector(BusInterruptLevel,
BusInterruptVector,
Irql,
Affinity);
}
/*

View file

@ -4,9 +4,11 @@
* FILE: hal/halx86/apic/apic.c
* PURPOSE: HAL APIC Management and Control Code
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
* REFERENCES: http://www.joseflores.com/docs/ExploringIrql.html
* REFERENCES: https://web.archive.org/web/20190407074221/http://www.joseflores.com/docs/ExploringIrql.html
* http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx
* http://bbs.unixmap.net/thread-2022-1-1.html
* https://www.codemachine.com/article_interruptdispatching.html
* https://www.osronline.com/article.cfm%5Earticle=211.htm
*/
/* INCLUDES *******************************************************************/
@ -17,7 +19,7 @@
#include <debug.h>
#ifndef _M_AMD64
//#define APIC_LAZY_IRQL //FIXME: Disabled due to bug.
#define APIC_LAZY_IRQL
#endif
/* GLOBALS ********************************************************************/
@ -329,30 +331,13 @@ ApicInitializeLocalApic(ULONG Cpu)
UCHAR
NTAPI
HalpAllocateSystemInterrupt(
IN UCHAR Irq,
IN KIRQL Irql)
_In_ UCHAR Irq,
_In_ UCHAR Vector)
{
IOAPIC_REDIRECTION_REGISTER ReDirReg;
IN UCHAR Vector;
/* Start with lowest vector */
Vector = IrqlToTpr(Irql) & 0xF0;
/* Find an empty vector */
while (HalpVectorToIndex[Vector] != APIC_FREE_VECTOR)
{
Vector++;
/* Check if we went over the edge */
if (TprToIrql(Vector) > Irql)
{
/* Nothing free, return failure */
return 0;
}
}
/* Save irq in the table */
HalpVectorToIndex[Vector] = Irq;
ASSERT(Irq < 24);
ASSERT(HalpVectorToIndex[Vector] == APIC_FREE_VECTOR);
/* Setup a redirection entry */
ReDirReg.Vector = Vector;
@ -369,6 +354,68 @@ HalpAllocateSystemInterrupt(
/* Initialize entry */
ApicWriteIORedirectionEntry(Irq, ReDirReg);
/* Save irq in the table */
HalpVectorToIndex[Vector] = Irq;
return Vector;
}
ULONG
NTAPI
HalpGetRootInterruptVector(
_In_ ULONG BusInterruptLevel,
_In_ ULONG BusInterruptVector,
_Out_ PKIRQL OutIrql,
_Out_ PKAFFINITY OutAffinity)
{
UCHAR Vector;
KIRQL Irql;
/* Get the vector currently registered */
Vector = HalpIrqToVector(BusInterruptLevel);
/* Check if it's used */
if (Vector != 0xFF)
{
/* Calculate IRQL */
NT_ASSERT(HalpVectorToIndex[Vector] == BusInterruptLevel);
*OutIrql = HalpVectorToIrql(Vector);
}
else
{
ULONG Offset;
/* Outer loop to find alternative slots, when all IRQLs are in use */
for (Offset = 0; Offset < 15; Offset++)
{
/* Loop allowed IRQL range */
for (Irql = CLOCK_LEVEL - 1; Irql >= CMCI_LEVEL; Irql--)
{
/* Calculate the vactor */
Vector = IrqlToTpr(Irql) + Offset;
/* Check if the vector is free */
if (HalpVectorToIrq(Vector) == APIC_FREE_VECTOR)
{
/* Found one, allocate the interrupt */
Vector = HalpAllocateSystemInterrupt(BusInterruptLevel, Vector);
*OutIrql = Irql;
goto Exit;
}
}
}
DPRINT1("Failed to get an interrupt vector for IRQ %lu\n", BusInterruptLevel);
*OutAffinity = 0;
*OutIrql = 0;
return 0;
}
Exit:
*OutAffinity = HalpDefaultInterruptAffinity;
ASSERT(HalpDefaultInterruptAffinity);
return Vector;
}
@ -416,13 +463,6 @@ ApicInitializeIOApic(VOID)
HalpVectorToIndex[Vector] = APIC_FREE_VECTOR;
}
// HACK: Allocate all IRQs, should rather do that on demand
for (Index = 0; Index <= 15; Index++)
{
/* Map the IRQs to IRQLs like with the PIC */
HalpAllocateSystemInterrupt(Index, 27 - Index);
}
/* Enable the timer interrupt */
ReDirReg.Vector = APIC_CLOCK_VECTOR;
ReDirReg.DeliveryMode = APIC_MT_Fixed;

View file

@ -11,7 +11,23 @@
#ifdef _M_AMD64
#define LOCAL_APIC_BASE 0xFFFFFFFFFFFE0000ULL
#define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL
#define APIC_SPURIOUS_VECTOR 0x3f
/* Vectors */
#define APC_VECTOR 0x1F // IRQL 01 (APC_LEVEL) - KiApcInterrupt
#define DISPATCH_VECTOR 0x2F // IRQL 02 (DISPATCH_LEVEL) - KiDpcInterrupt
#define CMCI_VECTOR 0x35 // IRQL 05 (CMCI_LEVEL) - HalpInterruptCmciService
#define APIC_CLOCK_VECTOR 0xD1 // IRQL 13 (CLOCK_LEVEL), IRQ 8 - HalpTimerClockInterrupt
#define CLOCK_IPI_VECTOR 0xD2 // IRQL 13 (CLOCK_LEVEL) - HalpTimerClockIpiRoutine
#define REBOOT_VECTOR 0xD7 // IRQL 15 (PROFILE_LEVEL) - HalpInterruptRebootService
#define STUB_VECTOR 0xD8 // IRQL 15 (PROFILE_LEVEL) - HalpInterruptStubService
#define APIC_SPURIOUS_VECTOR 0xDF // IRQL 13 (CLOCK_LEVEL) - HalpInterruptSpuriousService
#define APIC_IPI_VECTOR 0xE1 // IRQL 14 (IPI_LEVEL) - KiIpiInterrupt
#define APIC_ERROR_VECTOR 0xE2 // IRQL 14 (IPI_LEVEL) - HalpInterruptLocalErrorService
#define POWERFAIL_VECTOR 0xE3 // IRQL 14 (POWER_LEVEL) : HalpInterruptDeferredRecoveryService
#define APIC_PROFILE_VECTOR 0xFD // IRQL 15 (PROFILE_LEVEL) - HalpTimerProfileInterrupt
#define APIC_PERF_VECTOR 0xFE // IRQL 15 (PROFILE_LEVEL) - HalpPerfInterrupt
#define APIC_NMI_VECTOR 0xFF
#define IrqlToTpr(Irql) (Irql << 4)
#define IrqlToSoftVector(Irql) ((Irql << 4)|0xf)
#define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4))
@ -19,7 +35,21 @@
#else
#define LOCAL_APIC_BASE 0xFFFE0000
#define IOAPIC_BASE 0xFFFE1000
/* Vectors */
#define APIC_SPURIOUS_VECTOR 0x1f
#define APC_VECTOR 0x3D // IRQL 01
#define DISPATCH_VECTOR 0x41 // IRQL 02
#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27
#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28
#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28
#define APIC_IPI_VECTOR 0xE1 // IRQL 29
#define APIC_ERROR_VECTOR 0xE3
#define POWERFAIL_VECTOR 0xEF // IRQL 30
#define APIC_PROFILE_VECTOR 0xFD // IRQL 31
#define APIC_PERF_VECTOR 0xFE
#define APIC_NMI_VECTOR 0xFF
#define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql])
#define IrqlToSoftVector(Irql) IrqlToTpr(Irql)
#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4])
@ -42,18 +72,6 @@
#define IMCR_PIC_DIRECT 0x00
#define IMCR_PIC_VIA_APIC 0x01
#define ZERO_VECTOR 0x00 // IRQL 00
#define APC_VECTOR 0x3D // IRQL 01
#define DISPATCH_VECTOR 0x41 // IRQL 02
#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27
#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28
#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28
#define APIC_IPI_VECTOR 0xE1 // IRQL 29
#define APIC_ERROR_VECTOR 0xE3
#define POWERFAIL_VECTOR 0xEF // IRQL 30
#define APIC_PROFILE_VECTOR 0xFD // IRQL 31
#define APIC_PERF_VECTOR 0xFE
#define APIC_NMI_VECTOR 0xFF
/* APIC Register Address Map */
#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */

View file

@ -400,13 +400,11 @@ HalpAssignPCISlotResources(
ULONG
NTAPI
HalpGetSystemInterruptVector_Acpi(
ULONG BusNumber,
ULONG BusInterruptLevel,
ULONG BusInterruptVector,
PKIRQL Irql,
PKAFFINITY Affinity
);
HalpGetRootInterruptVector(
_In_ ULONG BusInterruptLevel,
_In_ ULONG BusInterruptVector,
_Out_ PKIRQL Irql,
_Out_ PKAFFINITY Affinity);
ULONG
NTAPI

View file

@ -110,35 +110,6 @@ HalpTranslateSystemBusAddress(IN PBUS_HANDLER BusHandler,
return FALSE;
}
ULONG
NTAPI
HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity)
{
UCHAR SystemVector;
/* Validate the IRQ */
if (BusInterruptLevel > 23)
{
/* Invalid vector */
DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel);
return 0;
}
/* Get the system vector */
SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel);
/* Return the IRQL and affinity */
*Irql = HalpVectorToIrql(SystemVector);
*Affinity = HalpDefaultInterruptAffinity;
ASSERT(HalpDefaultInterruptAffinity);
/* Return the vector */
return SystemVector;
}
ULONG
NTAPI
HalpGetSystemInterruptVector(IN PBUS_HANDLER BusHandler,

View file

@ -1233,6 +1233,35 @@ HalpDispatchInterrupt2(VOID)
return NULL;
}
ULONG
NTAPI
HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity)
{
UCHAR SystemVector;
/* Validate the IRQ */
if (BusInterruptLevel > 23)
{
/* Invalid vector */
DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel);
return 0;
}
/* Get the system vector */
SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel);
/* Return the IRQL and affinity */
*Irql = HalpVectorToIrql(SystemVector);
*Affinity = HalpDefaultInterruptAffinity;
ASSERT(HalpDefaultInterruptAffinity);
/* Return the vector */
return SystemVector;
}
#else /* _MINIHAL_ */
KIRQL