https://git.reactos.org/?p=reactos.git;a=commitdiff;h=16e988d10858ee1dd14d6ea17056797a18fa0cff

commit 16e988d10858ee1dd14d6ea17056797a18fa0cff
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Tue Jun 22 12:53:23 2021 +0200
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Sat Jun 26 21:10:43 2021 +0200

    [HAL:APIC] Improve code
    
    - Use an enum for the APIC registers
    - Add support routine for SMP.
---
 hal/halx86/apic.cmake     |   1 +
 hal/halx86/apic/apic.c    |  22 ++++-----
 hal/halx86/apic/apicp.h   | 120 ++++++++++++++++++++++++++--------------------
 hal/halx86/apic/apicsmp.c |  96 +++++++++++++++++++++++++++++++++++++
 4 files changed, 175 insertions(+), 64 deletions(-)

diff --git a/hal/halx86/apic.cmake b/hal/halx86/apic.cmake
index 10857eeea8f..8868f40c1a2 100644
--- a/hal/halx86/apic.cmake
+++ b/hal/halx86/apic.cmake
@@ -6,6 +6,7 @@ list(APPEND HAL_APIC_ASM_SOURCE
 list(APPEND HAL_APIC_SOURCE
     apic/apic.c
     apic/apictimer.c
+    apic/apicsmp.c
     apic/halinit.c
     apic/processor.c
     apic/rtctimer.c
diff --git a/hal/halx86/apic/apic.c b/hal/halx86/apic/apic.c
index eae012d61b2..9f204bded55 100644
--- a/hal/halx86/apic/apic.c
+++ b/hal/halx86/apic/apic.c
@@ -136,19 +136,19 @@ ApicReadIORedirectionEntry(
 
 FORCEINLINE
 VOID
-ApicRequestInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
+ApicRequestSelfInterrupt(IN UCHAR Vector, UCHAR TriggerMode)
 {
-    APIC_COMMAND_REGISTER CommandRegister;
+    APIC_INTERRUPT_COMMAND_REGISTER Icr;
 
     /* Setup the command register */
-    CommandRegister.Long0 = 0;
-    CommandRegister.Vector = Vector;
-    CommandRegister.MessageType = APIC_MT_Fixed;
-    CommandRegister.TriggerMode = TriggerMode;
-    CommandRegister.DestinationShortHand = APIC_DSH_Self;
+    Icr.Long0 = 0;
+    Icr.Vector = Vector;
+    Icr.MessageType = APIC_MT_Fixed;
+    Icr.TriggerMode = TriggerMode;
+    Icr.DestinationShortHand = APIC_DSH_Self;
 
     /* Write the low dword to send the interrupt */
-    ApicWrite(APIC_ICR0, CommandRegister.Long0);
+    ApicWrite(APIC_ICR0, Icr.Long0);
 }
 
 FORCEINLINE
@@ -615,7 +615,7 @@ FASTCALL
 HalRequestSoftwareInterrupt(IN KIRQL Irql)
 {
     /* Convert irql to vector and request an interrupt */
-    ApicRequestInterrupt(IrqlToSoftVector(Irql), APIC_TGM_Edge);
+    ApicRequestSelfInterrupt(IrqlToSoftVector(Irql), APIC_TGM_Edge);
 }
 
 VOID
@@ -745,7 +745,7 @@ HalBeginSystemInterrupt(
             RedirReg = ApicReadIORedirectionEntry(Index);
 
             /* Re-request the interrupt to be handled later */
-            ApicRequestInterrupt(Vector, (UCHAR)RedirReg.TriggerMode);
+            ApicRequestSelfInterrupt(Vector, (UCHAR)RedirReg.TriggerMode);
        }
        else
        {
@@ -753,7 +753,7 @@ HalBeginSystemInterrupt(
             ASSERT(Index == APIC_RESERVED_VECTOR);
 
             /* Re-request the interrupt to be handled later */
-            ApicRequestInterrupt(Vector, APIC_TGM_Edge);
+            ApicRequestSelfInterrupt(Vector, APIC_TGM_Edge);
        }
 
         /* Pretend it was a spurious interrupt */
diff --git a/hal/halx86/apic/apicp.h b/hal/halx86/apic/apicp.h
index bd06a3a0cf6..a532fdcad8d 100644
--- a/hal/halx86/apic/apicp.h
+++ b/hal/halx86/apic/apicp.h
@@ -74,46 +74,52 @@
 
 
 /* APIC Register Address Map */
-#define APIC_ID       0x0020 /* Local APIC ID Register (R/W) */
-#define APIC_VER      0x0030 /* Local APIC Version Register (R) */
-#define APIC_TPR      0x0080 /* Task Priority Register (R/W) */
-#define APIC_APR      0x0090 /* Arbitration Priority Register (R) */
-#define APIC_PPR      0x00A0 /* Processor Priority Register (R) */
-#define APIC_EOI      0x00B0 /* EOI Register (W) */
-#define APIC_RRR      0x00C0 /* Remote Read Register () */
-#define APIC_LDR      0x00D0 /* Logical Destination Register (R/W) */
-#define APIC_DFR      0x00E0 /* Destination Format Register (0-27 R, 28-31 
R/W) */
-#define APIC_SIVR     0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 
R/W) */
-#define APIC_ISR      0x0100 /* Interrupt Service Register 0-255 (R) */
-#define APIC_TMR      0x0180 /* Trigger Mode Register 0-255 (R) */
-#define APIC_IRR      0x0200 /* Interrupt Request Register 0-255 (r) */
-#define APIC_ESR      0x0280 /* Error Status Register (R) */
-#define APIC_ICR0     0x0300 /* Interrupt Command Register 0-31 (R/W) */
-#define APIC_ICR1     0x0310 /* Interrupt Command Register 32-63 (R/W) */
-#define APIC_TMRLVTR  0x0320 /* Timer Local Vector Table (R/W) */
-#define        APIC_THRMLVTR 0x0330 /* Thermal Local Vector Table */
-#define APIC_PCLVTR   0x0340 /* Performance Counter Local Vector Table (R/W) */
-#define APIC_LINT0    0x0350 /* LINT0 Local Vector Table (R/W) */
-#define APIC_LINT1    0x0360 /* LINT1 Local Vector Table (R/W) */
-#define APIC_ERRLVTR  0x0370 /* Error Local Vector Table (R/W) */
-#define APIC_TICR     0x0380 /* Initial Count Register for Timer (R/W) */
-#define APIC_TCCR     0x0390 /* Current Count Register for Timer (R) */
-#define APIC_TDCR     0x03E0 /* Timer Divide Configuration Register (R/W) */
-#define APIC_EAFR     0x0400 /* extended APIC Feature register (R/W) */
-#define APIC_EACR     0x0410 /* Extended APIC Control Register (R/W) */
-#define APIC_SEOI     0x0420 /* Specific End Of Interrupt Register (W) */
-#define APIC_EXT0LVTR 0x0500 /* Extended Interrupt 0 Local Vector Table */
-#define APIC_EXT1LVTR 0x0510 /* Extended Interrupt 1 Local Vector Table */
-#define APIC_EXT2LVTR 0x0520 /* Extended Interrupt 2 Local Vector Table */
-#define APIC_EXT3LVTR 0x0530 /* Extended Interrupt 3 Local Vector Table */
+typedef enum _APIC_REGISTER
+{
+    APIC_ID       = 0x0020, /* Local APIC ID Register (R/W) */
+    APIC_VER      = 0x0030, /* Local APIC Version Register (R) */
+    APIC_TPR      = 0x0080, /* Task Priority Register (R/W) */
+    APIC_APR      = 0x0090, /* Arbitration Priority Register (R) */
+    APIC_PPR      = 0x00A0, /* Processor Priority Register (R) */
+    APIC_EOI      = 0x00B0, /* EOI Register (W) */
+    APIC_RRR      = 0x00C0, /* Remote Read Register () */
+    APIC_LDR      = 0x00D0, /* Logical Destination Register (R/W) */
+    APIC_DFR      = 0x00E0, /* Destination Format Register (0-27 R, 28-31 R/W) 
*/
+    APIC_SIVR     = 0x00F0, /* Spurious Interrupt Vector Register (0-3 R, 4-9 
R/W) */
+    APIC_ISR      = 0x0100, /* Interrupt Service Register 0-255 (R) */
+    APIC_TMR      = 0x0180, /* Trigger Mode Register 0-255 (R) */
+    APIC_IRR      = 0x0200, /* Interrupt Request Register 0-255 (r) */
+    APIC_ESR      = 0x0280, /* Error Status Register (R) */
+    APIC_ICR0     = 0x0300, /* Interrupt Command Register 0-31 (R/W) */
+    APIC_ICR1     = 0x0310, /* Interrupt Command Register 32-63 (R/W) */
+    APIC_TMRLVTR  = 0x0320, /* Timer Local Vector Table (R/W) */
+    APIC_THRMLVTR = 0x0330, /* Thermal Local Vector Table */
+    APIC_PCLVTR   = 0x0340, /* Performance Counter Local Vector Table (R/W) */
+    APIC_LINT0    = 0x0350, /* LINT0 Local Vector Table (R/W) */
+    APIC_LINT1    = 0x0360, /* LINT1 Local Vector Table (R/W) */
+    APIC_ERRLVTR  = 0x0370, /* Error Local Vector Table (R/W) */
+    APIC_TICR     = 0x0380, /* Initial Count Register for Timer (R/W) */
+    APIC_TCCR     = 0x0390, /* Current Count Register for Timer (R) */
+    APIC_TDCR     = 0x03E0, /* Timer Divide Configuration Register (R/W) */
+    APIC_EAFR     = 0x0400, /* extended APIC Feature register (R/W) */
+    APIC_EACR     = 0x0410, /* Extended APIC Control Register (R/W) */
+    APIC_SEOI     = 0x0420, /* Specific End Of Interrupt Register (W) */
+    APIC_EXT0LVTR = 0x0500, /* Extended Interrupt 0 Local Vector Table */
+    APIC_EXT1LVTR = 0x0510, /* Extended Interrupt 1 Local Vector Table */
+    APIC_EXT2LVTR = 0x0520, /* Extended Interrupt 2 Local Vector Table */
+    APIC_EXT3LVTR = 0x0530  /* Extended Interrupt 3 Local Vector Table */
+} APIC_REGISTER;
 
 #define MSR_APIC_BASE 0x0000001B
 #define IOAPIC_PHYS_BASE 0xFEC00000
 #define APIC_CLOCK_INDEX 8
 #define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu))
 
-/* Message Type */
-enum
+/* The following definitions are based on AMD documentation.
+   They differ slightly in Intel documentation. */
+
+/* Message Type (Intel: "Delivery Mode") */
+typedef enum _APIC_MT
 {
     APIC_MT_Fixed = 0,
     APIC_MT_LowestPriority = 1,
@@ -123,40 +129,48 @@ enum
     APIC_MT_INIT = 5,
     APIC_MT_Startup = 6,
     APIC_MT_ExtInt = 7,
-};
+} APIC_MT;
 
 /* Trigger Mode */
-enum
+typedef enum _APIC_TGM
 {
     APIC_TGM_Edge,
     APIC_TGM_Level
-};
+} APIC_TGM;
 
-/* Delivery Mode */
-enum
+/* Destination Mode */
+typedef enum _APIC_DM
 {
     APIC_DM_Physical,
     APIC_DM_Logical
-};
+} APIC_DM;
 
 /* Destination Short Hand */
-enum
+typedef enum _APIC_DSH
 {
     APIC_DSH_Destination,
     APIC_DSH_Self,
     APIC_DSH_AllIncludingSelf,
     APIC_DSH_AllExclusingSelf
-};
+} APIC_DSH;
 
 /* Write Constants */
-enum
+typedef enum _APIC_DF
 {
     APIC_DF_Flat = 0xFFFFFFFF,
     APIC_DF_Cluster = 0x0FFFFFFF
-};
+} APIC_DF;
+
+/* Remote Read Status */
+typedef enum _APIC_RRS
+{
+    APIC_RRS_Invalid = 0,
+    APIC_RRS_Pending = 1,
+    APIC_RRS_Done = 2
+} APIC_RRS;
 
 /* Timer Constants */
-enum
+enum _TIMER_DV
 {
     TIMER_DV_DivideBy2 = 0,
     TIMER_DV_DivideBy4 = 1,
@@ -166,7 +180,7 @@ enum
     TIMER_DV_DivideBy64 = 9,
     TIMER_DV_DivideBy128 = 10,
     TIMER_DV_DivideBy1 = 11,
-};
+} TIMER_DV;
 
 #include <pshpack1.h>
 typedef union _APIC_BASE_ADRESS_REGISTER
@@ -220,7 +234,7 @@ typedef union _APIC_EXTENDED_CONTROL_REGISTER
     };
 } APIC_EXTENDED_CONTROL_REGISTER;
 
-typedef union _APIC_COMMAND_REGISTER
+typedef union _APIC_INTERRUPT_COMMAND_REGISTER
 {
     UINT64 LongLong;
     struct
@@ -237,12 +251,12 @@ typedef union _APIC_COMMAND_REGISTER
         UINT64 ReservedMBZ:1;
         UINT64 Level:1;
         UINT64 TriggerMode:1;
-        UINT64 RemoteReadStatus:2;
+        UINT64 RemoteReadStatus:2; /* Intel: Reserved */
         UINT64 DestinationShortHand:2;
         UINT64 Reserved2MBZ:36;
         UINT64 Destination:8;
     };
-} APIC_COMMAND_REGISTER;
+} APIC_INTERRUPT_COMMAND_REGISTER;
 
 typedef union _LVT_REGISTER
 {
@@ -304,16 +318,16 @@ typedef union _IOAPIC_REDIRECTION_REGISTER
 
 FORCEINLINE
 ULONG
-ApicRead(ULONG Offset)
+ApicRead(APIC_REGISTER Register)
 {
-    return READ_REGISTER_ULONG((PULONG)(APIC_BASE + Offset));
+    return READ_REGISTER_ULONG((PULONG)(APIC_BASE + Register));
 }
 
 FORCEINLINE
 VOID
-ApicWrite(ULONG Offset, ULONG Value)
+ApicWrite(APIC_REGISTER Register, ULONG Value)
 {
-    WRITE_REGISTER_ULONG((PULONG)(APIC_BASE + Offset), Value);
+    WRITE_REGISTER_ULONG((PULONG)(APIC_BASE + Register), Value);
 }
 
 VOID
diff --git a/hal/halx86/apic/apicsmp.c b/hal/halx86/apic/apicsmp.c
new file mode 100644
index 00000000000..6379922dda9
--- /dev/null
+++ b/hal/halx86/apic/apicsmp.c
@@ -0,0 +1,96 @@
+/*
+ * PROJECT:     ReactOS HAL
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * FILE:        hal/halx86/apic/apicsmp.c
+ * PURPOSE:     SMP specific APIC code
+ * PROGRAMMERS: Copyright 2021 Timo Kreuzer ([email protected])
+ */
+
+/* INCLUDES 
*******************************************************************/
+
+#include <hal.h>
+#include "apicp.h"
+#define NDEBUG
+#include <debug.h>
+
+/* INTERNAL FUNCTIONS 
*********************************************************/
+
+/*!
+    \param Vector - Specifies the interrupt vector to be delivered.
+
+    \param MessageType - Specifies the message type sent to the CPU core
+        interrupt handler. This can be one of the following values:
+        APIC_MT_Fixed - Delivers an interrupt to the target local APIC
+            specified in Destination field.
+        APIC_MT_LowestPriority - Delivers an interrupt to the local APIC
+            executing at the lowest priority of all local APICs.
+        APIC_MT_SMI - Delivers an SMI interrupt to target local APIC(s).
+        APIC_MT_RemoteRead - Delivers a read request to read an APIC register
+            in the target local APIC specified in Destination field.
+        APIC_MT_NMI - Delivers a non-maskable interrupt to the target local
+            APIC specified in the Destination field. Vector is ignored.
+        APIC_MT_INIT - Delivers an INIT request to the target local APIC(s)
+            specified in the Destination field. TriggerMode must be
+            APIC_TGM_Edge, Vector must be 0.
+        APIC_MT_Startup - Delivers a start-up request (SIPI) to the target
+            local APIC(s) specified in Destination field. Vector specifies
+            the startup address.
+        APIC_MT_ExtInt - Delivers an external interrupt to the target local
+            APIC specified in Destination field. 
+
+    \param TriggerMode - The trigger mode of the interrupt. Can be:
+        APIC_TGM_Edge - The interrupt is edge triggered.
+        APIC_TGM_Level - The interrupt is level triggered.
+
+    \param DestinationShortHand - Specifies where to send the interrupt.
+        APIC_DSH_Destination
+        APIC_DSH_Self
+        APIC_DSH_AllIncludingSelf
+        APIC_DSH_AllExclusingSelf
+
+    \see "AMD64 Architecture Programmer's Manual Volume 2 System Programming"
+        Chapter 16 "Advanced Programmable Interrupt Controller (APIC)"
+        16.5 "Interprocessor Interrupts (IPI)"
+
+ */
+FORCEINLINE
+VOID
+ApicRequestGlobalInterrupt(
+    _In_ UCHAR DestinationProcessor,
+    _In_ UCHAR Vector,
+    _In_ APIC_MT MessageType,
+    _In_ APIC_TGM TriggerMode,
+    _In_ APIC_DSH DestinationShortHand)
+{
+    APIC_INTERRUPT_COMMAND_REGISTER Icr;
+
+    /* Setup the command register */
+    Icr.LongLong = 0;
+    Icr.Vector = Vector;
+    Icr.MessageType = MessageType;
+    Icr.DestinationMode = APIC_DM_Physical;
+    Icr.DeliveryStatus = 0;
+    Icr.Level = 0;
+    Icr.TriggerMode = TriggerMode;
+    Icr.RemoteReadStatus = 0;
+    Icr.DestinationShortHand = DestinationShortHand;
+    Icr.Destination = DestinationProcessor;
+
+    /* Write the low dword last to send the interrupt */
+    ApicWrite(APIC_ICR1, Icr.Long1);
+    ApicWrite(APIC_ICR0, Icr.Long0);
+}
+
+
+/* SMP SUPPORT FUNCTIONS 
******************************************************/
+
+// Should be called by SMP version of HalRequestIpi
+VOID
+NTAPI
+HalpRequestIpi(KAFFINITY TargetProcessors)
+{
+    UNIMPLEMENTED;
+    __debugbreak();
+}
+
+// APIC specific SMP code here

Reply via email to