From 0ead895f52d24dad009f738037a7795d4e3d840a Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Tue, 25 Mar 2025 15:35:28 +0100 Subject: kernel: Refactor AHCI I/O path, enhance memory allocators, and cleanup obsolete script - Removed unused `build_gcc.sh` script. - Namespaced CPU feature flags under `NeOS` and transitioned from enum to unnamed enum for scoping. - Renamed `drv_std_input_output` to `drv_std_input_output_ahci` for clarity. - Improved AHCI driver documentation and added zeroing for read buffers. - Added optional `pad` parameter to memory allocators: `mm_alloc_bitmap`, `mm_new_heap`, `PageMgr::Request`, etc. - Updated bitmap allocator to correctly handle and align with padded sizes. - Added `fPad` field to memory header block. - Fixed `ATA-DMA` mode comment, corrected PRD usage and logic. - Improved code documentation and formatting in `UserProcessScheduler`, `PageMgr`, and related components. - Enhanced safety in process memory cleanup (e.g., `StackReserve` cleanup). Signed-off-by: Amlal El Mahrouss --- dev/kernel/HALKit/AMD64/CPUID.h | 131 ++++++++++++------------ dev/kernel/HALKit/AMD64/Paging.h | 2 +- dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc | 48 +++++++-- dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc | 36 ++++--- dev/kernel/KernelKit/MemoryMgr.h | 2 +- dev/kernel/KernelKit/UserProcessScheduler.h | 57 +++++++++-- dev/kernel/NewKit/Macros.h | 5 + dev/kernel/NewKit/PageMgr.h | 2 +- dev/kernel/src/BitMapMgr.cc | 55 ++++++---- dev/kernel/src/MemoryMgr.cc | 9 +- dev/kernel/src/PageMgr.cc | 4 +- dev/kernel/src/Pmm.cc | 4 +- dev/kernel/src/UserProcessScheduler.cc | 29 +++--- 13 files changed, 246 insertions(+), 138 deletions(-) (limited to 'dev') diff --git a/dev/kernel/HALKit/AMD64/CPUID.h b/dev/kernel/HALKit/AMD64/CPUID.h index 7f04ac27..6ea84106 100644 --- a/dev/kernel/HALKit/AMD64/CPUID.h +++ b/dev/kernel/HALKit/AMD64/CPUID.h @@ -15,72 +15,73 @@ #include -enum CPUFeatureEnum -{ - kCPUFeatureSSE3 = 1 << 0, - kCPUFeaturePCLMUL = 1 << 1, - kCPUFeatureDTES64 = 1 << 2, - kCPUFeatureMONITOR = 1 << 3, - kCPUFeatureDS_CPL = 1 << 4, - kCPUFeatureVMX = 1 << 5, - kCPUFeatureSMX = 1 << 6, - kCPUFeatureEST = 1 << 7, - kCPUFeatureTM2 = 1 << 8, - kCPUFeatureSSSE3 = 1 << 9, - kCPUFeatureCID = 1 << 10, - kCPUFeatureSDBG = 1 << 11, - kCPUFeatureFMA = 1 << 12, - kCPUFeatureCX16 = 1 << 13, - kCPUFeatureXTPR = 1 << 14, - kCPUFeaturePDCM = 1 << 15, - kCPUFeaturePCID = 1 << 17, - kCPUFeatureDCA = 1 << 18, - kCPUFeatureSSE4_1 = 1 << 19, - kCPUFeatureSSE4_2 = 1 << 20, - kCPUFeatureX2APIC = 1 << 21, - kCPUFeatureMOVBE = 1 << 22, - kCPUFeaturePOP3C = 1 << 23, - kCPUFeatureECXTSC = 1 << 24, - kCPUFeatureAES = 1 << 25, - kCPUFeatureXSAVE = 1 << 26, - kCPUFeatureOSXSAVE = 1 << 27, - kCPUFeatureAVX = 1 << 28, - kCPUFeatureF16C = 1 << 29, - kCPUFeatureRDRAND = 1 << 30, - kCPUFeatureHYPERVISOR = 1 << 31, - kCPUFeatureFPU = 1 << 0, - kCPUFeatureVME = 1 << 1, - kCPUFeatureDE = 1 << 2, - kCPUFeaturePSE = 1 << 3, - kCPUFeatureEDXTSC = 1 << 4, - kCPUFeatureMSR = 1 << 5, - kCPUFeaturePAE = 1 << 6, - kCPUFeatureMCE = 1 << 7, - kCPUFeatureCX8 = 1 << 8, - kCPUFeatureAPIC = 1 << 9, - kCPUFeatureSEP = 1 << 11, - kCPUFeatureMTRR = 1 << 12, - kCPUFeaturePGE = 1 << 13, - kCPUFeatureMCA = 1 << 14, - kCPUFeatureCMOV = 1 << 15, - kCPUFeaturePAT = 1 << 16, - kCPUFeaturePSE36 = 1 << 17, - kCPUFeaturePSN = 1 << 18, - kCPUFeatureCLFLUSH = 1 << 19, - kCPUFeatureDS = 1 << 21, - kCPUFeatureACPI = 1 << 22, - kCPUFeatureMMX = 1 << 23, - kCPUFeatureFXSR = 1 << 24, - kCPUFeatureSSE = 1 << 25, - kCPUFeatureSSE2 = 1 << 26, - kCPUFeatureSS = 1 << 27, - kCPUFeatureHTT = 1 << 28, - kCPUFeatureTM = 1 << 29, - kCPUFeatureIA64 = 1 << 30, - kCPUFeaturePBE = 1 << 31 -}; - namespace NeOS { + + enum + { + kCPUFeatureSSE3 = 1 << 0, + kCPUFeaturePCLMUL = 1 << 1, + kCPUFeatureDTES64 = 1 << 2, + kCPUFeatureMONITOR = 1 << 3, + kCPUFeatureDS_CPL = 1 << 4, + kCPUFeatureVMX = 1 << 5, + kCPUFeatureSMX = 1 << 6, + kCPUFeatureEST = 1 << 7, + kCPUFeatureTM2 = 1 << 8, + kCPUFeatureSSSE3 = 1 << 9, + kCPUFeatureCID = 1 << 10, + kCPUFeatureSDBG = 1 << 11, + kCPUFeatureFMA = 1 << 12, + kCPUFeatureCX16 = 1 << 13, + kCPUFeatureXTPR = 1 << 14, + kCPUFeaturePDCM = 1 << 15, + kCPUFeaturePCID = 1 << 17, + kCPUFeatureDCA = 1 << 18, + kCPUFeatureSSE4_1 = 1 << 19, + kCPUFeatureSSE4_2 = 1 << 20, + kCPUFeatureX2APIC = 1 << 21, + kCPUFeatureMOVBE = 1 << 22, + kCPUFeaturePOP3C = 1 << 23, + kCPUFeatureECXTSC = 1 << 24, + kCPUFeatureAES = 1 << 25, + kCPUFeatureXSAVE = 1 << 26, + kCPUFeatureOSXSAVE = 1 << 27, + kCPUFeatureAVX = 1 << 28, + kCPUFeatureF16C = 1 << 29, + kCPUFeatureRDRAND = 1 << 30, + kCPUFeatureHYPERVISOR = 1 << 31, + kCPUFeatureFPU = 1 << 0, + kCPUFeatureVME = 1 << 1, + kCPUFeatureDE = 1 << 2, + kCPUFeaturePSE = 1 << 3, + kCPUFeatureEDXTSC = 1 << 4, + kCPUFeatureMSR = 1 << 5, + kCPUFeaturePAE = 1 << 6, + kCPUFeatureMCE = 1 << 7, + kCPUFeatureCX8 = 1 << 8, + kCPUFeatureAPIC = 1 << 9, + kCPUFeatureSEP = 1 << 11, + kCPUFeatureMTRR = 1 << 12, + kCPUFeaturePGE = 1 << 13, + kCPUFeatureMCA = 1 << 14, + kCPUFeatureCMOV = 1 << 15, + kCPUFeaturePAT = 1 << 16, + kCPUFeaturePSE36 = 1 << 17, + kCPUFeaturePSN = 1 << 18, + kCPUFeatureCLFLUSH = 1 << 19, + kCPUFeatureDS = 1 << 21, + kCPUFeatureACPI = 1 << 22, + kCPUFeatureMMX = 1 << 23, + kCPUFeatureFXSR = 1 << 24, + kCPUFeatureSSE = 1 << 25, + kCPUFeatureSSE2 = 1 << 26, + kCPUFeatureSS = 1 << 27, + kCPUFeatureHTT = 1 << 28, + kCPUFeatureTM = 1 << 29, + kCPUFeatureIA64 = 1 << 30, + kCPUFeaturePBE = 1 << 31 + }; + typedef Int64 CPUID; } // namespace NeOS diff --git a/dev/kernel/HALKit/AMD64/Paging.h b/dev/kernel/HALKit/AMD64/Paging.h index 4e2ac1b1..09b6ade3 100644 --- a/dev/kernel/HALKit/AMD64/Paging.h +++ b/dev/kernel/HALKit/AMD64/Paging.h @@ -88,7 +88,7 @@ namespace NeOS::HAL NE_PTE* ALIGN(kPageAlign) fEntries[kPageMax]; }; - auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page) -> VoidPtr; + auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page, const SizeT pad = 0) -> VoidPtr; auto mm_free_bitmap(VoidPtr page_ptr) -> Bool; } // namespace NeOS::HAL diff --git a/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc b/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc index bd5c86f4..b1584c80 100644 --- a/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc +++ b/dev/kernel/HALKit/AMD64/Storage/AHCI+Generic.cc @@ -63,7 +63,7 @@ STATIC Char kCurrentDiskModel[50] = {"UNKNOWN AHCI DRIVE"}; STATIC UInt16 kSATAPortsImplemented = 0U; template -STATIC Void drv_std_input_output(UInt64 lba, UInt8* buffer, SizeT sector_sz, SizeT size_buffer) noexcept; +STATIC Void drv_std_input_output_ahci(UInt64 lba, UInt8* buffer, SizeT sector_sz, SizeT size_buffer) noexcept; STATIC Int32 drv_find_cmd_slot(HbaPort* port) noexcept; @@ -73,21 +73,29 @@ STATIC Void drv_compute_disk_ahci() noexcept { kSATASectorCount = 0UL; + /// Normally 512 bytes, but add an additional 512 bytes to make 1 KIB. const UInt16 kSzIdent = kib_cast(1); + /// Push it to the stack UInt8 identify_data[kSzIdent] = {0}; rt_set_memory(identify_data, 0, kSzIdent); - drv_std_input_output(0, identify_data, kAHCISectorSize, kSzIdent); + /// Send AHCI command. + drv_std_input_output_ahci(0, identify_data, kAHCISectorSize, kSzIdent); + /// Extract 28-bit LBA. kSATASectorCount = (identify_data[61] << 16) | identify_data[60]; + /// Show what we got. kout << "Disk Model: " << kCurrentDiskModel << kendl; kout << "Disk Size: " << number(drv_get_size()) << kendl; kout << "Disk Sector Count: " << number(kSATASectorCount) << kendl; } +/// @brief Finds a command slot for a HBA port. +/// @param port The port to search on. +/// @return The slot, or ~0. STATIC Int32 drv_find_cmd_slot(HbaPort* port) noexcept { UInt32 slots = (port->Sact | port->Ci); @@ -103,8 +111,13 @@ STATIC Int32 drv_find_cmd_slot(HbaPort* port) noexcept return ~0; } +/// @brief Send an AHCI command, according to the template parameters. +/// @param lba Logical Block Address to look for. +/// @param buffer The data buffer to transfer. +/// @param sector_sz The disk's sector size (unused) +/// @param size_buffer The size of the **buffer** parameter. template -STATIC Void drv_std_input_output(UInt64 lba, UInt8* buffer, SizeT sector_sz, SizeT size_buffer) noexcept +STATIC Void drv_std_input_output_ahci(UInt64 lba, UInt8* buffer, SizeT sector_sz, SizeT size_buffer) noexcept { UIntPtr slot = 0UL; @@ -113,6 +126,12 @@ STATIC Void drv_std_input_output(UInt64 lba, UInt8* buffer, SizeT sector_sz, Siz if (slot == ~0) return; + if (!Write) + { + // Zero-memory the buffer field. + rt_set_memory(buffer, 0, size_buffer); + } + volatile HbaCmdHeader* command_header = ((HbaCmdHeader*)(((UInt64)kSATAHba->Ports[kSATAIndex].Clb))); command_header += slot; @@ -310,6 +329,8 @@ STATIC Bool drv_std_init_ahci(UInt16& pi, BOOL& atapi) return NO; } +/// @brief Checks if an AHCI device is detected. +/// @return Either if detected, or not found. Bool drv_std_detected_ahci() { return kSATADev.DeviceId() != (UShort)PCI::PciConfigKind::Invalid && kSATADev.Bar(kSATABar5) != 0; @@ -317,6 +338,7 @@ Bool drv_std_detected_ahci() namespace NeOS { + /// @brief Initialize an AHCI device (StorageKit) UInt16 sk_init_ahci_device(BOOL atapi) { UInt16 pi = 0; @@ -327,6 +349,7 @@ namespace NeOS return pi; } + /// @brief Implementation details namespace. namespace Detail { /// @brief Read AHCI device. @@ -344,7 +367,7 @@ namespace NeOS if (!disk) return; - drv_std_input_output(disk->fPacket.fPacketLba, (UInt8*)disk->fPacket.fPacketContent, kAHCISectorSize, disk->fPacket.fPacketSize); + drv_std_input_output_ahci(disk->fPacket.fPacketLba, (UInt8*)disk->fPacket.fPacketContent, kAHCISectorSize, disk->fPacket.fPacketSize); } /// @brief Write AHCI device. @@ -362,10 +385,13 @@ namespace NeOS if (!disk) return; - drv_std_input_output(disk->fPacket.fPacketLba, (UInt8*)disk->fPacket.fPacketContent, kAHCISectorSize, disk->fPacket.fPacketSize); + drv_std_input_output_ahci(disk->fPacket.fPacketLba, (UInt8*)disk->fPacket.fPacketContent, kAHCISectorSize, disk->fPacket.fPacketSize); } } // namespace Detail + /// @brief Acquires a new AHCI device with drv_index in mind. + /// @param drv_index The drive index to assign. + /// @return A wrapped device interface if successful, or error code. ErrorOr sk_acquire_ahci_device(Int32 drv_index) { if (!drv_std_detected_ahci()) @@ -382,16 +408,24 @@ namespace NeOS } } // namespace NeOS +// ================================================================================================ + +// +// This applies only if we compile with AHCI as a default disk driver. +// + +// ================================================================================================ + #ifdef __AHCI__ Void drv_std_write(UInt64 lba, Char* buffer, SizeT sector_sz, SizeT size_buffer) { - drv_std_input_output(lba, (UInt8*)buffer, sector_sz, size_buffer); + drv_std_input_output_ahci(lba, (UInt8*)buffer, sector_sz, size_buffer); } Void drv_std_read(UInt64 lba, Char* buffer, SizeT sector_sz, SizeT size_buffer) { - drv_std_input_output(lba, (UInt8*)buffer, sector_sz, size_buffer); + drv_std_input_output_ahci(lba, (UInt8*)buffer, sector_sz, size_buffer); } Bool drv_std_init(UInt16& pi) diff --git a/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc b/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc index 0a03dafc..9624ea5b 100644 --- a/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc +++ b/dev/kernel/HALKit/AMD64/Storage/DMA+Generic.cc @@ -7,7 +7,7 @@ /** * @file ATA-PIO.cc * @author Amlal EL Mahrouss (amlal@nekernel.org) - * @brief ATA driver (PIO mode). + * @brief ATA driver (DMA mode). * @version 0.1 * @date 2024-02-02 * @@ -131,17 +131,15 @@ Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) return NO; } -namespace Detail +namespace NeOS::Detail { - using namespace NeOS; - struct PRDEntry { UInt32 mAddress; UInt16 mByteCount; UInt16 mFlags; }; -} // namespace Detail +} // namespace NeOS::Detail static UIntPtr kReadAddr = mib_cast(2); static UIntPtr kWriteAddr = mib_cast(4); @@ -151,7 +149,7 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz Lba /= SectorSz; if (Size > kib_cast(64)) - ke_panic(RUNTIME_CHECK_FAILED, "ATA-DMA only supports < 64kb DMA transfers."); + return; UInt8 Command = ((!Master) ? 0xE0 : 0xF0); @@ -168,7 +166,7 @@ Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - Detail::PRDEntry* prd = (Detail::PRDEntry*)(kATADevice.Bar(0x20) + 4); // The PRDEntry is not correct. + NeOS::Detail::PRDEntry* prd = (NeOS::Detail::PRDEntry*)(kATADevice.Bar(0x20) + 4); // The PRDEntry is not correct. prd->mAddress = (UInt32)(UIntPtr)kReadAddr; prd->mByteCount = Size - 1; @@ -196,7 +194,7 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS Lba /= SectorSz; if (Size > kib_cast(64)) - ke_panic(RUNTIME_CHECK_FAILED, "ATA-DMA only supports < 64kb DMA transfers."); + return; UInt8 Command = ((!Master) ? 0xE0 : 0xF0); @@ -211,10 +209,11 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - Detail::PRDEntry* prd = (Detail::PRDEntry*)(kATADevice.Bar(0x20) + 4); - prd->mAddress = (UInt32)(UIntPtr)kWriteAddr; - prd->mByteCount = Size - 1; - prd->mFlags = 0x8000; + NeOS::Detail::PRDEntry* prd = (NeOS::Detail::PRDEntry*)(kATADevice.Bar(0x20) + 4); + + prd->mAddress = (UInt32)(UIntPtr)kWriteAddr; + prd->mByteCount = Size - 1; + prd->mFlags = 0x8000; rt_out32(kATADevice.Bar(0x20) + 0x04, (UInt32)(UIntPtr)prd); rt_out8(kATADevice.Bar(0x20) + ATA_REG_COMMAND, ATA_CMD_WRITE_DMA); @@ -230,21 +229,28 @@ Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorS prd = nullptr; } -/// @brief is ATA detected? +/***********************************************************************************/ +/// @brief Is ATA detected? +/***********************************************************************************/ Boolean drv_std_detected(Void) { return kATADetected; } +/***********************************************************************************/ /*** - @brief Getter, gets the number of sectors inside the drive. + @brief Gets the number of sectors inside the drive. + @return Number of sectors, or zero. */ +/***********************************************************************************/ NeOS::SizeT drv_get_sector_count() { return (kATAData[61] << 16) | kATAData[60]; } -/// @brief Get the drive size. +/***********************************************************************************/ +/// @brief Get the size of the current drive. +/***********************************************************************************/ NeOS::SizeT drv_get_size() { return (drv_get_sector_count()) * kATASectorSize; diff --git a/dev/kernel/KernelKit/MemoryMgr.h b/dev/kernel/KernelKit/MemoryMgr.h index 139ae7aa..23a4721b 100644 --- a/dev/kernel/KernelKit/MemoryMgr.h +++ b/dev/kernel/KernelKit/MemoryMgr.h @@ -37,7 +37,7 @@ namespace NeOS /// @param wr Read Write bit. /// @param user User enable bit. /// @return The newly allocated pointer, or nullptr. - VoidPtr mm_new_heap(const SizeT sz, const Bool wr, const Bool user); + VoidPtr mm_new_heap(const SizeT sz, const Bool wr, const Bool user, const SizeT pad_amount = 0); /// @brief Protect the heap with a CRC value. /// @param heap_ptr pointer. diff --git a/dev/kernel/KernelKit/UserProcessScheduler.h b/dev/kernel/KernelKit/UserProcessScheduler.h index 10a08e0f..a2006db1 100644 --- a/dev/kernel/KernelKit/UserProcessScheduler.h +++ b/dev/kernel/KernelKit/UserProcessScheduler.h @@ -38,10 +38,14 @@ namespace NeOS typedef UInt64 PTime; + /***********************************************************************************/ //! @brief Local Process identifier. + /***********************************************************************************/ typedef Int64 ProcessID; + /***********************************************************************************/ //! @brief Local Process status enum. + /***********************************************************************************/ enum class ProcessStatusKind : Int32 { kInvalid, @@ -53,8 +57,9 @@ namespace NeOS kCount, }; - //! @brief Affinity is the amount of nano-seconds this process is going - //! to run. + /***********************************************************************************/ + //! @brief Affinity is the amount of nano-seconds this process is going to run. + /***********************************************************************************/ enum class AffinityKind : Int32 { kRealTime = 500, @@ -65,7 +70,9 @@ namespace NeOS kVeryLowUsage = 2000, }; - // operator overloading. + /***********************************************************************************/ + //! Operators for AffinityKind + /***********************************************************************************/ inline bool operator<(AffinityKind lhs, AffinityKind rhs) { @@ -99,7 +106,9 @@ namespace NeOS return lhs_int >= rhs_int; } - // end of operator overloading. + /***********************************************************************************/ + /// @brief Subsystem enum type. + /***********************************************************************************/ enum class ProcessSubsystem : Int32 { @@ -114,7 +123,9 @@ namespace NeOS using ProcessTime = UInt64; using PID = Int64; - // for permission manager, tells where we run the code. + /***********************************************************************************/ + /// @note For User manager, tells where we run the code. + /***********************************************************************************/ enum class ProcessLevelRing : Int32 { kRingStdUser = 1, @@ -123,7 +134,9 @@ namespace NeOS kRingCount = 5, }; + /***********************************************************************************/ /// @brief Helper type to describe a code image. + /***********************************************************************************/ using ImagePtr = VoidPtr; struct UserProcessImage final @@ -144,8 +157,10 @@ namespace NeOS } }; + /***********************************************************************************/ /// @name UserProcess /// @brief User process class, holds information about the running process/thread. + /***********************************************************************************/ class UserProcess final { public: @@ -207,38 +222,58 @@ namespace NeOS Int32 Kind{kExectuableKind}; public: + /***********************************************************************************/ //! @brief boolean operator, check status. + /***********************************************************************************/ operator bool(); + /***********************************************************************************/ ///! @brief Crashes the app, exits with code ~0. + /***********************************************************************************/ Void Crash(); + /***********************************************************************************/ ///! @brief Exits the app. + /***********************************************************************************/ Void Exit(const Int32& exit_code = 0); + /***********************************************************************************/ ///! @brief TLS allocate. - ///! @param sz size of new ptr. + ///! @param sz size of data structure. + ///! @param pad_amount amount to add after pointer. + ///! @return A wrapped pointer, or error code. + /***********************************************************************************/ ErrorOr New(const SizeT& sz, const SizeT& pad_amount = 0); + /***********************************************************************************/ ///! @brief TLS free. ///! @param ptr the pointer to free. ///! @param sz the size of it. + /***********************************************************************************/ template Boolean Delete(ErrorOr ptr, const SizeT& sz); - ///! @brief Wakes up threads. + /***********************************************************************************/ + ///! @brief Wakes up thread. + /***********************************************************************************/ Void Wake(const Bool wakeup = false); public: + /***********************************************************************************/ //! @brief Gets the local exit code. + /***********************************************************************************/ const UInt32& GetExitCode() noexcept; + /***********************************************************************************/ ///! @brief Get the process's name ///! @example 'C Runtime Library' + /***********************************************************************************/ const Char* GetName() noexcept; + /***********************************************************************************/ //! @brief return local error code of process. //! @return Int32 local error code. + /***********************************************************************************/ Int32& GetLocalCode() noexcept; const User* GetOwner() noexcept; @@ -278,8 +313,10 @@ namespace NeOS using UserProcessRef = UserProcess&; + /***********************************************************************************/ /// @brief Process scheduler class. /// The main class which you call to schedule user processes. + /***********************************************************************************/ class UserProcessScheduler final : public ISchedulable { friend class UserProcessHelper; @@ -315,9 +352,11 @@ namespace NeOS UserProcessTeam mTeam{}; }; - /* + /***********************************************************************************/ + /** * \brief UserProcess helper class, which contains needed utilities for the scheduler. */ + /***********************************************************************************/ class UserProcessHelper final { @@ -335,9 +374,7 @@ namespace NeOS #include //////////////////////////////////////////////////// - // END - //////////////////////////////////////////////////// #endif /* ifndef INC_PROCESS_SCHEDULER_H */ diff --git a/dev/kernel/NewKit/Macros.h b/dev/kernel/NewKit/Macros.h index 637a2a30..1d270929 100644 --- a/dev/kernel/NewKit/Macros.h +++ b/dev/kernel/NewKit/Macros.h @@ -6,6 +6,11 @@ #pragma once +/***********************************************************************************/ +/// @file NewKit/Macros.h +/// @brief Core Types and Macros. +/***********************************************************************************/ + #ifndef KIB #define KIB(X) (NeOS::UInt64)((X) / 1024) #endif diff --git a/dev/kernel/NewKit/PageMgr.h b/dev/kernel/NewKit/PageMgr.h index 3d8e1f9a..00638f8a 100644 --- a/dev/kernel/NewKit/PageMgr.h +++ b/dev/kernel/NewKit/PageMgr.h @@ -68,7 +68,7 @@ namespace NeOS PageMgr(const PageMgr&) = default; public: - PTEWrapper Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz); + PTEWrapper Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz, SizeT Pad); bool Free(Ref& wrapper); private: diff --git a/dev/kernel/src/BitMapMgr.cc b/dev/kernel/src/BitMapMgr.cc index 18b1a156..f65df8c6 100644 --- a/dev/kernel/src/BitMapMgr.cc +++ b/dev/kernel/src/BitMapMgr.cc @@ -28,7 +28,9 @@ namespace NeOS { namespace Detail { - /// \brief Proxy Interface to allocate a bitmap. + /***********************************************************************************/ + /// \brief Proxy Interface to manage a bitmap allocator. + /***********************************************************************************/ class IBitMapProxy final { public: @@ -79,27 +81,36 @@ namespace NeOS return flags; } - /// @brief Iterate over availables pages for a free one. - /// @return The new address which was found. - auto FindBitMap(VoidPtr base_ptr, SizeT size, Bool wr, Bool user) -> VoidPtr + /***********************************************************************************/ + /// @brief Iterate over availables bitmap, until we find a free entry. + /// @param base_ptr base pointer to look on. + /// @param size the size of the requested data structure. + /// @param wr is writable flag? + /// @param user is user flag? + /// @param pad additional padding added to **size** + /// @return The new free address, or nullptr. + /***********************************************************************************/ + auto FindBitMap(VoidPtr base_ptr, const SizeT size, const Bool wr, const Bool user, const SizeT pad) -> VoidPtr { if (!size) return nullptr; - VoidPtr base = reinterpret_cast(((UIntPtr)base_ptr) + kPageSize); + constexpr const UInt32 kStartOffset = 0x1000; - static SizeT biggest_block = 0UL; + VoidPtr base = reinterpret_cast(((UIntPtr)base_ptr) + kStartOffset); + + static SizeT biggest = 0UL; while (YES) { UIntPtr* ptr_bit_set = reinterpret_cast(base); if (ptr_bit_set[kBitMapMagIdx] == kBitMapMagic && - ptr_bit_set[kBitMapSizeIdx] == size) + ptr_bit_set[kBitMapSizeIdx] == (size + pad)) { if (ptr_bit_set[kBitMapUsedIdx] == No) { - ptr_bit_set[kBitMapSizeIdx] = size; + ptr_bit_set[kBitMapSizeIdx] = size + pad; ptr_bit_set[kBitMapUsedIdx] = Yes; this->GetBitMapStatus(ptr_bit_set); @@ -107,8 +118,8 @@ namespace NeOS UInt32 flags = this->MakeMMFlags(wr, user); mm_map_page(ptr_bit_set, ptr_bit_set, flags); - if (biggest_block < size) - biggest_block = size; + if (biggest < (size + pad)) + biggest = size + pad; return (VoidPtr)ptr_bit_set; } @@ -116,7 +127,7 @@ namespace NeOS else if (ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) { ptr_bit_set[kBitMapMagIdx] = kBitMapMagic; - ptr_bit_set[kBitMapSizeIdx] = size; + ptr_bit_set[kBitMapSizeIdx] = (size + pad); ptr_bit_set[kBitMapUsedIdx] = Yes; this->GetBitMapStatus(ptr_bit_set); @@ -124,13 +135,13 @@ namespace NeOS UInt32 flags = this->MakeMMFlags(wr, user); mm_map_page(ptr_bit_set, ptr_bit_set, flags); - if (biggest_block < size) - biggest_block = size; + if (biggest < (size + pad)) + biggest = (size + pad); return (VoidPtr)ptr_bit_set; } - base = reinterpret_cast(reinterpret_cast(base) + ((ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) ? (size) : ptr_bit_set[kBitMapSizeIdx])); + base = reinterpret_cast(reinterpret_cast(base) + ((ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) ? (size + pad) : ptr_bit_set[kBitMapSizeIdx])); } return nullptr; @@ -145,42 +156,46 @@ namespace NeOS return; } - kout << "Magic Number: " << hex_number(ptr_bit_set[kBitMapMagIdx]) << kendl; - kout << "Is Allocated: " << (ptr_bit_set[kBitMapUsedIdx] ? "Yes" : "No") << kendl; + kout << "Magic: " << hex_number(ptr_bit_set[kBitMapMagIdx]) << kendl; + kout << "Is Allocated? " << (ptr_bit_set[kBitMapUsedIdx] ? "YES" : "NO") << kendl; kout << "Size of BitMap (B): " << number(ptr_bit_set[kBitMapSizeIdx]) << kendl; kout << "Size of BitMap (KIB): " << number(KIB(ptr_bit_set[kBitMapSizeIdx])) << kendl; kout << "Size of BitMap (MIB): " << number(MIB(ptr_bit_set[kBitMapSizeIdx])) << kendl; kout << "Size of BitMap (GIB): " << number(GIB(ptr_bit_set[kBitMapSizeIdx])) << kendl; kout << "Size of BitMap (TIB): " << number(TIB(ptr_bit_set[kBitMapSizeIdx])) << kendl; - kout << "Address Of BitMap Header: " << hex_number((UIntPtr)ptr_bit_set) << kendl; + kout << "BitMap Address: " << hex_number((UIntPtr)ptr_bit_set) << kendl; } }; } // namespace Detail - auto mm_is_bitmap(VoidPtr ptr) -> Bool + auto mm_is_bitmap(VoidPtr ptr) -> BOOL { Detail::IBitMapProxy bitmp; return bitmp.IsBitMap(ptr); } + /***********************************************************************************/ /// @brief Allocate a new page to be used by the OS. /// @param wr read/write bit. /// @param user user bit. /// @return a new bitmap allocated pointer. - auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page) -> VoidPtr + /***********************************************************************************/ + auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page, const SizeT pad) -> VoidPtr { VoidPtr ptr_new = nullptr; Detail::IBitMapProxy bitmp; - ptr_new = bitmp.FindBitMap(kKernelBitMpStart, size, wr, user); + ptr_new = bitmp.FindBitMap(kKernelBitMpStart, size, wr, user, pad); MUST_PASS(ptr_new); return (UIntPtr*)ptr_new; } + /***********************************************************************************/ /// @brief Free Bitmap, and mark it as absent. /// @param ptr the pointer to free. + /***********************************************************************************/ auto mm_free_bitmap(VoidPtr ptr) -> Bool { if (!ptr) diff --git a/dev/kernel/src/MemoryMgr.cc b/dev/kernel/src/MemoryMgr.cc index 7a79b906..271dfa23 100644 --- a/dev/kernel/src/MemoryMgr.cc +++ b/dev/kernel/src/MemoryMgr.cc @@ -67,6 +67,9 @@ namespace NeOS /// @brief 64-bit target offset pointer. UIntPtr fOffset; + /// @brief Padding. + UInt32 fPad; + /// @brief Padding bytes for header. UInt8 fPadding[kMemoryMgrAlignSz]; }; @@ -116,7 +119,7 @@ namespace NeOS /// @param wr Read Write bit. /// @param user User enable bit. /// @return The newly allocated pointer. - _Output VoidPtr mm_new_heap(const SizeT sz, const bool wr, const bool user) + _Output VoidPtr mm_new_heap(const SizeT sz, const Bool wr, const Bool user, const SizeT pad_amount) { auto sz_fix = sz; @@ -126,7 +129,7 @@ namespace NeOS sz_fix += sizeof(Detail::MM_INFORMATION_BLOCK); PageMgr heap_mgr; - auto wrapper = heap_mgr.Request(wr, user, No, sz_fix); + auto wrapper = heap_mgr.Request(wr, user, No, sz_fix, pad_amount); Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = reinterpret_cast( @@ -140,6 +143,7 @@ namespace NeOS heap_info_ptr->fWriteRead = wr; heap_info_ptr->fUser = user; heap_info_ptr->fPresent = Yes; + heap_info_ptr->fPad = pad_amount; rt_set_memory(heap_info_ptr->fPadding, 0, kMemoryMgrAlignSz); @@ -232,6 +236,7 @@ namespace NeOS heap_info_ptr->fWriteRead = No; heap_info_ptr->fUser = No; heap_info_ptr->fMagic = 0; + heap_info_ptr->fPad = 0; kout << "Address has been successfully freed: " << hex_number((UIntPtr)heap_info_ptr) << kendl; diff --git a/dev/kernel/src/PageMgr.cc b/dev/kernel/src/PageMgr.cc index eb7c7e03..6a8622ed 100644 --- a/dev/kernel/src/PageMgr.cc +++ b/dev/kernel/src/PageMgr.cc @@ -57,10 +57,10 @@ namespace NeOS /// @param User user mode? /// @param ExecDisable disable execution on page? /// @return - PTEWrapper PageMgr::Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz) + PTEWrapper PageMgr::Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz, SizeT Pad) { // Store PTE wrapper right after PTE. - VoidPtr ptr = NeOS::HAL::mm_alloc_bitmap(Rw, User, Sz, false); + VoidPtr ptr = NeOS::HAL::mm_alloc_bitmap(Rw, User, Sz, NO, Pad); return PTEWrapper{Rw, User, ExecDisable, reinterpret_cast(ptr)}; } diff --git a/dev/kernel/src/Pmm.cc b/dev/kernel/src/Pmm.cc index b3d5e79e..a5ba0dcd 100644 --- a/dev/kernel/src/Pmm.cc +++ b/dev/kernel/src/Pmm.cc @@ -23,7 +23,7 @@ namespace NeOS Pmm::Pmm() : fPageMgr() { - kout << "[PMM] Allocate PageMemoryMgr"; + kout << "[PMM] Allocate PageMemoryMgr.\r"; } Pmm::~Pmm() = default; @@ -35,7 +35,7 @@ namespace NeOS /***********************************************************************************/ Ref Pmm::RequestPage(Boolean user, Boolean readWrite) { - PTEWrapper pt = fPageMgr.Leak().Request(user, readWrite, false, kPageSize); + PTEWrapper pt = fPageMgr.Leak().Request(user, readWrite, false, kPageSize, 0); if (pt.fPresent) { diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc index 19861dbe..98abe13c 100644 --- a/dev/kernel/src/UserProcessScheduler.cc +++ b/dev/kernel/src/UserProcessScheduler.cc @@ -111,11 +111,11 @@ namespace NeOS auto vm_register = hal_read_cr3(); hal_write_cr3(this->VMRegister); - auto ptr = mm_new_heap(sz + pad_amount, Yes, Yes); + auto ptr = mm_new_heap(sz, Yes, Yes, pad_amount); hal_write_cr3(vm_register); #else - auto ptr = mm_new_heap(sz + pad_amount, Yes, Yes); + auto ptr = mm_new_heap(sz, Yes, Yes, pad_amount); #endif if (!this->ProcessMemoryHeap) @@ -238,15 +238,23 @@ namespace NeOS if (this->Image.fCode && mm_is_valid_heap(this->Image.fCode)) mm_delete_heap(this->Image.fCode); + //! Delete blob too. if (this->Image.fBlob && mm_is_valid_heap(this->Image.fBlob)) mm_delete_heap(this->Image.fBlob); + //! Delete stack frame. if (this->StackFrame && mm_is_valid_heap(this->StackFrame)) mm_delete_heap((VoidPtr)this->StackFrame); - this->Image.fBlob = nullptr; - this->Image.fCode = nullptr; - this->StackFrame = nullptr; + //! Delete stack reserve. + if (this->StackReserve && mm_is_valid_heap(this->StackReserve)) + mm_delete_heap(reinterpret_cast(this->StackReserve)); + + //! Avoid use after free. + this->Image.fBlob = nullptr; + this->Image.fCode = nullptr; + this->StackFrame = nullptr; + this->StackReserve = nullptr; if (this->Kind == kExectuableDylibKind) { @@ -262,10 +270,7 @@ namespace NeOS this->DylibDelegate = nullptr; } - if (this->StackReserve) - mm_delete_heap(reinterpret_cast(this->StackReserve)); - - this->ProcessId = 0; + this->ProcessId = 0UL; this->Status = ProcessStatusKind::kFinished; --this->ProcessParentTeam->mProcessCount; @@ -311,7 +316,7 @@ namespace NeOS flags |= HAL::kMMFlagsUser; HAL::mm_map_page((VoidPtr)process.VMRegister, process.VMRegister, flags); -#endif // __NE_VIRTUAL_MEMORY_SUPPORT__ +#endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ process.StackFrame = new HAL::StackFrame(); @@ -327,7 +332,7 @@ namespace NeOS flags |= HAL::kMMFlagsUser; HAL::mm_map_page((VoidPtr)process.StackFrame, process.StackFrame, flags); -#endif // __NE_VIRTUAL_MEMORY_SUPPORT__ +#endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ // React according to process kind. switch (process.Kind) @@ -357,7 +362,7 @@ namespace NeOS flags |= HAL::kMMFlagsUser; HAL::mm_map_page((VoidPtr)process.StackReserve, process.StackReserve, flags); -#endif // __NE_VIRTUAL_MEMORY_SUPPORT__ +#endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ process.ProcessParentTeam = &mTeam; -- cgit v1.2.3