From 0d9020634a02d972a1bec2674e9e206a0c200868 Mon Sep 17 00:00:00 2001 From: Justin Miller Date: Mon, 3 May 2021 18:29:50 -0700 Subject: [PATCH] [HALX86] Disable Lazy IRQL in APIC HAL (#3609) Lazy IRQL feature has issues with interrupt delivery on VirtualBox, so disable it for now. For the feature description, see commit d28eae967a04320931241f06c88c801aa86397bd Meanwhile, merge and clean up APIC headers a bit --- hal/halx86/CMakeLists.txt | 6 +- hal/halx86/apic/apic.c | 8 +- hal/halx86/apic/apic.h | 286 -------------------- hal/halx86/apic/apictimer.c | 3 +- hal/halx86/apic/halaacpi.rc | 5 + hal/halx86/apic/halinit.c | 5 +- hal/halx86/apic/tsc.c | 3 +- hal/halx86/include/apic.h | 518 ++++++++++++++++++++---------------- hal/halx86/smp/halmacpi.rc | 9 + 9 files changed, 311 insertions(+), 532 deletions(-) delete mode 100644 hal/halx86/apic/apic.h create mode 100644 hal/halx86/apic/halaacpi.rc create mode 100644 hal/halx86/smp/halmacpi.rc diff --git a/hal/halx86/CMakeLists.txt b/hal/halx86/CMakeLists.txt index abb3c1dd469..0b1b18be370 100644 --- a/hal/halx86/CMakeLists.txt +++ b/hal/halx86/CMakeLists.txt @@ -60,14 +60,11 @@ if(ARCH STREQUAL "i386") # hal add_hal(hal SOURCES pic/halpic.rc COMPONENTS generic legacy up pic) add_hal(halacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up pic) - add_hal(halaacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi up apic) + add_hal(halaacpi SOURCES apic/halaacpi.rc COMPONENTS generic acpi up apic) add_hal(halxbox SOURCES xbox/halxbox.rc COMPONENTS xbox up) add_hal(halpc98 SOURCES pc98/halpc98.rc COMPONENTS pc98 up) - #add_hal(halmps SOURCES up/halup.rc COMPONENTS generic legacy smp pic) #add_hal(halmacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi smp pic) - #add_hal(halmapic SOURCES acpi/halacpi.rc COMPONENTS generic legacy smp apic) - #add_hal(halmaacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi smp apic) elseif(ARCH STREQUAL "amd64") @@ -75,6 +72,7 @@ elseif(ARCH STREQUAL "amd64") amd64/x86bios.c) add_hal(hal SOURCES ${HAL_SOURCE} COMPONENTS generic acpi up apic) + #add_hal(halmacpi SOURCES acpi/halacpi.rc COMPONENTS generic acpi smp pic) target_link_libraries(hal fast486) endif() diff --git a/hal/halx86/apic/apic.c b/hal/halx86/apic/apic.c index 54dbbf01f0a..4c98e13bdf9 100644 --- a/hal/halx86/apic/apic.c +++ b/hal/halx86/apic/apic.c @@ -12,14 +12,14 @@ /* INCLUDES *******************************************************************/ #include +#include #define NDEBUG #include -#include "apic.h" void __cdecl HackEoi(void); #ifndef _M_AMD64 -#define APIC_LAZY_IRQL +//#define APIC_LAZY_IRQL //FIXME: Disabled due to bug. #endif /* GLOBALS ********************************************************************/ @@ -263,10 +263,10 @@ ApicInitializeLocalApic(ULONG Cpu) LVT_REGISTER LvtEntry; /* Enable the APIC if it wasn't yet */ - BaseRegister.Long = __readmsr(MSR_APIC_BASE); + BaseRegister.LongLong = __readmsr(MSR_APIC_BASE); BaseRegister.Enable = 1; BaseRegister.BootStrapCPUCore = (Cpu == 0); - __writemsr(MSR_APIC_BASE, BaseRegister.Long); + __writemsr(MSR_APIC_BASE, BaseRegister.LongLong); /* Set spurious vector and SoftwareEnable to 1 */ SpIntRegister.Long = ApicRead(APIC_SIVR); diff --git a/hal/halx86/apic/apic.h b/hal/halx86/apic/apic.h deleted file mode 100644 index edabaa3b9db..00000000000 --- a/hal/halx86/apic/apic.h +++ /dev/null @@ -1,286 +0,0 @@ - -#pragma once - -#ifdef _M_AMD64 -#define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL // checkme -#define ZERO_VECTOR 0x00 // IRQL 00 -#define APC_VECTOR 0x3D // IRQL 01 -#define APIC_SPURIOUS_VECTOR 0x3f -#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_NMI_VECTOR 0xFF -#define IrqlToTpr(Irql) (Irql << 4) -#define IrqlToSoftVector(Irql) ((Irql << 4)|0xf) -#define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4)) -#define CLOCK2_LEVEL CLOCK_LEVEL -#else -#define IOAPIC_BASE 0xFFFE1000 // checkme -#define ZERO_VECTOR 0x00 // IRQL 00 -#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_NMI_VECTOR 0xFF -#define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql]) -#define IrqlToSoftVector(Irql) IrqlToTpr(Irql) -#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) -#endif - -#define MSR_APIC_BASE 0x0000001B -#define IOAPIC_PHYS_BASE 0xFEC00000 -#define APIC_CLOCK_INDEX 8 - -#define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu)) - -/* 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 */ - -enum -{ - APIC_MT_Fixed = 0, - APIC_MT_LowestPriority = 1, - APIC_MT_SMI = 2, - APIC_MT_RemoteRead = 3, - APIC_MT_NMI = 4, - APIC_MT_INIT = 5, - APIC_MT_Startup = 6, - APIC_MT_ExtInt = 7, -}; - -enum -{ - APIC_TGM_Edge, - APIC_TGM_Level -}; - -enum -{ - APIC_DM_Physical, - APIC_DM_Logical -}; - -enum -{ - APIC_DSH_Destination, - APIC_DSH_Self, - APIC_DSH_AllIncludingSelf, - APIC_DSH_AllExclusingSelf -}; - -enum -{ - APIC_DF_Flat = 0xFFFFFFFF, - APIC_DF_Cluster = 0x0FFFFFFF -}; - -enum -{ - TIMER_DV_DivideBy2 = 0, - TIMER_DV_DivideBy4 = 1, - TIMER_DV_DivideBy8 = 2, - TIMER_DV_DivideBy16 = 3, - TIMER_DV_DivideBy32 = 8, - TIMER_DV_DivideBy64 = 9, - TIMER_DV_DivideBy128 = 10, - TIMER_DV_DivideBy1 = 11, -}; - - -typedef union _APIC_BASE_ADRESS_REGISTER -{ - ULONG64 Long; - struct - { - ULONG64 Reserved1:8; - ULONG64 BootStrapCPUCore:1; - ULONG64 Reserved2:2; - ULONG64 Enable:1; - ULONG64 BaseAddress:40; - ULONG64 ReservedMBZ:12; - }; -} APIC_BASE_ADRESS_REGISTER; - -typedef union _APIC_SPURIOUS_INERRUPT_REGISTER -{ - ULONG Long; - struct - { - ULONG Vector:8; - ULONG SoftwareEnable:1; - ULONG FocusCPUCoreChecking:1; - ULONG ReservedMBZ:22; - }; -} APIC_SPURIOUS_INERRUPT_REGISTER; - -typedef union -{ - ULONG Long; - struct - { - ULONG Version:8; - ULONG ReservedMBZ:8; - ULONG MaxLVT:8; - ULONG ReservedMBZ1:7; - ULONG ExtRegSpacePresent:1; - }; -} APIC_VERSION_REGISTER; - -typedef union -{ - ULONG Long; - struct - { - ULONG Version:1; - ULONG SEOIEnable:1; - ULONG ExtApicIdEnable:1; - ULONG ReservedMBZ:29; - }; -} APIC_EXTENDED_CONTROL_REGISTER; - -typedef union _APIC_COMMAND_REGISTER -{ - ULONGLONG LongLong; - struct - { - ULONG Long0; - ULONG Long1; - }; - struct - { - ULONGLONG Vector:8; - ULONGLONG MessageType:3; - ULONGLONG DestinationMode:1; - ULONGLONG DeliveryStatus:1; - ULONGLONG ReservedMBZ:1; - ULONGLONG Level:1; - ULONGLONG TriggerMode:1; - ULONGLONG RemoteReadStatus:2; - ULONGLONG DestinationShortHand:2; - ULONGLONG Reserved2MBZ:36; - ULONGLONG Destination:8; - }; -} APIC_COMMAND_REGISTER; - -typedef union -{ - ULONG Long; - struct - { - ULONG Vector:8; - ULONG MessageType:3; - ULONG ReservedMBZ:1; - ULONG DeliveryStatus:1; - ULONG Reserved1MBZ:1; - ULONG RemoteIRR:1; - ULONG TriggerMode:1; - ULONG Mask:1; - ULONG TimerMode:1; - ULONG Reserved2MBZ:13; - }; -} LVT_REGISTER; - - -enum -{ - IOAPIC_IOREGSEL = 0x00, - IOAPIC_IOWIN = 0x10 -}; - -enum -{ - IOAPIC_ID = 0x00, - IOAPIC_VER = 0x01, - IOAPIC_ARB = 0x02, - IOAPIC_REDTBL = 0x10 -}; - -typedef union _IOAPIC_REDIRECTION_REGISTER -{ - ULONGLONG LongLong; - struct - { - ULONG Long0; - ULONG Long1; - }; - struct - { - ULONGLONG Vector:8; - ULONGLONG DeliveryMode:3; - ULONGLONG DestinationMode:1; - ULONGLONG DeliveryStatus:1; - ULONGLONG Polarity:1; - ULONGLONG RemoteIRR:1; - ULONGLONG TriggerMode:1; - ULONGLONG Mask:1; - ULONGLONG Reserved:39; - ULONGLONG Destination:8; - }; -} IOAPIC_REDIRECTION_REGISTER; - -FORCEINLINE -ULONG -ApicRead(ULONG Offset) -{ - return *(volatile ULONG *)(APIC_BASE + Offset); -} - -FORCEINLINE -VOID -ApicWrite(ULONG Offset, ULONG Value) -{ - *(volatile ULONG *)(APIC_BASE + Offset) = Value; -} - -VOID -NTAPI -ApicInitializeTimer(ULONG Cpu); - -VOID -NTAPI -HalInitializeProfiling(VOID); - -VOID __cdecl ApicSpuriousService(VOID); - diff --git a/hal/halx86/apic/apictimer.c b/hal/halx86/apic/apictimer.c index 5fe93056605..1a152e2d410 100644 --- a/hal/halx86/apic/apictimer.c +++ b/hal/halx86/apic/apictimer.c @@ -9,11 +9,10 @@ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include -#include "apic.h" - extern LARGE_INTEGER HalpCpuClockFrequency; /* HAL profiling variables */ diff --git a/hal/halx86/apic/halaacpi.rc b/hal/halx86/apic/halaacpi.rc new file mode 100644 index 00000000000..8d7142e80a2 --- /dev/null +++ b/hal/halx86/apic/halaacpi.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "X86 Uniprocessor Hardware Abstraction Layer" +#define REACTOS_STR_INTERNAL_NAME "halaacpi" +#define REACTOS_STR_ORIGINAL_FILENAME "halaacpi.dll" +#include diff --git a/hal/halx86/apic/halinit.c b/hal/halx86/apic/halinit.c index 0ade0fda11c..504f568dbb1 100644 --- a/hal/halx86/apic/halinit.c +++ b/hal/halx86/apic/halinit.c @@ -1,16 +1,16 @@ /* * PROJECT: ReactOS Hardware Abstraction Layer * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) - * PURPOSE: Initialize the x86 HAL + * PURPOSE: Initialize the APIC HAL * COPYRIGHT: Copyright 2011 Timo Kreuzer */ /* INCLUDES *****************************************************************/ #include +#include #define NDEBUG #include -#include "apic.h" VOID NTAPI @@ -36,7 +36,6 @@ HalpInitProcessor( /* Initialize the timer */ //ApicInitializeTimer(ProcessorNumber); - } VOID diff --git a/hal/halx86/apic/tsc.c b/hal/halx86/apic/tsc.c index a9b79eea233..ce06b2f6d8e 100644 --- a/hal/halx86/apic/tsc.c +++ b/hal/halx86/apic/tsc.c @@ -9,11 +9,10 @@ /* INCLUDES ******************************************************************/ #include +#include "tsc.h" #define NDEBUG #include -#include "tsc.h" - LARGE_INTEGER HalpCpuClockFrequency = {{INITIAL_STALL_COUNT * 1000000}}; UCHAR TscCalibrationPhase; diff --git a/hal/halx86/include/apic.h b/hal/halx86/include/apic.h index 315af0a6b3e..fe82a1425d8 100644 --- a/hal/halx86/include/apic.h +++ b/hal/halx86/include/apic.h @@ -1,253 +1,309 @@ /* - * + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Header file for APIC hal + * COPYRIGHT: Copyright 2011 Timo Kreuzer + * Copyright 2021 Justin Miller */ #pragma once #ifdef _M_AMD64 -#define APIC_DEFAULT_BASE 0xfffffffffee00000ULL; + #define LOCAL_APIC_BASE 0xFFFFFFFFFFFE0000ULL + #define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL + #define APIC_SPURIOUS_VECTOR 0x3f + #define IrqlToTpr(Irql) (Irql << 4) + #define IrqlToSoftVector(Irql) ((Irql << 4)|0xf) + #define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4)) + #define CLOCK2_LEVEL CLOCK_LEVEL #else -#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ + #define LOCAL_APIC_BASE 0xFFFE0000 + #define IOAPIC_BASE 0xFFFE1000 + #define APIC_SPURIOUS_VECTOR 0x1f + #define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql]) + #define IrqlToSoftVector(Irql) IrqlToTpr(Irql) + #define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) #endif +/* The IMCR is supported by two read/writable or write-only I/O ports, + 22h and 23h, which receive address and data respectively. + To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR. + Then write the data to I/O port 23h. The power-on default value is zero, + which connects the NMI and 8259 INTR lines directly to the BSP. + Writing a value of 01h forces the NMI and 8259 INTR signals to pass through the APIC. +*/ +#define IMCR_ADDRESS_PORT (PUCHAR)0x0022 +#define IMCR_DATA_PORT (PUCHAR)0x0023 +#define IMCR_SELECT 0x70 +#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) */ -#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_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_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */ -#define APIC_LVTTHMR 0x0330 -#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */ -#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */ -#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */ -#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */ -#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */ -#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */ -#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ +#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 */ -#define APIC_ID_MASK (0xF << 24) -#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) -#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) -#define APIC_VER_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x) & 0xFF) -#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) +#define MSR_APIC_BASE 0x0000001B +#define IOAPIC_PHYS_BASE 0xFEC00000 +#define APIC_CLOCK_INDEX 8 +#define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu)) -#define APIC_TPR_PRI 0xFF -#define APIC_TPR_INT 0xF0 -#define APIC_TPR_SUB 0xF -#define APIC_TPR_MAX 0xFF /* Maximum priority */ -#define APIC_TPR_MIN 0x20 /* Minimum priority */ - -#define APIC_LDR_MASK (0xFF << 24) - -#define APIC_SIVR_ENABLE (0x1 << 8) -#define APIC_SIVR_FOCUS (0x1 << 9) - -#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */ - -#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */ -#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */ -#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */ -#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */ -#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */ -#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */ -#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */ - -/* Delivery Modes */ -#define APIC_DM_FIXED (0x0 << 8) -#define APIC_DM_LOWEST (0x1 << 8) -#define APIC_DM_SMI (0x2 << 8) -#define APIC_DM_REMRD (0x3 << 8) -#define APIC_DM_NMI (0x4 << 8) -#define APIC_DM_INIT (0x5 << 8) -#define APIC_DM_STARTUP (0x6 << 8) -#define APIC_DM_EXTINT (0x7 << 8) -#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) -#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8)) - -/* Destination Shorthand values */ -#define APIC_ICR0_DESTS_FIELD (0x0 << 0) -#define APIC_ICR0_DESTS_SELF (0x1 << 18) -#define APIC_ICR0_DESTS_ALL (0x2 << 18) -#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18) - -#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */ -#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */ - -#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) -#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24) - -#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3) -#define SET_APIC_TIMER_BASE(x) ((x) << 18) -#define APIC_TIMER_BASE_CLKIN 0x0 -#define APIC_TIMER_BASE_TMBASE 0x1 -#define APIC_TIMER_BASE_DIV 0x2 - -#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */ -#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */ -#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */ -#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */ -#define APIC_LVT_MASKED (0x1 << 16) /* Mask */ -#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */ - -#define APIC_LVT3_DM (0x7 << 8) -#define APIC_LVT3_IIPP (0x1 << 13) -#define APIC_LVT3_TM (0x1 << 15) -#define APIC_LVT3_MASKED (0x1 << 16) -#define APIC_LVT3_OS (0x1 << 17) - -#define APIC_TDCR_TMBASE (0x1 << 2) -#define APIC_TDCR_MASK 0x0F -#define APIC_TDCR_2 0x00 -#define APIC_TDCR_4 0x01 -#define APIC_TDCR_8 0x02 -#define APIC_TDCR_16 0x03 -#define APIC_TDCR_32 0x08 -#define APIC_TDCR_64 0x09 -#define APIC_TDCR_128 0x0A -#define APIC_TDCR_1 0x0B - -#define APIC_TARGET_SELF 0x100 -#define APIC_TARGET_ALL 0x200 -#define APIC_TARGET_ALL_BUT_SELF 0x300 - -#define APIC_INTEGRATED(version) (version & 0xF0) - -typedef enum { - amPIC = 0, /* IMCR and PIC compatibility mode */ - amVWIRE /* Virtual Wire compatibility mode */ -} APIC_MODE; - -#ifdef CONFIG_SMP -#define MAX_CPU 32 -#else -#define MAX_CPU 1 -#endif - -/* - * Local APIC timer IRQ vector is on a different priority level, - * to work around the 'lost local interrupt if more than 2 IRQ - * sources per level' errata. - */ -#define LOCAL_TIMER_VECTOR 0xEF - -#define IPI_VECTOR 0xFB -#define ERROR_VECTOR 0xFE -#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ - -/* CPU flags */ -#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ -#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ -#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ -#define CPU_TSC 0x08 /* 1 if the CPU has a time stamp counter */ - -typedef struct _CPU_INFO +/* Message Type */ +enum { - UCHAR Flags; /* CPU flags */ - UCHAR APICId; /* Local APIC ID */ - UCHAR APICVersion; /* Local APIC version */ -// UCHAR MaxLVT; /* Number of LVT registers */ - ULONG BusSpeed; /* BUS speed */ - ULONG CoreSpeed; /* Core speed */ - UCHAR Padding[16-12]; /* Padding to 16-byte */ -} CPU_INFO, *PCPU_INFO; + APIC_MT_Fixed = 0, + APIC_MT_LowestPriority = 1, + APIC_MT_SMI = 2, + APIC_MT_RemoteRead = 3, + APIC_MT_NMI = 4, + APIC_MT_INIT = 5, + APIC_MT_Startup = 6, + APIC_MT_ExtInt = 7, +}; -extern ULONG CPUCount; /* Total number of CPUs */ -extern ULONG BootCPU; /* Bootstrap processor */ -extern ULONG OnlineCPUs; /* Bitmask of online CPUs */ -extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ -extern PULONG APICBase; /* Virtual address of local APIC */ -extern ULONG lastregr[MAX_CPU]; /* For debugging */ -extern ULONG lastvalr[MAX_CPU]; -extern ULONG lastregw[MAX_CPU]; -extern ULONG lastvalw[MAX_CPU]; - -/* Prototypes */ -VOID APICSendIPI(ULONG Target, ULONG Mode); -VOID APICSetup(VOID); -VOID HaliInitBSP(VOID); -VOID APICSyncArbIDs(VOID); -VOID APICCalibrateTimer(ULONG CPU); -VOID HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack); - -static __inline ULONG _APICRead(ULONG Offset) +/* Trigger Mode */ +enum { - PULONG p; + APIC_TGM_Edge, + APIC_TGM_Level +}; - p = (PULONG)((ULONG_PTR)APICBase + Offset); - return *p; +/* Delivery Mode */ +enum +{ + APIC_DM_Physical, + APIC_DM_Logical +}; + +/* Destination Short Hand */ +enum +{ + APIC_DSH_Destination, + APIC_DSH_Self, + APIC_DSH_AllIncludingSelf, + APIC_DSH_AllExclusingSelf +}; + +/* Write Constants */ +enum +{ + APIC_DF_Flat = 0xFFFFFFFF, + APIC_DF_Cluster = 0x0FFFFFFF +}; + +/* Timer Constants */ +enum +{ + TIMER_DV_DivideBy2 = 0, + TIMER_DV_DivideBy4 = 1, + TIMER_DV_DivideBy8 = 2, + TIMER_DV_DivideBy16 = 3, + TIMER_DV_DivideBy32 = 8, + TIMER_DV_DivideBy64 = 9, + TIMER_DV_DivideBy128 = 10, + TIMER_DV_DivideBy1 = 11, +}; + +#include +typedef union _APIC_BASE_ADRESS_REGISTER +{ + UINT64 LongLong; + struct + { + UINT64 Reserved1:8; + UINT64 BootStrapCPUCore:1; + UINT64 Reserved2:2; + UINT64 Enable:1; + UINT64 BaseAddress:40; + UINT64 ReservedMBZ:12; + }; +} APIC_BASE_ADRESS_REGISTER; + +typedef union _APIC_SPURIOUS_INERRUPT_REGISTER +{ + UINT32 Long; + struct + { + UINT32 Vector:8; + UINT32 SoftwareEnable:1; + UINT32 FocusCPUCoreChecking:1; + UINT32 ReservedMBZ:22; + }; +} APIC_SPURIOUS_INERRUPT_REGISTER; + +typedef union _APIC_VERSION_REGISTER +{ + UINT32 Long; + struct + { + UINT32 Version:8; + UINT32 ReservedMBZ:8; + UINT32 MaxLVT:8; + UINT32 ReservedMBZ1:7; + UINT32 ExtRegSpacePresent:1; + }; +} APIC_VERSION_REGISTER; + +typedef union _APIC_EXTENDED_CONTROL_REGISTER +{ + UINT32 Long; + struct + { + UINT32 Version:1; + UINT32 SEOIEnable:1; + UINT32 ExtApicIdEnable:1; + UINT32 ReservedMBZ:29; + }; +} APIC_EXTENDED_CONTROL_REGISTER; + +typedef union _APIC_COMMAND_REGISTER +{ + UINT64 LongLong; + struct + { + UINT32 Long0; + UINT32 Long1; + }; + struct + { + UINT64 Vector:8; + UINT64 MessageType:3; + UINT64 DestinationMode:1; + UINT64 DeliveryStatus:1; + UINT64 ReservedMBZ:1; + UINT64 Level:1; + UINT64 TriggerMode:1; + UINT64 RemoteReadStatus:2; + UINT64 DestinationShortHand:2; + UINT64 Reserved2MBZ:36; + UINT64 Destination:8; + }; +} APIC_COMMAND_REGISTER; + +typedef union _LVT_REGISTER +{ + UINT32 Long; + struct + { + UINT32 Vector:8; + UINT32 MessageType:3; + UINT32 ReservedMBZ:1; + UINT32 DeliveryStatus:1; + UINT32 Reserved1MBZ:1; + UINT32 RemoteIRR:1; + UINT32 TriggerMode:1; + UINT32 Mask:1; + UINT32 TimerMode:1; + UINT32 Reserved2MBZ:13; + }; +} LVT_REGISTER; + +/* IOAPIC offsets */ +enum +{ + IOAPIC_IOREGSEL = 0x00, + IOAPIC_IOWIN = 0x10 +}; + +/* IOAPIC Constants */ +enum +{ + IOAPIC_ID = 0x00, + IOAPIC_VER = 0x01, + IOAPIC_ARB = 0x02, + IOAPIC_REDTBL = 0x10 +}; + +typedef union _IOAPIC_REDIRECTION_REGISTER +{ + UINT64 LongLong; + struct + { + UINT32 Long0; + UINT32 Long1; + }; + struct + { + UINT64 Vector:8; + UINT64 DeliveryMode:3; + UINT64 DestinationMode:1; + UINT64 DeliveryStatus:1; + UINT64 Polarity:1; + UINT64 RemoteIRR:1; + UINT64 TriggerMode:1; + UINT64 Mask:1; + UINT64 Reserved:39; + UINT64 Destination:8; + }; +} IOAPIC_REDIRECTION_REGISTER; +#include + +FORCEINLINE +ULONG +ApicRead(ULONG Offset) +{ + return *(volatile ULONG *)(APIC_BASE + Offset); } -#if 0 -static __inline VOID APICWrite(ULONG Offset, - ULONG Value) +FORCEINLINE +VOID +ApicWrite(ULONG Offset, ULONG Value) { - PULONG p; - - p = (PULONG)((ULONG_PTR)APICBase + Offset); - - *p = Value; -} -#else -static __inline VOID APICWrite(ULONG Offset, - ULONG Value) -{ - PULONG p; - ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24; - - lastregw[CPU] = Offset; - lastvalw[CPU] = Value; - - p = (PULONG)((ULONG_PTR)APICBase + Offset); - - *p = Value; -} -#endif - -#if 0 -static __inline ULONG APICRead(ULONG Offset) -{ - PULONG p; - - p = (PULONG)((ULONG_PTR)APICBase + Offset); - return *p; -} -#else -static __inline ULONG APICRead(ULONG Offset) -{ - PULONG p; - ULONG CPU = (_APICRead(APIC_ID) & APIC_ID_MASK) >> 24; - - lastregr[CPU] = Offset; - lastvalr[CPU] = 0; - - p = (PULONG)((ULONG_PTR)APICBase + Offset); - - lastvalr[CPU] = *p; - return lastvalr[CPU]; -} -#endif - -static __inline ULONG ThisCPU(VOID) -{ - return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; + *(volatile ULONG *)(APIC_BASE + Offset) = Value; } -static __inline VOID APICSendEOI(VOID) -{ - // Send the EOI - APICWrite(APIC_EOI, 0); -} +VOID +NTAPI +ApicInitializeTimer(ULONG Cpu); -/* EOF */ +VOID +NTAPI +HalInitializeProfiling(VOID); + +VOID +NTAPI +HalpInitApicInfo(IN PLOADER_PARAMETER_BLOCK KeLoaderBlock); + +VOID __cdecl ApicSpuriousService(VOID); diff --git a/hal/halx86/smp/halmacpi.rc b/hal/halx86/smp/halmacpi.rc new file mode 100644 index 00000000000..883ed5cdbad --- /dev/null +++ b/hal/halx86/smp/halmacpi.rc @@ -0,0 +1,9 @@ +#define REACTOS_VERSION_DLL +#ifdef _M_AMD64 +#define REACTOS_STR_FILE_DESCRIPTION "X64 Multiprocessor Hardware Abstraction Layer" +#else +#define REACTOS_STR_FILE_DESCRIPTION "X86 Multiprocessor Hardware Abstraction Layer" +#endif +#define REACTOS_STR_INTERNAL_NAME "halmacpi" +#define REACTOS_STR_ORIGINAL_FILENAME "halmacpi.dll" +#include