summaryrefslogtreecommitdiffhomepage
path: root/src/kernel/HALKit/AMD64/Processor.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/HALKit/AMD64/Processor.h')
-rw-r--r--src/kernel/HALKit/AMD64/Processor.h283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/kernel/HALKit/AMD64/Processor.h b/src/kernel/HALKit/AMD64/Processor.h
new file mode 100644
index 00000000..db1ed573
--- /dev/null
+++ b/src/kernel/HALKit/AMD64/Processor.h
@@ -0,0 +1,283 @@
+/* ========================================
+
+ Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license.
+
+ File: Prcoessor.h
+ Purpose: AMD64 processor abstraction.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+======================================== */
+
+#pragma once
+
+#ifdef __NE_AMD64__
+
+#include <FirmwareKit/Handover.h>
+#include <HALKit/AMD64/Paging.h>
+#include <NeKit/Array.h>
+#include <NeKit/Defines.h>
+#include <NeKit/Utils.h>
+
+#include <HALKit/AMD64/CPUID.h>
+
+#define kPITControlPort (0x43)
+#define kPITChannel0Port (0x40)
+#define kPITFrequency (1193180)
+
+#define kPICCommand (0x20)
+#define kPICData (0x21)
+#define kPIC2Command (0xA0)
+#define kPIC2Data (0xA1)
+
+#define kIOAPICRegVal (4)
+#define kIOAPICRegReg (0)
+
+#define rtl_nop_op() asm volatile("nop")
+
+/// @brief Maximum entries of the interrupt descriptor table.
+#define kKernelIdtSize (0x100)
+
+/// @brief interrupt for system call.
+#define kKernelInterruptId (0x32)
+
+#define IsActiveLow(FLG) (FLG & 2)
+#define IsLevelTriggered(FLG) (FLG & 8)
+
+#define kInterruptGate (0x8E)
+#define kUserInterruptGate (0xEE)
+#define kTrapGate (0xEF)
+#define kTaskGate (0b10001100)
+#define kIDTSelector (0x08)
+
+namespace Kernel {
+namespace Detail::AMD64 {
+ struct PACKED InterruptDescriptorAMD64 final {
+ UInt16 OffsetLow; // offset bits 0..15
+ UInt16 Selector; // a code segment selector in GDT or LDT
+ UInt8 Ist;
+ UInt8 TypeAttributes;
+ UInt16 OffsetMid;
+ UInt32 OffsetHigh;
+ UInt32 Zero; // reserved
+ };
+} // namespace Detail::AMD64
+} // namespace Kernel
+
+namespace Kernel::HAL {
+/// @brief Memory Manager mapping flags.
+enum {
+ kMMFlagsInvalid = 1 << 0,
+ kMMFlagsPresent = 1 << 1,
+ kMMFlagsWr = 1 << 2,
+ kMMFlagsUser = 1 << 3,
+ kMMFlagsNX = 1 << 4,
+ kMMFlagsPCD = 1 << 5,
+ kMMFlagsPwt = 1 << 6,
+ kMMFlagsCount = 6,
+};
+
+struct PACKED Register64 final {
+ UShort Limit;
+ UIntPtr Base;
+};
+
+using RawRegister = UInt64;
+using Reg = RawRegister;
+using InterruptId = UInt16; /* For each element in the IVT */
+
+/// @brief Stack frame (as retrieved from assembly.)
+struct PACKED StackFrame {
+ Reg IP;
+ Reg SP;
+ Reg R8;
+ Reg R9;
+ Reg R10;
+ Reg R11;
+ Reg R12;
+ Reg R13;
+ Reg R14;
+ Reg R15;
+};
+
+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(Register64& gdt);
+ static Void Load(Ref<Register64>& gdt);
+};
+
+class IDTLoader final {
+ public:
+ static Void Load(Register64& idt);
+ static Void Load(Ref<Register64>& idt);
+};
+
+/***********************************************************************************/
+/// @brief Is the current config SMP aware?
+/// @return True if YES, False if not.
+/***********************************************************************************/
+
+Bool mp_is_smp(Void) noexcept;
+
+/***********************************************************************************/
+/// @brief Fetch and enable SMP scheduler.
+/// @param vendor_ptr SMP containing structure.
+/***********************************************************************************/
+Void mp_init_cores(VoidPtr vendor_ptr) noexcept;
+
+/***********************************************************************************/
+/// @brief Do a cpuid to check if MSR exists on CPU.
+/// @retval true it does exists.
+/// @retval false it doesn't.
+/***********************************************************************************/
+Bool hal_has_msr() noexcept;
+
+/***********************************************************************************/
+/// @brief Get Model specific register inside core.
+/// @param msr MSR
+/// @param lo low byte
+/// @param hi high byte
+/***********************************************************************************/
+Void hal_get_msr(UInt32 msr, UInt32* lo, UInt32* hi) noexcept;
+
+/// @brief Set Model-specific register.
+/// @param msr MSR
+/// @param lo low byte
+/// @param hi high byte
+Void hal_set_msr(UInt32 msr, UInt32 lo, UInt32 hi) noexcept;
+
+/// @brief Processor specific namespace.
+namespace Detail {
+ /* @brief TSS struct. */
+ struct NE_TSS final {
+ UInt32 fReserved1;
+ UInt64 fRsp0;
+ UInt64 fRsp1;
+ UInt64 fRsp2;
+ UInt64 fReserved2;
+ UInt64 fIst1;
+ UInt64 fIst2;
+ UInt64 fIst3;
+ UInt64 fIst4;
+ UInt64 fIst5;
+ UInt64 fIst6;
+ UInt64 fIst7;
+ UInt64 fReserved3;
+ UInt16 fReserved4;
+ UInt16 fIopb;
+ };
+
+ /**
+ @brief Global descriptor table entry, either null, code or data.
+ */
+
+ struct PACKED NE_GDT_ENTRY final {
+ UInt16 fLimitLow;
+ UInt16 fBaseLow;
+ UInt8 fBaseMid;
+ UInt8 fAccessByte;
+ UInt8 fFlags;
+ UInt8 fBaseHigh;
+ };
+} // namespace Detail
+
+class LAPICDmaWrapper final {
+ public:
+ explicit LAPICDmaWrapper(VoidPtr base);
+ ~LAPICDmaWrapper();
+
+ NE_COPY_DEFAULT(LAPICDmaWrapper)
+
+ public:
+ UInt32 Read(UInt16 reg) noexcept;
+ Void Write(UInt16 reg, UInt32 value) noexcept;
+
+ private:
+ VoidPtr fApic{nullptr};
+};
+
+/// @brief Set a PTE from pd_base.
+/// @param virt_addr a valid virtual address.
+/// @param phys_addr point to physical address.
+/// @param flags the flags to put on the page.
+/// @return Status code of page manip.
+EXTERN_C Int32 mm_map_page(VoidPtr virtual_address, VoidPtr physical_address, UInt32 flags,
+ UInt32 level = 2);
+
+EXTERN_C UInt8 rt_in8(UInt16 port);
+EXTERN_C UInt16 rt_in16(UInt16 port);
+EXTERN_C UInt32 rt_in32(UInt16 port);
+
+EXTERN_C Void rt_out16(UShort port, UShort byte);
+EXTERN_C Void rt_out8(UShort port, UChar byte);
+EXTERN_C Void rt_out32(UShort port, UInt byte);
+
+EXTERN_C Void rt_wait_400ns();
+EXTERN_C Void rt_halt();
+EXTERN_C Void rt_cli();
+EXTERN_C Void rt_sti();
+EXTERN_C Void rt_cld();
+EXTERN_C Void rt_std();
+
+EXTERN_C UIntPtr mm_get_page_addr(VoidPtr virtual_address);
+
+EXTERN_C Int32 mm_memory_fence(VoidPtr virtual_address);
+} // namespace Kernel::HAL
+
+EXTERN_C Kernel::Void idt_handle_generic(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_gpf(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_math(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_pf(Kernel::UIntPtr rsp);
+
+EXTERN_C ATTRIBUTE(naked) Kernel::Void hal_load_idt(Kernel::HAL::Register64 ptr);
+EXTERN_C ATTRIBUTE(naked) Kernel::Void hal_load_gdt(Kernel::HAL::Register64 ptr);
+
+inline Kernel::VoidPtr kKernelBitMpStart = nullptr;
+inline Kernel::UIntPtr kKernelBitMpSize = 0UL;
+
+#endif // __NE_AMD64__ */ \ No newline at end of file