From 5ce8823643f02e4d04c80e2dcf944b442b2ba69b Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Wed, 10 Jul 2024 09:36:03 +0200 Subject: MHR-36: IMP: - APICController class. - Prefix string enum with 'e'. - Document MSR functions. - ke_map_address returns 0 when mapped or not mapped, 1 when pde is invalid. Signed-off-by: Amlal El Mahrouss --- Kernel/HALKit/AMD64/HalAPIC.cxx | 36 +++ Kernel/HALKit/AMD64/HalBoot.asm | 41 ++++ .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp | 93 -------- .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx | 93 ++++++++ .../HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp | 263 --------------------- .../HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx | 242 +++++++++++++++++++ Kernel/HALKit/AMD64/HalInterruptAPI.asm | 2 +- Kernel/HALKit/AMD64/HalNewBoot.asm | 41 ---- Kernel/HALKit/AMD64/Hypervisor.hpp | 1 - Kernel/HALKit/AMD64/Processor.hpp | 85 +++++-- Kernel/NewKit/Macros.hpp | 2 +- Kernel/amd64-efi.make | 2 +- 12 files changed, 476 insertions(+), 425 deletions(-) create mode 100644 Kernel/HALKit/AMD64/HalAPIC.cxx create mode 100644 Kernel/HALKit/AMD64/HalBoot.asm delete mode 100644 Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp create mode 100644 Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx delete mode 100644 Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp create mode 100644 Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx delete mode 100644 Kernel/HALKit/AMD64/HalNewBoot.asm (limited to 'Kernel') diff --git a/Kernel/HALKit/AMD64/HalAPIC.cxx b/Kernel/HALKit/AMD64/HalAPIC.cxx new file mode 100644 index 00000000..a148acf9 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalAPIC.cxx @@ -0,0 +1,36 @@ +/* ------------------------------------------- + + Copyright Zeta Electronics Corporation + +------------------------------------------- */ + +#include +#include + +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/Kernel/HALKit/AMD64/HalBoot.asm b/Kernel/HALKit/AMD64/HalBoot.asm new file mode 100644 index 00000000..5f0342a3 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalBoot.asm @@ -0,0 +1,41 @@ +;; /* +;; * ======================================================== +;; * +;; * Kernel +;; * Copyright Zeta Electronics Corporation, all rights reserved. +;; * +;; * ======================================================== +;; */ + +[bits 64] + +;; Global symbol of this unit +[global MainLong] +[global MainUnsupported] + +%define kTypeKernel 100 +%define kArchAmd64 122 +%define kHandoverMagic 0xBADCC + +section .NewBoot + +HandoverMagic: dq kHandoverMagic +HandoverType: dw kTypeKernel +HandoverArch: dw kArchAmd64 +;; This NewBootStart points to Main. +HandoverStart: dq __ImageStart + +section .text + +global __ImageStart +global __NewBootJumpProc + +extern hal_init_platform + +;; Just a simple setup, we'd also need to tell some before +__NewBootJumpProc: +__ImageStart: + push rcx + call hal_init_platform + pop rcx + ret diff --git a/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp deleted file mode 100644 index f41ee55e..00000000 --- a/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* ------------------------------------------- - - Copyright Zeta Electronics Corporation - -------------------------------------------- */ - -#include -#include -#include - -/// @brief Handle GPF fault. -/// @param rsp -EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp) -{ - Kernel::kcout - << "newoskrnl: General Protection Fault, caused by " - << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); - - Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); -} - -/// @brief Handle page fault. -/// @param rsp -EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp) -{ - Kernel::kcout - << "newoskrnl: Segmentation Fault, caused by " - << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); - - Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); -} - -/// @brief Handle math fault. -/// @param rsp -EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp) -{ - Kernel::kcout - << "newoskrnl: Math error, caused by " - << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); - - Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); -} - -/// @brief Handle any generic fault. -/// @param rsp -EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp) -{ - Kernel::kcout - << "newoskrnl: Execution error, caused by " - << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); - - Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); -} - -/// @brief Handle #UD fault. -/// @param rsp -EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp) -{ - Kernel::kcout - << "newoskrnl: Invalid interrupt, caused by " - << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); - - Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); -} - -/// @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 != 0) - { - Kernel::kcout << "newoskrnl: kerncall: enter.\r"; - - Kernel::kcout << "newoskrnl: kerncall: exit.\r"; - } -} diff --git a/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx new file mode 100644 index 00000000..f41ee55e --- /dev/null +++ b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx @@ -0,0 +1,93 @@ +/* ------------------------------------------- + + Copyright Zeta Electronics Corporation + +------------------------------------------- */ + +#include +#include +#include + +/// @brief Handle GPF fault. +/// @param rsp +EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp) +{ + Kernel::kcout + << "newoskrnl: General Protection Fault, caused by " + << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); + + Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); +} + +/// @brief Handle page fault. +/// @param rsp +EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp) +{ + Kernel::kcout + << "newoskrnl: Segmentation Fault, caused by " + << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); + + Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); +} + +/// @brief Handle math fault. +/// @param rsp +EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp) +{ + Kernel::kcout + << "newoskrnl: Math error, caused by " + << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); + + Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); +} + +/// @brief Handle any generic fault. +/// @param rsp +EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp) +{ + Kernel::kcout + << "newoskrnl: Execution error, caused by " + << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); + + Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); +} + +/// @brief Handle #UD fault. +/// @param rsp +EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp) +{ + Kernel::kcout + << "newoskrnl: Invalid interrupt, caused by " + << Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetName(); + + Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().Crash(); +} + +/// @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 != 0) + { + Kernel::kcout << "newoskrnl: kerncall: enter.\r"; + + Kernel::kcout << "newoskrnl: kerncall: exit.\r"; + } +} diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp deleted file mode 100644 index 8f619b4f..00000000 --- a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* ------------------------------------------- - - Copyright Zeta Electronics Corporation - -------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include - -#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 - -/// @brief assembly routine. internal use only. -EXTERN_C void _hal_enable_smp(void); - -/// @note: _hal_switch_context - -/////////////////////////////////////////////////////////////////////////////////////// - -//! NOTE: fGSI stands 'Field Global System Interrupt' - -/////////////////////////////////////////////////////////////////////////////////////// - -namespace Kernel::HAL -{ - constexpr Int32 kThreadAPIC = 0; - constexpr Int32 kThreadLAPIC = 1; - constexpr Int32 kThreadIOAPIC = 2; - constexpr Int32 kThreadAPIC64 = 3; - constexpr Int32 kThreadBoot = 4; - - /* - * - * 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; - }; - - STATIC VoidPtr kApicMadt = nullptr; - STATIC const Char* kApicSignature = "APIC"; - - /// @brief Multiple APIC Descriptor Table. - struct MadtType final : public SDT - { - struct MadtAddress final - { - Char RecordType; - Char RecordLen; // record length - - UInt32 Address; - UInt32 Flags; // 1 = Dual Legacy PICs installed - } MadtRecords[]; - }; - - struct MadtProcessorLocalApic final - { - Char AcpiProcessorId; - Char ApicId; - UInt32 Flags; - }; - - struct MadtIOApic final - { - Char ApicId; - Char Reserved; - UInt32 Address; - UInt32 SystemInterruptBase; - }; - - struct MadtInterruptSource final - { - Char BusSource; - Char IrqSource; - UInt32 GSI; - UInt16 Flags; - }; - - struct MadtInterruptNmi final - { - Char NmiSource; - Char Reserved; - UInt16 Flags; - UInt32 GSI; - }; - - struct MadtLocalApicAddressOverride final - { - UInt16 Resvered; - UIntPtr Address; - }; - - STATIC Void hal_switch_context(HAL::StackFramePtr stackFrame); - - /////////////////////////////////////////////////////////////////////////////////////// - - STATIC MadtType* kApicInfoBlock = nullptr; - - STATIC struct - { - UIntPtr fAddress{0}; - UInt32 fKind{0}; - } kApicMadtAddresses[255] = {}; - - STATIC SizeT kApicMadtAddressesCount = 0UL; - - enum - { - cAPICEOI = 0xb0, - }; - - /////////////////////////////////////////////////////////////////////////////////////// - - /// @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); - } - - EXTERN_C Void _hal_spin_core(Void); - - /// @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 HAL::StackFramePtr cFramePtr = nullptr; - STATIC Int32 cSMPInterrupt = 34; - - EXTERN_C Void hal_apic_acknowledge_cont(Void) - { - kcout << "newoskrnl: Acknowledged.\r"; - } - - /// @brief Current context getter. - /// @retval StackFramePtr the current context. - EXTERN_C StackFramePtr _hal_leak_current_context(Void) - { - return cFramePtr; - } - - EXTERN_C Void hal_apic_acknowledge(Void) - { - hal_apic_acknowledge_cont(); - } - - EXTERN_C Void _hal_switch_context(HAL::StackFramePtr stackFrame) - { - hal_switch_context(stackFrame); - } - - STATIC Void hal_switch_context(HAL::StackFramePtr stackFrame) - { - Semaphore sem; - - HardwareTimer timer(Seconds(5)); - sem.LockOrWait(&ProcessScheduler::The().Leak().TheCurrent().Leak(), &timer); - - cFramePtr = stackFrame; - - 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() - { - UInt32 eax, edx; - - hal_get_msr(kAPIC_BASE_MSR, &eax, &edx); - - return (eax & 0xfffff000) | ((UIntPtr)(edx & 0x0f) << 32); - } - - /// @brief Fetch and enable cores inside main CPU. - /// @param rsdPtr RSD PTR structure. - Void hal_system_get_cores(voidPtr rsdPtr) - { - auto acpi = ACPIFactoryInterface(rsdPtr); - kApicMadt = acpi.Find(kApicSignature).Leak().Leak(); - - if (kApicMadt != nullptr) - { - MadtType* madt = reinterpret_cast(kApicMadt); - - const auto cMaxProbableCores = madt->Length / sizeof(MadtType::MadtAddress); // the amount of cores we want. - constexpr auto cStartAt = 0; // start here to avoid boot core. - - cpu_set_apic_base(cpu_get_apic_base()); - - // set SVR register to bit 8 to start recieve interrupts. - - auto flagsSet = Kernel::ke_dma_read(cAPICAddress, 0xF0); // SVR register. - flagsSet |= 0x100; - - Kernel::ke_dma_write(cAPICAddress, 0xF0, flagsSet | 0x100); - - for (SizeT coreAt = cStartAt; coreAt < cMaxProbableCores; ++coreAt) - { - MadtType::MadtAddress& madtRecord = madt->MadtRecords[coreAt]; - - kApicMadtAddresses[kApicMadtAddressesCount].fAddress = madtRecord.Address; - kApicMadtAddresses[kApicMadtAddressesCount].fKind = madt->MadtRecords[coreAt].RecordType; - - kcout << "newoskrnl: register ipi...\r"; - - ++kApicMadtAddressesCount; - } - } - else - { - kcout << "newoskrnl: APIC is not present! it is a vital component to enable SMP.\r"; - ke_stop(RUNTIME_CHECK_FAILED); - } - } -} // namespace Kernel::HAL - -/////////////////////////////////////////////////////////////////////////////////////// diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx new file mode 100644 index 00000000..cb7b1eeb --- /dev/null +++ b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cxx @@ -0,0 +1,242 @@ +/* ------------------------------------------- + + Copyright Zeta Electronics Corporation + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include + +#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 + +/// @brief assembly routine. internal use only. +EXTERN_C void _hal_enable_smp(void); + +/// @note: _hal_switch_context + +/////////////////////////////////////////////////////////////////////////////////////// + +//! NOTE: fGSI stands 'Field Global System Interrupt' + +/////////////////////////////////////////////////////////////////////////////////////// + +namespace Kernel::HAL +{ + constexpr Int32 kThreadAPIC = 0; + constexpr Int32 kThreadLAPIC = 1; + constexpr Int32 kThreadIOAPIC = 2; + constexpr Int32 kThreadAPIC64 = 3; + constexpr Int32 kThreadBoot = 4; + + /* + * + * 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; + }; + + STATIC VoidPtr kApicMadt = nullptr; + STATIC const Char* kApicSignature = "APIC"; + + /// @brief Multiple APIC Descriptor Table. + struct MadtType final : public SDT + { + struct MadtAddress final + { + Char RecordType; + Char RecordLen; // record length + + UInt32 Address; + UInt32 Flags; // 1 = Dual Legacy PICs installed + } MadtRecords[]; + }; + + struct MadtProcessorLocalApic final + { + Char AcpiProcessorId; + Char ApicId; + UInt32 Flags; + }; + + struct MadtIOApic final + { + Char ApicId; + Char Reserved; + UInt32 Address; + UInt32 SystemInterruptBase; + }; + + struct MadtInterruptSource final + { + Char BusSource; + Char IrqSource; + UInt32 GSI; + UInt16 Flags; + }; + + struct MadtInterruptNmi final + { + Char NmiSource; + Char Reserved; + UInt16 Flags; + UInt32 GSI; + }; + + struct MadtLocalApicAddressOverride final + { + UInt16 Resvered; + UIntPtr Address; + }; + + STATIC Void hal_switch_context(HAL::StackFramePtr stackFrame); + + /////////////////////////////////////////////////////////////////////////////////////// + + STATIC MadtType* kApicInfoBlock = nullptr; + + STATIC struct + { + UIntPtr fAddress{0}; + UInt32 fKind{0}; + } kApicMadtAddresses[255] = {}; + + STATIC SizeT kApicMadtAddressesCount = 0UL; + + enum + { + cAPICEOI = 0xb0, + }; + + /////////////////////////////////////////////////////////////////////////////////////// + + /// @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); + } + + EXTERN_C Void _hal_spin_core(Void); + + /// @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 HAL::StackFramePtr cFramePtr = nullptr; + STATIC Int32 cSMPInterrupt = 34; + + /// @brief Current context getter. + /// @retval StackFramePtr the current context. + EXTERN_C StackFramePtr _hal_leak_current_context(Void) + { + return cFramePtr; + } + + EXTERN_C Void hal_apic_acknowledge(Void) + { + } + + EXTERN_C Void _hal_switch_context(HAL::StackFramePtr stackFrame) + { + hal_switch_context(stackFrame); + } + + STATIC Void hal_switch_context(HAL::StackFramePtr stackFrame) + { + Semaphore sem; + + HardwareTimer timer(Seconds(5)); + sem.LockOrWait(&ProcessScheduler::The().Leak().TheCurrent().Leak(), &timer); + + cFramePtr = stackFrame; + + 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); + } + + /// @brief Fetch and enable cores inside main CPU. + /// @param rsdPtr RSD PTR structure. + Void hal_system_get_cores(voidPtr rsdPtr) + { + auto acpi = ACPIFactoryInterface(rsdPtr); + kApicMadt = acpi.Find(kApicSignature).Leak().Leak(); + + if (kApicMadt != nullptr) + { + MadtType* madt = reinterpret_cast(kApicMadt); + + cpu_set_apic_base(cpu_get_apic_base()); + + // set SVR register to bit 8 to start recieve interrupts. + + auto flagsSet = Kernel::ke_dma_read(cAPICAddress, 0xF0); // SVR register. + flagsSet |= 0x100; + + Kernel::ke_dma_write(cAPICAddress, 0xF0, flagsSet | 0x100); + } + else + { + kcout << "newoskrnl: APIC is not present! it is a vital component to enable SMP.\r"; + ke_stop(RUNTIME_CHECK_FAILED); + } + } +} // namespace Kernel::HAL + +/////////////////////////////////////////////////////////////////////////////////////// diff --git a/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/Kernel/HALKit/AMD64/HalInterruptAPI.asm index 4e9ace6f..7c483d95 100644 --- a/Kernel/HALKit/AMD64/HalInterruptAPI.asm +++ b/Kernel/HALKit/AMD64/HalInterruptAPI.asm @@ -132,7 +132,7 @@ __NEW_INT_34: mov rax, 0 ;; tell there local apic that we're done. - mov [cAPICAddress + 0xB0], rax ; send end of interrupt. + mov qword [cAPICAddress + 0xB0], rax ; send end of interrupt. iretq diff --git a/Kernel/HALKit/AMD64/HalNewBoot.asm b/Kernel/HALKit/AMD64/HalNewBoot.asm deleted file mode 100644 index 5f0342a3..00000000 --- a/Kernel/HALKit/AMD64/HalNewBoot.asm +++ /dev/null @@ -1,41 +0,0 @@ -;; /* -;; * ======================================================== -;; * -;; * Kernel -;; * Copyright Zeta Electronics Corporation, all rights reserved. -;; * -;; * ======================================================== -;; */ - -[bits 64] - -;; Global symbol of this unit -[global MainLong] -[global MainUnsupported] - -%define kTypeKernel 100 -%define kArchAmd64 122 -%define kHandoverMagic 0xBADCC - -section .NewBoot - -HandoverMagic: dq kHandoverMagic -HandoverType: dw kTypeKernel -HandoverArch: dw kArchAmd64 -;; This NewBootStart points to Main. -HandoverStart: dq __ImageStart - -section .text - -global __ImageStart -global __NewBootJumpProc - -extern hal_init_platform - -;; Just a simple setup, we'd also need to tell some before -__NewBootJumpProc: -__ImageStart: - push rcx - call hal_init_platform - pop rcx - ret diff --git a/Kernel/HALKit/AMD64/Hypervisor.hpp b/Kernel/HALKit/AMD64/Hypervisor.hpp index 1ab69ef4..fd7b70f2 100644 --- a/Kernel/HALKit/AMD64/Hypervisor.hpp +++ b/Kernel/HALKit/AMD64/Hypervisor.hpp @@ -21,6 +21,5 @@ namespace Kernel ENUM_STRING(ParallelsAlt, " lrpepyh vr "); ENUM_STRING(Bhyve, "bhyve bhyve "); ENUM_STRING(Qnx, " QNXQVMBSQG "); - END_STRING_ENUM() } // namespace Kernel diff --git a/Kernel/HALKit/AMD64/Processor.hpp b/Kernel/HALKit/AMD64/Processor.hpp index ff7045c2..8ec0b6f6 100644 --- a/Kernel/HALKit/AMD64/Processor.hpp +++ b/Kernel/HALKit/AMD64/Processor.hpp @@ -19,7 +19,10 @@ #include #include +EXTERN_C +{ #include +} #ifdef kCPUBackendName #undef kCPUBackendName @@ -73,16 +76,17 @@ namespace Kernel::HAL { UInt16 pml4_index = (virt_addr >> 39) & 0x1FF; - if (!pde->Pte[pml4_index].Present) + if (pde && !pde->Pte[pml4_index].Present) { pde->Pte[pml4_index].Present = true; - kcout << "PM is present now.\r"; 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 @@ -92,13 +96,13 @@ namespace Kernel::HAL kcout << "PhysicalAddress: " << hex_number(pde->Pte[pml4_index].PhysicalAddress); kcout << "\r"; - kcout << "User: " << (pde->Pte[pml4_index].User ? "YES" : "NO") << "\r"; - kcout << "RW: " << (pde->Pte[pml4_index].Rw ? "YES" : "NO") << "\r"; + kcout << "User: " << (pde->Pte[pml4_index].User ? "true" : "false") << "\r"; + kcout << "RW: " << (pde->Pte[pml4_index].Rw ? "true" : "false") << "\r"; - return 1; + return 0; } - return 0; + return 1; } /// @brief Map address to PDE. @@ -106,7 +110,7 @@ namespace Kernel::HAL /// @param phys_addr /// @param virt_addr /// @param flags - inline void ke_unmap_address(PDE* pde, UIntPtr phys_addr, UIntPtr virt_addr, UInt32 flags) + inline Void ke_unmap_address(PDE* pde, UIntPtr phys_addr, UIntPtr virt_addr, UInt32 flags) { UInt16 pml4_index = (virt_addr >> 39) & 0x1FF; @@ -202,11 +206,12 @@ namespace Kernel::HAL class SegmentDescriptorComparator final { public: - bool IsValid(SegmentDescriptor& seg) + Bool IsValid(SegmentDescriptor& seg) { return seg.Base > seg.Limit; } - bool Equals(SegmentDescriptor& seg, SegmentDescriptor& segRight) + + Bool Equals(SegmentDescriptor& seg, SegmentDescriptor& segRight) { return seg.Base == segRight.Base && seg.Limit == segRight.Limit; } @@ -217,21 +222,24 @@ namespace Kernel::HAL class GDTLoader final { public: - static void Load(RegisterGDT& gdt); - static void Load(Ref& gdt); + static Void Load(RegisterGDT& gdt); + static Void Load(Ref& gdt); }; class IDTLoader final { public: - static void Load(Register64& idt); - static void Load(Ref& idt); + static Void Load(Register64& idt); + static Void Load(Ref& 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 @@ -242,13 +250,24 @@ namespace Kernel::HAL 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" @@ -256,14 +275,12 @@ namespace Kernel::HAL : "a"(lo), "d"(hi), "c"(msr)); } - /// @brief Processor specific structures. + /// @brief Processor specific namespace. namespace Detail { - EXTERN_C void _ke_power_on_self_test(void); - /** - @brief Global descriptor table entry, either null, code or data. -*/ + @brief Global descriptor table entry, either null, code or data. + */ struct PACKED NewOSGDTRecord final { @@ -285,15 +302,35 @@ namespace Kernel::HAL 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 void idt_handle_generic(Kernel::UIntPtr rsp); -EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp); -EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp); -EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp); +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 void hal_load_idt(Kernel::HAL::Register64 ptr); -EXTERN_C void hal_load_gdt(Kernel::HAL::RegisterGDT ptr); +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 diff --git a/Kernel/NewKit/Macros.hpp b/Kernel/NewKit/Macros.hpp index 913ad7cf..b45d5b04 100644 --- a/Kernel/NewKit/Macros.hpp +++ b/Kernel/NewKit/Macros.hpp @@ -79,7 +79,7 @@ #endif #ifndef ENUM_STRING -#define ENUM_STRING(NAME, VAL) inline constexpr const char* NAME = VAL +#define ENUM_STRING(NAME, VAL) inline constexpr const char* e##NAME = VAL #endif #ifndef END_STRING_ENUM diff --git a/Kernel/amd64-efi.make b/Kernel/amd64-efi.make index b25685e2..83b4fd3d 100644 --- a/Kernel/amd64-efi.make +++ b/Kernel/amd64-efi.make @@ -59,7 +59,7 @@ newos-amd64-epm: clean $(wildcard HALKit/AMD64/*.s) $(ASM) $(ASMFLAGS) HALKit/AMD64/HalInterruptAPI.asm $(ASM) $(ASMFLAGS) HALKit/AMD64/HalSMPCoreManager.asm - $(ASM) $(ASMFLAGS) HALKit/AMD64/HalNewBoot.asm + $(ASM) $(ASMFLAGS) HALKit/AMD64/HalBoot.asm $(ASM) $(ASMFLAGS) HALKit/AMD64/HalInstallTIB.asm $(MOVEALL) -- cgit v1.2.3