https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6eccbe27ec9268e257df6…
commit 6eccbe27ec9268e257df6aaca80d2496afb52d0e
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Mon Jan 3 22:19:35 2022 -0500
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sun Feb 13 17:15:00 2022 -0500
[HAL:APIC] Ensure the interrupt gets requested immediately in
ApicRequestSelfInterrupt. CORE-17663
---
hal/halx86/apic/apic.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/hal/halx86/apic/apic.c b/hal/halx86/apic/apic.c
index 0d152539c33..0fe921149f6 100644
--- a/hal/halx86/apic/apic.c
+++ b/hal/halx86/apic/apic.c
@@ -138,7 +138,18 @@ FORCEINLINE
VOID
ApicRequestSelfInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
{
+ ULONG Flags;
APIC_INTERRUPT_COMMAND_REGISTER Icr;
+ APIC_INTERRUPT_COMMAND_REGISTER IcrStatus;
+
+ /*
+ * The IRR registers are spaced 16 bytes apart and hold 32 status bits each.
+ * Pre-compute the register and bit that match our vector.
+ */
+ ULONG VectorHigh = Vector / 32;
+ ULONG VectorLow = Vector % 32;
+ ULONG Irr = APIC_IRR + 0x10 * VectorHigh;
+ ULONG IrrBit = 1UL << VectorLow;
/* Setup the command register */
Icr.Long0 = 0;
@@ -147,8 +158,32 @@ ApicRequestSelfInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
Icr.TriggerMode = TriggerMode;
Icr.DestinationShortHand = APIC_DSH_Self;
+ /* Disable interrupts so that we can change IRR without being interrupted */
+ Flags = __readeflags();
+ _disable();
+
+ /* Wait for the APIC to be idle */
+ do
+ {
+ IcrStatus.Long0 = ApicRead(APIC_ICR0);
+ } while (IcrStatus.DeliveryStatus);
+
/* Write the low dword to send the interrupt */
ApicWrite(APIC_ICR0, Icr.Long0);
+
+ /* Wait until we see the interrupt request.
+ * It will stay in requested state until we re-enable interrupts.
+ */
+ while (!(ApicRead(Irr) & IrrBit))
+ {
+ NOTHING;
+ }
+
+ /* Finally, restore the original interrupt state */
+ if (Flags & EFLAGS_INTERRUPT_MASK)
+ {
+ _enable();
+ }
}
FORCEINLINE