Refactor APIC IPI dispatching
All checks were successful
All checks were successful
This commit is contained in:
@@ -828,7 +828,7 @@ HL::Pic::SendBroadcastIpi(IN ULONG Vector,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Dispatch the IPI to the target processor */
|
/* Dispatch the IPI to the target processor */
|
||||||
SendIpi(TargetProcessorBlock->HardwareId, Vector);
|
SendIpi(TargetProcessorBlock->HardwareId, Vector, APIC_DM_FIXED, APIC_DSH_Destination, APIC_TGM_EDGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,6 +865,15 @@ HL::Pic::SendEoi(VOID)
|
|||||||
* @param Vector
|
* @param Vector
|
||||||
* Supplies the IPI vector to send.
|
* Supplies the IPI vector to send.
|
||||||
*
|
*
|
||||||
|
* @param DeliveryMode
|
||||||
|
* Supplies the delivery mode for the IPI.
|
||||||
|
*
|
||||||
|
* @param DestinationShorthand
|
||||||
|
* Supplies the shorthand.
|
||||||
|
*
|
||||||
|
* @param TriggerMode
|
||||||
|
* Supplies the trigger mode (Edge or Level).
|
||||||
|
*
|
||||||
* @return This routine does not return any value.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
@@ -872,19 +881,85 @@ HL::Pic::SendEoi(VOID)
|
|||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
VOID
|
||||||
HL::Pic::SendIpi(IN ULONG ApicId,
|
HL::Pic::SendIpi(IN ULONG ApicId,
|
||||||
IN ULONG Vector)
|
IN ULONG Vector,
|
||||||
|
IN APIC_DM DeliveryMode,
|
||||||
|
IN APIC_DSH DestinationShortHand,
|
||||||
|
IN ULONG TriggerMode)
|
||||||
{
|
{
|
||||||
|
APIC_COMMAND_REGISTER Register;
|
||||||
|
BOOLEAN Interrupts;
|
||||||
|
|
||||||
|
/* Check whether interrupts are enabled */
|
||||||
|
Interrupts = AR::CpuFunc::InterruptsEnabled();
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
AR::CpuFunc::ClearInterruptFlag();
|
||||||
|
|
||||||
|
/* Check current APIC mode and destination */
|
||||||
|
if(ApicMode == APIC_MODE_X2APIC && DestinationShortHand == APIC_DSH_Self)
|
||||||
|
{
|
||||||
|
/* In x2APIC mode, a dedicated Self-IPI register is used */
|
||||||
|
WriteApicRegister(APIC_SIPI, Vector);
|
||||||
|
|
||||||
|
/* Check whether interrupts need to be re-enabled */
|
||||||
|
if(Interrupts)
|
||||||
|
{
|
||||||
|
/* Check whether interrupts need to be re-enabled */
|
||||||
|
AR::CpuFunc::SetInterruptFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing more to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare APIC command register struct */
|
||||||
|
Register.LongLong = 0;
|
||||||
|
Register.DeliveryMode = DeliveryMode;
|
||||||
|
Register.Destination = ApicId;
|
||||||
|
Register.DestinationShortHand = DestinationShortHand;
|
||||||
|
Register.Level = 1;
|
||||||
|
Register.TriggerMode = TriggerMode;
|
||||||
|
Register.Vector = Vector;
|
||||||
|
|
||||||
/* Check current APIC mode */
|
/* Check current APIC mode */
|
||||||
if(ApicMode == APIC_MODE_X2APIC)
|
if(ApicMode == APIC_MODE_X2APIC)
|
||||||
{
|
{
|
||||||
|
/* Set destination APIC ID */
|
||||||
|
Register.Long1 = ApicId;
|
||||||
|
|
||||||
/* Send IPI using x2APIC mode */
|
/* Send IPI using x2APIC mode */
|
||||||
WriteApicRegister(APIC_ICR0, ((ULONGLONG)ApicId << 32) | Vector);
|
WriteApicRegister(APIC_ICR0, Register.LongLong);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Send IPI using xAPIC compatibility mode */
|
/* Wait for the APIC to clear the delivery status */
|
||||||
WriteApicRegister(APIC_ICR1, ApicId << 24);
|
while((ReadApicRegister(APIC_ICR0) & 0x1000) != 0)
|
||||||
WriteApicRegister(APIC_ICR0, Vector);
|
{
|
||||||
|
/* Yield the processor */
|
||||||
|
AR::CpuFunc::YieldProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In xAPIC compatibility mode, write the command to the ICR registers */
|
||||||
|
WriteApicRegister(APIC_ICR1, Register.Long1);
|
||||||
|
WriteApicRegister(APIC_ICR0, Register.Long0);
|
||||||
|
|
||||||
|
/* Check if this is a Self-IPI */
|
||||||
|
if(DestinationShortHand == APIC_DSH_Self)
|
||||||
|
{
|
||||||
|
/* Wait until the interrupt physically arrives in the requested state */
|
||||||
|
while((ReadApicRegister((APIC_REGISTER)(APIC_IRR + (Vector / 32))) & (1UL << (Vector % 32))) == 0)
|
||||||
|
{
|
||||||
|
/* Yield the processor */
|
||||||
|
AR::CpuFunc::YieldProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether interrupts need to be re-enabled */
|
||||||
|
if(Interrupts)
|
||||||
|
{
|
||||||
|
/* Re-enable interrupts */
|
||||||
|
AR::CpuFunc::SetInterruptFlag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,55 +977,7 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
HL::Pic::SendSelfIpi(IN ULONG Vector)
|
HL::Pic::SendSelfIpi(IN ULONG Vector)
|
||||||
{
|
{
|
||||||
APIC_COMMAND_REGISTER Register;
|
SendIpi(0, Vector, APIC_DM_FIXED, APIC_DSH_Self, APIC_TGM_EDGE);
|
||||||
BOOLEAN Interrupts;
|
|
||||||
|
|
||||||
/* Check whether interrupts are enabled */
|
|
||||||
Interrupts = AR::CpuFunc::InterruptsEnabled();
|
|
||||||
|
|
||||||
/* Disable interrupts */
|
|
||||||
AR::CpuFunc::ClearInterruptFlag();
|
|
||||||
|
|
||||||
/* Check current APIC mode */
|
|
||||||
if(ApicMode == APIC_MODE_X2APIC)
|
|
||||||
{
|
|
||||||
/* In x2APIC mode, a dedicated Self-IPI register is used */
|
|
||||||
WriteApicRegister(APIC_SIPI, Vector);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Prepare APIC command register */
|
|
||||||
Register.LongLong = 0;
|
|
||||||
Register.DeliveryMode = APIC_DM_FIXED;
|
|
||||||
Register.DestinationShortHand = APIC_DSH_Self;
|
|
||||||
Register.TriggerMode = APIC_TGM_EDGE;
|
|
||||||
Register.Vector = Vector;
|
|
||||||
|
|
||||||
/* Wait for the APIC to clear the delivery status */
|
|
||||||
while((ReadApicRegister(APIC_ICR0) & 0x1000) != 0)
|
|
||||||
{
|
|
||||||
/* Yield the processor */
|
|
||||||
AR::CpuFunc::YieldProcessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In xAPIC compatibility mode, write the command to the ICR registers */
|
|
||||||
WriteApicRegister(APIC_ICR1, Register.Long1);
|
|
||||||
WriteApicRegister(APIC_ICR0, Register.Long0);
|
|
||||||
|
|
||||||
/* Wait until the interrupt physically arrives in the requested state */
|
|
||||||
while((ReadApicRegister((APIC_REGISTER)(APIC_IRR + (Vector / 32))) & (1UL << (Vector % 32))) == 0)
|
|
||||||
{
|
|
||||||
/* Yield the processor */
|
|
||||||
AR::CpuFunc::YieldProcessor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether interrupts need to be re-enabled */
|
|
||||||
if(Interrupts)
|
|
||||||
{
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
AR::CpuFunc::SetInterruptFlag();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ namespace HL
|
|||||||
IN BOOLEAN Self);
|
IN BOOLEAN Self);
|
||||||
STATIC XTAPI VOID SendEoi(VOID);
|
STATIC XTAPI VOID SendEoi(VOID);
|
||||||
STATIC XTAPI VOID SendIpi(IN ULONG ApicId,
|
STATIC XTAPI VOID SendIpi(IN ULONG ApicId,
|
||||||
IN ULONG Vector);
|
IN ULONG Vector,
|
||||||
|
IN APIC_DM DeliveryMode,
|
||||||
|
IN APIC_DSH Destination,
|
||||||
|
IN ULONG TriggerMode);
|
||||||
STATIC XTAPI VOID SendSelfIpi(IN ULONG Vector);
|
STATIC XTAPI VOID SendSelfIpi(IN ULONG Vector);
|
||||||
STATIC XTFASTCALL VOID WriteApicRegister(IN APIC_REGISTER Register,
|
STATIC XTFASTCALL VOID WriteApicRegister(IN APIC_REGISTER Register,
|
||||||
IN ULONGLONG Value);
|
IN ULONGLONG Value);
|
||||||
|
|||||||
Reference in New Issue
Block a user