[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 d28eae967a

Meanwhile, merge and clean up APIC headers a bit
This commit is contained in:
Justin Miller 2021-05-03 18:29:50 -07:00 committed by GitHub
parent 239266640f
commit 0d9020634a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 311 additions and 532 deletions

View file

@ -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()

View file

@ -12,14 +12,14 @@
/* INCLUDES *******************************************************************/
#include <hal.h>
#include <apic.h>
#define NDEBUG
#include <debug.h>
#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);

View file

@ -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);

View file

@ -9,11 +9,10 @@
/* INCLUDES ******************************************************************/
#include <hal.h>
#include <apic.h>
#define NDEBUG
#include <debug.h>
#include "apic.h"
extern LARGE_INTEGER HalpCpuClockFrequency;
/* HAL profiling variables */

View file

@ -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 <reactos/version.rc>

View file

@ -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 <timo.kreuzer@reactos.org>
*/
/* INCLUDES *****************************************************************/
#include <hal.h>
#include <apic.h>
#define NDEBUG
#include <debug.h>
#include "apic.h"
VOID
NTAPI
@ -36,7 +36,6 @@ HalpInitProcessor(
/* Initialize the timer */
//ApicInitializeTimer(ProcessorNumber);
}
VOID

View file

@ -9,11 +9,10 @@
/* INCLUDES ******************************************************************/
#include <hal.h>
#include "tsc.h"
#define NDEBUG
#include <debug.h>
#include "tsc.h"
LARGE_INTEGER HalpCpuClockFrequency = {{INITIAL_STALL_COUNT * 1000000}};
UCHAR TscCalibrationPhase;

View file

@ -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 <timo.kreuzer@reactos.org>
* Copyright 2021 Justin Miller <justinmiller100@gmail.com>
*/
#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 <pshpack1.h>
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 <poppack.h>
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);

View file

@ -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 <reactos/version.rc>