mirror of
https://github.com/reactos/reactos.git
synced 2024-09-27 21:16:34 +00:00
[HAL:APIC] Improve code
- Use an enum for the APIC registers - Add support routine for SMP.
This commit is contained in:
parent
e8277e51e2
commit
16e988d108
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
96
hal/halx86/apic/apicsmp.c
Normal file
96
hal/halx86/apic/apicsmp.c
Normal file
|
@ -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 (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* 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
|
Loading…
Reference in a new issue