summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit
diff options
context:
space:
mode:
authorAmlal <amlalelmahrouss@icloud.com>2024-12-21 21:59:13 +0100
committerAmlal <amlalelmahrouss@icloud.com>2024-12-21 21:59:45 +0100
commit610f91d87152cbe48d3054fcf437d8239da6ef35 (patch)
treea386f7047ab73d088169ab2371ddc6ffe8020f1c /dev/Kernel/HALKit
parent509fcca5986651c8ba712fb395f8498f2dea4109 (diff)
IMP: :boom: Breaking changes some checks are needed to be done.
Signed-off-by: Amlal <amlalelmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit')
-rw-r--r--dev/Kernel/HALKit/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/64x0/.hgkeep0
-rw-r--r--dev/Kernel/HALKit/64x0/APM/.hgkeep0
-rw-r--r--dev/Kernel/HALKit/64x0/HalVirtualMemory.cc17
-rw-r--r--dev/Kernel/HALKit/64x0/MBCI/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/64x0/ReadMe.md4
-rw-r--r--dev/Kernel/HALKit/AMD64/CPUID.h86
-rw-r--r--dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cc126
-rw-r--r--dev/Kernel/HALKit/AMD64/HalAP.cc51
-rw-r--r--dev/Kernel/HALKit/AMD64/HalAPICController.cc39
-rw-r--r--dev/Kernel/HALKit/AMD64/HalBoot.asm28
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCPUAMD64.cc101
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCommonAPI.asm53
-rw-r--r--dev/Kernel/HALKit/AMD64/HalControlRegister.s45
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc232
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCoreScheduler.cc240
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDebugOutput.cc146
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDebugPort.cc40
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc126
-rw-r--r--dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm406
-rw-r--r--dev/Kernel/HALKit/AMD64/HalKernelMain.cc103
-rw-r--r--dev/Kernel/HALKit/AMD64/HalPagingMgrAMD64.cc168
-rw-r--r--dev/Kernel/HALKit/AMD64/HalRoutineWait.s11
-rw-r--r--dev/Kernel/HALKit/AMD64/HalTimerAMD64.cc86
-rw-r--r--dev/Kernel/HALKit/AMD64/HalUtils.asm27
-rw-r--r--dev/Kernel/HALKit/AMD64/Hypervisor.h25
-rw-r--r--dev/Kernel/HALKit/AMD64/MBCI/HalMBCI.cc7
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/DMA.cc82
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Database.cc11
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Device.cc139
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Express.cc11
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/IO.cc7
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Iterator.cc41
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/PCI.cc7
-rw-r--r--dev/Kernel/HALKit/AMD64/Paging.h99
-rw-r--r--dev/Kernel/HALKit/AMD64/Processor.h331
-rw-r--r--dev/Kernel/HALKit/AMD64/ReadMe.md8
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/AHCI-DMA.cc319
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cc38
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cc197
-rw-r--r--dev/Kernel/HALKit/ARM64/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/ARM64/AP.h36
-rw-r--r--dev/Kernel/HALKit/ARM64/APM/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/ARM64/APM/APM.cc37
-rw-r--r--dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc31
-rw-r--r--dev/Kernel/HALKit/ARM64/HalAP.cc40
-rw-r--r--dev/Kernel/HALKit/ARM64/HalCoreMPScheduler.cc28
-rw-r--r--dev/Kernel/HALKit/ARM64/HalDebugOutput.cc83
-rw-r--r--dev/Kernel/HALKit/ARM64/HalKernelMain.cc57
-rw-r--r--dev/Kernel/HALKit/ARM64/HalPageInternal.S5
-rw-r--r--dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc86
-rw-r--r--dev/Kernel/HALKit/ARM64/HalSchedulerCore.cc34
-rw-r--r--dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc40
-rw-r--r--dev/Kernel/HALKit/ARM64/HalTimerARM64.cc14
-rw-r--r--dev/Kernel/HALKit/ARM64/MBCI/.keepme0
-rw-r--r--dev/Kernel/HALKit/ARM64/Paging.h120
-rw-r--r--dev/Kernel/HALKit/ARM64/Processor.h75
-rw-r--r--dev/Kernel/HALKit/ARM64/ReadMe.md3
-rw-r--r--dev/Kernel/HALKit/ARM64/Storage/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/ARM64/Storage/HalFlash.cc66
-rw-r--r--dev/Kernel/HALKit/AXP/CR.s11
-rw-r--r--dev/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp0
-rw-r--r--dev/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp24
-rw-r--r--dev/Kernel/HALKit/AXP/HAL.s13
-rw-r--r--dev/Kernel/HALKit/AXP/Processor.h7
-rw-r--r--dev/Kernel/HALKit/AXP/README1
-rw-r--r--dev/Kernel/HALKit/AXP/README.TXT1
-rw-r--r--dev/Kernel/HALKit/AXP/SYSCALL.s10
-rw-r--r--dev/Kernel/HALKit/AXP/VM.s5
-rw-r--r--dev/Kernel/HALKit/POWER/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/POWER/AP.h39
-rw-r--r--dev/Kernel/HALKit/POWER/APM/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/POWER/HalAP.cc40
-rw-r--r--dev/Kernel/HALKit/POWER/HalDebugOutput.cc27
-rw-r--r--dev/Kernel/HALKit/POWER/HalStartSequence.s14
-rw-r--r--dev/Kernel/HALKit/POWER/HalThread.cc8
-rw-r--r--dev/Kernel/HALKit/POWER/HalVirtualMemory.cc49
-rw-r--r--dev/Kernel/HALKit/POWER/MBCI/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cc8
-rw-r--r--dev/Kernel/HALKit/POWER/Processor.h62
-rw-r--r--dev/Kernel/HALKit/POWER/ReadMe.md4
-rw-r--r--dev/Kernel/HALKit/RISCV/.keep0
-rw-r--r--dev/Kernel/HALKit/RISCV/AP.h36
-rw-r--r--dev/Kernel/HALKit/RISCV/APM/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/RISCV/HalAP.cc40
-rw-r--r--dev/Kernel/HALKit/RISCV/ReadMe.md4
-rw-r--r--dev/Kernel/HALKit/RISCV/Storage/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/X86S/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/X86S/ACPI/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/X86S/Storage/.gitkeep0
90 files changed, 4615 insertions, 0 deletions
diff --git a/dev/Kernel/HALKit/.gitkeep b/dev/Kernel/HALKit/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/.gitkeep
diff --git a/dev/Kernel/HALKit/64x0/.hgkeep b/dev/Kernel/HALKit/64x0/.hgkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/64x0/.hgkeep
diff --git a/dev/Kernel/HALKit/64x0/APM/.hgkeep b/dev/Kernel/HALKit/64x0/APM/.hgkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/64x0/APM/.hgkeep
diff --git a/dev/Kernel/HALKit/64x0/HalVirtualMemory.cc b/dev/Kernel/HALKit/64x0/HalVirtualMemory.cc
new file mode 100644
index 00000000..6dd40325
--- /dev/null
+++ b/dev/Kernel/HALKit/64x0/HalVirtualMemory.cc
@@ -0,0 +1,17 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+
+using namespace Kernel;
+
+/// @brief Flush system TLB, looks like the POWER version, as it acts the same, no specific instruction for that.
+/// @note The 88K MMU should be present as well.
+EXTERN_C void hal_flush_tlb()
+{
+ asm volatile("invltlb");
+}
diff --git a/dev/Kernel/HALKit/64x0/MBCI/.gitkeep b/dev/Kernel/HALKit/64x0/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/64x0/MBCI/.gitkeep
diff --git a/dev/Kernel/HALKit/64x0/ReadMe.md b/dev/Kernel/HALKit/64x0/ReadMe.md
new file mode 100644
index 00000000..c131541e
--- /dev/null
+++ b/dev/Kernel/HALKit/64x0/ReadMe.md
@@ -0,0 +1,4 @@
+64x0 Hardware Abstraction Layer
+
+- Supported CPU: TQ B.V 64x0
+- Supported Firmware: CoreBoot
diff --git a/dev/Kernel/HALKit/AMD64/CPUID.h b/dev/Kernel/HALKit/AMD64/CPUID.h
new file mode 100644
index 00000000..44e1d842
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/CPUID.h
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: CPUID.h
+ Purpose: CPUID flags.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+enum CPUFeatureEnum
+{
+ kCPUFeatureSSE3 = 1 << 0,
+ kCPUFeaturePCLMUL = 1 << 1,
+ kCPUFeatureDTES64 = 1 << 2,
+ kCPUFeatureMONITOR = 1 << 3,
+ kCPUFeatureDS_CPL = 1 << 4,
+ kCPUFeatureVMX = 1 << 5,
+ kCPUFeatureSMX = 1 << 6,
+ kCPUFeatureEST = 1 << 7,
+ kCPUFeatureTM2 = 1 << 8,
+ kCPUFeatureSSSE3 = 1 << 9,
+ kCPUFeatureCID = 1 << 10,
+ kCPUFeatureSDBG = 1 << 11,
+ kCPUFeatureFMA = 1 << 12,
+ kCPUFeatureCX16 = 1 << 13,
+ kCPUFeatureXTPR = 1 << 14,
+ kCPUFeaturePDCM = 1 << 15,
+ kCPUFeaturePCID = 1 << 17,
+ kCPUFeatureDCA = 1 << 18,
+ kCPUFeatureSSE4_1 = 1 << 19,
+ kCPUFeatureSSE4_2 = 1 << 20,
+ kCPUFeatureX2APIC = 1 << 21,
+ kCPUFeatureMOVBE = 1 << 22,
+ kCPUFeaturePOP3C = 1 << 23,
+ kCPUFeatureECXTSC = 1 << 24,
+ kCPUFeatureAES = 1 << 25,
+ kCPUFeatureXSAVE = 1 << 26,
+ kCPUFeatureOSXSAVE = 1 << 27,
+ kCPUFeatureAVX = 1 << 28,
+ kCPUFeatureF16C = 1 << 29,
+ kCPUFeatureRDRAND = 1 << 30,
+ kCPUFeatureHYPERVISOR = 1 << 31,
+ kCPUFeatureFPU = 1 << 0,
+ kCPUFeatureVME = 1 << 1,
+ kCPUFeatureDE = 1 << 2,
+ kCPUFeaturePSE = 1 << 3,
+ kCPUFeatureEDXTSC = 1 << 4,
+ kCPUFeatureMSR = 1 << 5,
+ kCPUFeaturePAE = 1 << 6,
+ kCPUFeatureMCE = 1 << 7,
+ kCPUFeatureCX8 = 1 << 8,
+ kCPUFeatureAPIC = 1 << 9,
+ kCPUFeatureSEP = 1 << 11,
+ kCPUFeatureMTRR = 1 << 12,
+ kCPUFeaturePGE = 1 << 13,
+ kCPUFeatureMCA = 1 << 14,
+ kCPUFeatureCMOV = 1 << 15,
+ kCPUFeaturePAT = 1 << 16,
+ kCPUFeaturePSE36 = 1 << 17,
+ kCPUFeaturePSN = 1 << 18,
+ kCPUFeatureCLFLUSH = 1 << 19,
+ kCPUFeatureDS = 1 << 21,
+ kCPUFeatureACPI = 1 << 22,
+ kCPUFeatureMMX = 1 << 23,
+ kCPUFeatureFXSR = 1 << 24,
+ kCPUFeatureSSE = 1 << 25,
+ kCPUFeatureSSE2 = 1 << 26,
+ kCPUFeatureSS = 1 << 27,
+ kCPUFeatureHTT = 1 << 28,
+ kCPUFeatureTM = 1 << 29,
+ kCPUFeatureIA64 = 1 << 30,
+ kCPUFeaturePBE = 1 << 31
+};
+
+namespace Kernel
+{
+ typedef Int64 CPUID;
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cc b/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cc
new file mode 100644
index 00000000..f742c3d7
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cc
@@ -0,0 +1,126 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <HALKit/AMD64/Processor.h>
+#include <NewKit/KString.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Heap.h>
+
+namespace Kernel
+{
+ namespace Detail
+ {
+ struct FADT final : public SDT
+ {
+ UInt32 FirmwareCtrl;
+ UInt32 Dsdt;
+
+ // field used in ACPI 1.0; no longer in use, for compatibility only
+ UInt8 Reserved;
+
+ UInt8 PreferredPowerManagementProfile;
+ UInt16 SCI_Interrupt;
+ UInt32 SMI_CommandPort;
+ UInt8 AcpiEnable;
+ UInt8 AcpiDisable;
+ UInt8 S4BIOS_REQ;
+ UInt8 PSTATE_Control;
+ UInt32 PM1aEventBlock;
+ UInt32 PM1bEventBlock;
+ UInt32 PM1aControlBlock;
+ UInt32 PM1bControlBlock;
+ UInt32 PM2ControlBlock;
+ UInt32 PMTimerBlock;
+ UInt32 GPE0Block;
+ UInt32 GPE1Block;
+ UInt8 PM1EventLength;
+ UInt8 PM1ControlLength;
+ UInt8 PM2ControlLength;
+ UInt8 PMTimerLength;
+ UInt8 GPE0Length;
+ UInt8 GPE1Length;
+ UInt8 GPE1Base;
+ UInt8 CStateControl;
+ UInt16 WorstC2Latency;
+ UInt16 WorstC3Latency;
+ UInt16 FlushSize;
+ UInt16 FlushStride;
+ UInt8 DutyOffset;
+ UInt8 DutyWidth;
+ UInt8 DayAlarm;
+ UInt8 MonthAlarm;
+ UInt8 Century;
+
+ // reserved in ACPI 1.0; used since ACPI 2.0+
+ UInt16 BootArchitecturkMMFlags;
+
+ UInt8 Reserved2;
+ UInt32 Flags;
+
+ // 12 byte structure; see below for details
+ ACPI_ADDRESS ResetReg;
+
+ UInt8 ResetValue;
+ UInt8 Reserved3[3];
+
+ // 64bit pointers - Available on ACPI 2.0+
+ UInt64 X_FirmwareControl;
+ UInt64 X_Dsdt;
+
+ ACPI_ADDRESS X_PM1aEventBlock;
+ ACPI_ADDRESS X_PM1bEventBlock;
+ ACPI_ADDRESS X_PM1aControlBlock;
+ ACPI_ADDRESS X_PM1bControlBlock;
+ ACPI_ADDRESS X_PM2ControlBlock;
+ ACPI_ADDRESS X_PMTimerBlock;
+ ACPI_ADDRESS X_GPE0Block;
+ ACPI_ADDRESS X_GPE1Block;
+ };
+ } // namespace Detail
+
+ ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsp_ptr)
+ : fRsdp(rsp_ptr), fEntries(0)
+ {
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+ failed_to_shutdown:
+ // in case no acpi mode, or it's not available.
+ while (Yes)
+ {
+ asm volatile("cli; hlt");
+ }
+ }
+
+ /// @brief Reboot machine in either ACPI or by triple faulting.
+ /// @return nothing it's a reboot.
+ Void ACPIFactoryInterface::Reboot()
+ {
+ failed_to_reboot:
+ asm volatile(".intel_syntax noprefix; "
+ "rt_reset_hardware:; "
+ "cli; "
+ "wait_gate1: ; "
+ "in al,0x64 ; "
+ "and al,2 ; "
+ "jnz wait_gate1 ; "
+ "mov al,0x0D1 ; "
+ "out 0x64,al ; "
+ "wait_gate2: ; "
+ "in al,0x64 ; "
+ "and al,2 ; "
+ "jnz wait_gate2 ; "
+ "mov al,0x0FE ; "
+ "out 0x60,al ; "
+ "xor rax,rax ; "
+ "lidt [rax] ; "
+ "reset_wait: ; "
+ "jmp reset_wait ; "
+ ".att_syntax; ");
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalAP.cc b/dev/Kernel/HALKit/AMD64/HalAP.cc
new file mode 100644
index 00000000..aefe570c
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalAP.cc
@@ -0,0 +1,51 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Processor.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ /***********************************************************************************/
+ /// @brief Unimplemented function (crashes by default)
+ /// @param
+ /***********************************************************************************/
+
+ EXTERN_C Void __zka_pure_call(void)
+ {
+ UserProcessScheduler::The().GetCurrentProcess().Leak().Crash();
+ }
+
+ /***********************************************************************************/
+ /// @brief Validate user stack.
+ /// @param stack_ptr the frame pointer.
+ /***********************************************************************************/
+
+ Bool hal_check_stack(HAL::StackFramePtr stack_ptr)
+ {
+ if (!stack_ptr)
+ return No;
+
+ return stack_ptr->SP != 0 && stack_ptr->BP != 0;
+ }
+
+ /// @brief Wakes up thread.
+ /// Wakes up thread from the hang state.
+ Void mp_wakeup_thread(HAL::StackFrame* stack)
+ {
+ Kernel::UserProcessHelper::StartScheduling();
+ }
+
+ /// @brief makes the thread sleep on a loop.
+ /// hooks and hangs thread to prevent code from executing.
+ Void mp_hang_thread(HAL::StackFrame* stack)
+ {
+ while (Yes)
+ {
+ /* Nothing to do, code is spinning */
+ }
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalAPICController.cc b/dev/Kernel/HALKit/AMD64/HalAPICController.cc
new file mode 100644
index 00000000..e29bea67
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalAPICController.cc
@@ -0,0 +1,39 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <HALKit/AMD64/Processor.h>
+
+#define cIOAPICRegVal (4)
+#define cIOAPICRegReg (0)
+
+namespace Kernel::HAL
+{
+ /// @brief Read from APIC controller.
+ /// @param reg register.
+ UInt32 APICController::Read(UInt32 reg) noexcept
+ {
+ MUST_PASS(this->fApic);
+
+ UInt32 volatile* io_apic = (UInt32 volatile*)this->fApic;
+ io_apic[cIOAPICRegReg] = (reg & 0xFF);
+
+ return io_apic[cIOAPICRegVal];
+ }
+
+ /// @brief Write to APIC controller.
+ /// @param reg register.
+ /// @param value value.
+ Void APICController::Write(UInt32 reg, UInt32 value) noexcept
+ {
+ MUST_PASS(this->fApic);
+
+ UInt32 volatile* io_apic = (UInt32 volatile*)this->fApic;
+
+ io_apic[cIOAPICRegReg] = (reg & 0xFF);
+ io_apic[cIOAPICRegVal] = value;
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/AMD64/HalBoot.asm b/dev/Kernel/HALKit/AMD64/HalBoot.asm
new file mode 100644
index 00000000..8830f786
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalBoot.asm
@@ -0,0 +1,28 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright (C) 2024, TQ B.V, all rights reserved., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+;; Global symbol of this unit
+[extern hal_init_platform]
+
+%define kTypeKernel 100
+%define kArchAmd64 122
+%define kHandoverMagic 0xBADCC
+
+section .ldr
+
+HandoverMagic:
+ dq kHandoverMagic
+HandoverType:
+ dw kTypeKernel
+HandoverPad:
+ dw 0
+HandoverArch:
+ dw kArchAmd64
diff --git a/dev/Kernel/HALKit/AMD64/HalCPUAMD64.cc b/dev/Kernel/HALKit/AMD64/HalCPUAMD64.cc
new file mode 100644
index 00000000..9af3ce37
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCPUAMD64.cc
@@ -0,0 +1,101 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: HalCPU.cc
+ Purpose: Platform processor routines.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Paging.h>
+#include <HALKit/AMD64/Processor.h>
+
+/**
+ * @file HalCPU.cc
+ * @brief Common CPU API.
+ */
+
+namespace Kernel::HAL
+{
+ Void lrt_out8(UInt16 port, UInt8 value)
+ {
+ asm volatile("outb %%al, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void lrt_out16(UInt16 port, UInt16 value)
+ {
+ asm volatile("outw %%ax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void lrt_out32(UInt16 port, UInt32 value)
+ {
+ asm volatile("outl %%eax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ UInt8 lrt_in8(UInt16 port)
+ {
+ UInt8 value = 0UL;
+ asm volatile("inb %1, %%al"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt16 lrt_in16(UInt16 port)
+ {
+ UInt16 value = 0UL;
+ asm volatile("inw %1, %%ax"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt32 lrt_in32(UInt16 port)
+ {
+ UInt32 value = 0UL;
+ asm volatile("inl %1, %%eax"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ Void rt_halt()
+ {
+ asm volatile("hlt");
+ }
+
+ Void rt_cli()
+ {
+ asm volatile("cli");
+ }
+
+ Void rt_sti()
+ {
+ asm volatile("sti");
+ }
+
+ Void rt_cld()
+ {
+ asm volatile("cld");
+ }
+
+ Void rt_std()
+ {
+ asm volatile("std");
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm
new file mode 100644
index 00000000..fae0753b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCommonAPI.asm
@@ -0,0 +1,53 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright (C) 2024, TQ B.V, all rights reserved., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+section .text
+
+extern rt_wait_400ns
+
+global rt_out8
+global rt_out16
+global rt_out32
+
+global rt_in8
+global rt_in16
+global rt_in32
+
+rt_out8:
+ mov al, dl
+ mov dx, cx
+ out dx, al
+ ret
+
+rt_out16:
+ mov ax, dx
+ mov dx, cx
+ out dx, ax
+ ret
+
+rt_out32:
+ mov eax, edx
+ mov edx, ecx
+ out dx, eax
+ ret
+
+rt_in8:
+ mov dx, cx
+ in al, dx
+ ret
+
+rt_in16:
+ mov edx, ecx
+ in ax, dx
+ ret
+
+rt_in32:
+ mov rdx, rcx
+ in eax, dx
+ ret
diff --git a/dev/Kernel/HALKit/AMD64/HalControlRegister.s b/dev/Kernel/HALKit/AMD64/HalControlRegister.s
new file mode 100644
index 00000000..3ff54d15
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalControlRegister.s
@@ -0,0 +1,45 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+.globl hal_write_cr3
+.globl hal_write_cr0
+.globl hal_read_cr2
+.globl hal_read_cr3
+.globl hal_read_cr0
+.globl hal_flush_tlb
+.globl hal_invl_tlb
+
+.text
+
+hal_invl_tlb:
+ invlpg (%rcx)
+ retq
+
+hal_flush_tlb:
+ call hal_read_cr3
+ mov %rax, %rcx
+ call hal_write_cr3
+ retq
+
+hal_read_cr3:
+ movq %cr3, %rax
+ retq
+
+hal_read_cr0:
+ movq %cr0, %rax
+ retq
+
+hal_read_cr2:
+ movq %cr2, %rax
+ retq
+
+hal_write_cr3:
+ movq %rcx, %cr3
+ retq
+
+hal_write_cr0:
+ movq %rcx, %cr0
+ retq
diff --git a/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc
new file mode 100644
index 00000000..a5125e68
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc
@@ -0,0 +1,232 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <NewKit/KString.h>
+#include <POSIXKit/signal.h>
+
+/// @brief Handle GPF fault.
+/// @param rsp
+EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp)
+{
+ kcout << "Kernel: GPF.\r";
+
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ process.Leak().ProcessSignal.SignalIP = 0UL;
+ process.Leak().ProcessSignal.SignalID = SIGKILL;
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+
+ process.Leak().Crash();
+
+ Kernel::ke_stop(RUNTIME_CHECK_POINTER);
+}
+
+/// @brief Handle page fault.
+/// @param rsp
+EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp)
+{
+ kcout << "Kernel: Page Fault.\r";
+ kcout << "Kernel: SIGKILL set.\r";
+
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ process.Leak().ProcessSignal.SignalIP = 0UL;
+ process.Leak().ProcessSignal.SignalID = SIGKILL;
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+
+ process.Leak().Crash();
+
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+}
+
+/// @brief Handle scheduler interrupt.
+EXTERN_C void idt_handle_scheduler(Kernel::UIntPtr rsp)
+{
+ static BOOL is_scheduling = NO;
+ static Kernel::Int64 try_count_before_brute = 100000UL;
+
+ while (is_scheduling)
+ {
+ --try_count_before_brute;
+
+ if (try_count_before_brute < 1)
+ break;
+ }
+
+ try_count_before_brute = 100000UL;
+ is_scheduling = YES;
+
+ kcout << "Kernel: Timer IRQ (Scheduler Notification).\r";
+ Kernel::UserProcessHelper::StartScheduling();
+
+ is_scheduling = NO;
+}
+
+/// @brief Handle math fault.
+/// @param rsp
+EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp)
+{
+ kcout << "Kernel: Math error (division by zero?).\r";
+
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ process.Leak().ProcessSignal.SignalIP = 0UL;
+ process.Leak().ProcessSignal.SignalID = SIGKILL;
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+
+ process.Leak().Crash();
+
+ Kernel::ke_stop(RUNTIME_CHECK_UNEXCPECTED);
+}
+
+/// @brief Handle any generic fault.
+/// @param rsp
+EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp)
+{
+ kcout << "Kernel: Generic Process Fault.\r";
+
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ process.Leak().ProcessSignal.SignalIP = 0UL;
+ process.Leak().ProcessSignal.SignalID = SIGKILL;
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+
+ process.Leak().Crash();
+
+ Kernel::ke_stop(RUNTIME_CHECK_UNEXCPECTED);
+}
+
+EXTERN_C Kernel::Void idt_handle_breakpoint(Kernel::UIntPtr rip)
+{
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ kcout << "Kernel: Process RIP: " << Kernel::hex_number(rip) << endl;
+ kcout << "Kernel: SIGTRAP set.\r";
+
+ process.Leak().ProcessSignal.SignalIP = rip;
+ process.Leak().ProcessSignal.SignalID = SIGTRAP;
+
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+}
+
+/// @brief Handle #UD fault.
+/// @param rsp
+EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp)
+{
+ kcout << "Kernel: Undefined Opcode.\r";
+
+ auto process = Kernel::UserProcessScheduler::The().GetCurrentProcess();
+
+ if (!process)
+ Kernel::ke_stop(RUNTIME_CHECK_PAGE);
+
+ process.Leak().ProcessSignal.SignalIP = 0UL;
+ process.Leak().ProcessSignal.SignalID = SIGKILL;
+ process.Leak().ProcessSignal.PreviousStatus = process.Leak().Status;
+
+ kcout << "Kernel: PRCFROZE status set..\r";
+
+ process.Leak().Status = Kernel::ProcessStatusKind::kFrozen;
+
+ process.Leak().Crash();
+
+ Kernel::ke_stop(RUNTIME_CHECK_UNEXCPECTED);
+}
+
+/// @brief Enter syscall from assembly.
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_system_call_enter(Kernel::UIntPtr rcx_syscall_index, Kernel::UIntPtr rdx_syscall_struct)
+{
+ if (rcx_syscall_index < kSyscalls.Count())
+ {
+ kcout << "syscall: Enter Syscall.\r";
+
+ if (kSyscalls[rcx_syscall_index].fHooked)
+ {
+ if (kSyscalls[rcx_syscall_index].fProc)
+ {
+ (kSyscalls[rcx_syscall_index].fProc)((Kernel::VoidPtr)rdx_syscall_struct);
+ }
+ else
+ {
+ kcout << "syscall: syscall isn't valid at all! (is nullptr)\r";
+ }
+ }
+ else
+ {
+ kcout << "syscall: syscall isn't hooked at all! (is set to false)\r";
+ }
+
+ kcout << "syscall: Exit Syscall.\r";
+ }
+}
+
+/// @brief Enter Kernel call from assembly (DDK only).
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_kernel_call_enter(Kernel::UIntPtr rcx_kerncall_index, Kernel::UIntPtr rdx_kerncall_struct)
+{
+ if (rcx_kerncall_index < kKerncalls.Count())
+ {
+ kcout << "kerncall: Enter Kernel Call List.\r";
+
+ if (kKerncalls[rcx_kerncall_index].fHooked)
+ {
+ if (kKerncalls[rcx_kerncall_index].fProc)
+ {
+ (kKerncalls[rcx_kerncall_index].fProc)((Kernel::VoidPtr)rdx_kerncall_struct);
+ }
+ else
+ {
+ kcout << "kerncall: Kernel call isn't valid at all! (is nullptr)\r";
+ }
+ }
+ else
+ {
+ kcout << "kerncall: Kernel call isn't hooked at all! (is set to false)\r";
+ }
+
+ kcout << "kerncall: Exit Kernel Call List.\r";
+ }
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalCoreScheduler.cc b/dev/Kernel/HALKit/AMD64/HalCoreScheduler.cc
new file mode 100644
index 00000000..f6835b8f
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCoreScheduler.cc
@@ -0,0 +1,240 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <HALKit/AMD64/Processor.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Semaphore.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <KernelKit/Timer.h>
+#include <Modules/FB/Text.h>
+#include <NewKit/Stop.h>
+
+// Needed for SMP.
+#include <KernelKit/HardwareThreadScheduler.h>
+
+#define kApicSignature "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
+
+#define cSMPMax (32U)
+
+/// @note: _hal_switch_context is internal
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+//! NOTE: fGSI stands 'Field Global System Interrupt'
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+namespace Kernel::HAL
+{
+ struct MADT_TABLE;
+
+ EXTERN_C Void _hal_spin_core(Void);
+
+ STATIC struct MADT_TABLE* kMADTBlock = nullptr;
+ STATIC Bool kSMPAware = false;
+ STATIC Int64 kSMPCount = 0;
+
+ STATIC Int32 cSMPInterrupt = 0;
+ STATIC UInt64 kAPICLocales[cSMPMax] = {0};
+ STATIC VoidPtr kRawMADT = nullptr;
+
+ /// @brief Multiple APIC Descriptor Table.
+ struct MADT_TABLE final : public SDT
+ {
+ UInt32 Address; // Madt address
+ UInt8 Flags; // Madt flags
+
+ struct
+ {
+ UInt8 Type;
+ UInt8 Len;
+
+ union {
+ struct
+ {
+ UInt8 IoID;
+ UInt8 Resv;
+ UInt32 IoAddress;
+ UInt32 GISBase;
+ } IOAPIC;
+
+ struct
+ {
+ UInt8 Source;
+ UInt8 IRQSource;
+ UInt32 GSI;
+ UInt16 Flags;
+ } IOAPIC_NMI;
+
+ struct
+ {
+ UInt8 ProcessorID;
+ UInt16 Flags;
+ UInt8 LINT;
+ } LAPIC;
+
+ struct
+ {
+ UInt16 Reserved;
+ UInt64 Address;
+ } LAPIC_ADDRESS_OVERRIDE;
+
+ struct
+ {
+ UInt16 Reserved;
+ UInt32 x2APICID;
+ UInt32 Flags;
+ UInt32 AcpiID;
+ } LAPIC_ADDRESS;
+ };
+ } List[]; // Records List
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ /***********************************************************************************/
+ /// @brief Send IPI command to APIC.
+ /// @param apicId programmable interrupt controller id.
+ /// @param vector vector interrupt.
+ /// @param targetAddress target APIC adress.
+ /// @return
+ /***********************************************************************************/
+
+ Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ {
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_SIPI_Vector | vector);
+ }
+
+ /***********************************************************************************/
+ /// @brief Send end IPI for CPU.
+ /// @param apicId
+ /// @param vector
+ /// @param targetAddress
+ /// @return
+ /***********************************************************************************/
+ Void hal_send_end_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ {
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_EIPI_Vector | vector);
+ }
+
+ STATIC struct PROCESS_CONTROL_BLOCK final
+ {
+ HAL::StackFramePtr f_Frame;
+ UInt8* f_Stack;
+ VoidPtr f_Image;
+ } kProcessBlocks[kSchedProcessLimitPerTeam] = {0};
+
+ EXTERN_C HAL::StackFramePtr mp_get_current_context(Int64 pid)
+ {
+ const auto process_index = pid % kSchedProcessLimitPerTeam;
+ return kProcessBlocks[process_index].f_Frame;
+ }
+
+ EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame, ProcessID pid)
+ {
+ MUST_PASS(image && stack_ptr && stack_frame);
+
+ const auto process_index = pid % kSchedProcessLimitPerTeam;
+
+ kProcessBlocks[process_index].f_Frame = stack_frame;
+ kProcessBlocks[process_index].f_Stack = stack_ptr;
+ kProcessBlocks[process_index].f_Image = image;
+
+ if (!mp_is_smp())
+ {
+ /// TODO: Switch from process_index in hash list.
+ }
+
+ return Yes;
+ }
+
+ /***********************************************************************************/
+ /// @brief Is the current config SMP aware?
+ /// @return True if YES, False if not.
+ /***********************************************************************************/
+ Bool mp_is_smp(Void) noexcept
+ {
+ return kSMPAware;
+ }
+
+ /***********************************************************************************/
+ /// @brief Fetch and enable SMP scheduler.
+ /// @param vendor_ptr SMP containing structure.
+ /***********************************************************************************/
+ Void mp_get_cores(VoidPtr vendor_ptr) noexcept
+ {
+ if (!vendor_ptr)
+ return;
+
+ auto hw_and_pow_int = PowerFactoryInterface(vendor_ptr);
+ kRawMADT = hw_and_pow_int.Find(kApicSignature).Leak().Leak();
+
+ kMADTBlock = reinterpret_cast<MADT_TABLE*>(kRawMADT);
+ kSMPAware = NO;
+
+ if (kMADTBlock)
+ {
+ SizeT index = 0;
+
+ // reset values.
+
+ cSMPInterrupt = 0;
+ kSMPCount = 0;
+
+ kcout << "SMP: Probing Local APICs...\r";
+
+ UIntPtr madt_address = kMADTBlock->Address;
+
+ while (Yes)
+ {
+ if (kMADTBlock->List[index].Type > 9 ||
+ kSMPCount > cSMPMax)
+ break;
+
+ switch (kMADTBlock->List[index].Type)
+ {
+ case 0x00: {
+ kAPICLocales[index] = kMADTBlock->List[index].LAPIC.ProcessorID;
+ kcout << "SMP: APIC ID: " << number(kAPICLocales[index]) << endl;
+ ++kSMPCount;
+ break;
+ }
+ case 0x05: {
+ madt_address = kMADTBlock->List[index].LAPIC_ADDRESS_OVERRIDE.Address;
+ kcout << "SMP: APIC address: " << number(madt_address) << endl;
+ break;
+ }
+ }
+
+ ++index;
+ }
+
+ kcout << "SMP: number of cores: " << number(kSMPCount) << endl;
+
+ // 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.
+ }
+ }
+} // namespace Kernel::HAL
+
+///////////////////////////////////////////////////////////////////////////////////////
diff --git a/dev/Kernel/HALKit/AMD64/HalDebugOutput.cc b/dev/Kernel/HALKit/AMD64/HalDebugOutput.cc
new file mode 100644
index 00000000..41279d27
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDebugOutput.cc
@@ -0,0 +1,146 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+#include <NewKit/Utils.h>
+#include <NewKit/New.h>
+
+namespace Kernel
+{
+ enum CommStatus
+ {
+ kStateInvalid,
+ kStateReady = 0xCF,
+ kStateTransmit = 0xFC,
+ kStateCnt = 3
+ };
+
+ namespace Detail
+ {
+ constexpr short PORT = 0x3F8;
+
+ static int kState = kStateInvalid;
+
+ /// @brief Init COM1.
+ /// @return
+ bool hal_serial_init() noexcept
+ {
+#ifdef __DEBUG__
+ if (kState == kStateReady || kState == kStateTransmit)
+ return true;
+
+ HAL::rt_out8(PORT + 1, 0x00); // Disable all interrupts
+ HAL::rt_out8(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ HAL::rt_out8(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ HAL::rt_out8(PORT + 1, 0x00); // (hi byte)
+ HAL::rt_out8(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ HAL::rt_out8(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
+ HAL::rt_out8(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ HAL::rt_out8(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
+ HAL::rt_out8(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if
+ // serial returns same byte)
+
+ // Check if serial is faulty (i.e: not same byte as sent)
+ if (HAL::rt_in8(PORT) != 0xAE)
+ {
+ ke_stop(RUNTIME_CHECK_HANDSHAKE);
+ }
+
+ kState = kStateReady;
+
+ // If serial is not faulty set it in normal operation mode
+ // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+ HAL::rt_out8(Detail::PORT + 4, 0x0F);
+#endif // __DEBUG__
+
+ return true;
+ }
+ } // namespace Detail
+
+ TerminalDevice::~TerminalDevice() = default;
+
+ EXTERN_C void ke_io_write(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ Detail::hal_serial_init();
+
+ if (!bytes || Detail::kState != kStateReady)
+ return;
+ if (*bytes == 0)
+ return;
+
+ Detail::kState = kStateTransmit;
+
+ SizeT index = 0;
+ SizeT len = 0;
+
+ index = 0;
+ len = rt_string_len(bytes, 255);
+
+ while (index < len)
+ {
+ if (bytes[index] == '\r')
+ HAL::rt_out8(Detail::PORT, '\r');
+
+ HAL::rt_out8(Detail::PORT, bytes[index] == '\r' ? '\n' : bytes[index]);
+ ++index;
+ }
+
+ Detail::kState = kStateReady;
+#endif // __DEBUG__
+ }
+
+ EXTERN_C void ke_io_read(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ Detail::hal_serial_init();
+
+ if (!bytes || Detail::kState != kStateReady)
+ return;
+
+ Detail::kState = kStateTransmit;
+
+ SizeT index = 0;
+
+ ///! TODO: Look on how to wait for the UART to complete.
+ while (true)
+ {
+ auto in = HAL::rt_in8(Detail::PORT);
+
+ ///! If enter pressed then break.
+ if (in == 0xD)
+ {
+ break;
+ }
+
+ if (in < '0' || in < 'A' || in < 'a')
+ {
+ if (in != '@' || in != '!' || in != '?' || in != '.' || in != '/' ||
+ in != ':')
+ {
+ continue;
+ }
+ }
+
+ ((char*)bytes)[index] = in;
+
+ ++index;
+ }
+
+ ((char*)bytes)[index] = 0;
+
+ Detail::kState = kStateReady;
+#endif // __DEBUG__
+ }
+
+ TerminalDevice TerminalDevice::The() noexcept
+ {
+ TerminalDevice out(Kernel::ke_io_write, Kernel::ke_io_read);
+ return out;
+ }
+
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalDebugPort.cc b/dev/Kernel/HALKit/AMD64/HalDebugPort.cc
new file mode 100644
index 00000000..e9b2e3b5
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDebugPort.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+//! @file DebuggerPort.cc
+//! @brief UART debug via packets.
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+
+// after that we have start of additional data.
+
+namespace Kernel
+{
+ void rt_debug_listen(DebuggerPortHeader* theHook) noexcept
+ {
+ if (theHook == nullptr)
+ return;
+
+ for (UInt32 i = 0U; i < kDebugMaxPorts; ++i)
+ {
+ HAL::rt_out16(theHook->fPort[i], kDebugMag0);
+ HAL::rt_wait_400ns();
+
+ HAL::rt_out16(theHook->fPort[i], kDebugMag1);
+ HAL::rt_wait_400ns();
+
+ HAL::rt_out16(theHook->fPort[i], kDebugMag2);
+ HAL::rt_wait_400ns();
+
+ HAL::rt_out16(theHook->fPort[i], kDebugMag3);
+ HAL::rt_wait_400ns();
+
+ if (HAL::rt_in16(theHook->fPort[i] != kDebugUnboundPort))
+ ++theHook->fBoundCnt;
+ }
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
new file mode 100644
index 00000000..e5a3700b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
@@ -0,0 +1,126 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <HALKit/AMD64/Processor.h>
+
+#define kPITDefaultTicks (100U)
+
+namespace Kernel::HAL
+{
+ namespace Detail
+ {
+ STATIC ::Kernel::Detail::AMD64::InterruptDescriptorAMD64
+ kInterruptVectorTable[kKernelIdtSize] = {};
+
+ STATIC void hal_set_irq_mask(UInt8 irql);
+ STATIC void hal_clear_irq_mask(UInt8 irql);
+
+ STATIC Void hal_enable_pit(UInt16 ticks) noexcept
+ {
+ if (ticks == 0)
+ ticks = kPITDefaultTicks;
+
+ // Configure PIT to receieve scheduler interrupts.
+
+ UInt16 cCommonDivisor = kPITFrequency / ticks; // 100 Hz.
+
+ HAL::rt_out8(kPITControlPort, 0x36); // Command to PIT
+ HAL::rt_out8(kPITChannel0Port, cCommonDivisor & 0xFF); // Send low byte
+ HAL::rt_out8(kPITChannel0Port, (cCommonDivisor >> 8) & 0xFF); // Send high byte
+
+ hal_clear_irq_mask(32);
+ }
+
+ STATIC void hal_set_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = rt_in8(port) | (1 << irql);
+ rt_out8(port, value);
+ }
+
+ STATIC void hal_clear_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = rt_in8(port) & ~(1 << irql);
+ rt_out8(port, value);
+ }
+ } // namespace Detail
+
+ /// @brief Loads the provided Global Descriptor Table.
+ /// @param gdt
+ /// @return
+ Void GDTLoader::Load(RegisterGDT& gdt)
+ {
+ hal_load_gdt(gdt);
+ }
+
+ Void IDTLoader::Load(Register64& idt)
+ {
+ rt_cli();
+
+ const Int16 kPITTickForScheduler = kPITDefaultTicks;
+
+ volatile ::Kernel::UIntPtr** ptr_ivt = (volatile ::Kernel::UIntPtr**)idt.Base;
+
+ for (SizeT idt_indx = 0; idt_indx < kKernelIdtSize; ++idt_indx)
+ {
+ Detail::kInterruptVectorTable[idt_indx].Selector = kIDTSelector;
+ Detail::kInterruptVectorTable[idt_indx].Ist = 0;
+ Detail::kInterruptVectorTable[idt_indx].TypeAttributes = kInterruptGate;
+ Detail::kInterruptVectorTable[idt_indx].OffsetLow = ((UIntPtr)ptr_ivt[idt_indx] & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetMid = (((UIntPtr)ptr_ivt[idt_indx] >> 16) & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetHigh =
+ (((UIntPtr)ptr_ivt[idt_indx] >> 32) & 0xFFFFFFFF);
+
+ Detail::kInterruptVectorTable[idt_indx].Zero = 0;
+ }
+
+ idt.Base = (UIntPtr)&Detail::kInterruptVectorTable[0];
+ idt.Limit = sizeof(::Kernel::Detail::AMD64::InterruptDescriptorAMD64) *
+ (kKernelIdtSize);
+
+ hal_load_idt(idt);
+
+ Detail::hal_enable_pit(kPITTickForScheduler);
+
+ rt_sti();
+ }
+
+ void GDTLoader::Load(Ref<RegisterGDT>& gdt)
+ {
+ GDTLoader::Load(gdt.Leak());
+ }
+
+ void IDTLoader::Load(Ref<Register64>& idt)
+ {
+ IDTLoader::Load(idt.Leak());
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm
new file mode 100644
index 00000000..9d1bf367
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm
@@ -0,0 +1,406 @@
+;; /*
+;; * ---------------------------------------------------
+;; *
+;; * Copyright (C) 2024, TQ B.V, all rights reserved.
+;; *
+;; * File: HalInterruptAPI.asm
+;; * Purpose: Interrupt API, redirect raw interrupts into their handlers.
+;; *
+;; * ---------------------------------------------------
+;; */
+
+[bits 64]
+
+%define kInterruptId 0x21
+
+%macro IntExp 1
+global __ZKA_INT_%1
+__ZKA_INT_%1:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ sti
+ o64 iret
+%endmacro
+
+%macro IntNormal 1
+global __ZKA_INT_%1
+__ZKA_INT_%1:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ sti
+ o64 iret
+%endmacro
+
+; This file handles the core interrupt table
+; Last edited 31/01/24
+
+global ke_handle_irq
+global kInterruptVectorTable
+
+extern idt_handle_gpf
+extern idt_handle_pf
+extern ke_io_write
+extern idt_handle_ud
+extern idt_handle_generic
+extern idt_handle_breakpoint
+
+section .text
+
+IntNormal 0
+IntNormal 1
+IntNormal 2
+
+section .data
+
+__ZKA_INT_3_GET_RIP:
+ dq 0
+__ZKA_INT_3_GET_RIP_END:
+
+section .text
+
+;; @brief Triggers a breakpoint and freeze the process. RIP is also fetched.
+__ZKA_INT_3:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_breakpoint
+
+ lea rcx, [rel __ZKA_INT_3_GET_RIP]
+ sub rcx, 16
+ mov [rcx], rcx
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 4
+IntNormal 5
+
+;; Invalid opcode interrupt
+__ZKA_INT_6:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_ud
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 7
+
+;; Invalid opcode interrupt
+__ZKA_INT_8:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_generic
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 9
+IntExp 10
+IntExp 11
+
+IntExp 12
+
+__ZKA_INT_13:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_gpf
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+__ZKA_INT_14:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+ push rax
+ mov rax, idt_handle_pf
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 15
+IntNormal 16
+IntExp 17
+IntNormal 18
+IntNormal 19
+IntNormal 20
+IntNormal 21
+
+IntNormal 22
+
+IntNormal 23
+IntNormal 24
+IntNormal 25
+IntNormal 26
+IntNormal 27
+IntNormal 28
+IntNormal 29
+IntExp 30
+IntNormal 31
+
+[extern idt_handle_scheduler]
+
+__ZKA_INT_32:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rcx, rsp
+ call idt_handle_scheduler
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 33
+
+IntNormal 34
+IntNormal 35
+IntNormal 36
+IntNormal 37
+IntNormal 38
+IntNormal 39
+IntNormal 40
+
+IntNormal 41
+
+IntNormal 42
+IntNormal 43
+IntNormal 44
+IntNormal 45
+IntNormal 46
+IntNormal 47
+IntNormal 48
+IntNormal 49
+
+[extern hal_system_call_enter]
+[extern hal_kernel_call_enter]
+
+__ZKA_INT_50:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, hal_system_call_enter
+
+ mov rcx, r8
+ mov rdx, r9
+
+ call rax
+ pop rax
+
+ sti
+
+ o64 iret
+
+__ZKA_INT_51:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, hal_kernel_call_enter
+
+ mov rcx, r8
+ mov rdx, r9
+
+ call rax
+ pop rax
+
+ sti
+
+ o64 iret
+
+IntNormal 52
+
+IntNormal 53
+IntNormal 54
+IntNormal 55
+IntNormal 56
+IntNormal 57
+IntNormal 58
+IntNormal 59
+IntNormal 60
+
+%assign i 61
+%rep 195
+ IntNormal i
+%assign i i+1
+%endrep
+
+section .text
+
+[global hal_load_gdt]
+
+hal_load_gdt:
+ cld
+
+ lgdt [rcx]
+
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ mov rax, 0x08
+ push rax
+ push hal_reload_segments
+
+ o64 retf
+
+extern hal_real_init
+
+hal_reload_segments:
+ std
+ ;; Write address of syscall handler.
+ mov rdx, [mp_system_call_handler]
+ shr rdx, 32
+ mov rcx, 0xC0000082
+ wrmsr
+
+ ;; Set segments of syscall handler.
+
+ xor rax, rax
+ mov rdx, 0x230008
+ mov rcx, 0xC0000081
+ wrmsr
+
+ mov ecx, 0xC0000080
+ rdmsr
+ or eax, 1
+ wrmsr
+
+ jmp hal_real_init
+ ret
+
+global hal_load_idt
+global hal_user_code_start
+
+extern hal_system_call_enter
+global mp_system_call_handler
+
+mp_system_call_handler:
+
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ jmp hal_system_call_enter
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+
+ o64 sysret
+
+hal_load_idt:
+ lidt [rcx]
+
+ ; Master PIC initialization
+ mov al, 0x11 ; Start initialization in cascade mode
+ out 0x20, al ; Send initialization command to Master PIC
+ out 0xA0, al ; Send initialization command to Slave PIC
+
+ ; Remap the PIC to use vectors 32-39 for Master and 40-47 for Slave
+ mov al, 0x20 ; Set Master PIC offset to 32
+ out 0x21, al ; Send offset to Master PIC
+
+ mov al, 0x28 ; Set Slave PIC offset to 40
+ out 0xA1, al ; Send offset to Slave PIC
+
+ ; Configure Master PIC to inform Slave PIC at IRQ2
+ mov al, 0x04 ; Tell Master PIC there is a Slave PIC at IRQ2
+ out 0x21, al
+
+ ; Configure Slave PIC identity
+ mov al, 0x02 ; Tell Slave PIC its cascade identity
+ out 0xA1, al
+
+ ; Set both PICs to 8086 mode
+ mov al, 0x01 ; 8086 mode
+ out 0x21, al
+ out 0xA1, al
+
+ ret
+
+section .data
+
+kInterruptVectorTable:
+ %assign i 0
+ %rep 256
+ dq __ZKA_INT_%+i
+ %assign i i+1
+ %endrep
diff --git a/dev/Kernel/HALKit/AMD64/HalKernelMain.cc b/dev/Kernel/HALKit/AMD64/HalKernelMain.cc
new file mode 100644
index 00000000..a831cbc2
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalKernelMain.cc
@@ -0,0 +1,103 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <KernelKit/HardwareThreadScheduler.h>
+#include <KernelKit/CodeMgr.h>
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NetworkKit/IPC.h>
+#include <CFKit/Property.h>
+#include <Modules/FB/KWindow.h>
+#include <Modules/FB/Text.h>
+
+EXTERN_C Kernel::VoidPtr kInterruptVectorTable[];
+EXTERN_C Kernel::VoidPtr mp_user_switch_proc;
+EXTERN_C Kernel::Char mp_user_switch_proc_stack_begin[];
+
+EXTERN_C Kernel::rtl_ctor_kind __CTOR_LIST__[];
+EXTERN_C Kernel::VoidPtr __DTOR_LIST__;
+
+EXTERN_C Kernel::Void rtl_kernel_main(Kernel::SizeT argc, char** argv, char** envp, Kernel::SizeT envp_len);
+
+STATIC Kernel::Void hal_init_cxx_ctors()
+{
+ for (Kernel::SizeT index = 0UL; __CTOR_LIST__[index] != __DTOR_LIST__; ++index)
+ {
+ Kernel::rtl_ctor_kind constructor_cxx = (Kernel::rtl_ctor_kind)__CTOR_LIST__[index];
+ constructor_cxx();
+ }
+}
+
+/// @brief Kernel init procedure.
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::BootInfoHeader* handover_hdr)
+{
+ kHandoverHeader = handover_hdr;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ hal_init_cxx_ctors();
+
+ /************************************** */
+ /* INITIALIZE BIT MAP. */
+ /************************************** */
+
+ kKernelBitMpSize = kHandoverHeader->f_BitMapSize;
+ kKernelBitMpStart = reinterpret_cast<Kernel::VoidPtr>(
+ reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_BitMapStart));
+
+ /************************************** */
+ /* INITIALIZE GDT AND SEGMENTS. */
+ /************************************** */
+
+ STATIC CONST auto kGDTEntriesCount = 6;
+
+ /* GDT, mostly descriptors for user and kernel segments. */
+ STATIC Kernel::HAL::Detail::ZKA_GDT_ENTRY ALIGN(0x08) kGDTArray[kGDTEntriesCount] = {
+ {.fLimitLow = 0, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x00, .fFlags = 0x00, .fBaseHigh = 0}, // Null entry
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x9A, .fFlags = 0xAF, .fBaseHigh = 0}, // Kernel code
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x92, .fFlags = 0xCF, .fBaseHigh = 0}, // Kernel data
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0xF2, .fFlags = 0xCF, .fBaseHigh = 0}, // User data
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0xFA, .fFlags = 0xAF, .fBaseHigh = 0}, // User code
+ };
+
+ // Load memory descriptors.
+ Kernel::HAL::RegisterGDT gdt_reg;
+
+ gdt_reg.Base = reinterpret_cast<Kernel::UIntPtr>(kGDTArray);
+ gdt_reg.Limit = (sizeof(Kernel::HAL::Detail::ZKA_GDT_ENTRY) * kGDTEntriesCount) - 1;
+
+ //! GDT will load hal_read_init after it successfully loads the segments.
+ Kernel::HAL::GDTLoader gdt_loader;
+ gdt_loader.Load(gdt_reg);
+
+ Kernel::ke_stop(RUNTIME_CHECK_BOOTSTRAP);
+}
+
+EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept
+{
+ CG::CGDrawBackground();
+
+ rtl_kernel_main(0, nullptr, nullptr, 0);
+
+ if (kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled)
+ Kernel::HAL::mp_get_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ Kernel::HAL::Register64 idt_reg;
+ idt_reg.Base = (Kernel::UIntPtr)kInterruptVectorTable;
+
+ Kernel::HAL::IDTLoader idt_loader;
+ idt_loader.Load(idt_reg);
+
+ while (YES)
+ {
+ }
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalPagingMgrAMD64.cc b/dev/Kernel/HALKit/AMD64/HalPagingMgrAMD64.cc
new file mode 100644
index 00000000..b87aed5c
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalPagingMgrAMD64.cc
@@ -0,0 +1,168 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: HalPagingMgr.cc
+ Purpose: Platform Paging Manager..
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Paging.h>
+#include <HALKit/AMD64/Processor.h>
+
+namespace Kernel::HAL
+{
+ typedef UInt32 PageTableIndex;
+
+ /***********************************************************************************/
+ /// \brief Page store type.
+ /***********************************************************************************/
+ struct ZKA_PAGE_STORE final
+ {
+ struct
+ {
+ PDE* fPde{nullptr};
+ PTE* fPte{nullptr};
+ VoidPtr fVAddr{nullptr};
+ } fInternalStore;
+
+ Bool fStoreOp{No}; // Store operation is in progress.
+
+ bool IsValidPage(PTE* pte)
+ {
+ return pte && pte->Present;
+ }
+
+ bool IsWRPage(PTE* pte)
+ {
+ return pte && pte->Wr;
+ }
+
+ bool IsUserPage(PTE* pte)
+ {
+ return pte && pte->User;
+ }
+
+ static ZKA_PAGE_STORE& The()
+ {
+ static ZKA_PAGE_STORE the;
+ return the;
+ }
+ };
+
+ /***********************************************************************************/
+ /// \brief Retrieve the page status of a PTE.
+ /// \param pte Page Table Entry pointer.
+ /***********************************************************************************/
+ STATIC Void mmi_page_status(PTE* pte)
+ {
+ kcout << (pte->Present ? "Present" : "Not Present") << endl;
+ kcout << (pte->Wr ? "W/R" : "Not W/R") << endl;
+ kcout << (pte->ExecDisable ? "NX" : "Not NX") << endl;
+ kcout << (pte->User ? "User" : "Not User") << endl;
+ }
+
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, ZKA_PTE* pt_entry, ZKA_PDE* pd_entry);
+
+ /***********************************************************************************/
+ /// @brief Maps or allocates a page from virtual_address.
+ /// @param virtual_address a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manipulation process.
+ /***********************************************************************************/
+ EXTERN_C Int32 mm_map_page(VoidPtr virtual_address, UInt32 flags)
+ {
+ if (!virtual_address ||
+ !flags)
+ return 0;
+
+ // Constants for table index bits
+ const UInt64 cPmlIndexMask = 0x1FFULL; // Mask for PML4, PDPT, PD, PT index (9 bits)
+ const UInt64 cPtIndexMask = 0xFFFULL; // Mask for page table index (12 bits)
+
+ UInt64 cr3 = (UInt64)hal_read_cr3();
+
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ // Extract the indices from the virtual address
+ UInt64 pml4_index = ((UIntPtr)virtual_address >> 39) & cPmlIndexMask;
+ UInt64 pdpt_index = ((UIntPtr)virtual_address >> 30) & cPmlIndexMask;
+ UInt64 pd_index = ((UIntPtr)virtual_address >> 21) & cPmlIndexMask;
+ UInt64 pt_index = ((UIntPtr)virtual_address >> 12) & cPmlIndexMask;
+
+ page_store.fStoreOp = Yes;
+
+ if (page_store.fInternalStore.fVAddr == virtual_address)
+ {
+ page_store.fStoreOp = No;
+ return mmi_map_page_table_entry(page_store.fInternalStore.fVAddr, flags, page_store.fInternalStore.fPte, page_store.fInternalStore.fPde);
+ }
+
+ const auto cPmlEntrySize = 8;
+
+ // Read the PML4 entry from memory
+ UInt64 pml4_base = cr3 & ~cPtIndexMask; // CR3 points to the PML4 table base, mask off lower bits
+ UInt64 pml4_entry = (pml4_base + pml4_index * cPmlEntrySize); // Each entry is 8 bytes
+
+ // Read the PDPT entry
+ UInt64 pdpt_base = pml4_entry & ~cPtIndexMask; // Get the PDPT base physical address
+ UInt64 pdpt_entry = (pdpt_base + pdpt_index * cPmlEntrySize);
+
+ // Read the PD entry
+ UInt64 pd_base = pdpt_entry & ~cPtIndexMask; // Get the Page Directory base physical address
+ UInt64 pd_entry = (pd_base + pd_index * cPmlEntrySize);
+
+ // Read the PT entry
+ UInt64 pt_base = pd_entry & ~cPtIndexMask; // Get the Page Table base physical address
+ UInt64 pt_entry = (pt_base + pt_index * cPmlEntrySize);
+
+ // Lastly, grab the pte entry.
+ ZKA_PDE* pde_struct = reinterpret_cast<ZKA_PDE*>(pt_base);
+
+ return mmi_map_page_table_entry(virtual_address, flags, pde_struct->fEntries[pt_entry], pde_struct);
+ }
+
+ /***********************************************************************************/
+ /// @brief Maps flags for a specific pte.
+ /// @internal Internal function.
+ /***********************************************************************************/
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, ZKA_PTE* pt_entry, ZKA_PDE* pd_entry)
+ {
+ if (!pt_entry)
+ return 1;
+
+ pt_entry->Present = true;
+
+ if (flags & kMMFlagsWr)
+ pt_entry->Wr = true;
+ else if (flags & ~kMMFlagsWr)
+ pt_entry->Wr = false;
+
+ if (flags & kMMFlagsNX)
+ pt_entry->ExecDisable = true;
+ else if (flags & ~kMMFlagsNX)
+ pt_entry->ExecDisable = false;
+
+ if (flags & kMMFlagsUser)
+ pt_entry->User = true;
+ else if (flags & ~kMMFlagsUser)
+ pt_entry->User = false;
+
+ hal_invl_tlb(reinterpret_cast<VoidPtr>(pt_entry));
+
+ mmi_page_status(pt_entry);
+
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ // Update Internal store.
+
+ page_store.fInternalStore.fPde = pd_entry;
+ page_store.fInternalStore.fPte = pt_entry;
+ page_store.fInternalStore.fVAddr = virtual_address;
+
+ page_store.fStoreOp = No;
+
+ return 0;
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/AMD64/HalRoutineWait.s b/dev/Kernel/HALKit/AMD64/HalRoutineWait.s
new file mode 100644
index 00000000..89051ba4
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalRoutineWait.s
@@ -0,0 +1,11 @@
+.globl rt_wait_400ns
+
+.section .text
+rt_wait_400ns:
+ jmp .loop
+ pause
+ .loop:
+ jmp .loop2
+ pause
+ .loop2:
+ ret
diff --git a/dev/Kernel/HALKit/AMD64/HalTimerAMD64.cc b/dev/Kernel/HALKit/AMD64/HalTimerAMD64.cc
new file mode 100644
index 00000000..ade45ebb
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalTimerAMD64.cc
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Timer.h>
+
+// timer slot 0
+
+#define cHPETCounterRegValue (0x00)
+#define cHPETConfigRegValue (0x20)
+#define cHPETCompRegValue (0x24)
+#define cHPETInterruptRegValue (0x2C)
+
+///! BUGS: 0
+///! @file HalTimer.cc
+///! @brief Hardware Timer (HPET)
+
+namespace Kernel::Detail
+{
+ struct HPET_BLOCK : public Kernel::SDT
+ {
+ Kernel::UInt8 hardware_rev_id;
+ Kernel::UInt8 comparator_count : 5;
+ Kernel::UInt8 counter_size : 1;
+ Kernel::UInt8 reserved : 1;
+ Kernel::UInt8 legacy_replacement : 1;
+ Kernel::UInt16 pci_vendor_id;
+ ACPI_ADDRESS address;
+ Kernel::UInt8 hpet_number;
+ Kernel::UInt16 minimum_tick;
+ Kernel::UInt8 page_protection;
+ } PACKED;
+} // namespace Kernel::Detail
+
+using namespace Kernel;
+
+HardwareTimer::HardwareTimer(Int64 ms)
+ : fWaitFor(ms)
+{
+ auto power = PowerFactoryInterface(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ auto hpet = (Detail::HPET_BLOCK*)power.Find("HPET").Leak().Leak();
+ MUST_PASS(hpet);
+
+ fDigitalTimer = (IntPtr*)hpet->address.Address;
+}
+
+HardwareTimer::~HardwareTimer()
+{
+ fDigitalTimer = nullptr;
+ fWaitFor = 0;
+}
+
+Int32 HardwareTimer::Wait() noexcept
+{
+ if (fWaitFor < 1)
+ return 1;
+
+ // if not enabled yet.
+ if (!(*(fDigitalTimer + cHPETConfigRegValue) & (1 << 0)))
+ {
+ *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 0); // enable it
+ *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 3); // one shot conf
+ }
+
+ UInt64 ticks = fWaitFor / ((*(fDigitalTimer) >> 32) & __UINT32_MAX__);
+ UInt64 prev = *(fDigitalTimer + cHPETCounterRegValue);
+
+ prev += ticks;
+
+ while (*(fDigitalTimer + cHPETCounterRegValue) < (ticks))
+ ;
+
+ return 0;
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalUtils.asm b/dev/Kernel/HALKit/AMD64/HalUtils.asm
new file mode 100644
index 00000000..2f141352
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalUtils.asm
@@ -0,0 +1,27 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright (C) 2024, TQ B.V, all rights reserved., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global rt_install_tib]
+
+section .text
+
+;; changed: rs, fs
+;; expected: rcx, rdx
+
+rt_install_tib:
+ mov rcx, gs ;; TIB -> Thread Information Block
+ mov rdx, fs ;; PIB -> Process Information Block
+ ret
+
+;; //////////////////////////////////////////////////// ;;
+
+[extern cBspDone]
+[extern kApicMadtAddressesCount]
diff --git a/dev/Kernel/HALKit/AMD64/Hypervisor.h b/dev/Kernel/HALKit/AMD64/Hypervisor.h
new file mode 100644
index 00000000..f1c56205
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Hypervisor.h
@@ -0,0 +1,25 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace Kernel
+{
+ MAKE_STRING_ENUM(HYPERVISOR)
+ ENUM_STRING(Qemu, "TCGTCGTCGTCG");
+ ENUM_STRING(KVM, " KVMKVMKVM ");
+ ENUM_STRING(VMWare, "VMwareVMware");
+ ENUM_STRING(VirtualBox, "VBoxVBoxVBox");
+ ENUM_STRING(Xen, "XenVMMXenVMM");
+ ENUM_STRING(Microsoft, "Microsoft Hv");
+ ENUM_STRING(Parallels, " prl hyperv ");
+ ENUM_STRING(ParallelsAlt, " lrpepyh vr ");
+ ENUM_STRING(Bhyve, "bhyve bhyve ");
+ ENUM_STRING(Qnx, " QNXQVMBSQG ");
+ END_STRING_ENUM()
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/MBCI/HalMBCI.cc b/dev/Kernel/HALKit/AMD64/MBCI/HalMBCI.cc
new file mode 100644
index 00000000..4faa5365
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/MBCI/HalMBCI.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/MBCI/MBCI.h>
diff --git a/dev/Kernel/HALKit/AMD64/PCI/DMA.cc b/dev/Kernel/HALKit/AMD64/PCI/DMA.cc
new file mode 100644
index 00000000..192b37ba
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/DMA.cc
@@ -0,0 +1,82 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/DMA.h>
+
+namespace Kernel
+{
+ DMAWrapper::operator bool()
+ {
+ return fAddress;
+ }
+
+ bool DMAWrapper::operator!()
+ {
+ return !fAddress;
+ }
+
+ Boolean DMAWrapper::Check(UIntPtr offset) const
+ {
+ if (!fAddress)
+ return false;
+ if (offset == 0)
+ return true;
+
+ kcout << "[DMAWrapper::IsIn] Checking offset..\n";
+ return reinterpret_cast<UIntPtr>(fAddress) >= offset;
+ }
+
+ bool DMAWrapper::Write(const UIntPtr& bit, const UIntPtr& offset)
+ {
+ if (!fAddress)
+ return false;
+
+ kcout << "[DMAWrapper::Write] Writing at address..\n";
+
+ auto addr =
+ (volatile UIntPtr*)(reinterpret_cast<UIntPtr>(fAddress) + offset);
+ *addr = bit;
+
+ return true;
+ }
+
+ UIntPtr DMAWrapper::Read(const UIntPtr& offset)
+ {
+ kcout << "[DMAWrapper::Read] checking fAddress..\n";
+ if (!fAddress)
+ return 0;
+
+ kcout << "[DMAWrapper::Read] Reading fAddress..\n";
+ return *(volatile UIntPtr*)(reinterpret_cast<UIntPtr>(fAddress) + offset);
+ ;
+ }
+
+ UIntPtr DMAWrapper::operator[](const UIntPtr& offset)
+ {
+ return this->Read(offset);
+ }
+
+ OwnPtr<IOBuf<Char*>> DMAFactory::Construct(OwnPtr<DMAWrapper>& dma)
+ {
+ if (!dma)
+ return {};
+
+ OwnPtr<IOBuf<Char*>> dmaOwnPtr =
+ make_ptr<IOBuf<Char*>, char*>(reinterpret_cast<char*>(dma->fAddress));
+
+ if (!dmaOwnPtr)
+ return {};
+
+ kcout << "Returning the new OwnPtr<IOBuf<Char*>>!\r";
+ return dmaOwnPtr;
+ }
+
+ DMAWrapper& DMAWrapper::operator=(voidPtr Ptr)
+ {
+ fAddress = Ptr;
+ return *this;
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Database.cc b/dev/Kernel/HALKit/AMD64/PCI/Database.cc
new file mode 100644
index 00000000..381b63c4
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Database.cc
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Database.h>
+
+namespace Kernel
+{
+}
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Device.cc b/dev/Kernel/HALKit/AMD64/PCI/Device.cc
new file mode 100644
index 00000000..46286a03
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Device.cc
@@ -0,0 +1,139 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/PCI/Device.h>
+
+Kernel::UInt ZKA_PCIReadRaw(Kernel::UInt bar, Kernel::UShort bus, Kernel::UShort dev, Kernel::UShort fun)
+{
+ Kernel::UInt target = 0x80000000 | ((Kernel::UInt)bus << 16) |
+ ((Kernel::UInt)dev << 11) | ((Kernel::UInt)fun << 8) |
+ (bar & 0xFC);
+
+ Kernel::HAL::rt_out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+
+ return Kernel::HAL::rt_in32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigData);
+}
+
+void ZKA_PCISetCfgTarget(Kernel::UInt bar, Kernel::UShort bus, Kernel::UShort dev, Kernel::UShort fun)
+{
+ Kernel::UInt target = 0x80000000 | ((Kernel::UInt)bus << 16) |
+ ((Kernel::UInt)dev << 11) | ((Kernel::UInt)fun << 8) |
+ (bar & ~3);
+
+ Kernel::HAL::rt_out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+}
+
+#define PCI_BAR_IO 0x01
+#define PCI_BAR_LOWMEM 0x02
+#define PCI_BAR_64 0x04
+#define PCI_BAR_PREFETCH 0x08
+
+namespace Kernel::PCI
+{
+ Device::Device(UShort bus, UShort device, UShort func, UInt32 bar)
+ : fBus(bus), fDevice(device), fFunction(func), fBar(bar)
+ {
+ }
+
+ Device::~Device() = default;
+
+ UInt Device::Read(UInt bar, Size sz)
+ {
+ ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ return HAL::rt_in32((UShort)PciConfigKind::ConfigData + (bar & 3));
+ if (sz == 2)
+ return HAL::rt_in16((UShort)PciConfigKind::ConfigData + (bar & 3));
+ if (sz == 1)
+ return HAL::rt_in8((UShort)PciConfigKind::ConfigData + (bar & 3));
+
+ return 0xFFFF;
+ }
+
+ void Device::Write(UInt bar, UIntPtr data, Size sz)
+ {
+ ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ HAL::rt_out32((UShort)PciConfigKind::ConfigData + (fBar & 3), (UInt)data);
+ if (sz == 2)
+ HAL::rt_out16((UShort)PciConfigKind::ConfigData + (fBar & 3), (UShort)data);
+ if (sz == 1)
+ HAL::rt_out8((UShort)PciConfigKind::ConfigData + (fBar & 3), (UChar)data);
+ }
+
+ UShort Device::DeviceId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction));
+ }
+
+ UShort Device::VendorId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UShort Device::InterfaceId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::Class()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24);
+ }
+
+ UChar Device::Subclass()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::ProgIf()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8);
+ }
+
+ UChar Device::HeaderType()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
+ }
+
+ void Device::EnableMmio(UInt32 bar_in)
+ {
+ bool enable = Read(bar_in, sizeof(UChar)) | (1 << 1);
+ Write(bar_in, enable, sizeof(UShort));
+ }
+
+ void Device::BecomeBusMaster(UInt32 bar_in)
+ {
+ bool enable = Read(bar_in, sizeof(UShort)) | (1 << 2);
+ Write(bar_in, enable, sizeof(UShort));
+ }
+
+ UIntPtr Device::Bar(UInt32 bar_in)
+ {
+ UInt32 bar = ZKA_PCIReadRaw(bar_in, fBus, fDevice, fFunction);
+ return bar;
+ }
+
+ UShort Device::Vendor()
+ {
+ UShort vendor = VendorId();
+
+ if (vendor != (UShort)PciConfigKind::Invalid)
+ fDevice = (UShort)Read(0x0, sizeof(UShort));
+
+ return fDevice;
+ }
+
+ Device::operator bool()
+ {
+ return VendorId() != (UShort)PciConfigKind::Invalid;
+ }
+} // namespace Kernel::PCI
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Express.cc b/dev/Kernel/HALKit/AMD64/PCI/Express.cc
new file mode 100644
index 00000000..f24c5536
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Express.cc
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Express.h>
+
+namespace Kernel
+{
+}
diff --git a/dev/Kernel/HALKit/AMD64/PCI/IO.cc b/dev/Kernel/HALKit/AMD64/PCI/IO.cc
new file mode 100644
index 00000000..da81d38b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/IO.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/IO.h>
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Iterator.cc b/dev/Kernel/HALKit/AMD64/PCI/Iterator.cc
new file mode 100644
index 00000000..d87482ab
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Iterator.cc
@@ -0,0 +1,41 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Iterator.h>
+
+namespace Kernel::PCI
+{
+ Iterator::Iterator(const Types::PciDeviceKind& type)
+ {
+ // probe devices.
+ for (int bus = 0; bus < ZKA_BUS_COUNT; ++bus)
+ {
+ for (int device = 0; device < ZKA_DEVICE_COUNT; ++device)
+ {
+ for (int function = 0; function < ZKA_FUNCTION_COUNT; ++function)
+ {
+ auto bar = 0x00;
+
+ Device dev(bus, device, function, bar);
+
+ if (dev.Class() == (UChar)type)
+ {
+ fDevices[bus] = dev;
+ }
+ }
+ }
+ }
+ }
+
+ Iterator::~Iterator()
+ {
+ }
+
+ Ref<PCI::Device> Iterator::operator[](const Size& at)
+ {
+ return fDevices[at];
+ }
+} // namespace Kernel::PCI
diff --git a/dev/Kernel/HALKit/AMD64/PCI/PCI.cc b/dev/Kernel/HALKit/AMD64/PCI/PCI.cc
new file mode 100644
index 00000000..47a56e53
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/PCI.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/PCI.h>
diff --git a/dev/Kernel/HALKit/AMD64/Paging.h b/dev/Kernel/HALKit/AMD64/Paging.h
new file mode 100644
index 00000000..4e8c8c65
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Paging.h
@@ -0,0 +1,99 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR X86_64 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.h>
+
+#ifndef kPageMax
+#define kPageMax (0x200)
+#endif //! kPageMax
+
+#ifndef kPageAlign
+#define kPageAlign (0x08)
+#endif //! kPageAlign
+
+#ifndef kPageSize
+#define kPageSize (0x100)
+#endif // !kPageSize
+
+#ifndef kAlign
+#define kAlign __BIGGEST_ALIGNMENT__
+#endif // !kAlign
+
+EXTERN_C void hal_flush_tlb();
+EXTERN_C void hal_invl_tlb(Kernel::VoidPtr addr);
+EXTERN_C void hal_write_cr3(Kernel::VoidPtr cr3);
+EXTERN_C void hal_write_cr0(Kernel::VoidPtr bit);
+
+EXTERN_C Kernel::VoidPtr hal_read_cr0(); // @brief CPU control register.
+EXTERN_C Kernel::VoidPtr hal_read_cr2(); // @brief Fault address.
+EXTERN_C Kernel::VoidPtr hal_read_cr3(); // @brief Page table.
+
+namespace Kernel::HAL
+{
+ /// @brief Final page entry (Not PML, PDPT)
+ struct PACKED ZKA_PTE final
+ {
+ UInt64 Present : 1;
+ UInt64 Wr : 1;
+ UInt64 User : 1;
+ UInt64 Wt : 1;
+ UInt64 Cache : 1;
+ UInt64 Accessed : 1;
+ UInt64 Dirty : 1;
+ UInt64 MemoryType : 1;
+ UInt64 Global : 1;
+ UInt64 Resvered1 : 3;
+ UInt64 PhysicalAddress : 36;
+ UInt64 Reserved2 : 10;
+ UInt64 ProtectionKey : 5;
+ UInt64 ExecDisable : 1;
+ };
+
+ namespace Detail
+ {
+ enum class ControlRegisterBits
+ {
+ ProtectedModeEnable = 0,
+ MonitorCoProcessor = 1,
+ Emulation = 2,
+ TaskSwitched = 3,
+ ExtensionType = 4,
+ NumericError = 5,
+ WriteProtect = 16,
+ AlignementMask = 18,
+ NotWriteThrough = 29,
+ CacheDisable = 30,
+ PageEnable = 31,
+ };
+
+ inline UInt8 control_register_cast(ControlRegisterBits reg)
+ {
+ return static_cast<UInt8>(reg);
+ }
+ } // namespace Detail
+
+ struct ZKA_PDE final
+ {
+ ZKA_PTE* ALIGN(kPageAlign) fEntries[kPageMax];
+ };
+
+ auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page) -> VoidPtr;
+ auto mm_free_bitmap(VoidPtr page_ptr) -> Bool;
+} // namespace Kernel::HAL
+
+namespace Kernel
+{
+ typedef HAL::ZKA_PTE PTE;
+ typedef HAL::ZKA_PDE PDE;
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/Processor.h b/dev/Kernel/HALKit/AMD64/Processor.h
new file mode 100644
index 00000000..ce7d53f9
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Processor.h
@@ -0,0 +1,331 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: Prcoessor.h
+ Purpose: AMD64 processor abstraction.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+#include <FirmwareKit/Handover.h>
+#include <HALKit/AMD64/Paging.h>
+
+#define kPITControlPort 0x43
+#define kPITChannel0Port 0x40
+#define kPITFrequency 1193180
+
+#define kPICCommand 0x20
+#define kPICData 0x21
+#define kPIC2Command 0xA0
+#define kPIC2Data 0xA1
+
+EXTERN_C
+{
+#include <cpuid.h>
+}
+
+#include <HALKit/AMD64/CPUID.h>
+
+/// @brief Maximum entries of the interrupt descriptor table.
+#define kKernelIdtSize (0x100)
+
+/// @brief interrupt for system call.
+#define kKernelInterruptId (0x32)
+
+#define IsActiveLow(FLG) (FLG & 2)
+#define IsLevelTriggered(FLG) (FLG & 8)
+
+#define kInterruptGate (0x8E)
+#define kTrapGate (0xEF)
+#define kTaskGate (0b10001100)
+#define kIDTSelector (0x08)
+
+namespace Kernel
+{
+ namespace Detail::AMD64
+ {
+ struct PACKED InterruptDescriptorAMD64 final
+ {
+ UInt16 OffsetLow; // offset bits 0..15
+ UInt16 Selector; // a code segment selector in GDT or LDT
+ UInt8 Ist;
+ UInt8 TypeAttributes;
+ UInt16 OffsetMid;
+ UInt32 OffsetHigh;
+ UInt32 Zero; // reserved
+ };
+ } // namespace Detail::AMD64
+} // namespace Kernel
+
+namespace Kernel::HAL
+{
+ /// @brief Memory Manager mapping flags.
+ enum
+ {
+ kMMFlagsInvalid = 0 << 0,
+ kMMFlagsPresent = 1 << 0,
+ kMMFlagsWr = 1 << 1,
+ kMMFlagsUser = 1 << 2,
+ kMMFlagsNX = 1 << 3,
+ kMMFlagsCount = 4,
+ };
+
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ struct PACKED RegisterGDT final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ using RawRegister = UInt64;
+ using Reg = RawRegister;
+ using InterruptId = UInt16; /* For each element in the IVT */
+
+ /// @brief Stack frame (as retrieved from assembly.)
+ struct PACKED StackFrame final
+ {
+ RawRegister R8{0};
+ RawRegister R9{0};
+ RawRegister R10{0};
+ RawRegister FS{0};
+ RawRegister R12{0};
+ RawRegister R13{0};
+ RawRegister R14{0};
+ RawRegister R15{0};
+ RawRegister GS{0};
+ RawRegister SP{0};
+ RawRegister BP{0};
+ };
+
+ typedef StackFrame* StackFramePtr;
+
+ class InterruptDescriptor final
+ {
+ public:
+ UShort Offset;
+ UShort Selector;
+ UChar Ist;
+ UChar Atrributes;
+
+ UShort SecondOffset;
+ UInt ThirdOffset;
+ UInt Zero;
+
+ operator bool()
+ {
+ return Offset != 0xFFFF;
+ }
+ };
+
+ using InterruptDescriptorArray = Array<InterruptDescriptor, 256>;
+
+ class SegmentDescriptor final
+ {
+ public:
+ UInt16 Base;
+ UInt8 BaseMiddle;
+ UInt8 BaseHigh;
+
+ UShort Limit;
+ UChar Gran;
+ UChar AccessByte;
+ };
+
+ /***
+ * @brief Segment Boolean operations
+ */
+ class SegmentDescriptorComparator final
+ {
+ public:
+ Bool IsValid(SegmentDescriptor& seg)
+ {
+ return seg.Base > seg.Limit;
+ }
+
+ Bool Equals(SegmentDescriptor& seg, SegmentDescriptor& segRight)
+ {
+ return seg.Base == segRight.Base && seg.Limit == segRight.Limit;
+ }
+ };
+
+ using SegmentArray = Array<SegmentDescriptor, 6>;
+
+ class GDTLoader final
+ {
+ public:
+ static Void Load(RegisterGDT& gdt);
+ static Void Load(Ref<RegisterGDT>& gdt);
+ };
+
+ class IDTLoader final
+ {
+ public:
+ static Void Load(Register64& idt);
+ static Void Load(Ref<Register64>& idt);
+ };
+ /***********************************************************************************/
+ /// @brief Is the current config SMP aware?
+ /// @return True if YES, False if not.
+ /***********************************************************************************/
+ Bool mp_is_smp(Void) noexcept;
+
+ /***********************************************************************************/
+ /// @brief Fetch and enable SMP scheduler.
+ /// @param vendor_ptr SMP containing structure.
+ /***********************************************************************************/
+ Void mp_get_cores(VoidPtr vendor_ptr) noexcept;
+
+ /***********************************************************************************/
+
+ Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress);
+ Void hal_send_end_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress);
+
+ /***********************************************************************************/
+
+ /***********************************************************************************/
+ /// @brief Do a cpuid to check if MSR exists on CPU.
+ /// @retval true it does exists.
+ /// @retval false it doesn't.
+ /***********************************************************************************/
+ inline Bool hal_has_msr() noexcept
+ {
+ static UInt32 eax, unused, edx; // eax, edx
+
+ __get_cpuid(1, &eax, &unused, &unused, &edx);
+
+ // edx returns the flag for MSR (which is 1 shifted to 5.)
+ return edx & (1 << 5);
+ }
+
+ /***********************************************************************************/
+ /// @brief Get Model specific register inside core.
+ /// @param msr MSR
+ /// @param lo low byte
+ /// @param hi high byte
+ /***********************************************************************************/
+ inline Void hal_get_msr(UInt32 msr, UInt32* lo, UInt32* hi) noexcept
+ {
+ if (!lo || !hi)
+ return;
+
+ asm volatile("rdmsr"
+ : "=a"(*lo), "=d"(*hi)
+ : "c"(msr));
+ }
+
+ /// @brief Set Model-specific register.
+ /// @param msr MSR
+ /// @param lo low byte
+ /// @param hi high byte
+ inline Void hal_set_msr(UInt32 msr, UInt32 lo, UInt32 hi) noexcept
+ {
+ asm volatile("wrmsr"
+ :
+ : "a"(lo), "d"(hi), "c"(msr));
+ }
+
+ /// @brief Processor specific namespace.
+ namespace Detail
+ {
+ /* @brief TSS struct. */
+ struct ZKA_TSS final
+ {
+ UInt32 fReserved1;
+ UInt64 fRsp0;
+ UInt64 fRsp1;
+ UInt64 fRsp2;
+ UInt64 fReserved2;
+ UInt64 fIst1;
+ UInt64 fIst2;
+ UInt64 fIst3;
+ UInt64 fIst4;
+ UInt64 fIst5;
+ UInt64 fIst6;
+ UInt64 fIst7;
+ UInt64 fReserved3;
+ UInt16 fReserved4;
+ UInt16 fIopb;
+ };
+
+ /**
+ @brief Global descriptor table entry, either null, code or data.
+ */
+
+ struct PACKED ZKA_GDT_ENTRY final
+ {
+ UInt16 fLimitLow;
+ UInt16 fBaseLow;
+ UInt8 fBaseMid;
+ UInt8 fAccessByte;
+ UInt8 fFlags;
+ UInt8 fBaseHigh;
+ };
+ } // namespace Detail
+
+ class APICController
+ {
+ public:
+ explicit APICController(VoidPtr base)
+ : fApic(base)
+ {
+ }
+
+ ~APICController() = default;
+
+ ZKA_COPY_DEFAULT(APICController);
+
+ public:
+ UInt32 Read(UInt32 reg) noexcept;
+ Void Write(UInt32 reg, UInt32 value) noexcept;
+
+ private:
+ VoidPtr fApic{nullptr};
+ };
+
+ /// @brief Set a PTE from pd_base.
+ /// @param virt_addr a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manip.
+ EXTERN_C Int32 mm_map_page(VoidPtr virt_addr, UInt32 flags);
+
+ EXTERN_C UInt8 rt_in8(UInt16 port);
+ EXTERN_C UInt16 rt_in16(UInt16 port);
+ EXTERN_C UInt32 rt_in32(UInt16 port);
+
+ EXTERN_C void rt_out16(UShort port, UShort byte);
+ EXTERN_C void rt_out8(UShort port, UChar byte);
+ EXTERN_C void rt_out32(UShort port, UInt byte);
+
+ EXTERN_C void rt_wait_400ns();
+ EXTERN_C void rt_halt();
+ EXTERN_C void rt_cli();
+ EXTERN_C void rt_sti();
+ EXTERN_C void rt_cld();
+ EXTERN_C void rt_std();
+} // namespace Kernel::HAL
+
+EXTERN_C Kernel::Void idt_handle_generic(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_gpf(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_math(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_pf(Kernel::UIntPtr rsp);
+
+EXTERN_C ATTRIBUTE(naked) Kernel::Void hal_load_idt(Kernel::HAL::Register64 ptr);
+EXTERN_C ATTRIBUTE(naked) Kernel::Void hal_load_gdt(Kernel::HAL::RegisterGDT ptr);
+
+inline Kernel::VoidPtr kKernelBitMpStart = nullptr;
+inline Kernel::UIntPtr kKernelBitMpSize = 0UL;
diff --git a/dev/Kernel/HALKit/AMD64/ReadMe.md b/dev/Kernel/HALKit/AMD64/ReadMe.md
new file mode 100644
index 00000000..9570b33e
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/ReadMe.md
@@ -0,0 +1,8 @@
+# AMD64 Hardware Abstraction Layer
+
+## Brief
+
+- Supported CPU: AMD64 BASED CPUs.
+- Supported Firmware: EDK 2.
+
+###### Copyright (C) 2024, TQ B.V, all rights reserved. All rights reserved.
diff --git a/dev/Kernel/HALKit/AMD64/Storage/AHCI-DMA.cc b/dev/Kernel/HALKit/AMD64/Storage/AHCI-DMA.cc
new file mode 100644
index 00000000..e86bfde7
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/AHCI-DMA.cc
@@ -0,0 +1,319 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+/**
+ * @file AHCI.cc
+ * @author TQ B.V (amlalelmahrouss@icloud.com)
+ * @brief AHCI driver.
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @Copyright (C) 2024, TQ B.V, all rights reserved.
+ *
+ */
+
+#include <KernelKit/UserProcessScheduler.h>
+#include <KernelKit/LPC.h>
+
+#include <Modules/ATA/ATA.h>
+#include <Modules/AHCI/AHCI.h>
+#include <KernelKit/PCI/Iterator.h>
+#include <NewKit/Utils.h>
+#include <KernelKit/LockDelegate.h>
+
+#ifdef __AHCI__
+
+#define HBA_ERR_TFE (1 << 30)
+#define HBA_PxCMD_ST 0x0001
+#define HBA_PxCMD_FRE 0x0010
+#define HBA_PxCMD_FR 0x4000
+#define HBA_PxCMD_CR 0x8000
+
+#define kAhciStartAddress mib_cast(4)
+
+#define kAhciLBAMode (1 << 6)
+
+#define kAhciMaxPoll (100000U)
+
+#define kCmdOrCtrlCmd 1
+#define kCmdOrCtrlCtrl 0
+
+#define kAhciSRBsy 0x80
+#define kAhciSRDrq 0x08
+
+enum
+{
+ kSATAProgIfAHCI = 0x01,
+ kSATASubClass = 0x06,
+ kSATABar5 = 0x24,
+};
+
+STATIC Kernel::PCI::Device kAhciDevice;
+STATIC HbaPort* kAhciPort = nullptr;
+STATIC Kernel::Lba kCurrentDiskSectorCount = 0UL;
+
+Kernel::Void drv_calculate_disk_geometry()
+{
+ kCurrentDiskSectorCount = 0UL;
+ kcout << "Highest AHCI LBA (48-bit): " << Kernel::number(kCurrentDiskSectorCount) << endl;
+}
+
+/// @brief Initializes an AHCI disk.
+/// @param PortsImplemented the amount of kAhciPort that have been detected.
+/// @return if the disk was successfully initialized or not.
+Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
+{
+ using namespace Kernel;
+
+ PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController);
+
+ for (SizeT device_index = 0; device_index < ZKA_BUS_COUNT; ++device_index)
+ {
+ kAhciDevice = iterator[device_index].Leak(); // And then leak the reference.
+
+ // if SATA and then interface is AHCI...
+ if (kAhciDevice.Subclass() == kSATASubClass &&
+ kAhciDevice.ProgIf() == kSATAProgIfAHCI)
+ {
+ kAhciDevice.EnableMmio(0x24); // Enable the memory index_byte/o for this ahci device.
+ kAhciDevice.BecomeBusMaster(0x24); // Become bus master for this ahci device, so that we can control it.
+
+ HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar(0x24);
+
+ Kernel::UInt32 ports_implemented = mem_ahci->Pi;
+ Kernel::UInt16 ahci_index = 0;
+
+ const Kernel::UInt16 kMaxPortsImplemented = 32;
+ const Kernel::UInt32 kSATASignature = 0x00000101;
+ const Kernel::UInt8 kAhciPresent = 0x03;
+ const Kernel::UInt8 kAhciIPMActive = 0x01;
+
+ Kernel::Boolean detected = false;
+
+ while (ahci_index < kMaxPortsImplemented)
+ {
+ if (ports_implemented)
+ {
+ kcout << "Port is implemented by host.\r";
+
+ Kernel::UInt8 ipm = (mem_ahci->Ports[ahci_index].Ssts >> 8) & 0x0F;
+ Kernel::UInt8 det = mem_ahci->Ports[ahci_index].Ssts & 0x0F;
+
+ if (mem_ahci->Ports[ahci_index].Sig == kSATASignature)
+ {
+ kcout << "Port is AHCI controller.\r";
+
+ detected = true;
+
+ kAhciPort = &mem_ahci->Ports[ahci_index];
+
+ kAhciPort->Cmd &= ~HBA_PxCMD_FRE;
+
+ // Clear FRE (bit4)
+ kAhciPort->Cmd &= ~HBA_PxCMD_ST;
+
+ // Wait until FR (bit14), CR (bit15) are cleared
+ while (YES)
+ {
+ if (kAhciPort->Cmd & HBA_PxCMD_CR)
+ continue;
+
+ if (kAhciPort->Cmd & HBA_PxCMD_FR)
+ continue;
+ break;
+ }
+
+ // when it's stopped.
+
+ // do in-between
+
+ kAhciPort->Clb = kAhciStartAddress + (ahci_index << 10);
+ kAhciPort->Clbu = 0;
+ rt_set_memory((Kernel::VoidPtr)((Kernel::UIntPtr)kAhciPort->Clb + kAhciPort->Clbu), 0, 1024);
+
+ // FIS offset: 32K+256*ahci_index
+ // FIS entry size = 256 bytes per port
+ kAhciPort->Fb = kAhciStartAddress + (32 << 10) + (ahci_index << 8);
+ kAhciPort->Fbu = 0;
+ rt_set_memory((Kernel::VoidPtr)((Kernel::UIntPtr)kAhciPort->Fb + kAhciPort->Fbu), 0, 256);
+
+ // Command table offset: 40K + 8K*ahci_index
+ // Command table size = 256*32 = 8K per port
+ HbaCmdHeader* cmd_header = (HbaCmdHeader*)((Kernel::UIntPtr)kAhciPort->Clb + kAhciPort->Clbu);
+
+ for (SizeT i = 0; i < 32; i++)
+ {
+ cmd_header[i].Prdtl = 8; // 8 prdt entries per command table
+ // 256 bytes per command table, 64+16+48+16*8
+ // Command table offset: 40K + 8K*ahci_index + cmdheader_index*256
+ cmd_header[i].Ctba = kAhciStartAddress + (40 << 10) + (ahci_index << 13) + (i << 8);
+ cmd_header[i].Ctbau = 0;
+
+ rt_set_memory((VoidPtr)((Kernel::UIntPtr)cmd_header[i].Ctba + cmd_header[i].Ctbau), 0, 256);
+ }
+
+ // when it's starting
+
+ // check for bits again, to start it again.
+ while (YES)
+ {
+ if (kAhciPort->Cmd & HBA_PxCMD_FR)
+ continue;
+
+ break;
+ }
+
+ kAhciPort->Cmd |= HBA_PxCMD_FRE;
+ kAhciPort->Cmd |= HBA_PxCMD_ST;
+
+ drv_calculate_disk_geometry();
+
+ break;
+ }
+ }
+
+ ports_implemented >>= 1;
+ ++ahci_index;
+ }
+
+ return detected;
+ }
+ }
+
+ return No;
+}
+
+Kernel::Boolean drv_std_detected(Kernel::Void)
+{
+ return kAhciDevice.DeviceId() != 0xFFFF;
+}
+
+Kernel::Void drv_std_write(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer)
+{
+}
+
+Kernel::Void drv_std_read(Kernel::UInt64 lba, Kernel::Char* buffer, Kernel::SizeT sector_cnt, Kernel::SizeT size_buffer)
+{
+ kAhciPort->Is = -1;
+
+ Kernel::SizeT port = 0;
+ Kernel::UInt32 slots = (kAhciPort->Sact | kAhciPort->Ci);
+
+ for (; port < slots; ++port)
+ {
+ if ((slots & 1) == 0)
+ break;
+
+ slots >>= 1;
+ }
+
+ HbaCmdHeader* cmd_hdr = (HbaCmdHeader*)((Kernel::UIntPtr)kAhciPort->Clb + kAhciPort->Clbu);
+
+ cmd_hdr += port;
+ cmd_hdr->Cfl = sizeof(FisRegH2D) / sizeof(Kernel::UInt32);
+ cmd_hdr->Write = NO;
+ cmd_hdr->Prdtl = (Kernel::UInt16)((sector_cnt - 1) >> 4) + 1;
+
+ HbaCmdTbl* cmd_tbl = (HbaCmdTbl*)((Kernel::UIntPtr)cmd_hdr->Ctba + cmd_hdr->Ctbau);
+ Kernel::rt_set_memory(cmd_tbl, 0, (cmd_hdr->Prdtl - 1) * sizeof(HbaPrdtEntry));
+
+ Kernel::SizeT i = 0;
+
+ for (Kernel::SizeT i = 0; i < cmd_hdr->Prdtl - 1; i++)
+ {
+ cmd_tbl->PrdtEntries[i].Dba = (Kernel::UInt32)(Kernel::UInt64)buffer;
+ cmd_tbl->PrdtEntries[i].Dbau = (Kernel::UInt32)((Kernel::UInt64)(buffer) >> 32);
+ cmd_tbl->PrdtEntries[i].Dbc = size_buffer - 1; // 8K bytes (this value should always be set to 1 less than the actual value)
+ cmd_tbl->PrdtEntries[i].InterruptBit = 1;
+ }
+
+ cmd_tbl->PrdtEntries[i].Dba = (Kernel::UInt32)(Kernel::UInt64)buffer;
+ cmd_tbl->PrdtEntries[i].Dbau = (Kernel::UInt32)((Kernel::UInt64)(buffer) >> 32);
+ cmd_tbl->PrdtEntries[i].Dbc = size_buffer - 1; // 8K bytes (this value should always be set to 1 less than the actual value)
+ cmd_tbl->PrdtEntries[i].InterruptBit = 1;
+
+ FisRegH2D* cmd_fis = (FisRegH2D*)(&cmd_tbl->Cfis);
+
+ cmd_fis->FisType = kFISTypeRegH2D;
+ cmd_fis->CmdOrCtrl = YES; // Command
+ cmd_fis->Command = kAHCICmdReadDmaEx;
+
+ cmd_fis->Lba0 = (Kernel::UInt8)(Kernel::UInt32)lba & 0xFF;
+ cmd_fis->Lba1 = (Kernel::UInt8)((Kernel::UInt32)lba >> 8);
+ cmd_fis->Lba2 = (Kernel::UInt8)((Kernel::UInt32)lba >> 16);
+ cmd_fis->Device = kAhciLBAMode; // LBA mode
+
+ cmd_fis->Lba3 = (Kernel::UInt8)((Kernel::UInt32)lba >> 24);
+ cmd_fis->Lba4 = (Kernel::UInt8)(lba >> 32);
+ cmd_fis->Lba5 = (Kernel::UInt8)((lba >> 32) >> 8);
+
+ cmd_fis->CountLow = sector_cnt & 0xFF;
+ cmd_fis->CountHigh = (sector_cnt >> 8) & 0xFF;
+
+ Kernel::UInt64 spin = 0UL;
+
+ // The below loop waits until the port is no longer busy before issuing a new command
+ while ((kAhciPort->Tfd & (kAhciSRBsy | kAhciSRDrq)) && spin < kAhciMaxPoll)
+ {
+ spin++;
+ }
+ if (spin == 1000000)
+ {
+ kcout << "AHCI: Port is hung.\r";
+ return;
+ }
+
+ kAhciPort->Ci = 1 << port; // Issue command
+
+ // Wait for completion
+ while (YES)
+ {
+ // In some longer duration reads, it may be helpful to spin on the DPS bit
+ // in the PxIS port field as well (1 << 5)
+ if ((kAhciPort->Ci & (1 << port)) == 0)
+ break;
+ if (kAhciPort->Is & HBA_ERR_TFE) // Task file error
+ {
+ using namespace Kernel;
+ kcout << ("AHCI: Read disk error.\r");
+
+ err_global_get() = kErrorUnrecoverableDisk;
+
+ return;
+ }
+ }
+
+ // Check again for the last time.
+ if (kAhciPort->Is & HBA_ERR_TFE) // task file error status
+ {
+ using namespace Kernel;
+
+ kcout << ("AHCI: Read disk error.\r");
+ *buffer = 0;
+
+ err_global_get() = kErrorUnrecoverableDisk;
+
+ return;
+ }
+}
+
+/***
+ @brief Gets the number of sectors inside the drive.
+ @return Sector size in bytes.
+ */
+Kernel::SizeT drv_get_sector_count()
+{
+ return kCurrentDiskSectorCount;
+}
+
+/// @brief Get the drive size.
+/// @return Disk size in bytes.
+Kernel::SizeT drv_get_size()
+{
+ return drv_get_sector_count() * kAHCISectorSize;
+}
+
+#endif // ifdef __AHCI__
diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cc b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cc
new file mode 100644
index 00000000..d1751105
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cc
@@ -0,0 +1,38 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-DMA.cc
+ * @author TQ B.V (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (DMA mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) TQ B.V
+ *
+ */
+
+#include <StorageKit/PRDT.h>
+
+#include <Modules/ATA/ATA.h>
+#include <ArchKit/ArchKit.h>
+
+using namespace Kernel;
+
+EXTERN_C Int32 kPRDTTransferStatus;
+STATIC PRDT kPRDT;
+
+#ifdef __ATA_DMA__
+
+#ifdef __ATA_PIO__
+#error !!! You cant have both PIO and DMA enabled! !!!
+#endif /* ifdef __ATA_PIO__ */
+
+#ifdef __AHCI__
+#error !!! You cant have both ATA and AHCI enabled! !!!
+#endif /* ifdef __AHCI__ */
+
+#endif /* ifdef __ATA_DMA__ */
diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cc b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cc
new file mode 100644
index 00000000..678d65b7
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cc
@@ -0,0 +1,197 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-PIO.cc
+ * @author TQ B.V (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (PIO mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) TQ B.V
+ *
+ */
+
+#include <Modules/ATA/ATA.h>
+#include <ArchKit/ArchKit.h>
+
+#ifdef __ATA_PIO__
+
+using namespace Kernel;
+using namespace Kernel::HAL;
+
+/// bugs: 0
+
+#define kATADataLen 256
+
+STATIC Boolean kATADetected = false;
+STATIC Int32 kATADeviceType = kATADeviceCount;
+STATIC Char kATAData[kATADataLen] = {0};
+
+Boolean drv_std_wait_io(UInt16 IO)
+{
+ for (int i = 0; i < 400; i++)
+ rt_in8(IO + ATA_REG_STATUS);
+
+ATAWaitForIO_Retry:
+ auto statRdy = rt_in8(IO + ATA_REG_STATUS);
+
+ if ((statRdy & ATA_SR_BSY))
+ goto ATAWaitForIO_Retry;
+
+ATAWaitForIO_Retry2:
+ statRdy = rt_in8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ return false;
+
+ if (!(statRdy & ATA_SR_DRDY))
+ goto ATAWaitForIO_Retry2;
+
+ return true;
+}
+
+Void drv_std_select(UInt16 Bus)
+{
+ if (Bus == ATA_PRIMARY_IO)
+ rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL);
+ else
+ rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL);
+}
+
+Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
+{
+ UInt16 IO = Bus;
+
+ drv_std_select(IO);
+
+ATAInit_Retry:
+ // Bus init, NEIN bit.
+ rt_out8(IO + ATA_REG_NEIN, 1);
+
+ // identify until it's good
+
+ auto statRdy = rt_in8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ {
+ kcout << "ERROR: ATA DRIVE RETURNED ERROR BIT! ABORTING...\r";
+
+ return false;
+ }
+
+ if ((statRdy & ATA_SR_BSY))
+ {
+ kcout << "Retrying...";
+ goto ATAInit_Retry;
+ }
+
+ rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
+
+ /// fetch serial info
+ /// model, speed, number of sectors...
+
+ drv_std_wait_io(IO);
+
+ for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData)
+ {
+ kATAData[indexData] = rt_in16(IO + ATA_REG_DATA);
+ }
+
+ OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO;
+
+ OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE;
+
+ kcout << "INFO: INITIALIZED ATA DRIVE!\r";
+
+ return true;
+}
+
+Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ Lba /= SectorSz;
+
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz));
+
+ rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF);
+ rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+ rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24);
+
+ rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
+
+ drv_std_wait_io(IO);
+
+ for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
+ {
+ drv_std_wait_io(IO);
+ Buf[IndexOff] = rt_in16(IO + ATA_REG_DATA);
+ drv_std_wait_io(IO);
+ }
+
+ drv_std_wait_io(IO);
+}
+
+Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ Lba /= SectorSz;
+
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz));
+
+ rt_out8(IO + ATA_REG_LBA0, (Lba)&0xFF);
+ rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+ rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24);
+
+ rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
+
+ drv_std_wait_io(IO);
+
+ for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
+ {
+ drv_std_wait_io(IO);
+ rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]);
+ drv_std_wait_io(IO);
+ }
+
+ drv_std_wait_io(IO);
+}
+
+/// @brief is ATA detected?
+Boolean drv_std_detected(Void)
+{
+ return kATADetected;
+}
+
+/***
+ @brief Getter, gets the number of sectors inside the drive.
+*/
+Kernel::SizeT drv_get_sector_count()
+{
+ return (kATAData[61] << 16) | kATAData[60];
+}
+
+/// @brief Get the drive size.
+Kernel::SizeT drv_get_size()
+{
+ return drv_get_sector_count() * kATASectorSize;
+}
+
+#endif /* ifdef __ATA_PIO__ */
diff --git a/dev/Kernel/HALKit/ARM64/.gitkeep b/dev/Kernel/HALKit/ARM64/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/.gitkeep
diff --git a/dev/Kernel/HALKit/ARM64/AP.h b/dev/Kernel/HALKit/ARM64/AP.h
new file mode 100644
index 00000000..ba09e8ab
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/AP.h
@@ -0,0 +1,36 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: AP.h
+ Purpose: RISC-V hardware threads.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace Kernel
+{
+ typedef Int64 hal_ap_kind;
+
+ typedef struct HAL_HARDWARE_THREAD
+ {
+ Kernel::UIntPtr fStartAddress;
+ Kernel::UInt8 fPrivleged : 1;
+ Kernel::UInt32 fPageMemoryFlags;
+ hal_ap_kind fIdentNumber;
+ } HAL_HARDWARE_THREAD;
+
+ /// @brief Set PC to specific hart.
+ /// @param hart the hart
+ /// @param epc the pc.
+ /// @return
+ EXTERN_C Kernel::Void hal_set_pc_to_hart(HAL_HARDWARE_THREAD* hart, Kernel::VoidPtr epc);
+
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/APM/.gitkeep b/dev/Kernel/HALKit/ARM64/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/APM/.gitkeep
diff --git a/dev/Kernel/HALKit/ARM64/APM/APM.cc b/dev/Kernel/HALKit/ARM64/APM/APM.cc
new file mode 100644
index 00000000..d861420b
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/APM/APM.cc
@@ -0,0 +1,37 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/APM/APM.h>
+#include <KernelKit/LPC.h>
+
+using namespace Kernel;
+
+/// @brief Send a APM command into it's own IO space.
+/// @param base_dma the IO base port.
+/// @param cmd the command.
+/// @return status code.
+EXTERN_C Int32 apm_send_io_command(UInt16 cmd, APMPowerCmd value)
+{
+ switch (cmd)
+ {
+ case kAPMPowerCommandReboot: {
+ asm volatile(
+ "ldr x0, =0x84000009\n"
+ "hvc #0\n");
+
+ return kErrorSuccess;
+ }
+ case kAPMPowerCommandShutdown: {
+ asm volatile(
+ "ldr x0, =0x84000008\n"
+ "hvc #0\n");
+
+ return kErrorSuccess;
+ }
+ default:
+ return kErrorInvalidData;
+ }
+}
diff --git a/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc b/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
new file mode 100644
index 00000000..b43612cc
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
@@ -0,0 +1,31 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NewKit/KString.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Heap.h>
+#include <Modules/APM/APM.h>
+
+namespace Kernel
+{
+ ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsp_ptr)
+ : fRsdp(rsp_ptr), fEntries(0)
+ {
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+ apm_send_io_command(kAPMPowerCommandShutdown, 0);
+ }
+
+ /// @brief Reboot machine in either ACPI or by triple faulting.
+ /// @return nothing it's a reboot.
+ Void ACPIFactoryInterface::Reboot()
+ {
+ apm_send_io_command(kAPMPowerCommandReboot, 0);
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalAP.cc b/dev/Kernel/HALKit/ARM64/HalAP.cc
new file mode 100644
index 00000000..24ac5126
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalAP.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/ARM64/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/ARM64/AP.h>
+
+using namespace Kernel;
+
+namespace Kernel::Detail
+{
+ STATIC void mp_hang_fn(void)
+ {
+ while (YES)
+ ;
+ }
+} // namespace Kernel::Detail
+
+/// @brief wakes up thread.
+/// wakes up thread from hang.
+void mp_wakeup_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(stack->BP));
+}
+
+/// @brief makes thread sleep.
+/// hooks and hangs thread to prevent code from executing.
+void mp_hang_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(Kernel::Detail::mp_hang_fn));
+}
diff --git a/dev/Kernel/HALKit/ARM64/HalCoreMPScheduler.cc b/dev/Kernel/HALKit/ARM64/HalCoreMPScheduler.cc
new file mode 100644
index 00000000..78eead11
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalCoreMPScheduler.cc
@@ -0,0 +1,28 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+using namespace Kernel;
+
+STATIC struct PROCESS_CONTROL_BLOCK final
+{
+ HAL::StackFramePtr f_Frame;
+ UInt8* f_Stack;
+ VoidPtr f_Image;
+} kProcessBlocks[kSchedProcessLimitPerTeam] = {0};
+
+EXTERN_C HAL::StackFramePtr mp_get_current_context(ProcessID pid)
+{
+ return kProcessBlocks[pid % kSchedProcessLimitPerTeam].f_Frame;
+}
+
+EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame, ProcessID pid)
+{
+ MUST_PASS(image && stack_ptr && stack_frame);
+ return No;
+}
diff --git a/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc b/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc
new file mode 100644
index 00000000..9718ec7f
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc
@@ -0,0 +1,83 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+#include <NewKit/Utils.h>
+#include <NewKit/New.h>
+
+namespace Kernel
+{
+ EXTERN_C void ke_io_write(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ if (*bytes == 0)
+ return;
+
+ SizeT index = 0;
+ SizeT len = 0;
+
+ index = 0;
+ len = rt_string_len(bytes, 255);
+
+ volatile UInt8* uart_ptr = (UInt8*)0x09000000;
+
+ while (index < len)
+ {
+ if (bytes[index] == '\r')
+ *uart_ptr = '\r';
+
+ *uart_ptr = bytes[index] == '\r' ? '\n' : bytes[index];
+ ++index;
+ }
+#endif // __DEBUG__
+ }
+
+ TerminalDevice::~TerminalDevice() = default;
+
+ EXTERN_C void ke_io_read(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ SizeT index = 0;
+
+ volatile UInt8* uart_ptr = (UInt8*)0x09000000;
+
+ ///! TODO: Look on how to wait for the UART to complete.
+ while (Yes)
+ {
+ auto in = *uart_ptr;
+
+ ///! If enter pressed then break.
+ if (in == 0xD)
+ {
+ break;
+ }
+
+ if (in < '0' || in < 'A' || in < 'a')
+ {
+ if (in != '@' || in != '!' || in != '?' || in != '.' || in != '/' ||
+ in != ':')
+ {
+ continue;
+ }
+ }
+
+ ((char*)bytes)[index] = in;
+
+ ++index;
+ }
+
+ ((char*)bytes)[index] = 0;
+#endif // __DEBUG__
+ }
+
+ TerminalDevice TerminalDevice::The() noexcept
+ {
+ TerminalDevice out(Kernel::ke_io_write, Kernel::ke_io_read);
+ return out;
+ }
+
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalKernelMain.cc b/dev/Kernel/HALKit/ARM64/HalKernelMain.cc
new file mode 100644
index 00000000..57526aa0
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalKernelMain.cc
@@ -0,0 +1,57 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <Modules/FB/FB.h>
+#include <FirmwareKit/Handover.h>
+#include <KernelKit/FileMgr.h>
+#include <KernelKit/Heap.h>
+#include <KernelKit/PEFCodeMgr.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <NewKit/Json.h>
+#include <KernelKit/CodeMgr.h>
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NetworkKit/IPC.h>
+#include <Modules/FB/KWindow.h>
+#include <CFKit/Property.h>
+
+Kernel::Void hal_real_init(Kernel::Void) noexcept;
+EXTERN_C Kernel::Void rtl_kernel_main(Kernel::SizeT argc, char** argv, char** envp, Kernel::SizeT envp_len);
+
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::BootInfoHeader* handover_hdr)
+{
+
+ /************************************************** */
+ /* INITIALIZE AND VALIDATE HEADER. */
+ /************************************************** */
+
+ kHandoverHeader = handover_hdr;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ /************************************** */
+ /* INITIALIZE BIT MAP. */
+ /************************************** */
+
+ kKernelBitMpSize = kHandoverHeader->f_BitMapSize;
+ kKernelBitMpStart = reinterpret_cast<Kernel::VoidPtr>(
+ reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_BitMapStart));
+
+ /// @note do initialize the interrupts after it.
+
+ CG::CGDrawBackground();
+
+ rtl_kernel_main(0, nullptr, nullptr, 0);
+
+ while (YES)
+ {
+ }
+}
diff --git a/dev/Kernel/HALKit/ARM64/HalPageInternal.S b/dev/Kernel/HALKit/ARM64/HalPageInternal.S
new file mode 100644
index 00000000..8fcf40ff
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalPageInternal.S
@@ -0,0 +1,5 @@
+.text
+
+hal_flush_tlb:
+ tlbi
+ ret
diff --git a/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc b/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc
new file mode 100644
index 00000000..603ef301
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: HalPagingMgr.cc
+ Purpose: Platform Paging Manager..
+
+------------------------------------------- */
+
+#include <HALKit/ARM64/Paging.h>
+#include <HALKit/ARM64/Processor.h>
+
+namespace Kernel::HAL
+{
+ typedef UInt32 PageTableIndex;
+
+ /// \brief Page store type.
+ struct ZKA_PAGE_STORE final
+ {
+ struct
+ {
+ PDE* fPde{nullptr};
+ PTE* fPte{nullptr};
+ VoidPtr fVAddr{nullptr};
+ } fInternalStore;
+
+ Bool fStoreOp{No}; // Store operation in progress.
+
+ static ZKA_PAGE_STORE& The()
+ {
+ static ZKA_PAGE_STORE the;
+ return the;
+ }
+ };
+
+ /// \brief Retrieve the page status of a PTE.
+ STATIC Void mmi_page_status(PTE* pte)
+ {
+ }
+
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, PTE* pt_entry);
+
+ /// @brief Maps or allocates a page from virtual_address.
+ /// @param virtual_address a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manipulation process.
+ EXTERN_C Int32 mm_map_page(VoidPtr virtual_address, UInt32 flags)
+ {
+ if (!virtual_address ||
+ !flags)
+ return 0;
+
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ while (page_store.fStoreOp)
+ ;
+
+ page_store.fStoreOp = Yes;
+
+ if (page_store.fInternalStore.fVAddr == virtual_address)
+ {
+ page_store.fStoreOp = No;
+ return mmi_map_page_table_entry(page_store.fInternalStore.fVAddr, flags, page_store.fInternalStore.fPte);
+ }
+
+ return 1;
+ }
+
+ /// @brief Maps flags for a specific pte.
+ /// @internal Internal function.
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, PTE* pt_entry)
+ {
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ // Update Internal store.
+
+ page_store.fInternalStore.fPde = nullptr;
+ page_store.fInternalStore.fPte = pt_entry;
+ page_store.fInternalStore.fVAddr = virtual_address;
+
+ page_store.fStoreOp = No;
+
+ return 0;
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/ARM64/HalSchedulerCore.cc b/dev/Kernel/HALKit/ARM64/HalSchedulerCore.cc
new file mode 100644
index 00000000..c0b6d871
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalSchedulerCore.cc
@@ -0,0 +1,34 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Processor.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ /***********************************************************************************/
+ /// @brief Unimplemented function (crashes by default)
+ /// @param void
+ /***********************************************************************************/
+
+ EXTERN_C Void __zka_pure_call(void)
+ {
+ UserProcessScheduler::The().GetCurrentProcess().Leak().Crash();
+ }
+
+ /***********************************************************************************/
+ /// @brief Validate user stack.
+ /// @param stack_ptr the frame pointer.
+ /***********************************************************************************/
+
+ Bool hal_check_stack(HAL::StackFramePtr stack_ptr)
+ {
+ if (!stack_ptr)
+ return No;
+
+ return stack_ptr->SP != 0 && stack_ptr->BP != 0;
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc b/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc
new file mode 100644
index 00000000..d45b47e3
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ EXTERN_C Void __zka_pure_call(void)
+ {
+ UserProcessScheduler::The().GetCurrentProcess().Leak().Crash();
+ }
+
+ bool hal_check_stack(HAL::StackFramePtr stackPtr)
+ {
+ if (!stackPtr)
+ return No;
+
+ if (stackPtr->BP == 0 || stackPtr->SP == 0)
+ return No;
+
+ return Yes;
+ }
+
+ /// @brief Wakes up thread.
+ /// Wakes up thread from the hang state.
+ Void mp_wakeup_thread(HAL::StackFrame* stack)
+ {
+ ZKA_UNUSED(stack);
+ }
+
+ /// @brief makes the thread sleep on a loop.
+ /// hooks and hangs thread to prevent code from executing.
+ Void mp_hang_thread(HAL::StackFrame* stack)
+ {
+ ZKA_UNUSED(stack);
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc b/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc
new file mode 100644
index 00000000..f4c9ef01
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
diff --git a/dev/Kernel/HALKit/ARM64/MBCI/.keepme b/dev/Kernel/HALKit/ARM64/MBCI/.keepme
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/MBCI/.keepme
diff --git a/dev/Kernel/HALKit/ARM64/Paging.h b/dev/Kernel/HALKit/ARM64/Paging.h
new file mode 100644
index 00000000..430235de
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Paging.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR ARMV8 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.h>
+
+#ifndef kPageMax
+#define kPageMax (0x200)
+#endif //! kPageMax
+
+#ifndef kPageAlign
+#define kPageAlign (0x1000)
+#endif //! kPageAlign
+
+#ifndef kPageSize
+#define kPageSize (0x1000)
+#endif // !kPageSize
+
+//! short format address range
+
+#define c16KBPage 0b000
+#define c8KBPage 0b001
+#define c4KBPage 0b010
+#define c2KBPage 0b011
+#define c1KBPage 0b100
+#define c512BPage 0b101
+#define c256BPage 0b110
+#define c128BPage 0b111
+
+/// Long format address range
+
+#define cPageMAll \
+ { \
+ 0b000, 0b000 \
+ }
+#define cPageMToMax(M) \
+ { \
+ M, 0b000 \
+ }
+#define cPageMaxToM(M) \
+ { \
+ 0b000, M \
+ }
+#define cPageMToN(M, N) \
+ { \
+ M, N \
+ }
+
+namespace Kernel::HAL
+{
+ struct PACKED PTE_4KB final
+ {
+ UInt64 Valid : 1;
+ UInt64 Table : 1;
+ UInt64 AttrIndex : 3;
+ UInt64 NS : 1;
+ UInt64 AP : 2;
+ UInt64 SH : 2;
+ UInt64 AF : 1;
+ UInt64 NG : 1;
+ UInt64 Reserved1 : 1;
+ UInt64 Contiguous : 1;
+ UInt64 Dirty : 1;
+ UInt64 Reserved : 2;
+ UInt64 PhysicalAddress : 36;
+ UInt64 Reserved3 : 4;
+ UInt64 PXN : 1;
+ UInt64 XN : 1;
+ UInt64 Reserved4 : 9;
+ };
+
+ namespace Detail
+ {
+ enum class ControlRegisterBits
+ {
+ ProtectedModeEnable = 0,
+ MonitorCoProcessor = 1,
+ Emulation = 2,
+ TaskSwitched = 3,
+ ExtensionType = 4,
+ NumericError = 5,
+ WriteProtect = 16,
+ AlignementMask = 18,
+ NotWriteThrough = 29,
+ CacheDisable = 30,
+ PageEnable = 31,
+ };
+
+ inline UInt8 control_register_cast(ControlRegisterBits reg)
+ {
+ return static_cast<UInt8>(reg);
+ }
+ } // namespace Detail
+
+ struct PDE_4KB final
+ {
+ PTE_4KB ALIGN(kPageAlign) fEntries[kPageMax];
+ };
+
+ auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page) -> VoidPtr;
+ auto mm_free_bitmap(VoidPtr page_ptr) -> Bool;
+} // namespace Kernel::HAL
+
+namespace Kernel
+{
+ typedef HAL::PTE_4KB PTE;
+ typedef HAL::PDE_4KB PDE;
+} // namespace Kernel
+
+EXTERN_C void hal_flush_tlb();
diff --git a/dev/Kernel/HALKit/ARM64/Processor.h b/dev/Kernel/HALKit/ARM64/Processor.h
new file mode 100644
index 00000000..2fe9e31a
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Processor.h
@@ -0,0 +1,75 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+#include <FirmwareKit/Handover.h>
+
+#define kCPUBackendName "ARMv8"
+
+namespace Kernel::HAL
+{
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ /// @brief Memory Manager mapping flags.
+ enum
+ {
+ kMMFlagsPresent = 1 << 0,
+ kMMFlagsWr = 1 << 1,
+ kMMFlagsUser = 1 << 2,
+ kMMFlagsNX = 1 << 3,
+ kMMFlagsCount = 3,
+ };
+
+ /// @brief Set a PTE from pd_base.
+ /// @param virt_addr a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manip.
+ EXTERN_C Int32 mm_map_page(VoidPtr virt_addr, UInt32 flags);
+
+ typedef UIntPtr Reg;
+ typedef Register64 Register;
+
+ /// @note let's keep the same name as AMD64 HAL.
+ struct PACKED StackFrame final
+ {
+ Reg R8{0};
+ Reg R9{0};
+ Reg R10{0};
+ Reg R11{0};
+ Reg R12{0};
+ Reg R13{0};
+ Reg R14{0};
+ Reg R15{0};
+ Reg SP{0};
+ Reg BP{0};
+ };
+
+ typedef StackFrame* StackFramePtr;
+
+ inline Void rt_halt()
+ {
+ while (Yes)
+ {
+ }
+ }
+
+} // namespace Kernel::HAL
+
+inline Kernel::VoidPtr kKernelBitMpStart = nullptr;
+inline Kernel::UIntPtr kKernelBitMpSize = 0UL;
+
+inline Kernel::VoidPtr kKernelPhysicalStart = nullptr;
+
+#include <HALKit/ARM64/Paging.h>
diff --git a/dev/Kernel/HALKit/ARM64/ReadMe.md b/dev/Kernel/HALKit/ARM64/ReadMe.md
new file mode 100644
index 00000000..c51229f2
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/ReadMe.md
@@ -0,0 +1,3 @@
+# ARM64 Hardware Abstraction Layer
+
+- Supported Firmware: CoreBoot/EDK/OpenMobileBoot
diff --git a/dev/Kernel/HALKit/ARM64/Storage/.gitkeep b/dev/Kernel/HALKit/ARM64/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Storage/.gitkeep
diff --git a/dev/Kernel/HALKit/ARM64/Storage/HalFlash.cc b/dev/Kernel/HALKit/ARM64/Storage/HalFlash.cc
new file mode 100644
index 00000000..c3fe73e1
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Storage/HalFlash.cc
@@ -0,0 +1,66 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <NewKit/Defines.h>
+#include <ArchKit/ArchKit.h>
+
+/// @file Flash.cc
+/// @brief Flash memory builtin.
+
+#ifdef __USE_MBCI_FLASH__
+
+#define kMaxFlash (4U)
+
+namespace Kernel
+{
+ /// /:/BRIDGE/FLSH/1
+ constexpr auto kFlashBridgeMagic = "FLSH";
+ constexpr auto kFlashBridgeRevision = 1;
+
+ STATIC const Boolean kFlashEnabled = No;
+ STATIC SizeT kFlashSize[kMaxFlash] = {};
+ STATIC SizeT kFlashSectorSz[kMaxFlash] = {};
+
+ /// @brief Enable flash memory builtin.
+ STATIC Void drv_enable_flash(Int32 slot);
+
+ /// @brief Disable flash memory builtin.
+ STATIC Void drv_disable_flash(Int32 slot);
+
+ /// @brief get sector count.
+ /// @return drive sector count.
+ SizeT drv_get_sector_count(Int32 slot)
+ {
+ if (slot > kMaxFlash)
+ return 0;
+
+ return kFlashSectorSz[slot];
+ }
+
+ /// @brief get device size.
+ /// @return drive size
+ SizeT drv_get_size(Int32 slot)
+ {
+ if (slot > kMaxFlash)
+ return 0;
+
+ return kFlashSize[slot];
+ }
+
+ /// @brief Enable flash memory at slot.
+ STATIC Void drv_enable_flash(Int32 arg)
+ {
+ kcout << "Enabled FLSH hardware.\r";
+ }
+
+ /// @brief Disable flash memory at slot.
+ STATIC Void drv_disable_flash(Int32 arg)
+ {
+ kcout << "Disabled FLSH hardware.\r";
+ }
+} // namespace Kernel
+
+#endif // if __USE_MBCI_FLASH__ (Bridge)
diff --git a/dev/Kernel/HALKit/AXP/CR.s b/dev/Kernel/HALKit/AXP/CR.s
new file mode 100644
index 00000000..4d68257d
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/CR.s
@@ -0,0 +1,11 @@
+.globl read_lr1
+.globl read_lr0
+
+.section .text
+ read_lr0:
+ movq %r30, %cr3
+ ret
+
+ hal_read_cr0:
+ movq %r30, %cr0
+ ret \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp b/dev/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp
diff --git a/dev/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp b/dev/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp
new file mode 100644
index 00000000..16184673
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp
@@ -0,0 +1,24 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <HALKit/AXP/Processor.h>
+
+/// @brief Internal call for syscall, to work with C++.
+/// @param stack
+/// @return nothing.
+EXTERN_C void rt_syscall_handle(Kernel::HAL::StackFrame* stack)
+{
+ if (stack->Rcx <= (kSyscalls.Count() - 1))
+ {
+ kcout << "syscall: enter.\r";
+
+ if (kSyscalls[stack->Rcx].Leak().Leak().fHooked)
+ (kSyscalls[stack->Rcx].Leak().Leak().fProc)(stack);
+
+ kcout << "syscall: exit.\r";
+ }
+}
diff --git a/dev/Kernel/HALKit/AXP/HAL.s b/dev/Kernel/HALKit/AXP/HAL.s
new file mode 100644
index 00000000..0178527f
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/HAL.s
@@ -0,0 +1,13 @@
+.globl rt_wait_400ns
+
+.section .text
+rt_wait_400ns:
+ jmp .L
+.L:
+ jmp .L2
+ wtint ;; wait for interrupt
+.L2:
+
+ ret
+
+
diff --git a/dev/Kernel/HALKit/AXP/Processor.h b/dev/Kernel/HALKit/AXP/Processor.h
new file mode 100644
index 00000000..ec986d79
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/Processor.h
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
diff --git a/dev/Kernel/HALKit/AXP/README b/dev/Kernel/HALKit/AXP/README
new file mode 100644
index 00000000..91e7b134
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/README
@@ -0,0 +1 @@
+This is for DEC Alpha.
diff --git a/dev/Kernel/HALKit/AXP/README.TXT b/dev/Kernel/HALKit/AXP/README.TXT
new file mode 100644
index 00000000..11e138f9
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/README.TXT
@@ -0,0 +1 @@
+An toy HAL to test the Kernel portability.
diff --git a/dev/Kernel/HALKit/AXP/SYSCALL.s b/dev/Kernel/HALKit/AXP/SYSCALL.s
new file mode 100644
index 00000000..19cab808
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/SYSCALL.s
@@ -0,0 +1,10 @@
+.section .text
+system_handle_user_call:
+ .cfi_startproc
+
+ push %r0
+ jmp %r1
+ mov %r30, %r2
+
+ .cfi_endproc
+ retsys \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AXP/VM.s b/dev/Kernel/HALKit/AXP/VM.s
new file mode 100644
index 00000000..7024086b
--- /dev/null
+++ b/dev/Kernel/HALKit/AXP/VM.s
@@ -0,0 +1,5 @@
+.global hal_flush_tlb
+
+.section .text
+hal_flush_tlb:
+ swppal \ No newline at end of file
diff --git a/dev/Kernel/HALKit/POWER/.gitkeep b/dev/Kernel/HALKit/POWER/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/.gitkeep
diff --git a/dev/Kernel/HALKit/POWER/AP.h b/dev/Kernel/HALKit/POWER/AP.h
new file mode 100644
index 00000000..6965f27c
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/AP.h
@@ -0,0 +1,39 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: AP.h
+ Purpose: POWER hardware threads.
+
+ Revision History:
+
+ 14/04/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace Kernel
+{
+ struct HAL_HARDWARE_THREAD;
+
+ /// @brief hardware thread indentification type.
+ typedef Kernel::Int32 hal_ap_kind;
+
+ /// @brief Hardware thread information structure.
+ typedef struct HAL_HARDWARE_THREAD
+ {
+ Kernel::UIntPtr fStartAddress;
+ Kernel::UInt8 fPrivleged : 1;
+ Kernel::UInt32 fPageMemoryFlags;
+ hal_ap_kind fIdentNumber;
+ } HAL_HARDWARE_THREAD;
+
+ /// @brief Set PC to specific hart.
+ /// @param hart the hart
+ /// @param epc the pc.
+ /// @return
+ EXTERN_C Kernel::Void hal_set_pc_to_hart(HAL_HARDWARE_THREAD* hart, Kernel::VoidPtr epc);
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/POWER/APM/.gitkeep b/dev/Kernel/HALKit/POWER/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/APM/.gitkeep
diff --git a/dev/Kernel/HALKit/POWER/HalAP.cc b/dev/Kernel/HALKit/POWER/HalAP.cc
new file mode 100644
index 00000000..e354c915
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/HalAP.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/POWER/AP.h>
+
+using namespace Kernel;
+
+namespace Kernel::Detail
+{
+ STATIC void mp_hang_fn(void)
+ {
+ while (YES)
+ ;
+ }
+} // namespace Kernel::Detail
+
+/// @brief wakes up thread.
+/// wakes up thread from hang.
+void mp_wakeup_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(stack->BP));
+}
+
+/// @brief makes thread sleep.
+/// hooks and hangs thread to prevent code from executing.
+void mp_hang_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(Kernel::Detail::mp_hang_fn));
+}
diff --git a/dev/Kernel/HALKit/POWER/HalDebugOutput.cc b/dev/Kernel/HALKit/POWER/HalDebugOutput.cc
new file mode 100644
index 00000000..409ae3a0
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/HalDebugOutput.cc
@@ -0,0 +1,27 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+
+using namespace Kernel;
+
+/// @brief Writes to COM1.
+/// @param bytes
+void ke_io_write(const Char* bytes)
+{
+ if (!bytes)
+ return;
+
+ SizeT index = 0;
+ SizeT len = rt_string_len(bytes, 255);
+
+ while (index < len)
+ {
+ // TODO
+ ++index;
+ }
+}
diff --git a/dev/Kernel/HALKit/POWER/HalStartSequence.s b/dev/Kernel/HALKit/POWER/HalStartSequence.s
new file mode 100644
index 00000000..e99375a8
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/HalStartSequence.s
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+.globl __ImageStart
+.extern hal_init_platform
+.align 4
+.text
+
+__ImageStart:
+ bl hal_init_platform
+ blr
diff --git a/dev/Kernel/HALKit/POWER/HalThread.cc b/dev/Kernel/HALKit/POWER/HalThread.cc
new file mode 100644
index 00000000..fbd694ff
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/HalThread.cc
@@ -0,0 +1,8 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
diff --git a/dev/Kernel/HALKit/POWER/HalVirtualMemory.cc b/dev/Kernel/HALKit/POWER/HalVirtualMemory.cc
new file mode 100644
index 00000000..b5fefcfa
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/HalVirtualMemory.cc
@@ -0,0 +1,49 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/POWER/MMU.h>
+
+/// @note Refer to SoC documentation.
+
+using namespace Kernel;
+
+EXTERN_C Void hal_write_tlb(UInt32 mas0, UInt32 mas1, UInt32 mas2, UInt32 mas3, UInt32 mas7)
+{
+ hal_mtspr(MAS0, mas0);
+ hal_mtspr(MAS1, mas1);
+ hal_mtspr(MAS2, mas2);
+ hal_mtspr(MAS3, mas3);
+ hal_mtspr(MAS7, mas7);
+
+ hal_flush_tlb();
+}
+
+EXTERN_C Bool hal_set_tlb(UInt8 tlb, UInt32 epn, UInt64 rpn, UInt8 perms, UInt8 wimge, UInt8 ts, UInt8 esel, UInt8 tsize, UInt8 iprot)
+{
+ if ((hal_mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1 && (tsize & 1))
+ {
+ // this MMU does not allow odd tsize values
+ return false;
+ }
+
+ UInt32 mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+ UInt32 mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+ UInt32 mas2 = FSL_BOOKE_MAS2(epn, wimge);
+ UInt32 mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+ UInt32 mas7 = FSL_BOOKE_MAS7(rpn);
+
+ hal_write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ return true;
+}
+
+/// @brief Flush TLB
+EXTERN_C void hal_flush_tlb()
+{
+ asm volatile("isync;tlbwe;msync;isync");
+}
diff --git a/dev/Kernel/HALKit/POWER/MBCI/.gitkeep b/dev/Kernel/HALKit/POWER/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/MBCI/.gitkeep
diff --git a/dev/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cc b/dev/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cc
new file mode 100644
index 00000000..fbd694ff
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cc
@@ -0,0 +1,8 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
diff --git a/dev/Kernel/HALKit/POWER/Processor.h b/dev/Kernel/HALKit/POWER/Processor.h
new file mode 100644
index 00000000..e230b4a7
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/Processor.h
@@ -0,0 +1,62 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ Purpose: POWER processor header.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+
+#define NoOp() asm volatile("mr 0, 0")
+#define kHalPPCAlignment __attribute__((aligned(4)))
+
+namespace Kernel::HAL
+{
+ typedef UIntPtr Reg;
+
+ /// @brief Stack frame (as retrieved from assembly.)
+ struct PACKED StackFrame final
+ {
+ Reg R8{0};
+ Reg R9{0};
+ Reg R10{0};
+ Reg R11{0};
+ Reg R12{0};
+ Reg R13{0};
+ Reg R14{0};
+ Reg R15{0};
+ Reg SP{0};
+ Reg BP{0};
+ };
+
+ typedef StackFrame* StackFramePtr;
+
+ inline void rt_halt()
+ {
+ while (true)
+ {
+ NoOp(); // no oop.
+ }
+ }
+
+ inline void rt_cli()
+ {
+ NoOp(); // no oop
+ }
+} // namespace Kernel::HAL
+
+EXTERN_C Kernel::Void int_handle_math(Kernel::UIntPtr sp);
+EXTERN_C Kernel::Void int_handle_pf(Kernel::UIntPtr sp);
+
+/// @brief Set TLB.
+Kernel::Bool hal_set_tlb(Kernel::UInt8 tlb, Kernel::UInt32 epn, Kernel::UInt64 rpn, Kernel::UInt8 perms, Kernel::UInt8 wimge, Kernel::UInt8 ts, Kernel::UInt8 esel, Kernel::UInt8 tsize, Kernel::UInt8 iprot);
+
+/// @brief Write TLB.
+Kernel::Void hal_write_tlb(Kernel::UInt32 mas0, Kernel::UInt32 mas1, Kernel::UInt32 mas2, Kernel::UInt32 mas3, Kernel::UInt32 mas7);
+
+/// @brief Flush TLB.
+EXTERN_C Kernel::Void hal_flush_tlb();
diff --git a/dev/Kernel/HALKit/POWER/ReadMe.md b/dev/Kernel/HALKit/POWER/ReadMe.md
new file mode 100644
index 00000000..a9751581
--- /dev/null
+++ b/dev/Kernel/HALKit/POWER/ReadMe.md
@@ -0,0 +1,4 @@
+POWER Hardware Abstraction Layer
+
+- Supported CPU: POWER
+- Supported Firmware: CoreBoot \ No newline at end of file
diff --git a/dev/Kernel/HALKit/RISCV/.keep b/dev/Kernel/HALKit/RISCV/.keep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/.keep
diff --git a/dev/Kernel/HALKit/RISCV/AP.h b/dev/Kernel/HALKit/RISCV/AP.h
new file mode 100644
index 00000000..ba09e8ab
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/AP.h
@@ -0,0 +1,36 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+ File: AP.h
+ Purpose: RISC-V hardware threads.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace Kernel
+{
+ typedef Int64 hal_ap_kind;
+
+ typedef struct HAL_HARDWARE_THREAD
+ {
+ Kernel::UIntPtr fStartAddress;
+ Kernel::UInt8 fPrivleged : 1;
+ Kernel::UInt32 fPageMemoryFlags;
+ hal_ap_kind fIdentNumber;
+ } HAL_HARDWARE_THREAD;
+
+ /// @brief Set PC to specific hart.
+ /// @param hart the hart
+ /// @param epc the pc.
+ /// @return
+ EXTERN_C Kernel::Void hal_set_pc_to_hart(HAL_HARDWARE_THREAD* hart, Kernel::VoidPtr epc);
+
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/RISCV/APM/.gitkeep b/dev/Kernel/HALKit/RISCV/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/APM/.gitkeep
diff --git a/dev/Kernel/HALKit/RISCV/HalAP.cc b/dev/Kernel/HALKit/RISCV/HalAP.cc
new file mode 100644
index 00000000..7b168e4c
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/HalAP.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/RISCV/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/RISCV/AP.h>
+
+using namespace Kernel;
+
+namespace Kernel::Detail
+{
+ STATIC void mp_hang_fn(void)
+ {
+ while (YES)
+ ;
+ }
+} // namespace Kernel::Detail
+
+/// @brief wakes up thread.
+/// wakes up thread from hang.
+void mp_wakeup_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(stack->BP));
+}
+
+/// @brief makes thread sleep.
+/// hooks and hangs thread to prevent code from executing.
+void mp_hang_thread(HAL::StackFramePtr stack)
+{
+ if (!stack)
+ return;
+
+ hal_set_pc_to_hart(reinterpret_cast<HAL_HARDWARE_THREAD*>(stack->R15), reinterpret_cast<VoidPtr>(Kernel::Detail::mp_hang_fn));
+}
diff --git a/dev/Kernel/HALKit/RISCV/ReadMe.md b/dev/Kernel/HALKit/RISCV/ReadMe.md
new file mode 100644
index 00000000..b099aa31
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/ReadMe.md
@@ -0,0 +1,4 @@
+RISCV64 Hardware Abstraction Layer
+
+- Supported CPU: RISCV64
+- Supported Firmware: CoreBoot \ No newline at end of file
diff --git a/dev/Kernel/HALKit/RISCV/Storage/.gitkeep b/dev/Kernel/HALKit/RISCV/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/RISCV/Storage/.gitkeep
diff --git a/dev/Kernel/HALKit/X86S/.gitkeep b/dev/Kernel/HALKit/X86S/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/X86S/.gitkeep
diff --git a/dev/Kernel/HALKit/X86S/ACPI/.gitkeep b/dev/Kernel/HALKit/X86S/ACPI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/X86S/ACPI/.gitkeep
diff --git a/dev/Kernel/HALKit/X86S/Storage/.gitkeep b/dev/Kernel/HALKit/X86S/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/X86S/Storage/.gitkeep