summaryrefslogtreecommitdiffhomepage
path: root/src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2026-02-19 08:14:48 +0100
committerAmlal El Mahrouss <amlal@nekernel.org>2026-02-19 08:14:48 +0100
commitf0acad6f3206079d804b2f59aace0dc32dbeb6dc (patch)
tree44116f2771ebf146ec016337ba07d0320575dae3 /src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp
parent41117a33aa0dde66b8964b4bc0de0082fcd40667 (diff)
kernel: lots of tweaks and improvements, WIP: ASN, FileMgr support for OpenHeFS.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp')
-rw-r--r--src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp b/src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp
new file mode 100644
index 00000000..0450c71c
--- /dev/null
+++ b/src/kernel/HALKit/AMD64/HalApplicationProcessor.cpp
@@ -0,0 +1,218 @@
+// Copyright 2024-2025, Amlal El Mahrouss (amlal@nekernel.org)
+// Licensed under the Apache License, Version 2.0 (see LICENSE file)
+// Official repository: https://github.com/nekernel-org/nekernel
+
+#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 <NeKit/KernelPanic.h>
+#include <modules/ACPI/ACPIFactoryInterface.h>
+#include <modules/CoreGfx/TextGfx.h>
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/// @note: _hal_switch_context is internal.
+/// @brief The **HAL** namespace.
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+namespace Kernel::HAL {
+struct HAL_APIC_MADT;
+struct HAL_HARDWARE_THREAD;
+
+struct HAL_HARDWARE_THREAD final {
+ StackFramePtr mFramePtr;
+ ProcessID mThreadID{0};
+};
+
+EXTERN_C Void sched_jump_to_task(StackFramePtr stack_frame);
+
+STATIC HAL_APIC_MADT* kSMPBlock = nullptr;
+STATIC Bool kSMPAware = false;
+STATIC Int64 kSMPCount = 0;
+
+EXTERN_C UIntPtr kApicBaseAddress;
+
+STATIC Int32 kSMPInterrupt = 0;
+STATIC UInt64 kAPICLocales[kMaxAPInsideSched] = {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
+ UInt32 Flags; // Madt flags
+ UInt8 List[1]; // Records List
+};
+
+/// @brief Local APIC Descriptor Table.
+struct LAPIC final {
+ UInt8 Type;
+ UInt8 Length;
+ UInt8 ProcessorID;
+ UInt8 APICID;
+ UInt32 Flags;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/***********************************************************************************/
+/// @brief Send end IPI for CPU.
+/// @param apic_id
+/// @param vector
+/// @param target
+/// @return
+/***********************************************************************************/
+EXTERN_C 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, APIC_ICR_LOW) & 0x1000) {
+ NE_UNUSED(0);
+ }
+}
+
+/***********************************************************************************/
+/// @brief Get current stack frame for a thread.
+/// @param thrdid The thread ID.
+/***********************************************************************************/
+
+EXTERN_C HAL::StackFramePtr mp_get_current_task(ThreadID thrdid) {
+ if (thrdid > kSMPCount) return nullptr;
+ return kHWThread[thrdid].mFramePtr;
+}
+
+/***********************************************************************************/
+/// @brief Register current stack frame for a thread.
+/// @param stack_frame The current stack frame.
+/// @param thrdid The thread ID.
+/***********************************************************************************/
+
+EXTERN_C BOOL mp_register_task(HAL::StackFramePtr stack_frame, ThreadID thrdid) {
+ if (!stack_frame) return NO;
+
+ if (!kSMPAware) {
+ sched_jump_to_task(stack_frame);
+ return YES;
+ }
+
+ if (thrdid > kSMPCount) return NO;
+
+ kHWThread[thrdid].mThreadID = thrdid;
+ kHWThread[thrdid].mFramePtr = stack_frame;
+
+ hal_send_ipi_msg(thrdid, kAPICLocales[thrdid], kSMPInterrupt + 32);
+
+ return YES;
+}
+
+/***********************************************************************************/
+/// @brief Is the current config SMP aware?
+/// @return True if YES, False if not.
+/***********************************************************************************/
+
+Bool mp_is_smp(Void) {
+ return kSMPAware;
+}
+
+/***********************************************************************************/
+/// @brief Fetch and enable SMP scheduler.
+/// @param vendor_ptr SMP containing structure.
+/***********************************************************************************/
+
+Void mp_init_cores(VoidPtr vendor_ptr) {
+ if (!vendor_ptr) return;
+
+ 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();
+ kSMPBlock = reinterpret_cast<HAL_APIC_MADT*>(kRawMADT);
+ kSMPAware = NO;
+
+ if (kSMPBlock) {
+ kSMPInterrupt = 0;
+ kSMPCount = 0;
+
+ UInt32 lo = 0U, hi = 0U;
+
+ hal_get_msr(APIC_BASE_MSR, &lo, &hi);
+
+ UInt64 apic_base = ((UInt64) hi << 32) | lo;
+
+ apic_base |= APIC_BASE_MSR_ENABLE; // Enable APIC.
+
+ 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*>(kSMPBlock->List);
+ volatile UInt8* end_ptr = ((UInt8*) kSMPBlock) + kSMPBlock->Length;
+
+ while (entry_ptr < end_ptr) {
+ UInt8 type = *entry_ptr;
+ UInt8 length = *(entry_ptr + 1);
+
+ if (type == 0 && length == sizeof(struct LAPIC)) {
+ volatile LAPIC* entry_struct = (volatile LAPIC*) entry_ptr;
+
+ if (entry_struct->Flags & 0x1) {
+ kAPICLocales[kSMPCount] = entry_struct->ProcessorID;
+ kHWThread[kSMPCount].mThreadID = kAPICLocales[kSMPCount];
+
+ ++kSMPCount;
+
+ kout << "AP: kind: LAPIC: ON.\r";
+ } else {
+ kout << "AP: kind: LAPIC: OFF.\r";
+ }
+ } else {
+ kout << "AP: kind: UNKNOWN: OFF.\r";
+ }
+
+ entry_ptr += length;
+ }
+ }
+}
+} // namespace Kernel::HAL
+
+///////////////////////////////////////////////////////////////////////////////////////