Implement targeted IPI broadcasting using processor block array
All checks were successful
All checks were successful
This commit is contained in:
@@ -524,6 +524,8 @@ typedef struct _KPROCESSOR_BLOCK
|
|||||||
KAFFINITY SetMember;
|
KAFFINITY SetMember;
|
||||||
ULONG StallScaleFactor;
|
ULONG StallScaleFactor;
|
||||||
UCHAR CpuNumber;
|
UCHAR CpuNumber;
|
||||||
|
ULONG HardwareId;
|
||||||
|
VOLATILE BOOLEAN Started;
|
||||||
PINTERRUPT_HANDLER InterruptDispatchTable[256];
|
PINTERRUPT_HANDLER InterruptDispatchTable[256];
|
||||||
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
|
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
|
||||||
|
|
||||||
|
|||||||
@@ -483,6 +483,8 @@ typedef struct _KPROCESSOR_BLOCK
|
|||||||
KAFFINITY SetMember;
|
KAFFINITY SetMember;
|
||||||
ULONG StallScaleFactor;
|
ULONG StallScaleFactor;
|
||||||
UCHAR CpuNumber;
|
UCHAR CpuNumber;
|
||||||
|
ULONG HardwareId;
|
||||||
|
VOLATILE BOOLEAN Started;
|
||||||
PINTERRUPT_HANDLER InterruptDispatchTable[256];
|
PINTERRUPT_HANDLER InterruptDispatchTable[256];
|
||||||
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
|
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,24 @@ HL::Acpi::GetAcpiTimerInfo(OUT PACPI_TIMER_INFO *AcpiTimerInfo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ACPI system information structure containing processor and topology data.
|
||||||
|
*
|
||||||
|
* @param SystemInfo
|
||||||
|
* Supplies a pointer to the memory area where the pointer to the system information structure will be stored.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
HL::Acpi::GetSystemInformation(OUT PACPI_SYSTEM_INFO *SystemInfo)
|
||||||
|
{
|
||||||
|
/* Return a pointer to the ACPI system information */
|
||||||
|
*SystemInfo = &HL::Acpi::SystemInfo;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs an initialization of the ACPI subsystem.
|
* Performs an initialization of the ACPI subsystem.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -402,6 +402,9 @@ HL::Pic::InitializeApic(VOID)
|
|||||||
WriteApicRegister(APIC_LDR, (1UL << CpuNumber) << 24);
|
WriteApicRegister(APIC_LDR, (1UL << CpuNumber) << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Report the APIC ID to the kernel logic */
|
||||||
|
KE::Processor::RegisterHardwareId(GetCpuApicId());
|
||||||
|
|
||||||
/* Configure the spurious interrupt vector */
|
/* Configure the spurious interrupt vector */
|
||||||
SpuriousRegister.Long = ReadApicRegister(APIC_SIVR);
|
SpuriousRegister.Long = ReadApicRegister(APIC_SIVR);
|
||||||
SpuriousRegister.Vector = APIC_VECTOR_SPURIOUS;
|
SpuriousRegister.Vector = APIC_VECTOR_SPURIOUS;
|
||||||
@@ -781,25 +784,21 @@ VOID
|
|||||||
HL::Pic::SendBroadcastIpi(IN ULONG Vector,
|
HL::Pic::SendBroadcastIpi(IN ULONG Vector,
|
||||||
IN BOOLEAN Self)
|
IN BOOLEAN Self)
|
||||||
{
|
{
|
||||||
APIC_COMMAND_REGISTER Register;
|
PKPROCESSOR_BLOCK CurrentProcessorBlock, TargetProcessorBlock;
|
||||||
|
PACPI_SYSTEM_INFO SysInfo;
|
||||||
BOOLEAN Interrupts;
|
BOOLEAN Interrupts;
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
/* SMP not implemented */
|
/* Get the current processor block */
|
||||||
if(TRUE)
|
CurrentProcessorBlock = KE::Processor::GetCurrentProcessorBlock();
|
||||||
|
if(CurrentProcessorBlock == NULLPTR)
|
||||||
{
|
{
|
||||||
/* Check if IPI is addressed to the current CPU */
|
/* Processor block not available, return */
|
||||||
if(Self)
|
|
||||||
{
|
|
||||||
/* Send IPI to the current CPU */
|
|
||||||
SendSelfIpi(Vector);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
/* Get the ACPI system information */
|
||||||
/* Nothing to do */
|
HL::Acpi::GetSystemInformation(&SysInfo);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether interrupts are enabled */
|
/* Check whether interrupts are enabled */
|
||||||
Interrupts = AR::CpuFunc::InterruptsEnabled();
|
Interrupts = AR::CpuFunc::InterruptsEnabled();
|
||||||
@@ -807,32 +806,31 @@ HL::Pic::SendBroadcastIpi(IN ULONG Vector,
|
|||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
AR::CpuFunc::ClearInterruptFlag();
|
AR::CpuFunc::ClearInterruptFlag();
|
||||||
|
|
||||||
/* Prepare the APIC command register */
|
/* Iterate over all logical CPUs */
|
||||||
Register.LongLong = 0;
|
for(Index = 0; Index < SysInfo->CpuCount; Index++)
|
||||||
Register.DeliveryMode = APIC_DM_FIXED;
|
|
||||||
Register.DestinationShortHand = Self ? APIC_DSH_AllIncludingSelf : APIC_DSH_AllExclusingSelf;
|
|
||||||
Register.Level = 1;
|
|
||||||
Register.TriggerMode = APIC_TGM_EDGE;
|
|
||||||
Register.Vector = Vector;
|
|
||||||
|
|
||||||
/* Check current APIC mode */
|
|
||||||
if(ApicMode == APIC_MODE_X2APIC)
|
|
||||||
{
|
{
|
||||||
/* In x2APIC mode, writing the full 64-bit value to the ICR MSR is sufficient */
|
/* Retrieve the target processor block by its Logical CPU Number */
|
||||||
WriteApicRegister(APIC_ICR0, Register.LongLong);
|
TargetProcessorBlock = KE::Processor::GetProcessorBlock(Index);
|
||||||
|
|
||||||
|
/* Only send to processors that exist and have successfully started */
|
||||||
|
if(TargetProcessorBlock != NULLPTR && TargetProcessorBlock->Started)
|
||||||
|
{
|
||||||
|
/* Check if this processor originated the broadcast */
|
||||||
|
if(TargetProcessorBlock->HardwareId == CurrentProcessorBlock->HardwareId)
|
||||||
|
{
|
||||||
|
/* Check if this is a self broadcast */
|
||||||
|
if(Self)
|
||||||
|
{
|
||||||
|
/* Dispatch the IPI to the current processor */
|
||||||
|
SendSelfIpi(Vector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Wait for the APIC to clear the delivery status */
|
/* Dispatch the IPI to the target processor */
|
||||||
while((ReadApicRegister(APIC_ICR0) & 0x1000) != 0)
|
SendIpi(TargetProcessorBlock->HardwareId, Vector);
|
||||||
{
|
}
|
||||||
/* Yield the processor */
|
|
||||||
AR::CpuFunc::YieldProcessor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In xAPIC compatibility mode, write the command to the ICR registers */
|
|
||||||
WriteApicRegister(APIC_ICR1, Register.Long1);
|
|
||||||
WriteApicRegister(APIC_ICR0, Register.Long0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether interrupts need to be re-enabled */
|
/* Check whether interrupts need to be re-enabled */
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace HL
|
|||||||
STATIC XTAPI XTSTATUS GetAcpiTable(IN ULONG Signature,
|
STATIC XTAPI XTSTATUS GetAcpiTable(IN ULONG Signature,
|
||||||
OUT PACPI_DESCRIPTION_HEADER *AcpiTable);
|
OUT PACPI_DESCRIPTION_HEADER *AcpiTable);
|
||||||
STATIC XTAPI VOID GetAcpiTimerInfo(OUT PACPI_TIMER_INFO *AcpiTimerInfo);
|
STATIC XTAPI VOID GetAcpiTimerInfo(OUT PACPI_TIMER_INFO *AcpiTimerInfo);
|
||||||
|
STATIC XTAPI VOID GetSystemInformation(OUT PACPI_SYSTEM_INFO *SystemInfo);
|
||||||
STATIC XTAPI XTSTATUS InitializeAcpi(VOID);
|
STATIC XTAPI XTSTATUS InitializeAcpi(VOID);
|
||||||
STATIC XTAPI XTSTATUS InitializeAcpiSystemInformation(VOID);
|
STATIC XTAPI XTSTATUS InitializeAcpiSystemInformation(VOID);
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,18 @@ namespace KE
|
|||||||
{
|
{
|
||||||
class Processor
|
class Processor
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
STATIC ULONG InstalledCpus;
|
||||||
|
STATIC PKPROCESSOR_BLOCK *ProcessorBlocks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STATIC XTAPI PKPROCESSOR_BLOCK GetCurrentProcessorBlock(VOID);
|
STATIC XTAPI PKPROCESSOR_BLOCK GetCurrentProcessorBlock(VOID);
|
||||||
STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID);
|
STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID);
|
||||||
STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID);
|
STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID);
|
||||||
STATIC XTAPI PKTHREAD GetCurrentThread(VOID);
|
STATIC XTAPI PKTHREAD GetCurrentThread(VOID);
|
||||||
|
STATIC XTAPI PKPROCESSOR_BLOCK GetProcessorBlock(IN ULONG CpuNumber);
|
||||||
|
STATIC XTAPI XTSTATUS InitializeProcessorStructures(IN ULONG CpuCount);
|
||||||
|
STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId);
|
||||||
STATIC XTAPI VOID SaveProcessorState(OUT PKPROCESSOR_STATE CpuState);
|
STATIC XTAPI VOID SaveProcessorState(OUT PKPROCESSOR_STATE CpuState);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,92 @@ KE::Processor::GetCurrentThread(VOID)
|
|||||||
return (PKTHREAD)AR::CpuFunc::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
return (PKTHREAD)AR::CpuFunc::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the processor block for the specified processor number.
|
||||||
|
*
|
||||||
|
* @param CpuNumber
|
||||||
|
* Supplies the zero-indexed processor number.
|
||||||
|
*
|
||||||
|
* @return This routine returns a pointer to the processor block, or NULLPTR if invalid.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
PKPROCESSOR_BLOCK
|
||||||
|
KE::Processor::GetProcessorBlock(IN ULONG CpuNumber)
|
||||||
|
{
|
||||||
|
/* Check if the requested CPU number is within dynamic bounds */
|
||||||
|
if(ProcessorBlocks == NULLPTR || CpuNumber >= InstalledCpus)
|
||||||
|
{
|
||||||
|
/* Invalid CPU number, return NULLPTR */
|
||||||
|
return NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return requested processor block */
|
||||||
|
return ProcessorBlocks[CpuNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the global processor structures by allocating an array of processor block pointers.
|
||||||
|
*
|
||||||
|
* @param CpuCount
|
||||||
|
* Supplies the total number of processors present in the system.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code indicating the success or failure of the allocation.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
KE::Processor::InitializeProcessorStructures(IN ULONG CpuCount)
|
||||||
|
{
|
||||||
|
XTSTATUS Status;
|
||||||
|
|
||||||
|
/* Save number of CPUs installed */
|
||||||
|
InstalledCpus = CpuCount;
|
||||||
|
|
||||||
|
/* Allocate an array of pointers */
|
||||||
|
Status = MM::Allocator::AllocatePool(NonPagedPool,
|
||||||
|
CpuCount * sizeof(PKPROCESSOR_BLOCK),
|
||||||
|
(PVOID*)&ProcessorBlocks);
|
||||||
|
if(Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to allocate memory, return error */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero the array initially */
|
||||||
|
RTL::Memory::ZeroMemory(ProcessorBlocks, CpuCount * sizeof(PKPROCESSOR_BLOCK));
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the hardware APIC ID for the currently executing processor.
|
||||||
|
*
|
||||||
|
* @param ApicId
|
||||||
|
* Supplies the hardware APIC ID to register in the processor block.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
KE::Processor::RegisterHardwareId(IN ULONG HardwareId)
|
||||||
|
{
|
||||||
|
PKPROCESSOR_BLOCK CurrentBlock;
|
||||||
|
|
||||||
|
/* Retrieve the processor block for the executing core */
|
||||||
|
CurrentBlock = GetCurrentProcessorBlock();
|
||||||
|
if(CurrentBlock != NULLPTR)
|
||||||
|
{
|
||||||
|
/* Register the hardware identifier for IPI targeting */
|
||||||
|
CurrentBlock->HardwareId = HardwareId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the current processor state.
|
* Saves the current processor state.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ ETHREAD KE::KThread::InitialThread = {};
|
|||||||
/* Kernel UBSAN active frame flag */
|
/* Kernel UBSAN active frame flag */
|
||||||
BOOLEAN KE::KUbsan::ActiveFrame = FALSE;
|
BOOLEAN KE::KUbsan::ActiveFrame = FALSE;
|
||||||
|
|
||||||
|
/* Total number of installed processors in the system */
|
||||||
|
ULONG KE::Processor::InstalledCpus;
|
||||||
|
|
||||||
|
/* Array of pointers to processor control blocks */
|
||||||
|
PKPROCESSOR_BLOCK *KE::Processor::ProcessorBlocks;
|
||||||
|
|
||||||
/* Kernel shared data (KSD) */
|
/* Kernel shared data (KSD) */
|
||||||
PKSHARED_DATA KE::SharedData::KernelSharedData;
|
PKSHARED_DATA KE::SharedData::KernelSharedData;
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,92 @@ KE::Processor::GetCurrentThread(VOID)
|
|||||||
return (PKTHREAD)AR::CpuFunc::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
return (PKTHREAD)AR::CpuFunc::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the processor block for the specified processor number.
|
||||||
|
*
|
||||||
|
* @param CpuNumber
|
||||||
|
* Supplies the zero-indexed processor number.
|
||||||
|
*
|
||||||
|
* @return This routine returns a pointer to the processor block, or NULLPTR if invalid.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
PKPROCESSOR_BLOCK
|
||||||
|
KE::Processor::GetProcessorBlock(IN ULONG CpuNumber)
|
||||||
|
{
|
||||||
|
/* Check if the requested CPU number is within dynamic bounds */
|
||||||
|
if(ProcessorBlocks == NULLPTR || CpuNumber >= InstalledCpus)
|
||||||
|
{
|
||||||
|
/* Invalid CPU number, return NULLPTR */
|
||||||
|
return NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return requested processor block */
|
||||||
|
return ProcessorBlocks[CpuNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the global processor structures by allocating an array of processor block pointers.
|
||||||
|
*
|
||||||
|
* @param CpuCount
|
||||||
|
* Supplies the total number of processors present in the system.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code indicating the success or failure of the allocation.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
KE::Processor::InitializeProcessorStructures(IN ULONG CpuCount)
|
||||||
|
{
|
||||||
|
XTSTATUS Status;
|
||||||
|
|
||||||
|
/* Save number of CPUs installed */
|
||||||
|
InstalledCpus = CpuCount;
|
||||||
|
|
||||||
|
/* Allocate an array of pointers */
|
||||||
|
Status = MM::Allocator::AllocatePool(NonPagedPool,
|
||||||
|
CpuCount * sizeof(PKPROCESSOR_BLOCK),
|
||||||
|
(PVOID*)&ProcessorBlocks);
|
||||||
|
if(Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to allocate memory, return error */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero the array initially */
|
||||||
|
RTL::Memory::ZeroMemory(ProcessorBlocks, CpuCount * sizeof(PKPROCESSOR_BLOCK));
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the hardware APIC ID for the currently executing processor.
|
||||||
|
*
|
||||||
|
* @param ApicId
|
||||||
|
* Supplies the hardware APIC ID to register in the processor block.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
VOID
|
||||||
|
KE::Processor::RegisterHardwareId(IN ULONG HardwareId)
|
||||||
|
{
|
||||||
|
PKPROCESSOR_BLOCK CurrentBlock;
|
||||||
|
|
||||||
|
/* Retrieve the processor block for the executing core */
|
||||||
|
CurrentBlock = GetCurrentProcessorBlock();
|
||||||
|
if(CurrentBlock != NULLPTR)
|
||||||
|
{
|
||||||
|
/* Register the hardware identifier for IPI targeting */
|
||||||
|
CurrentBlock->HardwareId = HardwareId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the current processor state.
|
* Saves the current processor state.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user