diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2025-05-29 10:51:53 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-29 10:51:53 +0200 |
| commit | 5c0bb7ee7b1b0fee02cc179fb21f4c57a61d6c2d (patch) | |
| tree | cb17577bcdc9714c97a84ce417a075117097f146 /dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | |
| parent | d608230b1350b064ceb01e6572519b108f6139b0 (diff) | |
| parent | 3167f59dbb401d6a79b1524537e04218baf49ee3 (diff) | |
Merge pull request #32 from nekernel-org/dev
0.0.2e3
Diffstat (limited to 'dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc')
| -rw-r--r-- | dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | 246 |
1 files changed, 117 insertions, 129 deletions
diff --git a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc index dd9a36ed..3e10d577 100644 --- a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc +++ b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc @@ -4,27 +4,34 @@ ------------------------------------------- */ +#define APIC_MAG "APIC" + +#define APIC_ICR_LOW 0x300 +#define APIC_ICR_HIGH 0x310 +#define APIC_SIPI_VEC 0x00500 +#define APIC_EIPI_VEC 0x00400 + +#define LAPIC_REG_TIMER_LVT 0x320 +#define LAPIC_REG_TIMER_INITCNT 0x380 +#define LAPIC_REG_TIMER_CURRCNT 0x390 +#define LAPIC_REG_TIMER_DIV 0x3E0 +#define LAPIC_REG_ENABLE 0x80 +#define LAPIC_REG_SPURIOUS 0xF0 + +#define APIC_BASE_MSR 0x1B +#define APIC_BASE_MSR_BSP 0x100 +#define APIC_BASE_MSR_ENABLE 0x800 + #include <ArchKit/ArchKit.h> #include <HALKit/AMD64/Processor.h> #include <KernelKit/BinaryMutex.h> #include <KernelKit/HardwareThreadScheduler.h> #include <KernelKit/ProcessScheduler.h> #include <KernelKit/Timer.h> -#include <NewKit/KernelPanic.h> +#include <NeKit/KernelPanic.h> #include <modules/ACPI/ACPIFactoryInterface.h> #include <modules/CoreGfx/TextGfx.h> -#define kAPIC_Signature "APIC" - -#define kAPIC_ICR_Low 0x300 -#define kAPIC_ICR_High 0x310 -#define kAPIC_SIPI_Vector 0x00500 -#define kAPIC_EIPI_Vector 0x00400 - -#define kAPIC_BASE_MSR 0x1B -#define kAPIC_BASE_MSR_BSP 0x100 -#define kAPIC_BASE_MSR_ENABLE 0x800 - /// @note: _hal_switch_context is internal /////////////////////////////////////////////////////////////////////////////////////// @@ -39,83 +46,39 @@ struct HAL_HARDWARE_THREAD; struct HAL_HARDWARE_THREAD final { HAL::StackFramePtr mFramePtr; - ProcessID mProcessID{0}; - UInt8 mCoreID{0}; + ProcessID mThreadID{0}; }; +EXTERN_C Void sched_jump_to_task(HAL::StackFramePtr stack_frame); + STATIC HAL_APIC_MADT* kMADTBlock = nullptr; STATIC Bool kSMPAware = false; STATIC Int64 kSMPCount = 0; -STATIC UIntPtr kApicBaseAddress = 0UL; +EXTERN_C UIntPtr kApicBaseAddress; + +STATIC Int32 kSMPInterrupt = 0; +STATIC UInt64 kAPICLocales[kMaxAPInsideSched] = {0}; +STATIC VoidPtr kRawMADT = nullptr; -STATIC Int32 kSMPInterrupt = 0; -STATIC UInt64 kAPICLocales[kSchedProcessLimitPerTeam] = {0}; -STATIC VoidPtr kRawMADT = nullptr; +STATIC HAL_HARDWARE_THREAD kHWThread[kSchedProcessLimitPerTeam] = {{}}; /// @brief Multiple APIC Descriptor Table. struct HAL_APIC_MADT final SDT_OBJECT { UInt32 Address; // Madt address - UInt8 Flags; // Madt flags - - struct { - UInt8 Type; - UInt8 Len; - - union APIC { - struct IOAPIC { - UInt8 IoID; - UInt8 Zero; - UInt32 IoAddress; - UInt32 GISBase; - } IOAPIC; - - struct LAPIC_NMI { - UInt8 Source; - UInt8 IRQSource; - UInt32 GSI; - UInt16 Flags; - } LApicNMI; - - struct LAPIC { - UInt8 ProcessorID; - UInt16 Flags; - UInt8 LINT; - } LAPIC; - - struct LAPIC_OVERRIDE { - UInt16 Reserved; - UInt64 Address; - } LApicOverride; - - struct LAPIC_X2 { - UInt16 Reserved; - UInt32 x2APICID; - UInt32 Flags; - UInt32 AcpiID; - } LocalApicX2; - } Apic; - } List[1]; // Records List + UInt32 Flags; // Madt flags + UInt8 List[1]; // Records List }; -/////////////////////////////////////////////////////////////////////////////////////// - -/***********************************************************************************/ -/// @brief Send IPI command to APIC. -/// @param apic_id programmable interrupt controller id. -/// @param vector vector interrupt. -/// @param target target APIC adress. -/// @return -/***********************************************************************************/ - -Void hal_send_start_ipi(UInt32 target, UInt32 apic_id) { - Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_High, apic_id << 24); - Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_Low, 0x00000500 | 0x00004000 | 0x00000000); +struct LAPIC final { + UInt8 Type; + UInt8 Length; + UInt8 ProcessorID; + UInt8 APICID; + UInt32 Flags; +}; - while (Kernel::ke_dma_read<UInt32>(target, kAPIC_ICR_Low) & 0x1000) { - ; - } -} +/////////////////////////////////////////////////////////////////////////////////////// /***********************************************************************************/ /// @brief Send end IPI for CPU. @@ -124,36 +87,40 @@ Void hal_send_start_ipi(UInt32 target, UInt32 apic_id) { /// @param target /// @return /***********************************************************************************/ -Void hal_send_sipi(UInt32 target, UInt32 apic_id, UInt8 vector) { - Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_High, apic_id << 24); - Kernel::ke_dma_write<UInt32>(target, kAPIC_ICR_Low, - 0x00000600 | 0x00004000 | 0x00000000 | vector); +Void hal_send_ipi_msg(UInt32 target, UInt32 apic_id, UInt8 vector) { + Kernel::ke_dma_write<UInt32>(target, APIC_ICR_HIGH, apic_id << 24); + Kernel::ke_dma_write<UInt32>(target, APIC_ICR_LOW, 0x00000600 | 0x00004000 | 0x00000000 | vector); - while (Kernel::ke_dma_read<UInt32>(target, kAPIC_ICR_Low) & 0x1000) { + while (Kernel::ke_dma_read<UInt32>(target, APIC_ICR_LOW) & 0x1000) { NE_UNUSED(0); } } -STATIC HAL_HARDWARE_THREAD kHWThread[kSchedProcessLimitPerTeam] = {{}}; - -EXTERN_C HAL::StackFramePtr mp_get_current_context(Int64 pid) { - const auto process_index = pid % kSchedProcessLimitPerTeam; +/***********************************************************************************/ +/// @brief Get current stack frame for a thread. +/// @param thrdid The thread ID. +/***********************************************************************************/ - return kHWThread[process_index].mFramePtr; +EXTERN_C HAL::StackFramePtr mp_get_current_task(ThreadID thrdid) { + if (thrdid > kSMPCount) return nullptr; + return kHWThread[thrdid].mFramePtr; } -EXTERN_C BOOL mp_register_process(HAL::StackFramePtr stack_frame, ProcessID pid) { - MUST_PASS(stack_frame); +/***********************************************************************************/ +/// @brief Register current stack frame for a thread. +/// @param stack_frame The current stack frame. +/// @param thrdid The thread ID. +/***********************************************************************************/ - const auto process_index = pid % kSchedProcessLimitPerTeam; +EXTERN_C BOOL mp_register_task(HAL::StackFramePtr stack_frame, ThreadID thrdid) { + if (thrdid > kSMPCount) return NO; + if (!stack_frame) return NO; - kHWThread[process_index].mFramePtr = stack_frame; - kHWThread[process_index].mProcessID = pid; + kHWThread[thrdid].mFramePtr = stack_frame; - kHWThread[process_index].mCoreID = kAPICLocales[0]; + HardwareThreadScheduler::The()[thrdid].Leak()->Busy(NO); - hal_send_sipi(kApicBaseAddress, kHWThread[process_index].mCoreID, - (UInt8) (((UIntPtr) stack_frame->BP) >> 12)); + sched_jump_to_task(kHWThread[thrdid].mFramePtr); return YES; } @@ -162,24 +129,16 @@ EXTERN_C BOOL mp_register_process(HAL::StackFramePtr stack_frame, ProcessID pid) /// @brief Is the current config SMP aware? /// @return True if YES, False if not. /***********************************************************************************/ + Bool mp_is_smp(Void) noexcept { return kSMPAware; } /***********************************************************************************/ -/// @brief Assembly symbol to bootstrap AP. -/***********************************************************************************/ -EXTERN_C Char* hal_ap_blob_start; - -/***********************************************************************************/ -/// @brief Assembly symbol to bootstrap AP. -/***********************************************************************************/ -EXTERN_C Char* hal_ap_blob_end; - -/***********************************************************************************/ /// @brief Fetch and enable SMP scheduler. /// @param vendor_ptr SMP containing structure. /***********************************************************************************/ + Void mp_init_cores(VoidPtr vendor_ptr) noexcept { if (!vendor_ptr) return; @@ -188,51 +147,80 @@ Void mp_init_cores(VoidPtr vendor_ptr) noexcept { return; } - auto hw_and_pow_int = PowerFactoryInterface(vendor_ptr); - kRawMADT = hw_and_pow_int.Find(kAPIC_Signature).Leak().Leak(); + PowerFactoryInterface hw_and_pow_int{vendor_ptr}; + auto pwr = hw_and_pow_int.Find(APIC_MAG); + + if (pwr.HasError()) { + kSMPAware = NO; + return; + } + + kRawMADT = pwr.Leak().Leak(); kMADTBlock = reinterpret_cast<HAL_APIC_MADT*>(kRawMADT); kSMPAware = NO; if (kMADTBlock) { - SizeT index = 1; - kSMPInterrupt = 0; kSMPCount = 0; - kout << "SMP: Starting APs...\r"; + UInt32 lo = 0U, hi = 0U; - kApicBaseAddress = kMADTBlock->Address; + hal_get_msr(APIC_BASE_MSR, &lo, &hi); - while (Yes) { - /// @note Anything bigger than x2APIC type doesn't exist. - if (kMADTBlock->List[index].Type > 9 || kSMPCount > kSchedProcessLimitPerTeam) break; + UInt64 apic_base = ((UInt64) hi << 32) | lo; - switch (kMADTBlock->List[index].Type) { - case 0x00: { - if (kMADTBlock->List[kSMPCount].Apic.LAPIC.ProcessorID < 1) break; + apic_base |= APIC_BASE_MSR_ENABLE; // Enable APIC. - kAPICLocales[kSMPCount] = kMADTBlock->List[kSMPCount].Apic.LAPIC.ProcessorID; - (Void)(kout << "SMP: APIC ID: " << number(kAPICLocales[kSMPCount]) << kendl); + lo = apic_base & 0xFFFFFFFF; + hi = apic_base >> 32; + hal_set_msr(APIC_BASE_MSR, lo, hi); + + kApicBaseAddress = apic_base & 0xFFFFF000; + + LAPICDmaWrapper controller{(VoidPtr) kApicBaseAddress}; + + controller.Write(LAPIC_REG_ENABLE, 0); + controller.Write(LAPIC_REG_SPURIOUS, 0x1FF); // Enable bit, spurious interrupt vector register. + controller.Write(LAPIC_REG_TIMER_DIV, 0b0011); + controller.Write(LAPIC_REG_TIMER_LVT, 0x20 | (1 << 17)); + controller.Write(LAPIC_REG_TIMER_INITCNT, 1000000); + + volatile UInt8* entry_ptr = reinterpret_cast<volatile UInt8*>(kMADTBlock->List); + volatile UInt8* end_ptr = ((UInt8*) kMADTBlock) + kMADTBlock->Length; + + while (entry_ptr < end_ptr) { + UInt8 type = *entry_ptr; + UInt8 length = *(entry_ptr + 1); + + // Avoid infinite loop on bad APIC tables. + if (length < 2) break; + + if (type == 0) { + volatile LAPIC* entry_struct = (volatile LAPIC*) entry_ptr; + + if (entry_struct->Flags & 0x1) { + kAPICLocales[kSMPCount] = entry_struct->ProcessorID; + kHWThread[kSMPCount].mThreadID = kAPICLocales[kSMPCount]; + ++kSMPCount; - break; + + kout << "Kind: LAPIC: ON\r"; + + // 0x7c00, as recommended by the Intel SDM. + hal_send_ipi_msg(kApicBaseAddress, entry_struct->ProcessorID, 0x7c); + } else { + kout << "Kind: LAPIC: OFF\r"; } - default: - break; + } else { + kout << "Kind: UNKNOWN\r"; } - ++index; + entry_ptr += length; } - (Void)(kout << "SMP: Number of APs: " << number(kSMPCount) << kendl); - - // Kernel is now SMP aware. - // That means that the scheduler is now available (on MP Kernels) - - kSMPAware = true; - - /// TODO: Notify Boot AP that it must start. + kSMPAware = kSMPCount > 1; } } } // namespace Kernel::HAL |
