summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64
diff options
context:
space:
mode:
authorAmlal EL Mahrouss <amlalelmahrouss@icloud.com>2024-08-15 18:35:34 +0200
committerAmlal EL Mahrouss <amlalelmahrouss@icloud.com>2024-08-15 18:35:34 +0200
commitf3d931aa7cfaf96baef8383b59a8938779541ee7 (patch)
treefdb9fc51badb3dbd03e46ab0766a49d9522e13e2 /dev/Kernel/HALKit/AMD64
parent86640816e8b1d3595365f1fcc8a2a9e61fb40ff1 (diff)
[IMP] Moved source code into dev/ folder.
Signed-off-by: Amlal EL Mahrouss <amlalelmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit/AMD64')
-rw-r--r--dev/Kernel/HALKit/AMD64/CPUID.hxx81
-rw-r--r--dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx142
-rw-r--r--dev/Kernel/HALKit/AMD64/HalAPIC.cxx36
-rw-r--r--dev/Kernel/HALKit/AMD64/HalBoot.asm22
-rw-r--r--dev/Kernel/HALKit/AMD64/HalControlRegister.s40
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx76
-rw-r--r--dev/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx198
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDebugOutput.cxx145
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDebugPort.cxx40
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cxx91
-rw-r--r--dev/Kernel/HALKit/AMD64/HalHart.cxx33
-rw-r--r--dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm242
-rw-r--r--dev/Kernel/HALKit/AMD64/HalKernelMain.cxx251
-rw-r--r--dev/Kernel/HALKit/AMD64/HalKernelMouse.cxx190
-rw-r--r--dev/Kernel/HALKit/AMD64/HalPageAlloc.cxx120
-rw-r--r--dev/Kernel/HALKit/AMD64/HalPageAlloc.hxx92
-rw-r--r--dev/Kernel/HALKit/AMD64/HalProcessor.cxx97
-rw-r--r--dev/Kernel/HALKit/AMD64/HalRoutines.s9
-rw-r--r--dev/Kernel/HALKit/AMD64/HalSMPCoreManager.asm81
-rw-r--r--dev/Kernel/HALKit/AMD64/HalScheduler.cxx30
-rw-r--r--dev/Kernel/HALKit/AMD64/HalTimer.cxx14
-rw-r--r--dev/Kernel/HALKit/AMD64/HalUtils.asm33
-rw-r--r--dev/Kernel/HALKit/AMD64/Hypervisor.hxx25
-rw-r--r--dev/Kernel/HALKit/AMD64/MBCI/.gitkeep0
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Database.cxx11
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Device.cxx130
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Dma.cxx82
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Express.cxx11
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/IO.cxx7
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/Iterator.cxx44
-rw-r--r--dev/Kernel/HALKit/AMD64/PCI/PCI.cxx7
-rw-r--r--dev/Kernel/HALKit/AMD64/Processor.hxx348
-rw-r--r--dev/Kernel/HALKit/AMD64/ReadMe.md4
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx67
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx38
-rw-r--r--dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx199
36 files changed, 3036 insertions, 0 deletions
diff --git a/dev/Kernel/HALKit/AMD64/CPUID.hxx b/dev/Kernel/HALKit/AMD64/CPUID.hxx
new file mode 100644
index 00000000..f5ae5bb5
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/CPUID.hxx
@@ -0,0 +1,81 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+ File: CPUID.hxx
+ Purpose: CPUID flags.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+enum
+{
+ eCPU_FEATURE_ECX_SSE3 = 1 << 0,
+ eCPU_FEATURE_ECX_PCLMUL = 1 << 1,
+ eCPU_FEATURE_ECX_DTES64 = 1 << 2,
+ eCPU_FEATURE_ECX_MONITOR = 1 << 3,
+ eCPU_FEATURE_ECX_DS_CPL = 1 << 4,
+ eCPU_FEATURE_ECX_VMX = 1 << 5,
+ eCPU_FEATURE_ECX_SMX = 1 << 6,
+ eCPU_FEATURE_ECX_EST = 1 << 7,
+ eCPU_FEATURE_ECX_TM2 = 1 << 8,
+ eCPU_FEATURE_ECX_SSSE3 = 1 << 9,
+ eCPU_FEATURE_ECX_CID = 1 << 10,
+ eCPU_FEATURE_ECX_SDBG = 1 << 11,
+ eCPU_FEATURE_ECX_FMA = 1 << 12,
+ eCPU_FEATURE_ECX_CX16 = 1 << 13,
+ eCPU_FEATURE_ECX_XTPR = 1 << 14,
+ eCPU_FEATURE_ECX_PDCM = 1 << 15,
+ eCPU_FEATURE_ECX_PCID = 1 << 17,
+ eCPU_FEATURE_ECX_DCA = 1 << 18,
+ eCPU_FEATURE_ECX_SSE4_1 = 1 << 19,
+ eCPU_FEATURE_ECX_SSE4_2 = 1 << 20,
+ eCPU_FEATURE_ECX_X2APIC = 1 << 21,
+ eCPU_FEATURE_ECX_MOVBE = 1 << 22,
+ eCPU_FEATURE_ECX_POP3C = 1 << 23,
+ eCPU_FEATURE_ECX_TSC = 1 << 24,
+ eCPU_FEATURE_ECX_AES = 1 << 25,
+ eCPU_FEATURE_ECX_XSAVE = 1 << 26,
+ eCPU_FEATURE_ECX_OSXSAVE = 1 << 27,
+ eCPU_FEATURE_ECX_AVX = 1 << 28,
+ eCPU_FEATURE_ECX_F16C = 1 << 29,
+ eCPU_FEATURE_ECX_RDRAND = 1 << 30,
+ eCPU_FEATURE_ECX_HYPERVISOR = 1 << 31,
+ eCPU_FEATURE_EDX_FPU = 1 << 0,
+ eCPU_FEATURE_EDX_VME = 1 << 1,
+ eCPU_FEATURE_EDX_DE = 1 << 2,
+ eCPU_FEATURE_EDX_PSE = 1 << 3,
+ eCPU_FEATURE_EDX_TSC = 1 << 4,
+ eCPU_FEATURE_EDX_MSR = 1 << 5,
+ eCPU_FEATURE_EDX_PAE = 1 << 6,
+ eCPU_FEATURE_EDX_MCE = 1 << 7,
+ eCPU_FEATURE_EDX_CX8 = 1 << 8,
+ eCPU_FEATURE_EDX_APIC = 1 << 9,
+ eCPU_FEATURE_EDX_SEP = 1 << 11,
+ eCPU_FEATURE_EDX_MTRR = 1 << 12,
+ eCPU_FEATURE_EDX_PGE = 1 << 13,
+ eCPU_FEATURE_EDX_MCA = 1 << 14,
+ eCPU_FEATURE_EDX_CMOV = 1 << 15,
+ eCPU_FEATURE_EDX_PAT = 1 << 16,
+ eCPU_FEATURE_EDX_PSE36 = 1 << 17,
+ eCPU_FEATURE_EDX_PSN = 1 << 18,
+ eCPU_FEATURE_EDX_CLFLUSH = 1 << 19,
+ eCPU_FEATURE_EDX_DS = 1 << 21,
+ eCPU_FEATURE_EDX_ACPI = 1 << 22,
+ eCPU_FEATURE_EDX_MMX = 1 << 23,
+ eCPU_FEATURE_EDX_FXSR = 1 << 24,
+ eCPU_FEATURE_EDX_SSE = 1 << 25,
+ eCPU_FEATURE_EDX_SSE2 = 1 << 26,
+ eCPU_FEATURE_EDX_SS = 1 << 27,
+ eCPU_FEATURE_EDX_HTT = 1 << 28,
+ eCPU_FEATURE_EDX_TM = 1 << 29,
+ eCPU_FEATURE_EDX_IA64 = 1 << 30,
+ eCPU_FEATURE_EDX_PBE = 1 << 31
+};
+
+typedef long long int hal_cpu_feature_type; \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx b/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx
new file mode 100644
index 00000000..4a9af53b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx
@@ -0,0 +1,142 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.hxx>
+#include <HALKit/AMD64/Processor.hxx>
+#include <NewKit/String.hxx>
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/Heap.hxx>
+
+namespace Kernel
+{
+ /// Custom to the virtual machine, you'll need to parse the MADT instead.
+
+ void rt_shutdown_acpi_qemu_20(void)
+ {
+ HAL::Out16(0xb004, 0x2000);
+ }
+
+ void rt_shutdown_acpi_qemu_30_plus(void)
+ {
+ HAL::Out16(0x604, 0x2000);
+ }
+
+ void rt_shutdown_acpi_virtualbox(void)
+ {
+ HAL::Out16(0x4004, 0x3400);
+ }
+
+ /// You have to parse the MADT!
+
+ ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsdPtr)
+ : fRsdp(rsdPtr), fEntries(0)
+ {
+#ifdef __DEBUG__
+ kcout << "newoskrnl: ACPI: init interface.\r";
+#else
+
+#endif
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+#ifdef __DEBUG__
+ rt_shutdown_acpi_qemu_30_plus();
+#else
+
+#endif
+ }
+
+ /// @brief Reboot (shutdowns on qemu.)
+ /// @return
+ Void ACPIFactoryInterface::Reboot()
+ {
+#ifdef __DEBUG__
+ rt_shutdown_acpi_qemu_30_plus();
+#else
+
+#endif
+ }
+
+ /// @brief Finds a descriptor table inside ACPI XSDT.
+ ErrorOr<voidPtr> ACPIFactoryInterface::Find(const char* signature)
+ {
+ MUST_PASS(fRsdp);
+
+ if (!signature)
+ return ErrorOr<voidPtr>{-1};
+
+ if (*signature == 0)
+ return ErrorOr<voidPtr>{-1};
+
+ RSDP* rsdPtr = reinterpret_cast<RSDP*>(this->fRsdp);
+
+ if (rsdPtr->Revision <= 1)
+ return ErrorOr<voidPtr>{-1};
+
+ RSDT* xsdt = reinterpret_cast<RSDT*>(rsdPtr->RsdtAddress);
+
+ Int64 num = (xsdt->Length - sizeof(SDT)) / sizeof(UInt32);
+
+ /***
+ crucial to avoid - overflows.
+ */
+ if (num < 1)
+ {
+ /// stop here, we should have entries...
+ ke_stop(RUNTIME_CHECK_ACPI);
+ return ErrorOr<voidPtr>{-1};
+ }
+
+ this->fEntries = num;
+
+ kcout << "ACPI: Number of entries: " << number(this->fEntries) << endl;
+ kcout << "ACPI: Revision: " << number(xsdt->Revision) << endl;
+ kcout << "ACPI: Signature: " << xsdt->Signature << endl;
+ kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl;
+
+ const short cAcpiSignatureLength = 4;
+
+ for (Size index = 0; index < this->fEntries; ++index)
+ {
+ SDT* sdt = reinterpret_cast<SDT*>(xsdt->AddressArr[index]);
+
+ kcout << "ACPI: Checksum: " << number(sdt->Checksum) << endl;
+ kcout << "ACPI: Revision: " << number(sdt->Revision) << endl;
+
+ for (short signature_index = 0; signature_index < cAcpiSignatureLength; ++signature_index)
+ {
+ if (sdt->Signature[signature_index] != signature[signature_index])
+ break;
+
+ if (signature_index == (cAcpiSignatureLength - 1))
+ return ErrorOr<voidPtr>(reinterpret_cast<voidPtr>(xsdt->AddressArr[index]));
+ }
+ }
+
+ return ErrorOr<voidPtr>{-1};
+ }
+
+ /***
+ @brief check SDT header
+ @param checksum the header to checksum
+ @param len the length of it.
+*/
+ bool ACPIFactoryInterface::Checksum(const char* checksum, SSizeT len)
+ {
+ if (len == 0)
+ return -1;
+
+ char chr = 0;
+
+ for (int index = 0; index < len; ++index)
+ {
+ chr += checksum[index];
+ }
+
+ return chr == 0;
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalAPIC.cxx b/dev/Kernel/HALKit/AMD64/HalAPIC.cxx
new file mode 100644
index 00000000..caa2ce0b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalAPIC.cxx
@@ -0,0 +1,36 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.hxx>
+#include <HALKit/AMD64/Processor.hxx>
+
+namespace Kernel::HAL
+{
+ /// @brief Read from APIC controller.
+ /// @param reg register.
+ UInt32 APICController::Read(UInt32 reg) noexcept
+ {
+ MUST_PASS(this->fApic);
+
+ UInt32 volatile* ioapic = (UInt32 volatile*)this->fApic;
+ ioapic[0] = (reg & 0xff);
+
+ return ioapic[4];
+ }
+
+ /// @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* ioapic = (UInt32 volatile*)this->fApic;
+
+ ioapic[0] = (reg & 0xFF);
+ ioapic[4] = 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..8cc3c08f
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalBoot.asm
@@ -0,0 +1,22 @@
+;; /*
+;; * ========================================================
+;; *
+;; * Kernel
+;; * Copyright ZKA Technologies., 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
diff --git a/dev/Kernel/HALKit/AMD64/HalControlRegister.s b/dev/Kernel/HALKit/AMD64/HalControlRegister.s
new file mode 100644
index 00000000..879d35c1
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalControlRegister.s
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+.globl hal_write_cr3
+.globl hal_write_cr0
+.globl hal_read_cr2
+.globl hal_read_cr3
+.globl hal_read_cr0
+.globl hal_flush_tlb
+
+.text
+
+hal_flush_tlb:
+ call hal_read_cr3
+ mov %rcx, %rax
+ call hal_write_cr3
+ ret
+
+hal_read_cr3:
+ movq %cr3, %rax
+ ret
+
+hal_read_cr0:
+ movq %rax, %cr0
+ ret
+
+hal_read_cr2:
+ movq %rax, %cr2
+ ret
+
+hal_write_cr3:
+ movq %cr3, %rdi
+ ret
+
+hal_write_cr0:
+ movq %cr0, %rdi
+ ret
diff --git a/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx
new file mode 100644
index 00000000..88b5db36
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx
@@ -0,0 +1,76 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/ProcessScheduler.hxx>
+#include <NewKit/String.hxx>
+
+/// @brief Handle GPF fault.
+/// @param rsp
+EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp)
+{
+ Kernel::ke_stop(RUNTIME_CHECK_BAD_BEHAVIOR);
+}
+
+/// @brief Handle page fault.
+/// @param rsp
+EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp)
+{
+ Kernel::ke_stop(RUNTIME_CHECK_BAD_BEHAVIOR);
+}
+
+/// @brief Handle math fault.
+/// @param rsp
+EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp)
+{
+ Kernel::ke_stop(RUNTIME_CHECK_BAD_BEHAVIOR);
+}
+
+/// @brief Handle any generic fault.
+/// @param rsp
+EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp)
+{
+ Kernel::ke_stop(RUNTIME_CHECK_BAD_BEHAVIOR);
+}
+
+/// @brief Handle #UD fault.
+/// @param rsp
+EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp)
+{
+ Kernel::ke_stop(RUNTIME_CHECK_BAD_BEHAVIOR);
+}
+
+/// @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, Kernel::UIntPtr rdx)
+{
+ if (rcx <= (kSyscalls.Count() - 1))
+ {
+ Kernel::kcout << "newoskrnl: syscall: enter.\r";
+
+ if (kSyscalls[rcx].Leak().Leak()->fHooked)
+ (kSyscalls[rcx].Leak().Leak()->fProc)((Kernel::VoidPtr)rdx);
+
+ Kernel::kcout << "newoskrnl: syscall: exit.\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, Kernel::UIntPtr rdx, Kernel::UIntPtr r8, Kernel::UIntPtr r9)
+{
+ if (rcx <= (kSyscalls.Count() - 1))
+ {
+ Kernel::kcout << "newoskrnl: kerncall: enter.\r";
+
+ if (kKerncalls[rcx].Leak().Leak()->fHooked)
+ (kKerncalls[rcx].Leak().Leak()->fProc)((Kernel::VoidPtr)rdx);
+
+ Kernel::kcout << "newoskrnl: kerncall: exit.\r";
+ }
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx b/dev/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx
new file mode 100644
index 00000000..6018d20f
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx
@@ -0,0 +1,198 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.hxx>
+#include <HALKit/AMD64/Processor.hxx>
+#include <NewKit/KernelCheck.hxx>
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/Semaphore.hxx>
+#include <KernelKit/ProcessScheduler.hxx>
+#include <KernelKit/Timer.hxx>
+
+// Needed for SMP. //
+
+#include <KernelKit/MP.hxx>
+
+#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
+
+/// @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 Void hal_switch_context(HAL::StackFramePtr stack_frame);
+
+ constexpr Int32 kThreadAPIC = 0;
+ constexpr Int32 kThreadLAPIC = 1;
+ constexpr Int32 kThreadIOAPIC = 2;
+ constexpr Int32 kThreadAPIC64 = 3;
+ constexpr Int32 kThreadBoot = 4;
+
+ STATIC MADT_TABLE* kSMPBlock = nullptr;
+ Bool kSMPAware = false;
+
+ STATIC Int32 cSMPInterrupt = 34;
+
+ STATIC VoidPtr kRawMADT = nullptr;
+
+ /*
+ *
+ * this is used to store info about the current running thread
+ * we use this struct to determine if we can use it, or mark it as used or on
+ * sleep.
+ *
+ */
+
+ struct ProcessorInfoAMD64 final
+ {
+ Int32 ThreadType;
+ UIntPtr JumpAddress;
+
+ struct
+ {
+ UInt32 Code;
+ UInt32 Data;
+ UInt32 BSS;
+ } Selector;
+ };
+
+ /// @brief Multiple APIC Descriptor Table.
+ struct MADT_TABLE final : public SDT
+ {
+ UInt32 Address; // Madt address
+ UInt32 Flags; // Madt flags
+
+ struct {
+ UInt8 Type;
+ UInt8 Len;
+ } Records[]; // Records List
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ /// @brief Send start IPI for CPU.
+ /// @param apicId
+ /// @param vector
+ /// @param targetAddress
+ /// @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);
+ }
+
+ /// @internal
+ EXTERN_C Void hal_ap_startup(Void)
+ {
+ ke_stop(RUNTIME_CHECK_BOOTSTRAP);
+ }
+
+ /// @internal
+ EXTERN_C Void _hal_switch_context(HAL::StackFramePtr stack_frame)
+ {
+ hal_switch_context(stack_frame);
+ }
+
+ constexpr auto cMaxPCBBlocks = cMaxHWThreads;
+
+ struct PROCESS_CONTROL_BLOCK final
+ {
+ PROCESS_HEADER_BLOCK* f_Header;
+ HAL::StackFramePtr f_StackFrame;
+ } fBlocks[cMaxPCBBlocks] = {0};
+
+ EXTERN_C HAL::StackFramePtr _hal_leak_current_context(Void)
+ {
+ return fBlocks[ProcessScheduler::The().Leak().TheCurrent().Leak().ProcessId % cMaxPCBBlocks].f_StackFrame;
+ }
+
+ STATIC Void hal_switch_context(HAL::StackFramePtr stack_frame)
+ {
+ STATIC Semaphore sem;
+
+ constexpr auto cSeconds = 1U;
+
+ HardwareTimer timer(Seconds(cSeconds));
+ sem.LockOrWait(&ProcessScheduler::The().Leak().TheCurrent().Leak(), &timer);
+
+ fBlocks[ProcessScheduler::The().Leak().TheCurrent().Leak().ProcessId % cMaxPCBBlocks].f_Header = &ProcessScheduler::The().Leak().TheCurrent().Leak();
+ fBlocks[ProcessScheduler::The().Leak().TheCurrent().Leak().ProcessId % cMaxPCBBlocks].f_StackFrame = stack_frame;
+
+ sem.Unlock();
+ }
+
+ STATIC auto cAPICAddress = 0x0FEC00000;
+
+ STATIC Void cpu_set_apic_base(UIntPtr apic)
+ {
+ UInt32 edx = 0;
+ UInt32 eax = (apic & 0xfffff0000) | kAPIC_BASE_MSR_ENABLE;
+
+ edx = (apic >> 32) & 0x0f;
+
+ hal_set_msr(kAPIC_BASE_MSR, eax, edx);
+ }
+
+ STATIC UIntPtr cpu_get_apic_base(Void)
+ {
+ UInt32 eax, edx;
+
+ hal_get_msr(kAPIC_BASE_MSR, &eax, &edx);
+
+ return (eax & 0xfffff000) | ((UIntPtr)(edx & 0x0f) << 32);
+ }
+
+ EXTERN_C Void hal_ap_trampoline(Void);
+
+ /// @brief Fetch and enable cores inside main CPU.
+ /// @param rsdPtr RSD PTR structure.
+ Void hal_system_get_cores(voidPtr rsdPtr)
+ {
+ auto acpi = ACPIFactoryInterface(rsdPtr);
+ kRawMADT = acpi.Find(kApicSignature).Leak().Leak();
+
+ kSMPBlock = reinterpret_cast<MADT_TABLE*>(kRawMADT);
+
+ if (!kSMPBlock)
+ kSMPAware = false;
+
+ if (kSMPBlock)
+ {
+ kSMPAware = true;
+ }
+ }
+} // namespace Kernel::HAL
+
+///////////////////////////////////////////////////////////////////////////////////////
diff --git a/dev/Kernel/HALKit/AMD64/HalDebugOutput.cxx b/dev/Kernel/HALKit/AMD64/HalDebugOutput.cxx
new file mode 100644
index 00000000..d4e2b435
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDebugOutput.cxx
@@ -0,0 +1,145 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/DebugOutput.hxx>
+#include <KernelKit/Framebuffer.hxx>
+#include <NewKit/Utils.hxx>
+#include <NewKit/New.hxx>
+
+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::Out8(PORT + 1, 0x00); // Disable all interrupts
+ HAL::Out8(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ HAL::Out8(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ HAL::Out8(PORT + 1, 0x00); // (hi byte)
+ HAL::Out8(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ HAL::Out8(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
+ HAL::Out8(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ HAL::Out8(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
+ HAL::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::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::Out8(Detail::PORT + 4, 0x0F);
+#endif // __DEBUG__
+
+ return true;
+ }
+ } // namespace Detail
+
+ 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::Out8(Detail::PORT, '\r');
+
+ HAL::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::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.cxx b/dev/Kernel/HALKit/AMD64/HalDebugPort.cxx
new file mode 100644
index 00000000..1ea52b8d
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDebugPort.cxx
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+//! @file DebuggerPort.cxx
+//! @brief UART debug via packets.
+
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/DebugOutput.hxx>
+
+// 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::Out16(theHook->fPort[i], kDebugMag0);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag1);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag2);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag3);
+ HAL::rt_wait_400ns();
+
+ if (HAL::In16(theHook->fPort[i] != kDebugUnboundPort))
+ theHook->fBoundCnt++;
+ }
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cxx b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cxx
new file mode 100644
index 00000000..0339dd7f
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cxx
@@ -0,0 +1,91 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+
+namespace Kernel::HAL
+{
+ namespace Detail
+ {
+ STATIC RegisterGDT kRegGdt;
+ STATIC HAL::Register64 kRegIdt;
+
+ STATIC ::Kernel::Detail::AMD64::InterruptDescriptorAMD64
+ kInterruptVectorTable[kKernelIdtSize];
+
+ STATIC Void RemapPIC(Void) noexcept
+ {
+ // Remap PIC.
+ HAL::Out8(0x20, 0x10 | 0x01);
+ HAL::Out8(0xA0, 0x10 | 0x01);
+
+ HAL::Out8(0x21, 32);
+ HAL::Out8(0xA1, 40);
+
+ HAL::Out8(0x21, 4);
+ HAL::Out8(0xA1, 2);
+
+ HAL::Out8(0x21, 0x01);
+ HAL::Out8(0xA1, 0x01);
+
+ HAL::Out8(0x21, 0x00);
+ HAL::Out8(0xA1, 0x00);
+ }
+ } // namespace Detail
+
+ /// @brief Loads the provided Global Descriptor Table.
+ /// @param gdt
+ /// @return
+ Void GDTLoader::Load(RegisterGDT& gdt)
+ {
+ MUST_PASS(gdt.Base != 0);
+
+ Detail::kRegGdt.Base = gdt.Base;
+ Detail::kRegGdt.Limit = gdt.Limit;
+
+ hal_load_gdt(Detail::kRegGdt);
+ }
+
+ Void IDTLoader::Load(Register64& idt)
+ {
+ volatile ::Kernel::UIntPtr** baseIdt = (volatile ::Kernel::UIntPtr**)idt.Base;
+
+ MUST_PASS(baseIdt);
+
+ Detail::RemapPIC();
+
+ for (UInt16 i = 0; i < kKernelIdtSize; ++i)
+ {
+ MUST_PASS(baseIdt[i]);
+
+ Detail::kInterruptVectorTable[i].Selector = kGdtCodeSelector;
+ Detail::kInterruptVectorTable[i].Ist = 0x0;
+ Detail::kInterruptVectorTable[i].TypeAttributes = kInterruptGate;
+ Detail::kInterruptVectorTable[i].OffsetLow = ((UIntPtr)baseIdt[i] & __INT16_MAX__);
+ Detail::kInterruptVectorTable[i].OffsetMid = (((UIntPtr)baseIdt[i] >> 16) & __INT16_MAX__);
+ Detail::kInterruptVectorTable[i].OffsetHigh =
+ (((UIntPtr)baseIdt[i] >> 32) & __INT32_MAX__);
+
+ Detail::kInterruptVectorTable[i].Zero = 0x0;
+ }
+
+ Detail::kRegIdt.Base = reinterpret_cast<UIntPtr>(Detail::kInterruptVectorTable);
+ Detail::kRegIdt.Limit = sizeof(::Kernel::Detail::AMD64::InterruptDescriptorAMD64) *
+ (kKernelIdtSize - 1);
+
+ hal_load_idt(Detail::kRegIdt);
+ }
+
+ 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/HalHart.cxx b/dev/Kernel/HALKit/AMD64/HalHart.cxx
new file mode 100644
index 00000000..bc0a485e
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalHart.cxx
@@ -0,0 +1,33 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+
+// bugs = 0
+
+namespace Kernel
+{
+ /// @brief wakes up thread.
+ /// wakes up thread from hang.
+ void mp_wakeup_thread(HAL::StackFrame* stack)
+ {
+ HAL::rt_cli();
+
+ rt_do_context_switch(stack);
+
+ HAL::rt_sti();
+ }
+
+ /// @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 (true)
+ {
+ /* nohing, code is spinning */
+ }
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm
new file mode 100644
index 00000000..093da0db
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalInterruptAPI.asm
@@ -0,0 +1,242 @@
+;; /*
+;; * ---------------------------------------------------
+;; *
+;; * Copyright ZKA Technologies., all rights reserved.
+;; *
+;; * File: HalInterruptAPI.asm
+;; * Purpose: Interrupt routing, redirect raw interrupts into their handlers.
+;; *
+;; * ---------------------------------------------------
+;; */
+
+[bits 64]
+
+%define kInterruptId 0x21
+
+%macro IntExp 1
+global __NEW_INT_%1
+__NEW_INT_%1:
+ cld
+
+ iretq
+%endmacro
+
+%macro IntNormal 1
+global __NEW_INT_%1
+__NEW_INT_%1:
+ cld
+
+ iretq
+%endmacro
+
+; This file handles the core interrupt table
+; Last edited 31/01/24
+
+global ke_handle_irq
+global kInterruptVectorTable
+
+extern _hal_handle_mouse
+extern idt_handle_gpf
+extern idt_handle_pf
+extern ke_io_write
+extern idt_handle_ud
+
+section .text
+
+IntNormal 0
+IntNormal 1
+
+IntNormal 2
+
+IntNormal 3
+IntNormal 4
+IntNormal 5
+
+;; Invalid opcode interrupt
+__NEW_INT_6:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_ud
+
+ pop rax
+
+ sti
+ iretq
+
+IntNormal 7
+IntExp 8
+IntNormal 9
+IntExp 10
+IntExp 11
+
+IntExp 12
+
+__NEW_INT_13:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_gpf
+
+ pop rax
+
+ sti
+ iretq
+
+__NEW_INT_14:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_pf
+
+ pop rax
+
+ sti
+ iretq
+
+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
+
+IntNormal 32
+IntNormal 34
+
+IntNormal 33
+IntNormal 35
+IntNormal 36
+IntNormal 37
+IntNormal 38
+IntNormal 39
+IntNormal 40
+IntNormal 41
+IntNormal 42
+IntNormal 43
+
+__NEW_INT_44:
+ cli
+
+ ;; TODO: CoreEvents dispatch routine.
+
+ push rax
+ call _hal_handle_mouse
+ pop rax
+
+ sti
+ iretq
+
+IntNormal 45
+IntNormal 46
+IntNormal 47
+IntNormal 48
+IntNormal 49
+
+[extern hal_system_call_enter]
+[extern hal_kernel_call_enter]
+
+__NEW_INT_50:
+ cli
+
+ push rcx
+ push rdx
+ push rax
+
+ call hal_system_call_enter
+
+ pop rax
+ pop rdx
+ pop rcx
+
+ sti
+ iretq
+
+__NEW_INT_51:
+ cli
+
+ push rcx
+ push rdx
+ push r8
+ push r9
+ push rax
+
+ call hal_kernel_call_enter
+
+ pop rax
+ pop r9
+ pop r8
+ pop rdx
+ pop rcx
+
+ sti
+ iretq
+
+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:
+ lgdt [rcx]
+ push 0x08
+ lea rax, [rel rt_reload_segments]
+ push rax
+ retfq
+rt_reload_segments:
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ ret
+
+global hal_load_idt
+
+hal_load_idt:
+ lidt [rcx]
+ sti
+ ret
+
+section .data
+
+kInterruptVectorTable:
+ %assign i 0
+ %rep 256
+ dq __NEW_INT_%+i
+ %assign i i+1
+ %endrep
diff --git a/dev/Kernel/HALKit/AMD64/HalKernelMain.cxx b/dev/Kernel/HALKit/AMD64/HalKernelMain.cxx
new file mode 100644
index 00000000..49ddfa6c
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalKernelMain.cxx
@@ -0,0 +1,251 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+#include <Modules/CoreCG/FbRenderer.hxx>
+#include <FirmwareKit/Handover.hxx>
+#include <KernelKit/FileManager.hxx>
+#include <KernelKit/Framebuffer.hxx>
+#include <KernelKit/Heap.hxx>
+#include <KernelKit/PEFCodeManager.hxx>
+#include <KernelKit/ProcessScheduler.hxx>
+#include <KernelKit/ProcessHeap.hxx>
+#include <NewKit/Json.hxx>
+#include <Modules/CoreCG/Accessibility.hxx>
+#include <KernelKit/CodeManager.hxx>
+#include <Modules/ACPI/ACPIFactoryInterface.hxx>
+#include <NetworkKit/IPC.hxx>
+#include <CFKit/Property.hxx>
+#include <Modules/CoreCG/TextRenderer.hxx>
+
+Kernel::Property cKernelVersion;
+Kernel::Property cAutoFormatDisk;
+
+EXTERN Kernel::Boolean kAllocationInProgress;
+
+EXTERN_C Kernel::VoidPtr kInterruptVectorTable[];
+
+struct HEAP_ALLOC_INFO final
+{
+ Kernel::VoidPtr fThe;
+ Kernel::Size fTheSz;
+};
+
+struct PROCESS_BLOCK_INFO final
+{
+ THREAD_INFORMATION_BLOCK* fTIB;
+ THREAD_INFORMATION_BLOCK* fGIB;
+};
+
+struct PROCESS_EXIT_INFO final
+{
+ STATIC constexpr auto cReasonLen = 512;
+
+ Kernel::Int64 fCode;
+ Kernel::Char fReason[cReasonLen];
+};
+
+namespace Kernel::HAL
+{
+ /// @brief Gets the system cores using the MADT.
+ /// @param rsdPtr The 'RSD PTR' data structure.
+ EXTERN void hal_system_get_cores(Kernel::voidPtr rsdPtr);
+} // namespace Kernel::HAL
+
+/* GDT. */
+STATIC Kernel::HAL::Detail::NewOSGDT cGdt = {
+ {0, 0, 0, 0x00, 0x00, 0}, // null entry
+ {0, 0, 0, 0x9a, 0xaf, 0}, // kernel code
+ {0, 0, 0, 0x92, 0xaf, 0}, // kernel data
+ {0, 0, 0, 0x00, 0x00, 0}, // null entry
+ {0, 0, 0, 0x9a, 0xaf, 0}, // user code
+ {0, 0, 0, 0x92, 0xaf, 0}, // user data
+};
+
+Kernel::Void hal_real_init(Kernel::Void) noexcept;
+
+static Kernel::User* cRoot;
+
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::HandoverInformationHeader* HandoverHeader)
+{
+ /* Setup globals. */
+
+ kHandoverHeader = HandoverHeader;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ hal_real_init();
+}
+
+Kernel::Void hal_real_init(Kernel::Void) noexcept
+{
+ // reset kAllocationInProgress field to zero.
+ kAllocationInProgress = false;
+
+ // get page size.
+ kKernelVirtualSize = kHandoverHeader->f_VirtualSize;
+
+ // get virtual address start (for the heap)
+ kKernelVirtualStart = reinterpret_cast<Kernel::VoidPtr>(
+ reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_VirtualStart));
+
+ // get physical address start.
+ kKernelPhysicalStart = reinterpret_cast<Kernel::VoidPtr>(
+ reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_PhysicalStart));
+
+ // Load memory descriptors.
+ Kernel::HAL::RegisterGDT gdtBase;
+
+ gdtBase.Base = reinterpret_cast<Kernel::UIntPtr>(&cGdt);
+ gdtBase.Limit = sizeof(Kernel::HAL::Detail::NewOSGDT) - 1;
+
+ CONST Kernel::HAL::GDTLoader cGDT;
+ cGDT.Load(gdtBase);
+
+ // Load IDT now.
+
+ Kernel::HAL::Register64 idtBase;
+ idtBase.Base = (Kernel::UIntPtr)kInterruptVectorTable;
+ idtBase.Limit = 0;
+
+ CONST Kernel::HAL::IDTLoader cIDT;
+ cIDT.Load(idtBase);
+
+ // Register the basic system calls.
+
+ constexpr auto cTlsInterrupt = 0x11;
+ constexpr auto cTlsInstallInterrupt = 0x12;
+ constexpr auto cNewInterrupt = 0x13;
+ constexpr auto cDeleteInterrupt = 0x14;
+ constexpr auto cExitInterrupt = 0x15;
+ constexpr auto cLastExitInterrupt = 0x16;
+ constexpr auto cCatalogOpen = 0x17;
+ constexpr auto cForkRead = 0x18;
+ constexpr auto cForkWrite = 0x19;
+ constexpr auto cCatalogClose = 0x20;
+ constexpr auto cCatalogRemove = 0x21;
+ constexpr auto cCatalogCreate = 0x22;
+ constexpr auto cRebootInterrupt = 0x23;
+ constexpr auto cShutdownInterrupt = 0x24;
+ constexpr auto cLPCSendMsg = 0x25;
+ constexpr auto cLPCOpenMsg = 0x26;
+ constexpr auto cLPCCloseMsg = 0x27;
+
+ kSyscalls[cTlsInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ if (tls_check_syscall_impl(rdx) == false)
+ {
+ Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash();
+ }
+ };
+
+ kSyscalls[cNewInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ // get HAC struct.
+ HEAP_ALLOC_INFO* rdxInf = reinterpret_cast<HEAP_ALLOC_INFO*>(rdx);
+
+ if (!rdxInf)
+ return;
+
+ // assign the fThe field with the pointer.
+ rdxInf->fThe = Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().New(rdxInf->fTheSz);
+ };
+
+ kSyscalls[cDeleteInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ // get HAC struct.
+ HEAP_ALLOC_INFO* rdxInf = reinterpret_cast<HEAP_ALLOC_INFO*>(rdx);
+
+ if (!rdxInf)
+ return;
+
+ // delete ptr with sz in mind.
+ Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Delete(rdxInf->fThe, rdxInf->fTheSz);
+ };
+
+ kSyscalls[cTlsInstallInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ PROCESS_BLOCK_INFO* rdxPb = reinterpret_cast<PROCESS_BLOCK_INFO*>(rdx);
+
+ if (!rdxPb)
+ return;
+
+ // install the fTIB and fGIB.
+ rt_install_tib(rdxPb->fTIB, rdxPb->fGIB);
+ };
+
+ kSyscalls[cExitInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ PROCESS_EXIT_INFO* rdxEi = reinterpret_cast<PROCESS_EXIT_INFO*>(rdx);
+
+ if (!rdxEi)
+ return;
+
+ Kernel::kcout << "newoskrnl: " << rdxEi->fReason << "\r";
+ Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Exit(rdxEi->fCode);
+ };
+
+ kSyscalls[cLastExitInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ PROCESS_EXIT_INFO* rdxEi = reinterpret_cast<PROCESS_EXIT_INFO*>(rdx);
+
+ if (!rdxEi)
+ return;
+
+ rdxEi->fCode = Kernel::sched_get_exit_code();
+ };
+
+ kSyscalls[cRebootInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ Kernel::PowerFactoryInterface pow(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+ pow.Reboot();
+ };
+
+ kSyscalls[cShutdownInterrupt].Leak().Leak()->fProc = [](Kernel::VoidPtr rdx) -> void {
+ Kernel::PowerFactoryInterface pow(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+ pow.Shutdown();
+ };
+
+ kSyscalls[cTlsInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cTlsInstallInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cDeleteInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cNewInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cExitInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cLastExitInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cShutdownInterrupt].Leak().Leak()->fHooked = true;
+ kSyscalls[cRebootInterrupt].Leak().Leak()->fHooked = true;
+
+ Kernel::HAL::hal_system_get_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ Kernel::kcout << "newoskrnl: Creating filesystem and such.\r";
+
+ auto fs = new Kernel::NewFilesystemManager();
+
+ MUST_PASS(fs);
+ MUST_PASS(fs->GetParser());
+
+ Kernel::NewFilesystemManager::Mount(fs);
+
+ delete fs->GetParser()->CreateCatalog("\\Users\\", 0, kNewFSCatalogKindDir);
+
+ Kernel::kcout << "newoskrnl: Created filesystem and now creating " << kSuperUser << "..." << Kernel::endl;
+
+ cRoot = new Kernel::User(Kernel::RingKind::kRingSuperUser, kSuperUser);
+
+#ifdef __DEBUG__
+ const auto cPassword = "6aa162f3-20f6-4143-92f9-5dd37066aedc";
+#else
+ const auto cPassword = "password";
+#endif
+
+ Kernel::UserManager::The()->fRootUser = cRoot;
+
+ Kernel::kcout << "newoskrnl: Root is " << kSuperUser << "." << Kernel::endl;
+
+ cRoot->TrySave(cPassword);
+
+ Kernel::UserManager::The()->TryLogIn(cRoot, cPassword);
+
+ Kernel::ke_stop(RUNTIME_CHECK_FAILED);
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalKernelMouse.cxx b/dev/Kernel/HALKit/AMD64/HalKernelMouse.cxx
new file mode 100644
index 00000000..bff5e5ee
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalKernelMouse.cxx
@@ -0,0 +1,190 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <Modules/PS2/PS2MouseInterface.hxx>
+#include <Modules/CoreCG/FbRenderer.hxx>
+#include <Modules/CoreCG/Rsrc/Cursor.rsrc>
+#include <KernelKit/Framebuffer.hxx>
+#include <NewKit/Defines.hxx>
+
+/// @note forward decl.
+EXTERN_C Kernel::Boolean _hal_draw_mouse();
+EXTERN_C Kernel::Void _hal_init_mouse();
+
+STATIC Kernel::Int32 kPrevX = 10;
+STATIC Kernel::Int32 kPrevY = 10;
+STATIC Kernel::Int32 kX = 10;
+STATIC Kernel::Int32 kY = 10;
+STATIC Kernel::Int32 kMouseCycle = 0;
+STATIC Kernel::PS2MouseInterface kMousePS2;
+STATIC Kernel::Char kMousePacket[4] = {};
+STATIC Kernel::Boolean kMousePacketReady = false;
+
+STATIC CGInit();
+
+#define kPS2Leftbutton 0b00000001
+#define kPS2Middlebutton 0b00000010
+#define kPS2Rightbutton 0b00000100
+#define kPS2XSign 0b00010000
+#define kPS2YSign 0b00100000
+#define kPS2XOverflow 0b01000000
+#define kPS2YOverflow 0b10000000
+
+using namespace Kernel;
+
+Void hal_handle_mouse()
+{
+ Kernel::UInt8 data = HAL::In8(0x60);
+
+ switch (kMouseCycle)
+ {
+ case 0:
+ if (kMousePacketReady)
+ break;
+ if ((data & 0b00001000) == 0)
+ break;
+ kMousePacket[0] = data;
+ kMouseCycle++;
+ break;
+ case 1:
+ if (kMousePacketReady)
+ break;
+ kMousePacket[1] = data;
+ kMouseCycle++;
+ break;
+ case 2:
+ if (kMousePacketReady)
+ break;
+ kMousePacket[2] = data;
+ kMousePacketReady = true;
+ kMouseCycle = 0;
+ break;
+ }
+
+ // Notify PIC controller that we're done with it's interrupt.
+
+ Kernel::HAL::Out8(0x20, 0x20);
+ Kernel::HAL::Out8(0xA0, 0x20);
+}
+
+/// @brief Interrupt handler for the mouse.
+EXTERN_C Void _hal_handle_mouse()
+{
+ hal_handle_mouse();
+}
+
+EXTERN_C Boolean _hal_left_button_pressed()
+{
+ return kMousePacket[0] & kPS2Leftbutton;
+}
+EXTERN_C Boolean _hal_right_button_pressed()
+{
+ return kMousePacket[0] & kPS2Rightbutton;
+}
+EXTERN_C Boolean _hal_middle_button_pressed()
+{
+ return kMousePacket[0] & kPS2Middlebutton;
+}
+
+/// @brief Draws the kernel's mouse.
+EXTERN_C Boolean _hal_draw_mouse()
+{
+ if (!kMousePacketReady)
+ return false;
+
+ bool xNegative, yNegative, xOverflow, yOverflow;
+
+ if (kMousePacket[0] & kPS2XSign)
+ {
+ xNegative = true;
+ }
+ else
+ xNegative = false;
+
+ if (kMousePacket[0] & kPS2YSign)
+ {
+ yNegative = true;
+ }
+ else
+ yNegative = false;
+
+ if (kMousePacket[0] & kPS2XOverflow)
+ {
+ xOverflow = true;
+ }
+ else
+ xOverflow = false;
+
+ if (kMousePacket[0] & kPS2YOverflow)
+ {
+ yOverflow = true;
+ }
+ else
+ yOverflow = false;
+
+ if (!xNegative)
+ {
+ kX += kMousePacket[1];
+ if (xOverflow)
+ {
+ kX += 255;
+ }
+ }
+ else
+ {
+ kMousePacket[1] = 256 - kMousePacket[1];
+ kX -= kMousePacket[1];
+ if (xOverflow)
+ {
+ kX -= 255;
+ }
+ }
+
+ if (!yNegative)
+ {
+ kY -= kMousePacket[2];
+ if (yOverflow)
+ {
+ kY -= 255;
+ }
+ }
+ else
+ {
+ kMousePacket[2] = 256 - kMousePacket[2];
+ kY += kMousePacket[2];
+ if (yOverflow)
+ {
+ kY += 255;
+ }
+ }
+
+ if (kX < 0)
+ kX = 0;
+ if (kX > kHandoverHeader->f_GOP.f_Width - 8)
+ kX = kHandoverHeader->f_GOP.f_Width - 8;
+
+ if (kY < 0)
+ kY = 0;
+ if (kY > kHandoverHeader->f_GOP.f_Height - 16)
+ kY = kHandoverHeader->f_GOP.f_Height - 16;
+
+ /// Draw mouse here.
+
+ kPrevX = kX;
+ kPrevY = kY;
+
+ kMousePacketReady = false;
+ return true;
+}
+
+/// @brief Init kernel mouse.
+EXTERN_C Void _hal_init_mouse()
+{
+ kMousePS2.Init();
+
+ HAL::Out8(0x21, 0b11111001);
+ HAL::Out8(0xA1, 0b11101111);
+}
diff --git a/dev/Kernel/HALKit/AMD64/HalPageAlloc.cxx b/dev/Kernel/HALKit/AMD64/HalPageAlloc.cxx
new file mode 100644
index 00000000..0e39a0f1
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalPageAlloc.cxx
@@ -0,0 +1,120 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+
+#define cVMHMagic (0xDEEFD00D)
+
+#ifdef __NEWOS_AMD64__
+#include <HALKit/AMD64/HalPageAlloc.hxx>
+#elif defined(__NEWOS_ARM64__)
+#include <HALKit/ARM64/HalPageAlloc.hxx>
+#endif
+
+#include <NewKit/Defines.hxx>
+#include <NewKit/KernelCheck.hxx>
+
+Kernel::Boolean kAllocationInProgress = false;
+
+namespace Kernel
+{
+
+ namespace HAL
+ {
+ namespace Detail
+ {
+ struct VIRTUAL_MEMORY_HEADER
+ {
+ UInt32 Magic;
+ Boolean Present : 1;
+ Boolean ReadWrite : 1;
+ Boolean User : 1;
+ SizeT Size;
+ };
+
+ struct VirtualMemoryHeaderTraits final
+ {
+ /// @brief Get next header.
+ /// @param current
+ /// @return
+ VIRTUAL_MEMORY_HEADER* Next(VIRTUAL_MEMORY_HEADER* current)
+ {
+ if (current->Magic != cVMHMagic)
+ current->Size = 8196;
+
+ return current + sizeof(VIRTUAL_MEMORY_HEADER) + current->Size;
+ }
+
+ /// @brief Get previous header.
+ /// @param current
+ /// @return
+ VIRTUAL_MEMORY_HEADER* Prev(VIRTUAL_MEMORY_HEADER* current)
+ {
+ if (current->Magic != cVMHMagic)
+ current->Size = 8196;
+
+ return current - sizeof(VIRTUAL_MEMORY_HEADER) - current->Size;
+ }
+ };
+ } // namespace Detail
+
+ /// @brief Allocates a new page of memory.
+ /// @param sz the size of it.
+ /// @param rw read/write flag.
+ /// @param user user flag.
+ /// @return the page table of it.
+ STATIC auto hal_try_alloc_new_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr
+ {
+ if (kAllocationInProgress)
+ return nullptr;
+
+ kAllocationInProgress = true;
+
+ //! fetch from the start.
+ Detail::VIRTUAL_MEMORY_HEADER* vmh_header = reinterpret_cast<Detail::VIRTUAL_MEMORY_HEADER*>(kKernelVMTStart);
+ Detail::VirtualMemoryHeaderTraits traits;
+
+ while (vmh_header->Present &&
+ vmh_header->Magic == cVMHMagic)
+ {
+ vmh_header = traits.Next(vmh_header);
+ }
+
+ vmh_header->Magic = cVMHMagic;
+ vmh_header->Present = true;
+ vmh_header->ReadWrite = rw;
+ vmh_header->User = user;
+ vmh_header->Size = size;
+
+ kAllocationInProgress = false;
+
+ return reinterpret_cast<VoidPtr>(vmh_header + sizeof(Detail::VIRTUAL_MEMORY_HEADER));
+ }
+
+ /// @brief Allocate a new page to be used by the OS.
+ /// @param rw read/write bit.
+ /// @param user user bit.
+ /// @return
+ auto hal_alloc_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr
+ {
+ kcout << "Waiting now...";
+
+ // Wait for a ongoing allocation to complete.
+ while (kAllocationInProgress)
+ {
+ (void)0;
+ }
+
+ kcout << ", done waiting, allocating...\r";
+
+ if (size == 0)
+ ++size;
+
+ // allocate new page.
+ return hal_try_alloc_new_page(rw, user, size);
+ }
+ } // namespace HAL
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalPageAlloc.hxx b/dev/Kernel/HALKit/AMD64/HalPageAlloc.hxx
new file mode 100644
index 00000000..30cb7911
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalPageAlloc.hxx
@@ -0,0 +1,92 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR X86_64 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.hxx>
+
+#ifndef kPTEMax
+#define kPTEMax (0x200)
+#endif //! kPTEMax
+
+#ifndef kPTEAlign
+#define kPTEAlign (0x1000)
+#endif //! kPTEAlign
+
+#ifndef kPTESize
+#define kPTESize (0x1000)
+#endif // !kPTESize
+
+#ifndef kAlign
+#define kAlign __BIGGEST_ALIGNMENT__
+#endif // !kAlign
+
+EXTERN_C void hal_flush_tlb();
+EXTERN_C void hal_write_cr3(Kernel::UIntPtr pde);
+EXTERN_C void hal_write_cr0(Kernel::UIntPtr bit);
+
+EXTERN_C Kernel::UIntPtr hal_read_cr0(); // @brief CPU control register.
+EXTERN_C Kernel::UIntPtr hal_read_cr2(); // @brief Fault address.
+EXTERN_C Kernel::UIntPtr hal_read_cr3(); // @brief Page table.
+
+namespace Kernel::HAL
+{
+ struct PACKED PageTable64 final
+ {
+ bool Present : 1;
+ bool Rw : 1;
+ bool User : 1;
+ bool Wt : 1;
+ bool Cache : 1;
+ bool Accessed : 1;
+ Kernel::Int32 Reserved : 6;
+ Kernel::UInt64 PhysicalAddress : 36;
+ Kernel::Int32 Reserved1 : 15;
+ bool 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 PageDirectory64 final
+ {
+ PageTable64 ALIGN(kPTEAlign) Pte[kPTEMax];
+ };
+
+ VoidPtr hal_alloc_page(Boolean rw, Boolean user, SizeT size);
+} // namespace Kernel::HAL
+
+namespace Kernel
+{
+ typedef HAL::PageTable64 PTE;
+ typedef HAL::PageDirectory64 PDE;
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalProcessor.cxx b/dev/Kernel/HALKit/AMD64/HalProcessor.cxx
new file mode 100644
index 00000000..367e9314
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalProcessor.cxx
@@ -0,0 +1,97 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Processor.hxx>
+
+/**
+ * @file Processor.cpp
+ * @brief This file is about processor specific functions (in/out/cli/std...)
+ */
+
+namespace Kernel::HAL
+{
+ Void Out8(UInt16 port, UInt8 value)
+ {
+ asm volatile("outb %%al, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void Out16(UInt16 port, UInt16 value)
+ {
+ asm volatile("outw %%ax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void Out32(UInt16 port, UInt32 value)
+ {
+ asm volatile("outl %%eax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ UInt8 In8(UInt16 port)
+ {
+ UInt8 value = 0UL;
+ asm volatile("inb %1, %%al"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt16 In16(UInt16 port)
+ {
+ UInt16 value = 0UL;
+ asm volatile("inw %1, %%ax"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt32 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/HalRoutines.s b/dev/Kernel/HALKit/AMD64/HalRoutines.s
new file mode 100644
index 00000000..d794882d
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalRoutines.s
@@ -0,0 +1,9 @@
+.globl rt_wait_400ns
+
+.section .text
+rt_wait_400ns:
+ jmp .loop
+ .loop:
+ jmp .loop2
+ .loop2:
+ ret
diff --git a/dev/Kernel/HALKit/AMD64/HalSMPCoreManager.asm b/dev/Kernel/HALKit/AMD64/HalSMPCoreManager.asm
new file mode 100644
index 00000000..3c53d49d
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalSMPCoreManager.asm
@@ -0,0 +1,81 @@
+;; /*
+;; * ========================================================
+;; *
+;; * Kernel
+;; * Copyright ZKA Technologies., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global rt_get_current_context]
+[global rt_do_context_switch]
+[global _hal_spin_core]
+[extern _hal_switch_context]
+[extern _hal_leak_current_context]
+
+section .text
+
+;; writes to rdx the stackframe inside rcx.
+;; rcx: Stack Pointer
+;; rdx: SMP core address.
+rt_do_context_switch:
+ push rax
+ call _hal_switch_context
+ pop rax
+
+ ;; Now grab newly allocated process's stack frame.
+
+ push rax
+ call _hal_leak_current_context
+ mov rax, r9
+ pop rax
+
+ ;; Take care of context switching within AP.
+
+ mov r9, rax
+
+ mov rbp, [r9 + (8 * 5)]
+ mov rsp, [r9 + (8 * 6)]
+
+ mov gs, [r9 + (8 * 19)]
+ mov fs, [r9 + (8 * 20)]
+
+ mov rcx, [r9 + (8 * 3)]
+ mov rdx, [r9 + (8 * 4)]
+ mov rbx, [r9 + (8 * 7)]
+ mov rax, [r9 + (8 * 8)]
+ movq xmm0, [r9 + (8 * 9)]
+ movq xmm1, [r9 + (8 * 10)]
+
+ mov r8, [r9 + (8 * 11)]
+ mov r10, [r9 + (8 * 13)]
+ mov r11, [r9 + (8 * 14)]
+ mov r12, [r9 + (8 * 15)]
+ mov r13, [r9 + (8 * 16)]
+ mov r14, [r9 + (8 * 17)]
+ mov r15, [r9 + (8 * 18)]
+
+ fldcw word [r9 + (8 * 21)]
+
+ mov r9, [r9 + (8 * 12)]
+
+ retfq
+
+;; gets the current stack frame.
+rt_get_current_context:
+ push rax
+
+ call _hal_leak_current_context
+
+ mov rax, r9
+ pop rax
+
+ mov r9, rax
+
+ retfq
+
+_hal_spin_core:
+ jmp $
+ ret
diff --git a/dev/Kernel/HALKit/AMD64/HalScheduler.cxx b/dev/Kernel/HALKit/AMD64/HalScheduler.cxx
new file mode 100644
index 00000000..d3094c4b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalScheduler.cxx
@@ -0,0 +1,30 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/ProcessScheduler.hxx>
+
+using namespace Kernel;
+Void PROCESS_HEADER_BLOCK::SetEntrypoint(UIntPtr& imageStart) noexcept
+{
+ if (imageStart == 0)
+ this->Crash();
+
+ this->StackFrame->BP = imageStart;
+ this->StackFrame->SP = this->StackFrame->BP;
+}
+
+namespace Kernel
+{
+ bool rt_check_stack(HAL::StackFramePtr stackPtr)
+ {
+ if (!stackPtr)
+ return false;
+ if (stackPtr->BP == 0 || stackPtr->SP == 0)
+ return false;
+
+ return true;
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/AMD64/HalTimer.cxx b/dev/Kernel/HALKit/AMD64/HalTimer.cxx
new file mode 100644
index 00000000..ff65a4a1
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalTimer.cxx
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+ File: HalTimer.cxx
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx> \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AMD64/HalUtils.asm b/dev/Kernel/HALKit/AMD64/HalUtils.asm
new file mode 100644
index 00000000..5b4da821
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalUtils.asm
@@ -0,0 +1,33 @@
+;; /*
+;; * ========================================================
+;; *
+;; * Kernel
+;; * Copyright ZKA Technologies., 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]
+[extern hal_ap_startup]
+[global hal_ap_trampoline]
+
+hal_ap_trampoline:
+hal_ap_trampoline_1:
+ jmp hal_ap_startup
diff --git a/dev/Kernel/HALKit/AMD64/Hypervisor.hxx b/dev/Kernel/HALKit/AMD64/Hypervisor.hxx
new file mode 100644
index 00000000..7871288f
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Hypervisor.hxx
@@ -0,0 +1,25 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.hxx>
+
+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/.gitkeep b/dev/Kernel/HALKit/AMD64/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/MBCI/.gitkeep
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Database.cxx b/dev/Kernel/HALKit/AMD64/PCI/Database.cxx
new file mode 100644
index 00000000..971d43f9
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Database.cxx
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Database.hxx>
+
+namespace Kernel
+{
+}
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Device.cxx b/dev/Kernel/HALKit/AMD64/PCI/Device.cxx
new file mode 100644
index 00000000..214a640a
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Device.cxx
@@ -0,0 +1,130 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hxx>
+#include <KernelKit/PCI/Device.hxx>
+
+Kernel::UInt NewOSPCIReadRaw(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::Out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+
+ return Kernel::HAL::In32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigData);
+}
+
+void NewOSPCISetCfgTarget(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::Out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+}
+
+namespace Kernel::PCI
+{
+ Device::Device(UShort bus, UShort device, UShort func, UShort bar)
+ : fBus(bus), fDevice(device), fFunction(func), fBar(bar)
+ {
+ }
+
+ Device::~Device()
+ {
+ }
+
+ UInt Device::Read(UInt bar, Size sz)
+ {
+ NewOSPCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ return HAL::In32((UShort)PciConfigKind::ConfigData + (fBar & 3));
+ if (sz == 2)
+ return HAL::In16((UShort)PciConfigKind::ConfigData + (fBar & 3));
+ if (sz == 1)
+ return HAL::In8((UShort)PciConfigKind::ConfigData + (fBar & 3));
+
+ return 0xFFFF;
+ }
+
+ void Device::Write(UInt bar, UIntPtr data, Size sz)
+ {
+ NewOSPCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ HAL::Out32((UShort)PciConfigKind::ConfigData + (fBar & 3), (UInt)data);
+ if (sz == 2)
+ HAL::Out16((UShort)PciConfigKind::ConfigData + (fBar & 3), (UShort)data);
+ if (sz == 1)
+ HAL::Out8((UShort)PciConfigKind::ConfigData + (fBar & 3), (UChar)data);
+ }
+
+ UShort Device::DeviceId()
+ {
+ return (UShort)(NewOSPCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction));
+ }
+
+ UShort Device::VendorId()
+ {
+ return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UShort Device::InterfaceId()
+ {
+ return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::Class()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24);
+ }
+
+ UChar Device::Subclass()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::ProgIf()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8);
+ }
+
+ UChar Device::HeaderType()
+ {
+ return (UChar)(NewOSPCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
+ }
+
+ void Device::EnableMmio()
+ {
+ bool enable = Read(0x04, sizeof(UChar)) | (1 << 1);
+ Write(0x04, enable, sizeof(UShort));
+ }
+
+ void Device::BecomeBusMaster()
+ {
+ bool enable = Read(0x04, sizeof(UShort)) | (1 << 2);
+ Write(0x04, enable, sizeof(UShort));
+ }
+
+ 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/Dma.cxx b/dev/Kernel/HALKit/AMD64/PCI/Dma.cxx
new file mode 100644
index 00000000..bf1730d8
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Dma.cxx
@@ -0,0 +1,82 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Dma.hxx>
+
+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/Express.cxx b/dev/Kernel/HALKit/AMD64/PCI/Express.cxx
new file mode 100644
index 00000000..6a926827
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Express.cxx
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Express.hxx>
+
+namespace Kernel
+{
+}
diff --git a/dev/Kernel/HALKit/AMD64/PCI/IO.cxx b/dev/Kernel/HALKit/AMD64/PCI/IO.cxx
new file mode 100644
index 00000000..ea91c7b7
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/IO.cxx
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/IO.hxx>
diff --git a/dev/Kernel/HALKit/AMD64/PCI/Iterator.cxx b/dev/Kernel/HALKit/AMD64/PCI/Iterator.cxx
new file mode 100644
index 00000000..47b16462
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/Iterator.cxx
@@ -0,0 +1,44 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Iterator.hxx>
+
+#define PCI_ITERATOR_FIND_AND_UNWRAP(DEV, SZ) \
+ if (DEV.Leak().Leak()) \
+ return *DEV.Leak().Leak();
+
+namespace Kernel::PCI
+{
+ Iterator::Iterator(const Types::PciDeviceKind& type)
+ {
+ // probe devices.
+ for (int bus = 0; bus < NEWOS_BUS_COUNT; ++bus)
+ {
+ for (int device = 0; device < NEWOS_DEVICE_COUNT; ++device)
+ {
+ for (int function = 0; function < NEWOS_FUNCTION_COUNT; ++function)
+ {
+ Device dev(bus, device, function, 0);
+
+ if (dev.Class() == (UChar)type)
+ {
+ *fDevices[bus].Leak().Leak() = dev;
+ }
+ }
+ }
+ }
+ }
+
+ Iterator::~Iterator()
+ {
+ }
+
+ Ref<PCI::Device> Iterator::operator[](const Size& sz)
+ {
+ PCI_ITERATOR_FIND_AND_UNWRAP(fDevices[sz], sz);
+ return {};
+ }
+} // namespace Kernel::PCI
diff --git a/dev/Kernel/HALKit/AMD64/PCI/PCI.cxx b/dev/Kernel/HALKit/AMD64/PCI/PCI.cxx
new file mode 100644
index 00000000..59e3b06e
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/PCI/PCI.cxx
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/PCI.hxx>
diff --git a/dev/Kernel/HALKit/AMD64/Processor.hxx b/dev/Kernel/HALKit/AMD64/Processor.hxx
new file mode 100644
index 00000000..d80a2834
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Processor.hxx
@@ -0,0 +1,348 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+ File: Prcoessor.hxx
+ Purpose: AMD64 processor abstraction.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.hxx>
+#include <NewKit/Defines.hxx>
+#include <NewKit/Utils.hxx>
+#include <FirmwareKit/Handover.hxx>
+#include <HALKit/AMD64/HalPageAlloc.hxx>
+
+EXTERN_C
+{
+#include <cpuid.h>
+}
+
+#ifdef kCPUBackendName
+#undef kCPUBackendName
+#endif // ifdef kCPUBackendName
+
+#define kCPUBackendName "AMD64"
+
+#define kSyscallRoute 0x32
+
+#define IsActiveLow(FLG) (FLG & 2)
+#define IsLevelTriggered(FLG) (FLG & 8)
+
+#define kInterruptGate (0x8E)
+#define kTrapGate (0xEF)
+#define kTaskGate (0b10001100)
+#define kGdtCodeSelector (0x08)
+#define kGdtUserCodeSelector (0x10)
+#define cHeapStartOffset (0x80000000)
+
+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; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
+ UInt8 TypeAttributes; // gate type, dpl, and p fields
+ UInt16 OffsetMid; // offset bits 16..31
+ UInt32 OffsetHigh; // offset bits 32..63
+ UInt32 Zero; // reserved
+ };
+ } // namespace Detail::AMD64
+} // namespace Kernel
+
+namespace Kernel::HAL
+{
+ /// @brief Virtual memory flags.
+ enum
+ {
+ eFlagsUser,
+ eFlagsRw,
+ eFlagsExecDisable
+ };
+
+ /// @brief Map address to PDE.
+ /// @param pde a valid page directory.
+ /// @param phys_addr a valid phyiscal address.
+ /// @param virt_addr a valid virtual address.
+ /// @param flags the flags to put on the page.
+ inline Int32 ke_map_address(PDE* pde, UIntPtr phys_addr, UIntPtr virt_addr, UInt32 flags)
+ {
+ UInt16 pml4_index = (virt_addr >> 39) & 0x1FF;
+
+ if (pde && !pde->Pte[pml4_index].Present)
+ {
+ pde->Pte[pml4_index].Present = true;
+
+ pde->Pte[pml4_index].PhysicalAddress = phys_addr;
+ pde->Pte[pml4_index].Rw = flags & eFlagsRw;
+ pde->Pte[pml4_index].User = flags & eFlagsUser;
+ pde->Pte[pml4_index].ExecDisable = flags & eFlagsExecDisable;
+
+ kcout << "PTE is present now.\r";
+
+ return 0;
+ }
+ else
+ {
+ kcout << "PM is already present.\r";
+
+ kcout << "PhysicalAddress: " << hex_number(pde->Pte[pml4_index].PhysicalAddress);
+ kcout << "\r";
+
+ kcout << "User: " << (pde->Pte[pml4_index].User ? "true" : "false") << "\r";
+ kcout << "RW: " << (pde->Pte[pml4_index].Rw ? "true" : "false") << "\r";
+
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /// @brief Map address to PDE.
+ /// @param pde
+ /// @param phys_addr
+ /// @param virt_addr
+ /// @param flags
+ inline Void ke_unmap_address(PDE* pde, UIntPtr phys_addr, UIntPtr virt_addr, UInt32 flags)
+ {
+ UInt16 pml4_index = (virt_addr >> 39) & 0x1FF;
+
+ if (pde->Pte[pml4_index].Present)
+ {
+ pde->Pte[pml4_index].Present = false;
+ pde->Pte[pml4_index].PhysicalAddress = 0;
+ pde->Pte[pml4_index].Rw = 0;
+ pde->Pte[pml4_index].User = 0;
+ pde->Pte[pml4_index].ExecDisable = 0;
+ }
+ }
+
+ EXTERN_C UChar In8(UInt16 port);
+ EXTERN_C UShort In16(UInt16 port);
+ EXTERN_C UInt In32(UInt16 port);
+
+ EXTERN_C void Out16(UShort port, UShort byte);
+ EXTERN_C void Out8(UShort port, UChar byte);
+ EXTERN_C void 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();
+
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ struct PACKED RegisterGDT final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ using RawRegister = UInt64;
+
+ using InterruptId = UShort; /* For each element in the IVT */
+ using InterruptTrapKind = UIntPtr(UIntPtr sp);
+
+ typedef UIntPtr Reg;
+
+ /// @brief Stack frame (as retrieved from assembly.)
+ struct PACKED StackFrame final
+ {
+ Reg IntNum, Exception;
+ Reg A0, A2, BP, SP, A3, A4, A5, A6;
+ Reg R8, R9, R10, R11, R12, R13, R14, R15;
+ Reg Gs, Fs;
+ Reg ControlWord;
+ };
+
+ 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);
+ };
+
+ Void hal_system_get_cores(VoidPtr rsdPtr);
+ 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.
+ /// @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 Global descriptor table entry, either null, code or data.
+ */
+
+ struct PACKED NewOSGDTRecord final
+ {
+ UInt16 Limit0;
+ UInt16 Base0;
+ UInt8 Base1;
+ UInt8 AccessByte;
+ UInt8 Limit1_Flags;
+ UInt8 Base2;
+ };
+
+ struct PACKED ALIGN(0x1000) NewOSGDT final
+ {
+ NewOSGDTRecord Null;
+ NewOSGDTRecord KernCode;
+ NewOSGDTRecord KernData;
+ NewOSGDTRecord UserNull;
+ NewOSGDTRecord UserCode;
+ NewOSGDTRecord UserData;
+ };
+ } // namespace Detail
+
+ class APICController
+ {
+ public:
+ explicit APICController(VoidPtr base)
+ : fApic(base)
+ {
+ }
+
+ ~APICController() = default;
+
+ NEWOS_COPY_DEFAULT(APICController);
+
+ public:
+ UInt32 Read(UInt32 reg) noexcept;
+ Void Write(UInt32 reg, UInt32 value) noexcept;
+
+ private:
+ VoidPtr fApic{nullptr};
+ };
+} // 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 Kernel::Void hal_load_idt(Kernel::HAL::Register64 ptr);
+EXTERN_C Kernel::Void hal_load_gdt(Kernel::HAL::RegisterGDT ptr);
+
+/// @brief Maximum size of the IDT.
+#define kKernelIdtSize 0x100
+#define kKernelInterruptId 0x32
+
+inline Kernel::VoidPtr kKernelVMTStart = (Kernel::VoidPtr)cHeapStartOffset;
+inline Kernel::VoidPtr kKernelVirtualStart = nullptr;
+inline Kernel::UIntPtr kKernelVirtualSize = 0UL;
+
+inline Kernel::VoidPtr kKernelPhysicalStart = nullptr;
diff --git a/dev/Kernel/HALKit/AMD64/ReadMe.md b/dev/Kernel/HALKit/AMD64/ReadMe.md
new file mode 100644
index 00000000..0be48c77
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/ReadMe.md
@@ -0,0 +1,4 @@
+AMD64 Hardware Abstraction Layer
+
+- Supported CPU: AMD64 CPU
+- Supported Firmware: EDK 2 \ No newline at end of file
diff --git a/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx
new file mode 100644
index 00000000..0974c240
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/AHCI.cxx
@@ -0,0 +1,67 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+/**
+ * @file AHCI.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief AHCI driver.
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) ZKA Technologies
+ *
+ */
+
+#include <Modules/AHCI/AHCI.hxx>
+#include <KernelKit/PCI/Iterator.hxx>
+
+#ifdef __AHCI__
+enum
+{
+ kSATAProgIfAHCI = 0x01,
+ kSATASubClass = 0x06
+};
+
+static Kernel::PCI::Device kAhciDevice;
+
+/// @brief Initializes an AHCI disk.
+/// @param PortsImplemented the amount of port that have been detected.
+/// @return
+Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
+{
+ using namespace Kernel;
+
+ PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController);
+ for (SizeT devIndex = 0; devIndex < NEWOS_BUS_COUNT; ++devIndex)
+ {
+ if (iterator[devIndex].Leak().Subclass() == kSATASubClass &&
+ iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI)
+ {
+ iterator[devIndex].Leak().EnableMmio(); /// enable the memory i/o for this ahci device.
+ kAhciDevice = iterator[devIndex].Leak(); /// and then leak the reference.
+
+ kcout << "newoskrnl: [PCI] Found AHCI controller.\r";
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Kernel::Boolean drv_std_detected(Kernel::Void)
+{
+ return kAhciDevice.DeviceId() != 0xFFFF;
+}
+
+Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
+{
+}
+
+Kernel::Void drv_std_write(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
+{
+}
+#endif // __AHCI__
diff --git a/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx
new file mode 100644
index 00000000..49d10a7e
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx
@@ -0,0 +1,38 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-DMA.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (DMA mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) ZKA Technologies
+ *
+ */
+
+#include <StorageKit/PRDT.hxx>
+
+#include <Modules/ATA/ATA.hxx>
+#include <ArchKit/ArchKit.hxx>
+
+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.cxx b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx
new file mode 100644
index 00000000..c1cdd013
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx
@@ -0,0 +1,199 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-PIO.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (PIO mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) ZKA Technologies
+ *
+ */
+
+#include <Modules/ATA/ATA.hxx>
+#include <ArchKit/ArchKit.hxx>
+
+#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 < 4; i++)
+ In8(IO + ATA_REG_STATUS);
+
+ATAWaitForIO_Retry:
+ auto statRdy = In8(IO + ATA_REG_STATUS);
+
+ if ((statRdy & ATA_SR_BSY))
+ goto ATAWaitForIO_Retry;
+
+ATAWaitForIO_Retry2:
+ statRdy = 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)
+ Out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL);
+ else
+ 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);
+
+ Kernel::kcout << "newoskrnl: Initializing drive...\r";
+
+ATAInit_Retry:
+ // Bus init, NEIN bit.
+ Out8(IO + ATA_REG_NEIN, 1);
+
+ // identify until it's good
+
+ auto statRdy = In8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ {
+ Kernel::kcout << "newoskrnl: Failing drive...\r";
+
+ return false;
+ }
+
+ if ((statRdy & ATA_SR_BSY))
+ {
+ kcout << "Retrying...";
+ goto ATAInit_Retry;
+ }
+
+ 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] = 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;
+
+ Kernel::kcout << "newoskrnl: Create ATA module.\r";
+
+ return true;
+}
+
+Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ Lba /= SectorSz;
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ /// Compute sector count.
+ Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2));
+
+ Out8(IO + ATA_REG_LBA0, (Lba));
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+
+ 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] = 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)
+{
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ Lba /= SectorSz;
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ /// Compute sector count.
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2));
+
+ Out8(IO + ATA_REG_LBA0, (Lba));
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+
+ 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);
+ 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_std_get_sector_count()
+{
+ return (kATAData[61] << 16) | kATAData[60];
+}
+
+/// @brief Get the drive size.
+Kernel::SizeT drv_std_get_drv_size()
+{
+ return drv_std_get_sector_count() * kATASectorSize;
+}
+
+#endif /* ifdef __ATA_PIO__ */