diff --git a/Core/Lock.cpp b/Core/Lock.cpp index 3a5cc112..7c12dc17 100644 --- a/Core/Lock.cpp +++ b/Core/Lock.cpp @@ -23,7 +23,11 @@ #include "../kernel.h" #ifdef DEBUG -#define PRINT_BACKTRACE +/* This might end up in a deadlock in the deadlock handler. + Nobody can escape the deadlock, not even the + deadlock handler itself. */ + +// #define PRINT_BACKTRACE #endif #ifdef PRINT_BACKTRACE diff --git a/Core/Memory/HeapAllocators/Xalloc/README.md b/Core/Memory/HeapAllocators/Xalloc/README.md index 4c54e9ca..a8324fb4 100644 --- a/Core/Memory/HeapAllocators/Xalloc/README.md +++ b/Core/Memory/HeapAllocators/Xalloc/README.md @@ -1,6 +1,7 @@ # Xalloc -Xalloc is a custom memory allocator designed for hobby operating systems. It is written in C++ and provides a simple and efficient way to manage memory in your hobby OS. +Xalloc is a custom memory allocator designed for hobby operating systems. +Written in C++ and provides a simple and efficient way to manage memory in your hobby OS. #### ❗ This project is still in development and is not ready for use in production environments. ❗ @@ -8,9 +9,11 @@ Xalloc is a custom memory allocator designed for hobby operating systems. It is ## Features -- **Simple API** - Xalloc provides a simple API for allocating and freeing memory. It is designed to be easy to use and understand. +- **Simple API** - Simple API for allocating and freeing memory. -- [ ] todo complete this +- **Efficient** - Uses a free-list to manage memory and is designed to be fast. + +- **No dependencies** - No dependencies and is designed to be easy to integrate into your OS. --- @@ -32,11 +35,13 @@ extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages) // ... } +/* Mandatory only if Xalloc_MapPages is set to true */ extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags) { // ... } +/* Mandatory only if Xalloc_MapPages is set to true */ extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress) { // ... @@ -45,13 +50,21 @@ extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress) ##### Xalloc.hpp ```cpp +#define Xalloc_StopOnFail /* Infinite loop on failure */ +#define Xalloc_MapPages /* Map pages on allocation */ #define Xalloc_PAGE_SIZE /* <-- Replace with your page size */ #define Xalloc_trace(m, ...) #define Xalloc_warn(m, ...) #define Xalloc_err(m, ...) -#define Xalloc_def /* eg. std::mutex Xalloc_lock; */ -#define Xalloc_lock -#define Xalloc_unlock + +#define XallocV1_def /* eg. std::mutex Xalloc_lock; */ +#define XallocV1_lock +#define XallocV1_unlock + +/* Same as above */ +#define XallocV2_def +#define XallocV2_lock +#define XallocV2_unlock ``` ### Typical usage @@ -135,3 +148,7 @@ If `Size` is equal to zero, and `Address` is not `nullptr`, then the call is equ - `Size` - The new size of the memory block in bytes. --- + +## To-do + +- [ ] Multiple free-lists for different block sizes diff --git a/Core/Memory/HeapAllocators/Xalloc/Wrapper.cpp b/Core/Memory/HeapAllocators/Xalloc/Wrapper.cpp index 68258d70..b80d0747 100644 --- a/Core/Memory/HeapAllocators/Xalloc/Wrapper.cpp +++ b/Core/Memory/HeapAllocators/Xalloc/Wrapper.cpp @@ -21,20 +21,20 @@ extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages) { - return KernelAllocator.RequestPages(Pages); + return KernelAllocator.RequestPages(Pages); } extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages) { - KernelAllocator.FreePages(Address, Pages); + KernelAllocator.FreePages(Address, Pages); } extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags) { - Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags); + Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags); } extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress) { - Memory::Virtual(KernelPageTable).Unmap(VirtualAddress); + Memory::Virtual(KernelPageTable).Unmap(VirtualAddress); } diff --git a/Core/Memory/HeapAllocators/Xalloc/Xalloc.hpp b/Core/Memory/HeapAllocators/Xalloc/Xalloc.hpp index 07006a96..9fee2393 100644 --- a/Core/Memory/HeapAllocators/Xalloc/Xalloc.hpp +++ b/Core/Memory/HeapAllocators/Xalloc/Xalloc.hpp @@ -22,98 +22,215 @@ #include #include -typedef long unsigned Xuint64_t; -typedef long unsigned Xsize_t; +typedef __UINT8_TYPE__ Xuint8_t; +typedef __SIZE_TYPE__ Xsize_t; +typedef __UINTPTR_TYPE__ Xuintptr_t; #define Xalloc_StopOnFail true +#define Xalloc_MapPages true #define Xalloc_PAGE_SIZE PAGE_SIZE #define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__) #define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__) #define Xalloc_err(m, ...) error(m, ##__VA_ARGS__) -#define Xalloc_def NewLock(XallocLock) -#define Xalloc_lock XallocLock.Lock(__FUNCTION__) -#define Xalloc_unlock XallocLock.Unlock() + +#define XallocV1_def NewLock(XallocV1Lock) +#define XallocV1_lock XallocV1Lock.Lock(__FUNCTION__) +#define XallocV1_unlock XallocV1Lock.Unlock() + +#define XallocV2_def NewLock(XallocV2Lock) +#define XallocV2_lock XallocV2Lock.Lock(__FUNCTION__) +#define XallocV2_unlock XallocV2Lock.Unlock() namespace Xalloc { - class V1 - { - private: - void *BaseVirtualAddress = nullptr; - void *FirstBlock = nullptr; - void *LastBlock = nullptr; + class V1 + { + private: + void *BaseVirtualAddress = nullptr; + void *FirstBlock = nullptr; + void *LastBlock = nullptr; - bool UserMapping = false; - bool SMAPUsed = false; + bool UserMapping = false; + bool SMAPUsed = false; - public: - /** @brief Execute "stac" instruction if the kernel has SMAP enabled */ - void Xstac(); + public: + /** @brief Execute "stac" instruction if the kernel has SMAP enabled */ + void Xstac(); - /** @brief Execute "clac" instruction if the kernel has SMAP enabled */ - void Xclac(); + /** @brief Execute "clac" instruction if the kernel has SMAP enabled */ + void Xclac(); - /** - * @brief Arrange the blocks to optimize the memory usage - * The allocator is not arranged by default - * to avoid performance issues. - * This function will defragment the memory - * and free the unused blocks. - * - * You should call this function when the - * kernel is idle or when is not using - * the allocator. - */ - void Arrange(); + /** + * @brief Arrange the blocks to optimize the memory usage + * The allocator is not arranged by default + * to avoid performance issues. + * This function will defragment the memory + * and free the unused blocks. + * + * You should call this function when the + * kernel is idle or when is not using + * the allocator. + */ + void Arrange(); - /** - * @brief Allocate a new memory block - * - * @param Size Size of the block to allocate. - * @return void* Pointer to the allocated block. - */ - void *malloc(Xsize_t Size); + /** + * @brief Allocate a new memory block + * + * @param Size Size of the block to allocate. + * @return void* Pointer to the allocated block. + */ + void *malloc(Xsize_t Size); - /** - * @brief Free a previously allocated block - * - * @param Address Address of the block to free. - */ - void free(void *Address); + /** + * @brief Free a previously allocated block + * + * @param Address Address of the block to free. + */ + void free(void *Address); - /** - * @brief Allocate a new memory block - * - * @param NumberOfBlocks Number of blocks to allocate. - * @param Size Size of the block to allocate. - * @return void* Pointer to the allocated block. - */ - void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size); + /** + * @brief Allocate a new memory block + * + * @param NumberOfBlocks Number of blocks to allocate. + * @param Size Size of the block to allocate. + * @return void* Pointer to the allocated block. + */ + void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size); - /** - * @brief Reallocate a previously allocated block - * - * @param Address Address of the block to reallocate. - * @param Size New size of the block. - * @return void* Pointer to the reallocated block. - */ - void *realloc(void *Address, Xsize_t Size); + /** + * @brief Reallocate a previously allocated block + * + * @param Address Address of the block to reallocate. + * @param Size New size of the block. + * @return void* Pointer to the reallocated block. + */ + void *realloc(void *Address, Xsize_t Size); - /** - * @brief Construct a new Allocator object - * - * @param BaseVirtualAddress Virtual address to map the pages. - * @param UserMode Map the new pages with USER flag? - * @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled? - */ - V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled); + /** + * @brief Construct a new Allocator object + * + * @param BaseVirtualAddress Virtual address to map the pages. + * @param UserMode Map the new pages with USER flag? + * @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled? + */ + V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled); - /** - * @brief Destroy the Allocator object - * - */ - ~V1(); - }; + /** + * @brief Destroy the Allocator object + * + */ + ~V1(); + }; + + class V2 + { + private: + class Block + { + public: + int Sanity = 0xA110C; + Block *Next = nullptr; + bool IsFree = true; + V2 *ctx = nullptr; + + Xuint8_t *Data = nullptr; + Xsize_t DataSize = 0; + + void Check(); + Block(Xsize_t Size, V2 *ctx); + ~Block(); + void *operator new(Xsize_t); + void operator delete(void *Address); + } __attribute__((packed, aligned((16)))); + + /* The base address of the virtual memory */ + Xuintptr_t BaseVirtualAddress = 0x0; + + /* The size of the heap */ + Xsize_t HeapSize = 0x0; + + /* The used size of the heap */ + Xsize_t HeapUsed = 0x0; + + Block *FirstBlock = nullptr; + + Xuint8_t *AllocateHeap(Xsize_t Size); + void FreeHeap(Xuint8_t *At, Xsize_t Size); + + Xsize_t Align(Xsize_t Size); + void *FindFreeBlock(Xsize_t Size, + Block *&CurrentBlock); + + public: + /** + * Arrange the blocks to optimize the memory + * usage. + * The allocator is not arranged by default + * to avoid performance issues. + * This function will defragment the memory + * and free the unused blocks. + * + * You should call this function when the + * kernel is idle or when is not using the + * allocator. + */ + void Arrange(); + + /** + * Allocate a new memory block + * + * @param Size Size of the block to allocate. + * @return void* Pointer to the allocated + * block. + */ + void *malloc(Xsize_t Size); + + /** + * Free a previously allocated block + * + * @param Address Address of the block to + * free. + */ + void free(void *Address); + + /** + * Allocate a new memory block + * + * @param NumberOfBlocks Number of blocks + * to allocate. + * @param Size Size of the block to allocate. + * @return void* Pointer to the allocated + * block. + */ + void *calloc(Xsize_t NumberOfBlocks, + Xsize_t Size); + + /** + * Reallocate a previously allocated block + * + * @param Address Address of the block + * to reallocate. + * @param Size New size of the block. + * @return void* Pointer to the reallocated + * block. + */ + void *realloc(void *Address, Xsize_t Size); + + /** + * Construct a new Allocator object + * + * @param VirtualBase Virtual address + * to map the pages. + */ + V2(void *VirtualBase); + + /** + * Destroy the Allocator object + */ + ~V2(); + + friend class Block; + }; } #endif // !__FENNIX_KERNEL_Xalloc_H__ diff --git a/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp b/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp index 46f8d22d..23fcc97f 100644 --- a/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp +++ b/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp @@ -17,7 +17,7 @@ #include "Xalloc.hpp" -Xalloc_def; +XallocV1_def; #define XALLOC_CONCAT(x, y) x##y #define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE) @@ -30,261 +30,261 @@ extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, X extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress); // TODO: Change memcpy with an optimized version -void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length) +void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xsize_t Length) { - unsigned char *dst = (unsigned char *)Destination; - const unsigned char *src = (const unsigned char *)Source; - for (Xuint64_t i = 0; i < Length; i++) - dst[i] = src[i]; - return Destination; + unsigned char *dst = (unsigned char *)Destination; + const unsigned char *src = (const unsigned char *)Source; + for (Xsize_t i = 0; i < Length; i++) + dst[i] = src[i]; + return Destination; } // TODO: Change memset with an optimized version -void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length) +void *Xmemset(void *__restrict__ Destination, int Data, Xsize_t Length) { - unsigned char *Buffer = (unsigned char *)Destination; - for (Xuint64_t i = 0; i < Length; i++) - Buffer[i] = (unsigned char)Data; - return Destination; + unsigned char *Buffer = (unsigned char *)Destination; + for (Xsize_t i = 0; i < Length; i++) + Buffer[i] = (unsigned char)Data; + return Destination; } namespace Xalloc { - class Block - { - public: - void *Address = nullptr; + class Block + { + public: + void *Address = nullptr; - int Sanity = Xalloc_BlockSanityKey; - Xsize_t Size = 0; - Block *Next = nullptr; - Block *Last = nullptr; - bool IsFree = true; + int Sanity = Xalloc_BlockSanityKey; + Xsize_t Size = 0; + Block *Next = nullptr; + Block *Last = nullptr; + bool IsFree = true; - bool Check() - { - if (this->Sanity != Xalloc_BlockSanityKey) - return false; - return true; - } + bool Check() + { + if (this->Sanity != Xalloc_BlockSanityKey) + return false; + return true; + } - Block(Xsize_t Size) - { - this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1)); - this->Size = Size; - Xmemset(this->Address, 0, Size); - } + Block(Xsize_t Size) + { + this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1)); + this->Size = Size; + Xmemset(this->Address, 0, Size); + } - ~Block() - { - Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1)); - } + ~Block() + { + Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1)); + } - /** - * @brief Overload new operator to allocate memory from the heap - * @param Size Unused - * @return void* Pointer to the allocated memory - */ - void *operator new(Xsize_t Size) - { - void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block))); - return ptr; - (void)(Size); - } + /** + * @brief Overload new operator to allocate memory from the heap + * @param Size Unused + * @return void* Pointer to the allocated memory + */ + void *operator new(Xsize_t Size) + { + void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block))); + return ptr; + (void)(Size); + } - /** - * @brief Overload delete operator to free memory from the heap - * @param Address Pointer to the memory to free - */ - void operator delete(void *Address) - { - Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block))); - } - } __attribute__((packed, aligned((16)))); + /** + * @brief Overload delete operator to free memory from the heap + * @param Address Pointer to the memory to free + */ + void operator delete(void *Address) + { + Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block))); + } + } __attribute__((packed, aligned((16)))); - class SmartSMAPClass - { - private: - V1 *allocator = nullptr; + class SmartSMAPClass + { + private: + V1 *allocator = nullptr; - public: - SmartSMAPClass(V1 *allocator) - { - this->allocator = allocator; - this->allocator->Xstac(); - } - ~SmartSMAPClass() { this->allocator->Xclac(); } - }; + public: + SmartSMAPClass(V1 *allocator) + { + this->allocator = allocator; + this->allocator->Xstac(); + } + ~SmartSMAPClass() { this->allocator->Xclac(); } + }; #define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this) - void V1::Xstac() - { - if (this->SMAPUsed) - { + void V1::Xstac() + { + if (this->SMAPUsed) + { #if defined(a86) - asm volatile("stac" :: - : "cc"); + asm volatile("stac" :: + : "cc"); #endif - } - } + } + } - void V1::Xclac() - { - if (this->SMAPUsed) - { + void V1::Xclac() + { + if (this->SMAPUsed) + { #if defined(a86) - asm volatile("clac" :: - : "cc"); + asm volatile("clac" :: + : "cc"); #endif - } - } + } + } - void V1::Arrange() - { - Xalloc_err("Arrange() is not implemented yet!"); - } + void V1::Arrange() + { + Xalloc_err("Arrange() is not implemented yet!"); + } - void *V1::malloc(Xsize_t Size) - { - if (Size == 0) - { - Xalloc_warn("Attempted to allocate 0 bytes!"); - return nullptr; - } + void *V1::malloc(Xsize_t Size) + { + if (Size == 0) + { + Xalloc_warn("Attempted to allocate 0 bytes!"); + return nullptr; + } - SmartSMAP; - Xalloc_lock; + SmartSMAP; + XallocV1_lock; - if (this->FirstBlock == nullptr) - { - this->FirstBlock = new Block(Size); - ((Block *)this->FirstBlock)->IsFree = false; - Xalloc_unlock; - return ((Block *)this->FirstBlock)->Address; - } + if (this->FirstBlock == nullptr) + { + this->FirstBlock = new Block(Size); + ((Block *)this->FirstBlock)->IsFree = false; + XallocV1_unlock; + return ((Block *)this->FirstBlock)->Address; + } - Block *CurrentBlock = ((Block *)this->FirstBlock); - while (CurrentBlock != nullptr) - { - if (!CurrentBlock->Check()) - { - Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", - (Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); - while (Xalloc_StopOnFail) - ; - } - else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size) - { - CurrentBlock->IsFree = false; - Xmemset(CurrentBlock->Address, 0, Size); - Xalloc_unlock; - return CurrentBlock->Address; - } - CurrentBlock = CurrentBlock->Next; - } + Block *CurrentBlock = ((Block *)this->FirstBlock); + while (CurrentBlock != nullptr) + { + if (!CurrentBlock->Check()) + { + Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", + (Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); + while (Xalloc_StopOnFail) + ; + } + else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size) + { + CurrentBlock->IsFree = false; + Xmemset(CurrentBlock->Address, 0, Size); + XallocV1_unlock; + return CurrentBlock->Address; + } + CurrentBlock = CurrentBlock->Next; + } - CurrentBlock = ((Block *)this->FirstBlock); - while (CurrentBlock->Next != nullptr) - CurrentBlock = CurrentBlock->Next; + CurrentBlock = ((Block *)this->FirstBlock); + while (CurrentBlock->Next != nullptr) + CurrentBlock = CurrentBlock->Next; - CurrentBlock->Next = new Block(Size); - ((Block *)CurrentBlock->Next)->Last = CurrentBlock; - ((Block *)CurrentBlock->Next)->IsFree = false; - Xalloc_unlock; - return ((Block *)CurrentBlock->Next)->Address; - } + CurrentBlock->Next = new Block(Size); + ((Block *)CurrentBlock->Next)->Last = CurrentBlock; + ((Block *)CurrentBlock->Next)->IsFree = false; + XallocV1_unlock; + return ((Block *)CurrentBlock->Next)->Address; + } - void V1::free(void *Address) - { - if (Address == nullptr) - { - Xalloc_warn("Attempted to free a null pointer!"); - return; - } + void V1::free(void *Address) + { + if (Address == nullptr) + { + Xalloc_warn("Attempted to free a null pointer!"); + return; + } - SmartSMAP; - Xalloc_lock; + SmartSMAP; + XallocV1_lock; - Block *CurrentBlock = ((Block *)this->FirstBlock); - while (CurrentBlock != nullptr) - { - if (!CurrentBlock->Check()) - { - Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", - (Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); - while (Xalloc_StopOnFail) - ; - } - else if (CurrentBlock->Address == Address) - { - if (CurrentBlock->IsFree) - { - Xalloc_warn("Attempted to free an already freed pointer!"); - Xalloc_unlock; - return; - } + Block *CurrentBlock = ((Block *)this->FirstBlock); + while (CurrentBlock != nullptr) + { + if (!CurrentBlock->Check()) + { + Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", + (Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); + while (Xalloc_StopOnFail) + ; + } + else if (CurrentBlock->Address == Address) + { + if (CurrentBlock->IsFree) + { + Xalloc_warn("Attempted to free an already freed pointer!"); + XallocV1_unlock; + return; + } - CurrentBlock->IsFree = true; - Xalloc_unlock; - return; - } - CurrentBlock = CurrentBlock->Next; - } + CurrentBlock->IsFree = true; + XallocV1_unlock; + return; + } + CurrentBlock = CurrentBlock->Next; + } - Xalloc_err("Invalid address %#lx.", Address); - Xalloc_unlock; - } + Xalloc_err("Invalid address %#lx.", Address); + XallocV1_unlock; + } - void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size) - { - if (NumberOfBlocks == 0 || Size == 0) - { - Xalloc_warn("The %s%s%s is 0!", - NumberOfBlocks == 0 ? "NumberOfBlocks" : "", - NumberOfBlocks == 0 && Size == 0 ? " and " : "", - Size == 0 ? "Size" : ""); - return nullptr; - } + void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size) + { + if (NumberOfBlocks == 0 || Size == 0) + { + Xalloc_warn("The %s%s%s is 0!", + NumberOfBlocks == 0 ? "NumberOfBlocks" : "", + NumberOfBlocks == 0 && Size == 0 ? " and " : "", + Size == 0 ? "Size" : ""); + return nullptr; + } - return this->malloc(NumberOfBlocks * Size); - } + return this->malloc(NumberOfBlocks * Size); + } - void *V1::realloc(void *Address, Xsize_t Size) - { - if (Address == nullptr) - return this->malloc(Size); + void *V1::realloc(void *Address, Xsize_t Size) + { + if (Address == nullptr) + return this->malloc(Size); - if (Size == 0) - { - this->free(Address); - return nullptr; - } + if (Size == 0) + { + this->free(Address); + return nullptr; + } - // SmartSMAP; - // Xalloc_lock; - // ... - // Xalloc_unlock; + // SmartSMAP; + // XallocV1_lock; + // ... + // XallocV1_unlock; - // TODO: Implement realloc - this->free(Address); - return this->malloc(Size); - } + // TODO: Implement realloc + this->free(Address); + return this->malloc(Size); + } - V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled) - { - SmartSMAP; - Xalloc_lock; - this->SMAPUsed = SMAPEnabled; - this->UserMapping = UserMode; - this->BaseVirtualAddress = BaseVirtualAddress; - Xalloc_unlock; - } + V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled) + { + SmartSMAP; + XallocV1_lock; + this->SMAPUsed = SMAPEnabled; + this->UserMapping = UserMode; + this->BaseVirtualAddress = BaseVirtualAddress; + XallocV1_unlock; + } - V1::~V1() - { - SmartSMAP; - Xalloc_lock; - Xalloc_trace("Destructor not implemented yet."); - Xalloc_unlock; - } + V1::~V1() + { + SmartSMAP; + XallocV1_lock; + Xalloc_trace("Destructor not implemented yet."); + XallocV1_unlock; + } } diff --git a/Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp b/Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp new file mode 100644 index 00000000..15063bcd --- /dev/null +++ b/Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp @@ -0,0 +1,281 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "Xalloc.hpp" + +XallocV2_def; + +#define XALLOC_CONCAT(x, y) x##y +#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE) +#define XPtoS(d) ((d)*PAGE_SIZE) + +extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages); +extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages); +extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, + void *PhysicalAddress, + Xsize_t Flags); +extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress); + +#define Xalloc_BlockSanityKey 0xA110C + +/* + [ IN DEVELOPMENT ] +*/ + +namespace Xalloc +{ + void V2::Block::Check() + { + if (unlikely(this->Sanity != Xalloc_BlockSanityKey)) + { + Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", + this, this->Sanity, Xalloc_BlockSanityKey); + + while (Xalloc_StopOnFail) + ; + } + } + + V2::Block::Block(Xsize_t Size, V2 *ctx) + { + this->ctx = ctx; + this->Data = ctx->AllocateHeap(Size); + this->DataSize = Size; + } + + V2::Block::~Block() + { + } + + void *V2::Block::operator new(Xsize_t) + { + constexpr Xsize_t bPgs = XStoP(sizeof(Block)); + void *ptr = Xalloc_REQUEST_PAGES(bPgs); + /* TODO: Do something with the rest of + the allocated memory */ + return ptr; + } + + void V2::Block::operator delete(void *Address) + { + constexpr Xsize_t bPgs = XStoP(sizeof(Block)); + Xalloc_FREE_PAGES(Address, bPgs); + } + + /* ========================================= */ + + Xuint8_t *V2::AllocateHeap(Xsize_t Size) + { + Size = this->Align(Size); + Xsize_t Pages = XStoP(Size); + + Xuint8_t *FinalAddress = 0x0; + if (this->HeapUsed + Size >= this->HeapSize) + { + void *Address = Xalloc_REQUEST_PAGES(Pages); + void *VirtualAddress = (void *)(this->BaseVirtualAddress + this->HeapSize); + if (Xalloc_MapPages) + { + for (Xsize_t i = 0; i < Pages; i++) + { + Xuintptr_t Page = i * Xalloc_PAGE_SIZE; + void *vAddress = (void *)((Xuintptr_t)VirtualAddress + Page); + Xalloc_MAP_MEMORY(vAddress, (void *)((Xuintptr_t)Address + Page), 0x3); + } + } + + this->HeapSize += XPtoS(Pages); + FinalAddress = (Xuint8_t *)VirtualAddress; + } + else + FinalAddress = (Xuint8_t *)(this->BaseVirtualAddress + this->HeapUsed); + + this->HeapUsed += Size; + return (uint8_t *)FinalAddress; + } + + void V2::FreeHeap(Xuint8_t *At, Xsize_t Size) + { + Xsize_t Pages = XStoP(Size); + + if (Xalloc_MapPages) + { + for (Xsize_t i = 0; i < Pages; i++) + { + Xuintptr_t Page = i * Xalloc_PAGE_SIZE; + void *VirtualAddress = (void *)((Xuintptr_t)At + Page); + Xalloc_UNMAP_MEMORY(VirtualAddress); + } + } + + Xalloc_FREE_PAGES(At, Pages); + this->HeapUsed -= Size; + } + + Xsize_t V2::Align(Xsize_t Size) + { + return (Size + 0xF) & ~0xF; + } + + void *V2::FindFreeBlock(Xsize_t Size, Block *&CurrentBlock) + { + if (this->FirstBlock == nullptr) + { + this->FirstBlock = new Block(Size, this); + this->FirstBlock->IsFree = false; + return this->FirstBlock->Data; + } + + while (true) + { + CurrentBlock->Check(); + + /* FIXME: This will waste a lot of space + need better algorithm */ + if (CurrentBlock->IsFree && + CurrentBlock->DataSize >= Size) + { + CurrentBlock->IsFree = false; + return CurrentBlock->Data; + } + + if (CurrentBlock->Next == nullptr) + break; + + CurrentBlock = CurrentBlock->Next; + } + + return nullptr; + } + + void V2::Arrange() + { + Xalloc_err("Arrange() is not implemented yet!"); + } + + void *V2::malloc(Xsize_t Size) + { + if (Size == 0) + { + Xalloc_warn("Attempted to allocate 0 bytes!"); + return nullptr; + } + + XallocV2_lock; + Block *CurrentBlock = this->FirstBlock; + void *ret = this->FindFreeBlock(Size, CurrentBlock); + if (ret) + { + XallocV2_unlock; + return ret; + } + + CurrentBlock->Next = new Block(Size, this); + CurrentBlock->Next->IsFree = false; + XallocV2_unlock; + return CurrentBlock->Next->Data; + } + + void V2::free(void *Address) + { + if (Address == nullptr) + { + Xalloc_warn("Attempted to free a null pointer!"); + return; + } + + XallocV2_lock; + + Block *CurrentBlock = ((Block *)this->FirstBlock); + while (CurrentBlock != nullptr) + { + CurrentBlock->Check(); + + if (CurrentBlock->Data == Address) + { + if (CurrentBlock->IsFree) + Xalloc_warn("Attempted to free an already freed block! %#lx", Address); + + CurrentBlock->IsFree = true; + XallocV2_unlock; + return; + } + CurrentBlock = CurrentBlock->Next; + } + + Xalloc_err("Invalid address %#lx.", Address); + XallocV2_unlock; + } + + void *V2::calloc(Xsize_t NumberOfBlocks, Xsize_t Size) + { + if (NumberOfBlocks == 0 || Size == 0) + { + Xalloc_warn("The %s%s%s is 0!", + NumberOfBlocks == 0 ? "NumberOfBlocks" : "", + NumberOfBlocks == 0 && Size == 0 ? " and " : "", + Size == 0 ? "Size" : ""); + return nullptr; + } + + return this->malloc(NumberOfBlocks * Size); + } + + void *V2::realloc(void *Address, Xsize_t Size) + { + if (Address == nullptr && Size != 0) + return this->malloc(Size); + + if (Size == 0) + { + this->free(Address); + return nullptr; + } + + // XallocV2_lock; + // ... + // XallocV2_unlock; + + // TODO: Implement realloc + static int once = 0; + if (!once++) + Xalloc_trace("realloc is stub!"); + this->free(Address); + return this->malloc(Size); + } + + V2::V2(void *VirtualBase) + { + if (VirtualBase == 0x0 && Xalloc_MapPages) + { + Xalloc_err("VirtualBase is 0x0 and Xalloc_MapPages is true!"); + while (true) + ; + } + + XallocV2_lock; + this->BaseVirtualAddress = Xuintptr_t(VirtualBase); + XallocV2_unlock; + } + + V2::~V2() + { + XallocV2_lock; + Xalloc_trace("Destructor not implemented yet."); + XallocV2_unlock; + } +} diff --git a/Library/liballoc_1_1.c b/Core/Memory/HeapAllocators/liballoc_1_1/liballoc_1_1.c similarity index 100% rename from Library/liballoc_1_1.c rename to Core/Memory/HeapAllocators/liballoc_1_1/liballoc_1_1.c diff --git a/Library/liballoc_1_1.h b/Core/Memory/HeapAllocators/liballoc_1_1/liballoc_1_1.h similarity index 100% rename from Library/liballoc_1_1.h rename to Core/Memory/HeapAllocators/liballoc_1_1/liballoc_1_1.h diff --git a/Core/Memory/HeapAllocators/liballoc_1_1/liballoc_hooks.cpp b/Core/Memory/HeapAllocators/liballoc_1_1/liballoc_hooks.cpp new file mode 100644 index 00000000..ea09bf8f --- /dev/null +++ b/Core/Memory/HeapAllocators/liballoc_1_1/liballoc_hooks.cpp @@ -0,0 +1,26 @@ +#include +#include +#include + +NewLock(liballocLock); + +EXTERNC int liballoc_lock() +{ + return liballocLock.Lock(__FUNCTION__); +} + +EXTERNC int liballoc_unlock() +{ + return liballocLock.Unlock(); +} + +EXTERNC void *liballoc_alloc(size_t Pages) +{ + return KernelAllocator.RequestPages(Pages); +} + +EXTERNC int liballoc_free(void *Address, size_t Pages) +{ + KernelAllocator.FreePages(Address, Pages); + return 0; +} diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 15771c4f..976ab94e 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -25,10 +25,9 @@ #endif #include "HeapAllocators/Xalloc/Xalloc.hpp" -#include "../Library/liballoc_1_1.h" +#include "HeapAllocators/liballoc_1_1/liballoc_1_1.h" #include "../../kernel.h" -// #define DEBUG_ALLOCATIONS_SL 1 // #define DEBUG_ALLOCATIONS 1 #ifdef DEBUG_ALLOCATIONS @@ -39,11 +38,6 @@ #define memdbg(m, ...) #endif -#ifdef DEBUG_ALLOCATIONS_SL -NewLock(AllocatorLock); -NewLock(OperatorAllocatorLock); -#endif - using namespace Memory; Physical KernelAllocator; @@ -53,6 +47,7 @@ bool PSESupport = false; MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages; Xalloc::V1 *XallocV1Allocator = nullptr; +Xalloc::V2 *XallocV2Allocator = nullptr; #ifdef DEBUG NIF void tracepagetable(PageTable *pt) @@ -119,27 +114,6 @@ NIF void MapFramebuffer(PageTable *PT) (size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height), PTFlag::RW | PTFlag::US | PTFlag::G); itrfb++; - -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Framebuffer[itrfb].BaseAddress, - (bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height) + PAGE_SIZE); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } } @@ -253,37 +227,6 @@ NIF void MapKernel(PageTable *PT) KernelAllocator.ReservePage((void *)k); } } - -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Kernel.PhysicalBase, - bInfo.Kernel.Size); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Kernel.VirtualBase, - bInfo.Kernel.Size); - mExtTrkLock.Unlock(); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - } -#endif } NIF void InitializeMemoryManagement() @@ -404,20 +347,22 @@ NIF void InitializeMemoryManagement() CPU::PageTable(KernelPageTable); debug("Page table updated."); - /* FIXME: Read kernel config */ XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false); - AllocatorType = MemoryAllocatorType::XallocV1; - trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator); + XallocV2Allocator = new Xalloc::V2((void *)KERNEL_HEAP_BASE); + trace("XallocV1 Allocator initialized at %#lx", XallocV1Allocator); + trace("XallocV2 Allocator initialized at %#lx", XallocV2Allocator); + + /* FIXME: Read kernel config */ + AllocatorType = MemoryAllocatorType::liballoc11; } void *malloc(size_t Size) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("malloc(%d)->[%s]", Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); void *ret = nullptr; switch (AllocatorType) @@ -425,7 +370,6 @@ void *malloc(size_t Size) case MemoryAllocatorType::Pages: { ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); - memset(ret, 0, Size); break; } case MemoryAllocatorType::XallocV1: @@ -433,10 +377,14 @@ void *malloc(size_t Size) ret = XallocV1Allocator->malloc(Size); break; } + case MemoryAllocatorType::XallocV2: + { + ret = XallocV2Allocator->malloc(Size); + break; + } case MemoryAllocatorType::liballoc11: { ret = PREFIX(malloc)(Size); - memset(ret, 0, Size); break; } default: @@ -445,26 +393,8 @@ void *malloc(size_t Size) CPU::Stop(); } } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif + + memset(ret, 0, Size); return ret; } @@ -472,10 +402,9 @@ void *calloc(size_t n, size_t Size) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("calloc(%d, %d)->[%s]", n, Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); void *ret = nullptr; switch (AllocatorType) @@ -483,7 +412,6 @@ void *calloc(size_t n, size_t Size) case MemoryAllocatorType::Pages: { ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1)); - memset(ret, 0, n * Size); break; } case MemoryAllocatorType::XallocV1: @@ -491,10 +419,14 @@ void *calloc(size_t n, size_t Size) ret = XallocV1Allocator->calloc(n, Size); break; } + case MemoryAllocatorType::XallocV2: + { + ret = XallocV2Allocator->calloc(n, Size); + break; + } case MemoryAllocatorType::liballoc11: { void *ret = PREFIX(calloc)(n, Size); - memset(ret, 0, Size); return ret; } default: @@ -503,26 +435,8 @@ void *calloc(size_t n, size_t Size) CPU::Stop(); } } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r", - n, Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif + + memset(ret, 0, n * Size); return ret; } @@ -530,10 +444,9 @@ void *realloc(void *Address, size_t Size) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("realloc(%#lx, %d)->[%s]", Address, Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); void *ret = nullptr; switch (AllocatorType) @@ -541,7 +454,6 @@ void *realloc(void *Address, size_t Size) case unlikely(MemoryAllocatorType::Pages): { ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak - memset(ret, 0, Size); break; } case MemoryAllocatorType::XallocV1: @@ -549,10 +461,14 @@ void *realloc(void *Address, size_t Size) ret = XallocV1Allocator->realloc(Address, Size); break; } + case MemoryAllocatorType::XallocV2: + { + ret = XallocV2Allocator->realloc(Address, Size); + break; + } case MemoryAllocatorType::liballoc11: { void *ret = PREFIX(realloc)(Address, Size); - memset(ret, 0, Size); return ret; } default: @@ -561,26 +477,8 @@ void *realloc(void *Address, size_t Size) CPU::Stop(); } } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r", - Address, Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif + + memset(ret, 0, Size); return ret; } @@ -588,10 +486,9 @@ void free(void *Address) { assert(Address != nullptr); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("free(%#lx)->[%s]", Address, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); switch (AllocatorType) { @@ -605,6 +502,11 @@ void free(void *Address) XallocV1Allocator->free(Address); break; } + case MemoryAllocatorType::XallocV2: + { + XallocV2Allocator->free(Address); + break; + } case MemoryAllocatorType::liballoc11: { PREFIX(free) @@ -617,58 +519,17 @@ void free(void *Address) CPU::Stop(); } } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "free( %p )~%p\n\r", - Address, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } void *operator new(std::size_t Size) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("new(%d)->[%s]", Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif return ret; } @@ -676,32 +537,11 @@ void *operator new[](std::size_t Size) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("new[](%d)->[%s]", Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif return ret; } @@ -709,39 +549,14 @@ void *operator new(std::size_t Size, std::align_val_t Alignment) { assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - fixme("operator new with alignment(%#lx) is not implemented", Alignment); + memdbg("new(%d, %d)->[%s]", Size, Alignment, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + + fixme("operator new with alignment(%#lx) is not implemented", + Alignment); void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); -#if defined(a64) || defined(aa64) - sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r", - Size, (uintptr_t)Alignment, - ret, __builtin_return_address(0)); -#elif defined(a32) - sprintf(mExtTrkLog, "new( %ld %#x )=%p~%p\n\r", - Size, (uintptr_t)Alignment, - ret, __builtin_return_address(0)); -#endif - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif return ret; } @@ -749,64 +564,22 @@ void operator delete(void *Pointer) { assert(Pointer != nullptr); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("delete(%#lx)->[%s]", Pointer, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); free(Pointer); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete( %p )~%p\n\r", - Pointer, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } void operator delete[](void *Pointer) { assert(Pointer != nullptr); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("delete[](%#lx)->[%s]", Pointer, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); free(Pointer); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r", - Pointer, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } void operator delete(void *Pointer, long unsigned int Size) @@ -814,32 +587,12 @@ void operator delete(void *Pointer, long unsigned int Size) assert(Pointer != nullptr); assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("delete(%#lx, %d)->[%s]", + Pointer, Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); free(Pointer); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r", - Pointer, Size, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } void operator delete[](void *Pointer, long unsigned int Size) @@ -847,30 +600,10 @@ void operator delete[](void *Pointer, long unsigned int Size) assert(Pointer != nullptr); assert(Size > 0); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + memdbg("delete[](%#lx, %d)->[%s]", + Pointer, Size, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); free(Pointer); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r", - Pointer, Size, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } diff --git a/Core/Memory/MemoryManager.cpp b/Core/Memory/MemoryManager.cpp index 5e01d87e..f8b46ad3 100644 --- a/Core/Memory/MemoryManager.cpp +++ b/Core/Memory/MemoryManager.cpp @@ -24,7 +24,7 @@ namespace Memory { ReadFSFunction(MEM_Read) { - if (!Size) + if (Size <= 0) Size = node->Length; if (RefOffset > node->Length) @@ -39,7 +39,7 @@ namespace Memory WriteFSFunction(MEM_Write) { - if (!Size) + if (Size <= 0) Size = node->Length; if (RefOffset > node->Length) diff --git a/Core/Memory/PageMapIndexer.cpp b/Core/Memory/PageMapIndexer.cpp index ccf7f906..98270e6e 100644 --- a/Core/Memory/PageMapIndexer.cpp +++ b/Core/Memory/PageMapIndexer.cpp @@ -19,25 +19,36 @@ namespace Memory { - Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress) - { + Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress) + { + uintptr_t Address = VirtualAddress; #if defined(a64) - uintptr_t Address = VirtualAddress; - Address >>= 12; - this->PTEIndex = Address & 0x1FF; - Address >>= 9; - this->PDEIndex = Address & 0x1FF; - Address >>= 9; - this->PDPTEIndex = Address & 0x1FF; - Address >>= 9; - this->PMLIndex = Address & 0x1FF; + Address >>= 12; + this->PTEIndex = Address & 0x1FF; + Address >>= 9; + this->PDEIndex = Address & 0x1FF; + Address >>= 9; + this->PDPTEIndex = Address & 0x1FF; + Address >>= 9; + this->PMLIndex = Address & 0x1FF; #elif defined(a32) - uintptr_t Address = VirtualAddress; - Address >>= 12; - this->PTEIndex = Address & 0x3FF; - Address >>= 10; - this->PDEIndex = Address & 0x3FF; + Address >>= 12; + this->PTEIndex = Address & 0x3FF; + Address >>= 10; + this->PDEIndex = Address & 0x3FF; #elif defined(aa64) #endif - } + + if (VirtualAddress > PAGE_SIZE) + { + assert( + this->PTEIndex != 0 || + this->PDEIndex != 0 +#if defined(a64) + || this->PDPTEIndex != 0 || + this->PMLIndex != 0 +#endif + ); + } + } } diff --git a/Core/Memory/PageTable.cpp b/Core/Memory/PageTable.cpp index 9970c35f..14e3a023 100644 --- a/Core/Memory/PageTable.cpp +++ b/Core/Memory/PageTable.cpp @@ -1,20 +1,41 @@ #include +#include + namespace Memory { - void PageTable::Update() - { + void PageTable::Update() + { #if defined(a86) - asmv("mov %0, %%cr3" ::"r"(this)); + asmv("mov %0, %%cr3" ::"r"(this)); #elif defined(aa64) - asmv("msr ttbr0_el1, %0" ::"r"(this)); + asmv("msr ttbr0_el1, %0" ::"r"(this)); #endif - } + } - PageTable PageTable::Fork() - { - PageTable NewTable; - memcpy(&NewTable, this, sizeof(PageTable)); - return NewTable; - } + PageTable PageTable::Fork() + { + PageTable NewTable; + memcpy(&NewTable, this, sizeof(PageTable)); + return NewTable; + } + + template + T PageTable::Get(T Address) + { + Virtual vmm = Virtual(this); + void *PhysAddr = vmm.GetPhysical((void *)Address); + uintptr_t Diff = uintptr_t(Address); + Diff &= 0xFFF; + Diff = uintptr_t(PhysAddr) + Diff; + return (T)Diff; + } + + /* Templates */ + template struct stat *PageTable::Get(struct stat *); + template const char *PageTable::Get(const char *); + template const void *PageTable::Get(const void *); + template uintptr_t PageTable::Get(uintptr_t); + template void *PageTable::Get(void *); + /* ... */ } diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index b12327e9..acda70ea 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -88,25 +88,6 @@ namespace Memory continue; this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r", - (void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif return (void *)(PageBitmapIndex * PAGE_SIZE); } @@ -152,26 +133,6 @@ namespace Memory } this->LockPages((void *)(Index * PAGE_SIZE), Count); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r", - Count, - (void *)(Index * PAGE_SIZE), __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif return (void *)(Index * PAGE_SIZE); NextPage: @@ -228,26 +189,6 @@ namespace Memory PageBitmapIndex = Index; } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r", - Address, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif } void Physical::FreePages(void *Address, size_t Count) @@ -257,26 +198,6 @@ namespace Memory warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : ""); return; } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r", - Address, Count, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif for (size_t t = 0; t < Count; t++) this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE))); } diff --git a/Core/Memory/ProgramBreak.cpp b/Core/Memory/ProgramBreak.cpp new file mode 100644 index 00000000..9c2b5a46 --- /dev/null +++ b/Core/Memory/ProgramBreak.cpp @@ -0,0 +1,98 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include + +#include + +namespace Memory +{ + void *ProgramBreak::brk(void *Address) + { + if (HeapStart == 0x0 || Break == 0x0) + { + error("HeapStart or Break is 0x0"); + return (void *)-EAGAIN; + } + + /* Get the current program break. */ + if (Address == nullptr) + return (void *)Break; + + /* Check if the address is valid. */ + if (Address < (void *)HeapStart) + return (void *)-ENOMEM; + + Virtual vmm = Virtual(this->Table); + + if (Address > (void *)Break) + { + /* Allocate more memory. */ + size_t Pages = TO_PAGES(uintptr_t(Address) - Break); + void *Allocated = mm->RequestPages(Pages); + if (Allocated == nullptr) + return (void *)-ENOMEM; + + /* Map the allocated pages. */ + for (size_t i = 0; i < Pages; i++) + { + void *VirtAddr = (void *)(Break + (i * PAGE_SIZE)); + void *PhysAddr = (void *)(uintptr_t(Allocated) + (i * PAGE_SIZE)); + vmm.Map(VirtAddr, PhysAddr, RW | US); + } + + Break = (uint64_t)Address; + return (void *)Break; + } + else if (Address < (void *)Break) + { + /* Free memory. */ + size_t Pages = TO_PAGES(uintptr_t(Address) - Break); + mm->FreePages((void *)Break, Pages); + + /* Unmap the freed pages. */ + for (size_t i = 0; i < Pages; i++) + { + uint64_t Page = Break - (i * 0x1000); + vmm.Unmap((void *)Page); + } + + Break = (uint64_t)Address; + return (void *)Break; + } + + assert(false); + } + + ProgramBreak::ProgramBreak(PageTable *Table, MemMgr *mm) + { + assert(Table != nullptr); + assert(mm != nullptr); + + this->Table = Table; + this->mm = mm; + } + + ProgramBreak::~ProgramBreak() + { + /* Do nothing because MemMgr + will be destroyed later. */ + } +} diff --git a/Core/Time/TimeStampCounter.cpp b/Core/Time/TimeStampCounter.cpp index 7a26ac29..90e192b0 100644 --- a/Core/Time/TimeStampCounter.cpp +++ b/Core/Time/TimeStampCounter.cpp @@ -66,9 +66,9 @@ namespace Time { #if defined(a86) fixme(""); // FIXME: This is not a good way to measure the clock speed - size_t Start = CPU::Counter(); + uint64_t Start = CPU::Counter(); TimeManager->Sleep(1, Units::Milliseconds); - size_t End = CPU::Counter(); + uint64_t End = CPU::Counter(); this->clk = End - Start; this->ClassCreationTime = this->GetCounter(); diff --git a/Core/Video/Display.cpp b/Core/Video/Display.cpp index 39e17f70..0e35743f 100644 --- a/Core/Video/Display.cpp +++ b/Core/Video/Display.cpp @@ -253,28 +253,22 @@ namespace Video this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10); else this->Buffers[Index].Color = 0xFFFFFF; - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); this->ColorPickerIteration++; if (this->ColorPickerIteration == 6) { this->ColorPickerIteration = 0; - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']'); this->ColorIteration = false; } return Char; } - if (WriteToUART) + if (WriteToUART && Char != '\e') UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); switch (Char) { case '\e': { - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('['); this->ColorIteration = true; return Char; } diff --git a/ExecutionLayer/Elf/ElfLoader.cpp b/ExecutionLayer/Elf/ElfLoader.cpp index 4e1d0c7e..708a1670 100644 --- a/ExecutionLayer/Elf/ElfLoader.cpp +++ b/ExecutionLayer/Elf/ElfLoader.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,57 @@ using namespace VirtualFileSystem; namespace Execute { + void ELFObject::GenerateAuxiliaryVector_x86_32(Memory::MemMgr *mm, + int fd, + Elf32_Ehdr ELFHeader, + uint32_t EntryPoint, + uint32_t BaseAddress) + { + } + + void ELFObject::GenerateAuxiliaryVector_x86_64(Memory::MemMgr *mm, + int fd, + Elf64_Ehdr ELFHeader, + uint64_t EntryPoint, + uint64_t BaseAddress) + { + char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ + strcpy(aux_platform, "x86_64"); + + std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd); + void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true); + strcpy((char *)execfn_str, execfn.c_str()); + void *at_random = mm->RequestPages(1, true); + *(uint64_t *)at_random = Random::rand16(); + + // prep. for AT_PHDR + void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true); + lseek(fd, ELFHeader.e_phoff, SEEK_SET); + fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr)); + + Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}}); + // AT_HWCAP2 26 + Elfauxv.push_back({.archaux = {.a_type = AT_RANDOM, .a_un = {.a_val = (uint64_t)at_random}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_SECURE, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); + // AT_FLAGS 8 + Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); + // AT_CLKTCK 17 + Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + // AT_HWCAP 16 + // AT_MINSIGSTKSZ 51 + // AT_SYSINFO_EHDR 33 + } + void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess) { stub; @@ -104,10 +156,10 @@ namespace Execute Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable); Memory::MemMgr *mm = TargetProcess->Memory; - uint64_t BaseAddress = 0; /* Copy segments into memory */ { + Elf64_Phdr ProgramBreakHeader{}; Elf64_Phdr ProgramHeader; for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) { @@ -129,9 +181,6 @@ namespace Execute debug("Mapped %#lx to %#lx", SegmentDestination, pAddr); - if (BaseAddress == 0) - BaseAddress = (uintptr_t)SegmentDestination; - debug("Copying segment to p: %#lx-%#lx; v: %#lx-%#lx (%ld file bytes, %ld mem bytes)", pAddr, uintptr_t(pAddr) + ProgramHeader.p_memsz, SegmentDestination, uintptr_t(SegmentDestination) + ProgramHeader.p_memsz, @@ -148,6 +197,7 @@ namespace Execute void *zAddr = (void *)(uintptr_t(pAddr) + ProgramHeader.p_filesz); memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); } + ProgramBreakHeader = ProgramHeader; break; } default: @@ -158,6 +208,13 @@ namespace Execute } } } + + /* Set program break */ + uintptr_t ProgramBreak = ROUND_UP(ProgramBreakHeader.p_vaddr + + ProgramBreakHeader.p_memsz, + PAGE_SIZE); + + TargetProcess->ProgramBreak->InitBrk(ProgramBreak); } struct stat statbuf; @@ -169,39 +226,8 @@ namespace Execute debug("Entry Point: %#lx", EntryPoint); - char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ - strcpy(aux_platform, "x86_64"); - - std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd); - void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true); - strcpy((char *)execfn_str, execfn.c_str()); - - // prep. for AT_PHDR - void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true); - lseek(fd, ELFHeader.e_phoff, SEEK_SET); - fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr)); - - Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}}); - // AT_HWCAP2 26 - // AT_RANDOM 25 - // AT_SECURE 23 - Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); - // AT_FLAGS 8 - Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); - // AT_CLKTCK 17 - Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - // AT_HWCAP 16 - // AT_MINSIGSTKSZ 51 - // AT_SYSINFO_EHDR 33 + this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader, + EntryPoint, 0); this->ip = EntryPoint; this->IsElfValid = true; @@ -282,6 +308,7 @@ namespace Execute /* Copy segments into memory */ { + Elf64_Phdr ProgramBreakHeader{}; Elf64_Phdr ProgramHeader; std::size_t SegmentsSize = 0; for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) @@ -336,6 +363,7 @@ namespace Execute void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz); memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); } + ProgramBreakHeader = ProgramHeader; break; } case PT_DYNAMIC: @@ -373,6 +401,14 @@ namespace Execute } } } + + /* Set program break */ + uintptr_t ProgramBreak = ROUND_UP(BaseAddress + + ProgramBreakHeader.p_vaddr + + ProgramBreakHeader.p_memsz, + PAGE_SIZE); + + TargetProcess->ProgramBreak->InitBrk(ProgramBreak); } EntryPoint += BaseAddress; @@ -578,39 +614,8 @@ namespace Execute debug("Entry Point: %#lx", EntryPoint); - char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ - strcpy(aux_platform, "x86_64"); - - std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd); - void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true); - strcpy((char *)execfn_str, execfn.c_str()); - - // prep. for AT_PHDR - void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true); - lseek(fd, ELFHeader.e_phoff, SEEK_SET); - fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr)); - - Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}}); - // AT_HWCAP2 26 - // AT_RANDOM 25 - // AT_SECURE 23 - Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ - Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); - // AT_FLAGS 8 - Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); - Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); - // AT_CLKTCK 17 - Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - // AT_HWCAP 16 - // AT_MINSIGSTKSZ 51 - // AT_SYSINFO_EHDR 33 + this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader, + EntryPoint, BaseAddress); this->ip = EntryPoint; this->IsElfValid = true; diff --git a/ExecutionLayer/Spawn.cpp b/ExecutionLayer/Spawn.cpp index b067ad0a..4e9167d6 100644 --- a/ExecutionLayer/Spawn.cpp +++ b/ExecutionLayer/Spawn.cpp @@ -33,7 +33,8 @@ namespace Execute { int Spawn(char *Path, const char **argv, const char **envp, Tasking::PCB *Parent, - Tasking::TaskCompatibility Compatibility) + Tasking::TaskCompatibility Compatibility, + bool Critical) { int fd = fopen(Path, "r"); if (fd < 0) @@ -141,11 +142,16 @@ namespace Execute return -ENOEXEC; } - TCB *Thread = TaskManager->CreateThread(Process, - obj->InstructionPointer, - obj->argv, obj->envp, obj->auxv, - Arch, - Compatibility); + TCB *Thread = nullptr; + { + CriticalSection cs; + Thread = TaskManager->CreateThread(Process, + obj->InstructionPointer, + obj->argv, obj->envp, obj->auxv, + Arch, + Compatibility); + Thread->SetCritical(true); + } fclose(fd); return Thread->ID; } diff --git a/FileSystem/FS/ustar.cpp b/FileSystem/FS/ustar.cpp index 51fe5751..56a84fb9 100644 --- a/FileSystem/FS/ustar.cpp +++ b/FileSystem/FS/ustar.cpp @@ -26,7 +26,7 @@ namespace VirtualFileSystem { ReadFSFunction(USTAR_Read) { - if (!Size) + if (Size <= 0) Size = node->Length; if (RefOffset > node->Length) diff --git a/FileSystem/FileDescriptor.cpp b/FileSystem/FileDescriptor.cpp index 443d1d8f..0641c977 100644 --- a/FileSystem/FileDescriptor.cpp +++ b/FileSystem/FileDescriptor.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,7 @@ namespace VirtualFileSystem { ReadFSFunction(fd_Read) { - if (!Size) + if (Size <= 0) Size = node->Length; if (RefOffset > node->Length) @@ -45,7 +46,7 @@ namespace VirtualFileSystem WriteFSFunction(fd_Write) { - if (!Size) + if (Size <= 0) Size = node->Length; if (RefOffset > node->Length) @@ -64,15 +65,32 @@ namespace VirtualFileSystem // .Write = fd_Write, }; - FileDescriptorTable::FileDescriptor + FileDescriptorTable::Fildes FileDescriptorTable::GetFileDescriptor(int FileDescriptor) { foreach (auto fd in FileDescriptors) { if (fd.Descriptor == FileDescriptor) + { + debug("Found file descriptor %d", FileDescriptor); return fd; + } } - return {.Descriptor = -1}; + return {}; + } + + FileDescriptorTable::DupFildes + FileDescriptorTable::GetDupFildes(int FileDescriptor) + { + foreach (auto fd in FildesDuplicates) + { + if (fd.Descriptor == FileDescriptor) + { + debug("Found duplicated file descriptor %d", FileDescriptor); + return fd; + } + } + return {}; } int FileDescriptorTable::ProbeMode(mode_t Mode, int Flags) @@ -118,9 +136,8 @@ namespace VirtualFileSystem if (!n) { - error("Failed to create file %s: %d", - AbsolutePath, errno); - return -1; + debug("%s: File already exists, continuing...", + AbsolutePath); } } @@ -132,23 +149,25 @@ namespace VirtualFileSystem if (!File) { errno = EEXIST; + error("Failed to open file %s: %d", + AbsolutePath, errno); return -1; } } if (Flags & O_TRUNC) { - fixme("Implement O_TRUNC"); + fixme("O_TRUNC"); } if (Flags & O_APPEND) { - fixme("Implement O_APPEND"); + fixme("O_APPEND"); } if (Flags & O_CLOEXEC) { - fixme("Implement O_CLOEXEC"); + fixme("O_CLOEXEC"); } RefNode *File = vfs->Open(AbsolutePath, @@ -161,8 +180,7 @@ namespace VirtualFileSystem return -1; } - FileDescriptorTable::FileDescriptor fd; - fd.Descriptor = GetFreeFileDescriptor(); + Fildes fd = {.Descriptor = GetFreeFileDescriptor()}; if (fd.Descriptor < 0) { @@ -205,6 +223,19 @@ namespace VirtualFileSystem } } + forItr(itr, FildesDuplicates) + { + if (itr->Descriptor == FileDescriptor) + { + FildesDuplicates.erase(itr); + + char FileName[64]; + sprintf(FileName, "%d", FileDescriptor); + vfs->Delete(FileName, false, this->fdDir); + return 0; + } + } + errno = EBADF; return -1; } @@ -223,6 +254,19 @@ namespace VirtualFileSystem break; } } + + if (!Found) + { + foreach (auto fd in FildesDuplicates) + { + if (fd.Descriptor == i) + { + Found = true; + break; + } + } + } + if (!Found) return i; i++; @@ -234,12 +278,20 @@ namespace VirtualFileSystem std::string FileDescriptorTable::GetAbsolutePath(int FileDescriptor) { - FileDescriptorTable::FileDescriptor fd = - this->GetFileDescriptor(FileDescriptor); - if (fd.Descriptor == -1) + Fildes fd = this->GetFileDescriptor(FileDescriptor); + DupFildes dfd = this->GetDupFildes(FileDescriptor); + + if (fd.Descriptor == -1 && + dfd.Descriptor == -1) return ""; - Node *node = fd.Handle->node; + RefNode *hnd = nullptr; + if (fd.Descriptor != -1) + hnd = fd.Handle; + else + hnd = dfd.Handle; + + Node *node = hnd->node; std::string absolutePath = vfs->GetPathFromNode(node); std::string path = absolutePath.c_str(); return path; @@ -264,36 +316,52 @@ namespace VirtualFileSystem ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count) { - FileDescriptor fdesc; - fdesc = this->GetFileDescriptor(fd); - - if (fdesc.Descriptor < 0) + Fildes fdesc = this->GetFileDescriptor(fd); + DupFildes dfdesc = this->GetDupFildes(fd); + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) { errno = EBADF; return -1; } - return fdesc.Handle->Read((uint8_t *)buf, count); + RefNode *hnd = nullptr; + if (fdesc.Descriptor != -1) + hnd = fdesc.Handle; + else + hnd = dfdesc.Handle; + + return hnd->Read((uint8_t *)buf, count); } ssize_t FileDescriptorTable::_write(int fd, const void *buf, size_t count) { - FileDescriptor fdesc; - fdesc = this->GetFileDescriptor(fd); - - if (fdesc.Descriptor < 0) + Fildes fdesc = this->GetFileDescriptor(fd); + DupFildes dfdesc = this->GetDupFildes(fd); + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) + { + errno = EBADF; return -1; + } - return fdesc.Handle->Write((uint8_t *)buf, count); + RefNode *hnd = nullptr; + if (fdesc.Descriptor != -1) + hnd = fdesc.Handle; + else + hnd = dfdesc.Handle; + + return hnd->Write((uint8_t *)buf, count); } int FileDescriptorTable::_close(int fd) { - FileDescriptor fdesc; - fdesc = this->GetFileDescriptor(fd); + Fildes fdesc = this->GetFileDescriptor(fd); + DupFildes dfdesc = this->GetDupFildes(fd); - if (fdesc.Descriptor < 0) + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) { errno = EBADF; return -1; @@ -305,22 +373,61 @@ namespace VirtualFileSystem return -1; } - delete fdesc.Handle; + /* If the file descriptor is a duplicate, + we don't need to close the handle, + because it's a duplicate of another + file descriptor. */ + + bool Found = false; + RefNode *hnd = nullptr; + + if (fdesc.Descriptor != -1) + hnd = fdesc.Handle; + else + hnd = dfdesc.Handle; + + foreach (auto dfd in FileDescriptors) + { + if (dfd.Handle == hnd) + { + Found = true; + break; + } + } + + foreach (auto dfd in FildesDuplicates) + { + if (dfd.Handle == hnd) + { + Found = true; + break; + } + } + + if (!Found) + delete hnd; return 0; } off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence) { - FileDescriptor fdesc; - fdesc = this->GetFileDescriptor(fd); + Fildes fdesc = this->GetFileDescriptor(fd); + DupFildes dfdesc = this->GetDupFildes(fd); - if (fdesc.Descriptor < 0) + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) { errno = EBADF; return -1; } - return fdesc.Handle->Seek(offset, whence); + RefNode *hnd = nullptr; + if (fdesc.Descriptor != -1) + hnd = fdesc.Handle; + else + hnd = dfdesc.Handle; + + return hnd->Seek(offset, whence); } int FileDescriptorTable::_stat(const char *pathname, @@ -353,22 +460,29 @@ namespace VirtualFileSystem statbuf->st_size = node->Length; statbuf->st_blksize = 0; /* FIXME: stub */ statbuf->st_blocks = 0; /* FIXME: stub */ - statbuf->st_attr = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ return 0; } int FileDescriptorTable::_fstat(int fd, struct stat *statbuf) { - FileDescriptor fdesc; - fdesc = this->GetFileDescriptor(fd); + Fildes fdesc = this->GetFileDescriptor(fd); + DupFildes dfdesc = this->GetDupFildes(fd); - if (fdesc.Descriptor < 0) + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) { errno = EBADF; return -1; } - Node *node = fdesc.Handle->node; + RefNode *hnd = nullptr; + if (fdesc.Descriptor != -1) + hnd = fdesc.Handle; + else + hnd = dfdesc.Handle; + + Node *node = hnd->node; statbuf->st_dev = 0; /* FIXME: stub */ statbuf->st_ino = node->IndexNode; statbuf->st_mode = node->Flags | node->Mode; @@ -379,7 +493,7 @@ namespace VirtualFileSystem statbuf->st_size = node->Length; statbuf->st_blksize = 0; /* FIXME: stub */ statbuf->st_blocks = 0; /* FIXME: stub */ - statbuf->st_attr = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ return 0; } @@ -413,7 +527,112 @@ namespace VirtualFileSystem statbuf->st_size = node->Length; statbuf->st_blksize = 0; /* FIXME: stub */ statbuf->st_blocks = 0; /* FIXME: stub */ - statbuf->st_attr = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ + return 0; + } + + int FileDescriptorTable::_dup(int oldfd) + { + Fildes fdesc = this->GetFileDescriptor(oldfd); + DupFildes dfdesc = this->GetDupFildes(oldfd); + + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + int newfd = this->GetFreeFileDescriptor(); + if (newfd < 0) + { + errno = EMFILE; + return -1; + } + + DupFildes new_dfd{}; + if (fdesc.Descriptor != -1) + { + new_dfd.Handle = fdesc.Handle; + new_dfd.Mode = fdesc.Mode; + } + else + { + new_dfd.Handle = dfdesc.Handle; + new_dfd.Mode = dfdesc.Mode; + } + + new_dfd.Descriptor = newfd; + this->FildesDuplicates.push_back(new_dfd); + debug("Duplicated file descriptor %d to %d", + oldfd, newfd); + return newfd; + } + + int FileDescriptorTable::_dup2(int oldfd, int newfd) + { + Fildes fdesc = this->GetFileDescriptor(oldfd); + DupFildes dfdesc = this->GetDupFildes(oldfd); + + if (fdesc.Descriptor < 0 && + dfdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + if (newfd < 0) + { + errno = EBADF; + return -1; + } + + if (newfd == oldfd) + return newfd; + + /* Even if it's not valid + we ignore it. */ + this->_close(newfd); + + DupFildes new_dfd{}; + if (fdesc.Descriptor != -1) + { + new_dfd.Handle = fdesc.Handle; + new_dfd.Mode = fdesc.Mode; + } + else + { + new_dfd.Handle = dfdesc.Handle; + new_dfd.Mode = dfdesc.Mode; + } + + new_dfd.Descriptor = newfd; + this->FildesDuplicates.push_back(new_dfd); + debug("Duplicated file descriptor %d to %d", + oldfd, newfd); + return newfd; + } + + int FileDescriptorTable::_ioctl(int fd, unsigned long request, void *argp) + { + struct winsize *ws = (struct winsize *)argp; + Video::ScreenBuffer *sb = Display->GetBuffer(0); + Video::FontInfo fi = Display->GetCurrentFont()->GetInfo(); + + switch (request) + { + case TIOCGWINSZ: + fixme("TIOCGWINSZ: stub"); + ws->ws_xpixel = uint16_t(sb->Width); + ws->ws_ypixel = uint16_t(sb->Height); + ws->ws_col = uint16_t(sb->Width / fi.Width); + ws->ws_row = uint16_t(sb->Height / fi.Height); + break; + default: + fixme("Unknown request %#lx", request); + errno = ENOSYS; + return -1; + } return 0; } diff --git a/FileSystem/FileNode.cpp b/FileSystem/FileNode.cpp index 17d277cd..fbeddc22 100644 --- a/FileSystem/FileNode.cpp +++ b/FileSystem/FileNode.cpp @@ -17,6 +17,13 @@ #include +#ifdef DEBUG +const char *SeekStrings[] = + {"SEEK_SET", + "SEEK_CUR", + "SEEK_END"}; +#endif + namespace VirtualFileSystem { ReferenceNode *Node::CreateReference() @@ -83,10 +90,10 @@ namespace VirtualFileSystem return -1; } - off_t ReferenceNode::Seek(off_t Offset, int Whence) + off_t ReferenceNode::Seek(off_t _Offset, int Whence) { if (this->SymlinkTo) - return this->SymlinkTo->Seek(Offset, Whence); + return this->SymlinkTo->Seek(_Offset, Whence); if (!this->node->Operator) { @@ -99,25 +106,40 @@ namespace VirtualFileSystem if (this->node->Operator->Seek) { off_t RefOffset = off_t(this->Offset.load()); - return this->node->Operator->Seek(this->node, Offset, Whence, RefOffset); + debug("The node has a seek function"); + return this->node->Operator->Seek(this->node, _Offset, Whence, RefOffset); } + debug("Current offset is %d", this->Offset.load()); switch (Whence) { case SEEK_SET: { - if (Offset > this->node->Length) + if (_Offset > this->node->Length) { errno = EINVAL; return -1; } - this->Offset.store(Offset); + if (_Offset < 0) + { + fixme("Negative offset %d is not implemented", _Offset); + _Offset = 0; + } + + if (_Offset > this->node->Length) + { + fixme("Offset %d is bigger than file size %d", + _Offset, this->node->Length); + _Offset = this->node->Length; + } + + this->Offset.store(_Offset); break; } case SEEK_CUR: { - off_t NewOffset = off_t(this->Offset.load()) + Offset; + off_t NewOffset = off_t(this->Offset.load()) + _Offset; if (NewOffset > this->node->Length || NewOffset < 0) { @@ -130,7 +152,7 @@ namespace VirtualFileSystem } case SEEK_END: { - off_t NewOffset = this->node->Length + Offset; + off_t NewOffset = this->node->Length + _Offset; if (NewOffset > this->node->Length || NewOffset < 0) { @@ -149,7 +171,12 @@ namespace VirtualFileSystem } } - return (off_t)this->Offset.load(); + off_t RetOffset = off_t(this->Offset.load()); + debug("( %d %ld %s[%d] ) -> %d", + _Offset, this->Offset.load(), + SeekStrings[Whence], Whence, + RetOffset); + return RetOffset; } ReferenceNode::ReferenceNode(Node *node) diff --git a/FileSystem/Mounts/Null.cpp b/FileSystem/Mounts/Null.cpp new file mode 100644 index 00000000..1630149d --- /dev/null +++ b/FileSystem/Mounts/Null.cpp @@ -0,0 +1,49 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +ReadFSFunction(Null_Read) +{ + if (Size <= 0) + return 0; + + memset(Buffer, 0, Size); + return Size; +} + +ReadFSFunction(Null_Write) +{ + return Size; +} + +FileSystemOperations null_op = { + .Name = "Null", + .Read = Null_Read, + .Write = Null_Write, +}; + +void Init_Null(Virtual *vfs_ctx) +{ + Node *n = vfs_ctx->Create("null", CHARDEVICE, DevFS); + n->Operator = &null_op; +} diff --git a/FileSystem/Mounts/Random.cpp b/FileSystem/Mounts/Random.cpp new file mode 100644 index 00000000..69081898 --- /dev/null +++ b/FileSystem/Mounts/Random.cpp @@ -0,0 +1,52 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +ReadFSFunction(Random_Read) +{ + if (Size <= 0) + return 0; + + uint64_t *buf = (uint64_t *)Buffer; + for (size_t i = 0; i < Size / sizeof(uint64_t); i++) + buf[i] = Random::rand64(); + return Size; +} + +ReadFSFunction(Random_Write) +{ + return Size; +} + +FileSystemOperations random_op = { + .Name = "Random", + .Read = Random_Read, + .Write = Random_Write, +}; + +void Init_Random(Virtual *vfs_ctx) +{ + Node *n = vfs_ctx->Create("random", CHARDEVICE, DevFS); + n->Operator = &random_op; +} diff --git a/FileSystem/Mounts/Teletype.cpp b/FileSystem/Mounts/Teletype.cpp new file mode 100644 index 00000000..fb4894d7 --- /dev/null +++ b/FileSystem/Mounts/Teletype.cpp @@ -0,0 +1,43 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +ReadFSFunction(tty_Write) +{ + for (size_t i = 0; i < Size; i++) + putchar(((char *)Buffer)[i]); + + Display->SetBuffer(0); + return Size; +} + +FileSystemOperations tty_op = { + .Name = "tty", + .Write = tty_Write, +}; + +void Init_Teletype(Virtual *vfs_ctx) +{ + Node *n = vfs_ctx->Create("tty", CHARDEVICE, DevFS); + n->Operator = &tty_op; +} diff --git a/FileSystem/Mounts/Zero.cpp b/FileSystem/Mounts/Zero.cpp new file mode 100644 index 00000000..b441e449 --- /dev/null +++ b/FileSystem/Mounts/Zero.cpp @@ -0,0 +1,49 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +ReadFSFunction(Zero_Read) +{ + if (Size <= 0) + return 0; + + memset(Buffer, 0, Size); + return Size; +} + +ReadFSFunction(Zero_Write) +{ + return Size; +} + +FileSystemOperations zero_op = { + .Name = "Zero", + .Read = Zero_Read, + .Write = Zero_Write, +}; + +void Init_Zero(Virtual *vfs_ctx) +{ + Node *n = vfs_ctx->Create("zero", CHARDEVICE, DevFS); + n->Operator = &zero_op; +} diff --git a/Kernel.cpp b/Kernel.cpp index f1ba763f..8132b5f2 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -17,10 +17,11 @@ #include "kernel.h" +#include #include -#include #include #include +#include #include #include #include @@ -34,12 +35,6 @@ bool DebuggerIsAttached = false; -#ifdef DEBUG -bool EnableExternalMemoryTracer = false; /* This can be modified while we are debugging with GDB. */ -char mExtTrkLog[MEM_TRK_MAX_SIZE]; -LockClass mExtTrkLock; -#endif - /** * Fennix Kernel * ------------- @@ -223,7 +218,7 @@ Time::time *TimeManager = nullptr; VirtualFileSystem::Virtual *vfs = nullptr; KernelConfig Config = { - .AllocatorType = Memory::MemoryAllocatorType::XallocV1, + .AllocatorType = Memory::MemoryAllocatorType::liballoc11, .SchedulerType = Multi, .DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'}, .InitPath = {'/', 'b', 'i', 'n', '/', 'i', 'n', 'i', 't', '\0'}, @@ -521,6 +516,11 @@ EXTERNC NIF void Main() } } + Init_Null(vfs); + Init_Random(vfs); + Init_Teletype(vfs); + Init_Zero(vfs); + KPrint("\e058C19################################"); TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread)); CPU::Halt(true); @@ -574,9 +574,9 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info) * is a global constructor but we need * memory management to be initialized first. */ + TestMemoryAllocation(); TestString(); Test_std(); - TestMemoryAllocation(); #endif EnableProfiler = true; Main(); diff --git a/KernelConfig.cpp b/KernelConfig.cpp index d331bb55..2d4fac77 100644 --- a/KernelConfig.cpp +++ b/KernelConfig.cpp @@ -162,6 +162,11 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig) KPrint("\eAAFFAAUsing XallocV1 as memory allocator"); ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV1; } + else if (strcmp(value, "xallocv2") == 0) + { + KPrint("\eAAFFAAUsing XallocV2 as memory allocator"); + ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV2; + } else if (strcmp(value, "liballoc11") == 0) { KPrint("\eAAFFAAUsing Liballoc11 as memory allocator"); diff --git a/KernelShell/Commands/lsof.cpp b/KernelShell/Commands/lsof.cpp index 5fe92a79..c0ddf661 100644 --- a/KernelShell/Commands/lsof.cpp +++ b/KernelShell/Commands/lsof.cpp @@ -27,7 +27,8 @@ void cmd_lsof(const char *) if (!Proc) continue; - std::vector fds_array = Proc->FileDescriptors->GetFileDescriptors(); + std::vector fds_array = + Proc->FileDescriptors->GetFileDescriptors(); foreach (auto fd in fds_array) printf("%s %d: %s\n", Proc->Name, fd.Descriptor, fd.Handle->AbsolutePath.c_str()); diff --git a/KernelThread.cpp b/KernelThread.cpp index 0b56e4e0..9f52698a 100644 --- a/KernelThread.cpp +++ b/KernelThread.cpp @@ -254,7 +254,8 @@ void lsof() printf("%s:\n", Proc->Name); - std::vector fds_array = Proc->FileDescriptors->GetFileDescriptors(); + std::vector fds_array = + Proc->FileDescriptors->GetFileDescriptors(); foreach (auto fd in fds_array) printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str()); } @@ -307,7 +308,10 @@ int SpawnInit() "--critical", nullptr}; - return Execute::Spawn(Config.InitPath, argv, envp); + return Execute::Spawn(Config.InitPath, argv, envp, + nullptr, + Tasking::TaskCompatibility::Native, + true); } /* Files: 0.tga 1.tga ... 26.tga */ @@ -451,7 +455,10 @@ void ExitLogoAnimationThread() } } -void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); } +void CleanupProcessesThreadWrapper() +{ + TaskManager->CleanupProcessesThread(); +} void KernelMainThread() { @@ -530,11 +537,10 @@ void KernelMainThread() goto Exit; } - initThread = TaskManager->GetThreadByID(tid); - initThread->SetCritical(true); KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath); thisThread->SetPriority(Tasking::Idle); + initThread = TaskManager->GetThreadByID(tid); TaskManager->WaitForThread(initThread); ExitCode = initThread->GetExitCode(); Exit: diff --git a/Library/Convert.cpp b/Library/Convert.cpp index b86d2e63..f4e5ade5 100644 --- a/Library/Convert.cpp +++ b/Library/Convert.cpp @@ -29,721 +29,725 @@ EXTERNC int memcmp(const void *vl, const void *vr, size_t n) { - const unsigned char *l = (unsigned char *)vl, *r = (unsigned char *)vr; - for (; n && *l == *r; n--, l++, r++) - ; - return n ? *l - *r : 0; + const unsigned char *l = (unsigned char *)vl, *r = (unsigned char *)vr; + for (; n && *l == *r; n--, l++, r++) + ; + return n ? *l - *r : 0; } EXTERNC void backspace(char s[]) { - int len = s_cst(int, strlen(s)); - s[len - 1] = '\0'; + int len = s_cst(int, strlen(s)); + s[len - 1] = '\0'; } EXTERNC void append(char s[], char n) { - int len = s_cst(int, strlen(s)); - s[len] = n; - s[len + 1] = '\0'; + int len = s_cst(int, strlen(s)); + s[len] = n; + s[len + 1] = '\0'; } EXTERNC int strncmp(const char *s1, const char *s2, size_t n) { - for (size_t i = 0; i < n; i++) - { - char c1 = s1[i], c2 = s2[i]; - if (c1 != c2) - return c1 - c2; - if (!c1) - return 0; - } - return 0; + for (size_t i = 0; i < n; i++) + { + char c1 = s1[i], c2 = s2[i]; + if (c1 != c2) + return c1 - c2; + if (!c1) + return 0; + } + return 0; } EXTERNC long unsigned strlen(const char s[]) { - long unsigned i = 0; - if (s) - while (s[i] != '\0') - ++i; - return i; + long unsigned i = 0; + if (s) + while (s[i] != '\0') + ++i; + return i; } EXTERNC char *strcat_unsafe(char *destination, const char *source) { - if ((destination == NULL) || (source == NULL)) - return NULL; - char *start = destination; - while (*start != '\0') - { - start++; - } - while (*source != '\0') - { - *start++ = *source++; - } - *start = '\0'; - return destination; + if ((destination == NULL) || (source == NULL)) + return NULL; + + char *start = destination; + while (*start != '\0') + start++; + + while (*source != '\0') + *start++ = *source++; + + *start = '\0'; + return destination; } EXTERNC char *strcpy_unsafe(char *destination, const char *source) { - if (destination == NULL) - return NULL; - char *ptr = destination; - while (*source != '\0') - { - *destination = *source; - destination++; - source++; - } - *destination = '\0'; - return ptr; + if (destination == NULL) + return NULL; + + char *ptr = destination; + while (*source != '\0') + { + *destination = *source; + destination++; + source++; + } + + *destination = '\0'; + return ptr; } EXTERNC char *strncpy(char *destination, const char *source, unsigned long num) { - if (destination == NULL) - return NULL; - char *ptr = destination; - while (*source && num--) - { - *destination = *source; - destination++; - source++; - } - *destination = '\0'; - return ptr; + if (destination == NULL) + return NULL; + + char *ptr = destination; + while (*source && num--) + { + *destination = *source; + destination++; + source++; + } + + *destination = '\0'; + return ptr; } EXTERNC int strcmp(const char *l, const char *r) { - for (; *l == *r && *l; l++, r++) - ; - return *(unsigned char *)l - *(unsigned char *)r; + for (; *l == *r && *l; l++, r++) + ; + + return *(unsigned char *)l - *(unsigned char *)r; } EXTERNC char *strstr(const char *haystack, const char *needle) { - const char *a = haystack, *b = needle; - while (1) - { - if (!*b) - return (char *)haystack; - if (!*a) - return NULL; - if (*a++ != *b++) - { - a = ++haystack; - b = needle; - } - } + const char *a = haystack, *b = needle; + while (1) + { + if (!*b) + return (char *)haystack; + if (!*a) + return NULL; + if (*a++ != *b++) + { + a = ++haystack; + b = needle; + } + } } EXTERNC char *strchr(const char *String, int Char) { - while (*String != (char)Char) - { - if (!*String++) - return 0; - } - return (char *)String; + while (*String != (char)Char) + { + if (!*String++) + return 0; + } + return (char *)String; } EXTERNC char *strdup(const char *String) { - char *OutBuffer = (char *)kmalloc(strlen((char *)String) + 1); - strncpy(OutBuffer, String, strlen(String) + 1); - return OutBuffer; + char *OutBuffer = (char *)kmalloc(strlen((char *)String) + 1); + strncpy(OutBuffer, String, strlen(String) + 1); + return OutBuffer; } EXTERNC int isalpha(int c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } EXTERNC int isupper(int c) { - return (c >= 'A' && c <= 'Z'); + return (c >= 'A' && c <= 'Z'); } EXTERNC long int strtol(const char *str, char **endptr, int base) { - const char *s; - long acc, cutoff; - int c; - int neg, any, cutlim; + const char *s; + long acc, cutoff; + int c; + int neg, any, cutlim; - s = str; - do - { - c = *s++; - } while (isspace(c)); - if (c == '-') - { - neg = 1; - c = *s++; - } - else - { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) - { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; + s = str; + do + { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else + { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; - cutoff = neg ? LONG_MIN : LONG_MAX; - cutlim = s_cst(int, cutoff % base); - cutoff /= base; - for (acc = 0, any = 0;; c = *s++) - { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else - { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) - { - acc = neg ? LONG_MIN : LONG_MAX; - } - else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *)(any ? s - 1 : str); - return (acc); + cutoff = neg ? LONG_MIN : LONG_MAX; + cutlim = s_cst(int, cutoff % base); + cutoff /= base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : str); + return (acc); } EXTERNC unsigned long int strtoul(const char *str, char **endptr, int base) { - const char *s; - unsigned long acc, cutoff; - int c; - int neg, any, cutlim; + const char *s; + unsigned long acc, cutoff; + int c; + int neg, any, cutlim; - s = str; - do - { - c = *s++; - } while (isspace(c)); - if (c == '-') - { - neg = 1; - c = *s++; - } - else - { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) - { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; + s = str; + do + { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else + { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; - cutoff = neg ? LONG_MIN : LONG_MAX; - cutlim = s_cst(int, cutoff % base); - cutoff /= base; - for (acc = 0, any = 0;; c = *s++) - { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else - { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) - { - acc = neg ? LONG_MIN : LONG_MAX; - } - else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *)(any ? s - 1 : str); - return (acc); + cutoff = neg ? LONG_MIN : LONG_MAX; + cutlim = s_cst(int, cutoff % base); + cutoff /= base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : str); + return (acc); } EXTERNC int isdigit(int c) { - return c >= '0' && c <= '9'; + return c >= '0' && c <= '9'; } EXTERNC int isspace(int c) { - return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v'; + return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v'; } EXTERNC int isempty(char *str) { - if (strlen(str) == 0) - return 1; - while (*str != '\0') - { - if (!isspace(*str)) - return 0; - str++; - } - return 1; + if (strlen(str) == 0) + return 1; + while (*str != '\0') + { + if (!isspace(*str)) + return 0; + str++; + } + return 1; } EXTERNC unsigned int isdelim(char c, const char *delim) { - while (*delim != '\0') - { - if (c == *delim) - return 1; - delim++; - } - return 0; + while (*delim != '\0') + { + if (c == *delim) + return 1; + delim++; + } + return 0; } EXTERNC long abs(long i) { return i < 0 ? -i : i; } EXTERNC void swap(char *x, char *y) { - char t = *x; - *x = *y; - *y = t; + char t = *x; + *x = *y; + *y = t; } EXTERNC char *reverse(char *Buffer, int i, int j) { - while (i < j) - swap(&Buffer[i++], &Buffer[j--]); - return Buffer; + while (i < j) + swap(&Buffer[i++], &Buffer[j--]); + return Buffer; } EXTERNC float sqrtf(float x) { - if (x < 0.0f) - return NAN; + if (x < 0.0f) + return NAN; - if (x < 1e-7f) - return 0.0f; + if (x < 1e-7f) + return 0.0f; - float guess = x / 2.0f; - for (short i = 0; i < 10; i++) - { + float guess = x / 2.0f; + for (short i = 0; i < 10; i++) + { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" - if (guess == 0.0f) - return 0.0f; + if (guess == 0.0f) + return 0.0f; #pragma GCC diagnostic pop - guess = (guess + x / guess) / 2.0f; - } - return guess; + guess = (guess + x / guess) / 2.0f; + } + return guess; } EXTERNC double clamp(double x, double low, double high) { - if (x < low) - return low; - else if (x > high) - return high; - else - return x; + if (x < low) + return low; + else if (x > high) + return high; + else + return x; } EXTERNC float lerp(float a, float b, float t) { - return (1 - t) * a + t * b; + return (1 - t) * a + t * b; } EXTERNC float smoothstep(float a, float b, float t) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-conversion" - t = clamp(s_cst(double, t), 0.0, 1.0); + t = clamp(s_cst(double, t), 0.0, 1.0); #pragma GCC diagnostic pop - return lerp(a, b, t * t * (3 - 2 * t)); + return lerp(a, b, t * t * (3 - 2 * t)); } EXTERNC float cubicInterpolate(float a, float b, float t) { - float t2 = t * t; - float t3 = t2 * t; - return a + (-2 * t3 + 3 * t2) * b; + float t2 = t * t; + float t3 = t2 * t; + return a + (-2 * t3 + 3 * t2) * b; } EXTERNC char *strtok(char *src, const char *delim) { - static char *src1; - if (!src) - src = src1; + static char *src1; + if (!src) + src = src1; - if (!src) - return NULL; + if (!src) + return NULL; - while (1) - { - if (isdelim(*src, (char *)delim)) - { - src++; - continue; - } - if (*src == '\0') - return NULL; + while (1) + { + if (isdelim(*src, (char *)delim)) + { + src++; + continue; + } + if (*src == '\0') + return NULL; - break; - } - char *ret = src; - while (1) - { - if (*src == '\0') - { - src1 = src; - return ret; - } - if (isdelim(*src, (char *)delim)) - { - *src = '\0'; - src1 = src + 1; - return ret; - } - src++; - } - return NULL; + break; + } + char *ret = src; + while (1) + { + if (*src == '\0') + { + src1 = src; + return ret; + } + if (isdelim(*src, (char *)delim)) + { + *src = '\0'; + src1 = src + 1; + return ret; + } + src++; + } + return NULL; } int strcasecmp(const char *s1, const char *s2) { - const unsigned char *p1 = (const unsigned char *)s1; - const unsigned char *p2 = (const unsigned char *)s2; - int result; - if (p1 == p2) - return 0; - while ((result = std::tolower(*p1) - std::tolower(*p2++)) == 0) - if (*p1++ == '\0') - break; - return result; + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + int result; + if (p1 == p2) + return 0; + while ((result = std::tolower(*p1) - std::tolower(*p2++)) == 0) + if (*p1++ == '\0') + break; + return result; } size_t wcslen(const wchar_t *s) { - size_t len = 0; + size_t len = 0; - while (s[len] != L'\0') - { - if (s[++len] == L'\0') - return len; - if (s[++len] == L'\0') - return len; - if (s[++len] == L'\0') - return len; - ++len; - } + while (s[len] != L'\0') + { + if (s[++len] == L'\0') + return len; + if (s[++len] == L'\0') + return len; + if (s[++len] == L'\0') + return len; + ++len; + } - return len; + return len; } size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps) { - UNUSED(ps); - size_t count = 0; + UNUSED(ps); + size_t count = 0; - while (len > 0) - { - wchar_t wc = **src; - if (wc == L'\0') - break; + while (len > 0) + { + wchar_t wc = **src; + if (wc == L'\0') + break; - if (wc < 0x80) - { - if (dst) - *dst++ = (char)wc; - count++; - len--; - } - else if (wc < 0x800) - { - if (dst) - { - *dst++ = (char)(0xC0 | (wc >> 6)); - *dst++ = (char)(0x80 | (wc & 0x3F)); - } - count += 2; - len -= 2; - } - else if (wc < 0x10000) - { - if (dst) - { - *dst++ = (char)(0xE0 | (wc >> 12)); - *dst++ = (char)(0x80 | ((wc >> 6) & 0x3F)); - *dst++ = (char)(0x80 | (wc & 0x3F)); - } - count += 3; - len -= 3; - } - else - { - if (dst) - { - *dst++ = (char)(0xF0 | (wc >> 18)); - *dst++ = (char)(0x80 | ((wc >> 12) & 0x3F)); - *dst++ = (char)(0x80 | ((wc >> 6) & 0x3F)); - *dst++ = (char)(0x80 | (wc & 0x3F)); - } - count += 4; - len -= 4; - } + if (wc < 0x80) + { + if (dst) + *dst++ = (char)wc; + count++; + len--; + } + else if (wc < 0x800) + { + if (dst) + { + *dst++ = (char)(0xC0 | (wc >> 6)); + *dst++ = (char)(0x80 | (wc & 0x3F)); + } + count += 2; + len -= 2; + } + else if (wc < 0x10000) + { + if (dst) + { + *dst++ = (char)(0xE0 | (wc >> 12)); + *dst++ = (char)(0x80 | ((wc >> 6) & 0x3F)); + *dst++ = (char)(0x80 | (wc & 0x3F)); + } + count += 3; + len -= 3; + } + else + { + if (dst) + { + *dst++ = (char)(0xF0 | (wc >> 18)); + *dst++ = (char)(0x80 | ((wc >> 12) & 0x3F)); + *dst++ = (char)(0x80 | ((wc >> 6) & 0x3F)); + *dst++ = (char)(0x80 | (wc & 0x3F)); + } + count += 4; + len -= 4; + } - (*src)++; - } + (*src)++; + } - if (dst) - *dst = '\0'; + if (dst) + *dst = '\0'; - return count; + return count; } EXTERNC int atoi(const char *String) { - uint64_t Length = strlen((char *)String); - int OutBuffer = 0; - int Power = 1; - for (uint64_t i = Length; i > 0; --i) - { - OutBuffer += (String[i - 1] - 48) * Power; - Power *= 10; - } - return OutBuffer; + uint64_t Length = strlen((char *)String); + int OutBuffer = 0; + int Power = 1; + for (uint64_t i = Length; i > 0; --i) + { + OutBuffer += (String[i - 1] - 48) * Power; + Power *= 10; + } + return OutBuffer; } EXTERNC double atof(const char *String) { - // Originally from https://github.com/GaloisInc/minlibc/blob/master/atof.c - /* - Copyright (c) 2014 Galois Inc. - All rights reserved. + // Originally from https://github.com/GaloisInc/minlibc/blob/master/atof.c + /* + Copyright (c) 2014 Galois Inc. + All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. - * Neither the name of Galois, Inc. nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. + * Neither the name of Galois, Inc. nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - double a = 0.0; - int e = 0; - int c; - while ((c = *String++) != '\0' && isdigit(c)) - { - a = a * 10.0 + (c - '0'); - } - if (c == '.') - { - while ((c = *String++) != '\0' && isdigit(c)) - { - a = a * 10.0 + (c - '0'); - e = e - 1; - } - } - if (c == 'e' || c == 'E') - { - int sign = 1; - int i = 0; - c = *String++; - if (c == '+') - c = *String++; - else if (c == '-') - { - c = *String++; - sign = -1; - } - while (isdigit(c)) - { - i = i * 10 + (c - '0'); - c = *String++; - } - e += i * sign; - } - while (e > 0) - { - a *= 10.0; - e--; - } - while (e < 0) - { - a *= 0.1; - e++; - } - return a; + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + double a = 0.0; + int e = 0; + int c; + while ((c = *String++) != '\0' && isdigit(c)) + { + a = a * 10.0 + (c - '0'); + } + if (c == '.') + { + while ((c = *String++) != '\0' && isdigit(c)) + { + a = a * 10.0 + (c - '0'); + e = e - 1; + } + } + if (c == 'e' || c == 'E') + { + int sign = 1; + int i = 0; + c = *String++; + if (c == '+') + c = *String++; + else if (c == '-') + { + c = *String++; + sign = -1; + } + while (isdigit(c)) + { + i = i * 10 + (c - '0'); + c = *String++; + } + e += i * sign; + } + while (e > 0) + { + a *= 10.0; + e--; + } + while (e < 0) + { + a *= 0.1; + e++; + } + return a; } EXTERNC char *itoa(int Value, char *Buffer, int Base) { - if (Base < 2 || Base > 32) - return Buffer; + if (Base < 2 || Base > 32) + return Buffer; - int n = s_cst(int, abs(Value)); - int i = 0; + int n = s_cst(int, abs(Value)); + int i = 0; - while (n) - { - int r = s_cst(int, n % Base); - if (r >= 10) - Buffer[i++] = s_cst(char, 65 + (r - 10)); - else - Buffer[i++] = s_cst(char, 48 + r); - n = n / Base; - } + while (n) + { + int r = s_cst(int, n % Base); + if (r >= 10) + Buffer[i++] = s_cst(char, 65 + (r - 10)); + else + Buffer[i++] = s_cst(char, 48 + r); + n = n / Base; + } - if (i == 0) - Buffer[i++] = '0'; + if (i == 0) + Buffer[i++] = '0'; - if (Value < 0 && Base == 10) - Buffer[i++] = '-'; + if (Value < 0 && Base == 10) + Buffer[i++] = '-'; - Buffer[i] = '\0'; - return reverse(Buffer, 0, i - 1); + Buffer[i] = '\0'; + return reverse(Buffer, 0, i - 1); } EXTERNC char *ltoa(long Value, char *Buffer, int Base) { - if (Base < 2 || Base > 32) - return Buffer; + if (Base < 2 || Base > 32) + return Buffer; - long n = abs(Value); - int i = 0; + long n = abs(Value); + int i = 0; - while (n) - { - int r = s_cst(int, n % Base); - if (r >= 10) - Buffer[i++] = s_cst(char, 65 + (r - 10)); - else - Buffer[i++] = s_cst(char, 48 + r); - n = n / Base; - } + while (n) + { + int r = s_cst(int, n % Base); + if (r >= 10) + Buffer[i++] = s_cst(char, 65 + (r - 10)); + else + Buffer[i++] = s_cst(char, 48 + r); + n = n / Base; + } - if (i == 0) - Buffer[i++] = '0'; + if (i == 0) + Buffer[i++] = '0'; - if (Value < 0 && Base == 10) - Buffer[i++] = '-'; + if (Value < 0 && Base == 10) + Buffer[i++] = '-'; - Buffer[i] = '\0'; - return reverse(Buffer, 0, i - 1); + Buffer[i] = '\0'; + return reverse(Buffer, 0, i - 1); } EXTERNC char *ultoa(unsigned long Value, char *Buffer, int Base) { - if (Base < 2 || Base > 32) - return Buffer; + if (Base < 2 || Base > 32) + return Buffer; - unsigned long n = Value; - int i = 0; + unsigned long n = Value; + int i = 0; - while (n) - { - int r = s_cst(int, n % Base); - if (r >= 10) - Buffer[i++] = s_cst(char, 65 + (r - 10)); - else - Buffer[i++] = s_cst(char, 48 + r); - n = n / Base; - } + while (n) + { + int r = s_cst(int, n % Base); + if (r >= 10) + Buffer[i++] = s_cst(char, 65 + (r - 10)); + else + Buffer[i++] = s_cst(char, 48 + r); + n = n / Base; + } - if (i == 0) - Buffer[i++] = '0'; + if (i == 0) + Buffer[i++] = '0'; - Buffer[i] = '\0'; - return reverse(Buffer, 0, i - 1); + Buffer[i] = '\0'; + return reverse(Buffer, 0, i - 1); } EXTERNC int log2(unsigned int n) { - if (n == 0) - { - error("log2(0) is undefined."); - return -1; - } + if (n == 0) + { + error("log2(0) is undefined."); + return -1; + } - int log = 0; + int log = 0; - if ((n & 0xFFFF0000) != 0) - { - n >>= 16; - log = 16; - } + if ((n & 0xFFFF0000) != 0) + { + n >>= 16; + log = 16; + } - if (n >= 256) - { - n >>= 8; - log += 8; - } + if (n >= 256) + { + n >>= 8; + log += 8; + } - if (n >= 16) - { - n >>= 4; - log += 4; - } + if (n >= 16) + { + n >>= 4; + log += 4; + } - if (n >= 4) - { - n >>= 2; - log += 2; - } + if (n >= 4) + { + n >>= 2; + log += 2; + } - return log + (n >> 1); + return log + (n >> 1); } EXTERNC void __chk_fail(void) __noreturn; @@ -751,11 +755,11 @@ EXTERNC void __chk_fail(void) __noreturn; __noreturn __always_inline static inline void __convert_chk_fail(void) { #if defined(a86) - asmv("int3"); + asmv("int3"); #else #warning "Not implemented!" #endif - __builtin_unreachable(); + __builtin_unreachable(); } // #define DBG_CHK 1 @@ -763,350 +767,305 @@ __noreturn __always_inline static inline void __convert_chk_fail(void) EXTERNC __no_stack_protector void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen) { #ifdef DBG_CHK - debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", dest, src, len, slen); + debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", + dest, src, len, slen); #endif - if (unlikely(dest == NULL)) - { - error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(dest == NULL)) + { + error("dest is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(src == NULL)) - { - error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(src == NULL)) + { + error("src is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len == 0)) - { - error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(len == 0)) + { + error("len is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(slen == 0)) - { - error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(slen == 0)) + { + error("slen is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len > slen)) - __chk_fail(); + if (unlikely(len > slen)) + __chk_fail(); - void *ret = nullptr; - if (0) /* FIXME */ - { - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memcpy_sse4_2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memcpy_sse4_1(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memcpy_ssse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memcpy_sse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memcpy_sse2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memcpy_sse(dest, src, len); - else - ret = memcpy_unsafe(dest, src, len); - } - else - { - static int once = 0; - if (!once++) - fixme("SIMD memcpy disabled"); - ret = memcpy_unsafe(dest, src, len); - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "memcpy( %p %p %ld %ld )=%p~%p\n\r", - dest, src, len, slen, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif - return ret; + void *ret = nullptr; + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memcpy_sse4_2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memcpy_sse4_1(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memcpy_ssse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memcpy_sse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memcpy_sse2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memcpy_sse(dest, src, len); + else + ret = memcpy_unsafe(dest, src, len); + } + else + { + static int once = 0; + if (!once++) + fixme("SIMD memcpy disabled"); + ret = memcpy_unsafe(dest, src, len); + } + return ret; } EXTERNC __no_stack_protector void *__memset_chk(void *dest, int val, size_t len, size_t slen) { #ifdef DBG_CHK - debug("( dest:%#lx val:%#x len:%llu slen:%llu )", dest, val, len, slen); + debug("( dest:%#lx val:%#x len:%llu slen:%llu )", dest, val, len, slen); #endif - if (unlikely(dest == NULL)) - { - error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(dest == NULL)) + { + error("dest is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len == 0)) - { - error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(len == 0)) + { + error("len is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(slen == 0)) - { - error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(slen == 0)) + { + error("slen is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len > slen)) - __chk_fail(); + if (unlikely(len > slen)) + __chk_fail(); - void *ret = nullptr; - if (0) /* FIXME */ - { - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memset_sse4_2(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memset_sse4_1(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memset_ssse3(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memset_sse3(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memset_sse2(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memset_sse(dest, val, len); - else - ret = memset_unsafe(dest, val, len); - } - else - { - static int once = 0; - if (!once++) - fixme("SIMD memset disabled"); - ret = memset_unsafe(dest, val, len); - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "memset( %p %d %ld %ld )=%p~%p\n\r", - dest, val, len, slen, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif - return ret; + void *ret = nullptr; + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memset_sse4_2(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memset_sse4_1(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memset_ssse3(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memset_sse3(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memset_sse2(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memset_sse(dest, val, len); + else + ret = memset_unsafe(dest, val, len); + } + else + { + static int once = 0; + if (!once++) + fixme("SIMD memset disabled"); + ret = memset_unsafe(dest, val, len); + } + return ret; } EXTERNC __no_stack_protector void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen) { #ifdef DBG_CHK - debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", dest, src, len, slen); + debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", + dest, src, len, slen); #endif - if (unlikely(dest == NULL)) - { - error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(dest == NULL)) + { + error("dest is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(src == NULL)) - { - error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(src == NULL)) + { + error("src is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len == 0)) - { - error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(len == 0)) + { + error("len is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(slen == 0)) - { - error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(slen == 0)) + { + error("slen is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(len > slen)) - __chk_fail(); + if (unlikely(len > slen)) + __chk_fail(); - void *ret = nullptr; - if (0) /* FIXME */ - { - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memmove_sse4_2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memmove_sse4_1(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memmove_ssse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memmove_sse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memmove_sse2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memmove_sse(dest, src, len); - else - ret = memmove_unsafe(dest, src, len); - } - else - { - static int once = 0; - if (!once++) - fixme("SIMD memmove disabled"); - ret = memmove_unsafe(dest, src, len); - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "memmove( %p %p %ld %ld )=%p~%p\n\r", - dest, src, len, slen, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif - return ret; + void *ret = nullptr; + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memmove_sse4_2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memmove_sse4_1(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memmove_ssse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memmove_sse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memmove_sse2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memmove_sse(dest, src, len); + else + ret = memmove_unsafe(dest, src, len); + } + else + { + static int once = 0; + if (!once++) + fixme("SIMD memmove disabled"); + ret = memmove_unsafe(dest, src, len); + } + return ret; } EXTERNC __no_stack_protector char *__strcat_chk(char *dest, const char *src, size_t slen) { #ifdef DBG_CHK - debug("( dest:%#lx src:%#lx slen:%llu )", dest, src, slen); + debug("( dest:%#lx src:%#lx slen:%llu )", + dest, src, slen); #endif - if (unlikely(dest == NULL)) - { - error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(dest == NULL)) + { + error("dest is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(src == NULL)) - { - error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(src == NULL)) + { + error("src is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(slen == 0)) - { - error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(slen == 0)) + { + error("slen is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - size_t dest_len = strlen(dest); - if (unlikely(dest_len + strlen(src) + 1 > slen)) - __chk_fail(); - return strcat_unsafe(dest, src); + size_t dest_len = strlen(dest); + if (unlikely(dest_len + strlen(src) + 1 > slen)) + __chk_fail(); + return strcat_unsafe(dest, src); } EXTERNC __no_stack_protector char *__strcpy_chk(char *dest, const char *src, size_t slen) { #ifdef DBG_CHK - debug("( dest:%#lx src:%#lx slen:%llu )", dest, src, slen); + debug("( dest:%#lx src:%#lx slen:%llu )", + dest, src, slen); #endif - if (unlikely(dest == NULL)) - { - error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(dest == NULL)) + { + error("dest is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(src == NULL)) - { - error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(src == NULL)) + { + error("src is NULL (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - if (unlikely(slen == 0)) - { - error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - __convert_chk_fail(); - } + if (unlikely(slen == 0)) + { + error("slen is 0 (for %#lx %s)", + __builtin_return_address(0), + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) + : "Unknown"); + __convert_chk_fail(); + } - size_t len = strlen(src); + size_t len = strlen(src); - if (unlikely(len >= slen)) - __chk_fail(); + if (unlikely(len >= slen)) + __chk_fail(); - return strcpy_unsafe(dest, src); + return strcpy_unsafe(dest, src); } #undef memcpy EXTERNC __no_stack_protector void *memcpy(void *dest, const void *src, size_t len) { - void *ret = __memcpy_chk(dest, src, len, __builtin_object_size(dest, 0)); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "!memcpy( %p %p %ld )=%p~%p\n\r", - dest, src, len, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif - return ret; + void *ret = __memcpy_chk(dest, src, len, __builtin_object_size(dest, 0)); + return ret; } #undef memset EXTERNC __no_stack_protector void *memset(void *dest, int val, size_t len) { - void *ret = __memset_chk(dest, val, len, __builtin_object_size(dest, 0)); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "!memset( %p %d %ld )=%p~%p\n\r", - dest, val, len, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } -#endif - return ret; + void *ret = __memset_chk(dest, val, len, __builtin_object_size(dest, 0)); + return ret; } diff --git a/Library/liballocimpl.cpp b/Library/liballocimpl.cpp deleted file mode 100644 index 7080190d..00000000 --- a/Library/liballocimpl.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include - -NewLock(liballocLock); - -EXTERNC int liballoc_lock() { return liballocLock.Lock(__FUNCTION__); } -EXTERNC int liballoc_unlock() { return liballocLock.Unlock(); } -EXTERNC void *liballoc_alloc(size_t Pages) { return KernelAllocator.RequestPages(Pages); } -EXTERNC int liballoc_free(void *Address, size_t Pages) -{ - KernelAllocator.FreePages(Address, Pages); - return 0; -} diff --git a/SystemCalls/Linux/Linux.cpp b/SystemCalls/Linux/Linux.cpp index 9a7dc45d..43637e34 100644 --- a/SystemCalls/Linux/Linux.cpp +++ b/SystemCalls/Linux/Linux.cpp @@ -40,6 +40,27 @@ using Tasking::TaskStatus::Terminated; #define ARCH_GET_FS 0x1003 #define ARCH_GET_GS 0x1004 +#define ARCH_GET_CPUID 0x1011 +#define ARCH_SET_CPUID 0x1012 + +#define ARCH_GET_XCOMP_SUPP 0x1021 +#define ARCH_GET_XCOMP_PERM 0x1022 +#define ARCH_REQ_XCOMP_PERM 0x1023 +#define ARCH_GET_XCOMP_GUEST_PERM 0x1024 +#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025 + +#define ARCH_XCOMP_TILECFG 17 +#define ARCH_XCOMP_TILEDATA 18 + +#define ARCH_MAP_VDSO_X32 0x2001 +#define ARCH_MAP_VDSO_32 0x2002 +#define ARCH_MAP_VDSO_64 0x2003 + +#define ARCH_GET_UNTAG_MASK 0x4001 +#define ARCH_ENABLE_TAGGED_ADDR 0x4002 +#define ARCH_GET_MAX_TAG_BITS 0x4003 +#define ARCH_FORCE_TAGGED_SVA 0x4004 + #define PROT_NONE 0 #define PROT_READ 1 #define PROT_WRITE 2 @@ -47,16 +68,14 @@ using Tasking::TaskStatus::Terminated; #define PROT_GROWSDOWN 0x01000000 #define PROT_GROWSUP 0x02000000 -#define MAP_FAILED ((void *)-1) +#define MAP_TYPE 0x0f #define MAP_FILE 0 #define MAP_SHARED 0x01 #define MAP_PRIVATE 0x02 #define MAP_SHARED_VALIDATE 0x03 -#define MAP_TYPE 0x0f #define MAP_FIXED 0x10 -#define MAP_ANON 0x20 -#define MAP_ANONYMOUS MAP_ANON +#define MAP_ANONYMOUS 0x20 #define MAP_NORESERVE 0x4000 #define MAP_GROWSDOWN 0x0100 #define MAP_DENYWRITE 0x0800 @@ -96,17 +115,41 @@ static int ConvertErrno(int r) /* https://man7.org/linux/man-pages/man2/read.2.html */ static ssize_t sys_read(int fd, void *buf, size_t count) { + debug("Reading %d bytes from fd %d", count, fd); Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_read(fd, buf, count)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check(buf, Memory::US)) + { + warn("Invalid address %#lx", buf); + return -EFAULT; + } + auto pBuf = pcb->PageTable->Get(buf); + + ssize_t ret = ConvertErrno(fdt->_read(fd, pBuf, count)); + debug("Read %d bytes from fd %d, got %d", count, fd, ret); + return ret; } /* https://man7.org/linux/man-pages/man2/write.2.html */ static ssize_t sys_write(int fd, const void *buf, size_t count) { + debug("Writing %d bytes to fd %d", count, fd); Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_write(fd, buf, count)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)buf, Memory::US)) + { + warn("Invalid address %#lx", buf); + return -EFAULT; + } + auto pBuf = pcb->PageTable->Get(buf); + + ssize_t ret = ConvertErrno(fdt->_write(fd, pBuf, count)); + debug("Wrote %d bytes to fd %d, got %d", count, fd, ret); + return ret; } /* https://man7.org/linux/man-pages/man2/open.2.html */ @@ -114,7 +157,19 @@ static int sys_open(const char *pathname, int flags, mode_t mode) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_open(pathname, flags, mode)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)pathname, Memory::US)) + { + warn("Invalid address %#lx", pathname); + return -EFAULT; + } + auto pPathname = pcb->PageTable->Get(pathname); + + int ret = ConvertErrno(fdt->_open(pPathname, flags, mode)); + debug("Opened %s with flags %d and mode %d, got fd %d", + pPathname, flags, mode, ret); + return ret; } /* https://man7.org/linux/man-pages/man2/close.2.html */ @@ -122,7 +177,9 @@ static int sys_close(int fd) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_close(fd)); + int ret = ConvertErrno(fdt->_close(fd)); + debug("Closed fd %d, got %d", fd, ret); + return ret; } /* https://man7.org/linux/man-pages/man3/stat.3p.html */ @@ -130,7 +187,16 @@ static int sys_stat(const char *pathname, struct stat *statbuf) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_stat(pathname, statbuf)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)pathname, Memory::US)) + { + warn("Invalid address %#lx", pathname); + return -EFAULT; + } + auto pPathname = pcb->PageTable->Get(pathname); + + return ConvertErrno(fdt->_stat(pPathname, statbuf)); } /* https://man7.org/linux/man-pages/man3/fstat.3p.html */ @@ -139,7 +205,16 @@ static int sys_fstat(int fd, struct stat *statbuf) #undef fstat Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_fstat(fd, statbuf)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)statbuf, Memory::US)) + { + warn("Invalid address %#lx", statbuf); + return -EFAULT; + } + auto pStatbuf = pcb->PageTable->Get(statbuf); + + return ConvertErrno(fdt->_fstat(fd, pStatbuf)); } /* https://man7.org/linux/man-pages/man2/lstat.2.html */ @@ -148,7 +223,24 @@ static int sys_lstat(const char *pathname, struct stat *statbuf) #undef lstat Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_lstat(pathname, statbuf)); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)pathname, Memory::US)) + { + warn("Invalid address %#lx", pathname); + return -EFAULT; + } + + if (!vmm.Check((void *)statbuf, Memory::US)) + { + warn("Invalid address %#lx", statbuf); + return -EFAULT; + } + + auto pPathname = pcb->PageTable->Get(pathname); + auto pStatbuf = pcb->PageTable->Get(statbuf); + + return ConvertErrno(fdt->_lstat(pPathname, pStatbuf)); } /* https://man7.org/linux/man-pages/man2/lseek.2.html */ @@ -156,7 +248,10 @@ static off_t sys_lseek(int fd, off_t offset, int whence) { Tasking::PCB *pcb = thisProcess; VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; - return ConvertErrno(fdt->_lseek(fd, offset, whence)); + + off_t ret = ConvertErrno(fdt->_lseek(fd, offset, whence)); + debug("(%d, %d, %d) = %d", fd, offset, whence, ret); + return ret; } /* https://man7.org/linux/man-pages/man3/mmap.3p.html */ @@ -165,49 +260,66 @@ static void *sys_mmap(void *addr, size_t length, int prot, { UNUSED(offset); /* FIXME */ Tasking::PCB *pcb = thisProcess; - Memory::MemMgr *mgr = pcb->Memory; + Memory::MemMgr *mm = pcb->Memory; - if (!addr) + void *newPages = mm->RequestPages(TO_PAGES(length)); + if (newPages == nullptr) + return (void *)-ENOMEM; + + bool MustUseAddr = (flags & MAP_FIXED) != 0; + if (addr == NULL && !MustUseAddr) + addr = newPages; + + if (MustUseAddr) { - void *newPages = mgr->RequestPages(TO_PAGES(length)); - if (newPages == nullptr) - return MAP_FAILED; - - Memory::Virtual vma = Memory::Virtual(pcb->PageTable); - - if (prot & PROT_READ) - vma.Map(newPages, newPages, length, Memory::P | Memory::US, Memory::Virtual::FourKiB); - if (prot & PROT_WRITE) - vma.Map(newPages, newPages, length, Memory::RW, Memory::Virtual::FourKiB); - if (prot & PROT_EXEC) - fixme("PROT_EXEC not implemented"); - - if (flags & MAP_FILE) - fixme("MAP_FILE not implemented"); - if (flags & MAP_SHARED) - fixme("MAP_SHARED not implemented"); - if (flags & MAP_PRIVATE) - fixme("MAP_PRIVATE not implemented"); - if (flags & MAP_SHARED_VALIDATE) - fixme("MAP_SHARED_VALIDATE not implemented"); - if (flags & MAP_TYPE) - fixme("MAP_TYPE not implemented"); - if (flags & MAP_FIXED) - fixme("MAP_FIXED not implemented"); - if (flags & MAP_ANONYMOUS) - fixme("MAP_ANONYMOUS not implemented"); - - if (fildes != -1) - { - fixme("File mapping not implemented"); - return MAP_FAILED; - } - - return newPages; + debug("Using fixed address %#lx", addr); } - stub; - return MAP_FAILED; + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + uint64_t MapFlags = Memory::P; + if (prot & PROT_READ) + MapFlags |= Memory::US; + if (prot & PROT_WRITE) + MapFlags |= Memory::RW; + if (prot & PROT_EXEC) + debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */ + + switch (flags & MAP_TYPE) + { + case MAP_FILE: + debug("MAP_FILE ignored"); + [[fallthrough]]; + case MAP_SHARED: + fixme("MAP_SHARED not implemented"); + [[fallthrough]]; + case MAP_SHARED_VALIDATE: + fixme("MAP_SHARED_VALIDATE not implemented"); + [[fallthrough]]; + case MAP_PRIVATE: + debug("MAP_PRIVATE ignored"); + [[fallthrough]]; + case MAP_ANONYMOUS: + fixme("MAP_ANONYMOUS not implemented"); + [[fallthrough]]; + default: + { + debug("mmap flags %#x", flags); + break; + } + } + + vmm.Map(addr, newPages, length, MapFlags, Memory::Virtual::FourKiB); + debug("Mapped %#lx to %#lx (%d pages)", addr, newPages, TO_PAGES(length)); + + if (fildes != -1) + { + fixme("File mapping not implemented"); + mm->FreePages(newPages, TO_PAGES(length)); + return (void *)-ENOSYS; + } + + return addr; } /* https://man7.org/linux/man-pages/man3/mprotect.3p.html */ @@ -215,37 +327,58 @@ static int sys_mprotect(void *addr, size_t len, int prot) { Tasking::PCB *pcb = thisProcess; - Memory::Virtual vma = Memory::Virtual(pcb->PageTable); - vma.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB); + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + vmm.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB); if (prot & PROT_READ) - vma.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB); + vmm.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB); if (prot & PROT_WRITE) - vma.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB); + vmm.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB); if (prot & PROT_EXEC) - fixme("PROT_EXEC not implemented"); + debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */ + + return 0; +} + +/* https://man7.org/linux/man-pages/man3/munmap.3p.html */ +static int sys_munmap(void *addr, size_t length) +{ + Tasking::PCB *pcb = thisProcess; + Memory::MemMgr *mm = pcb->Memory; + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + mm->FreePages(addr, TO_PAGES(length)); + vmm.Unmap(addr, length, Memory::Virtual::FourKiB); return 0; } /* https://man7.org/linux/man-pages/man2/brk.2.html */ -static void *sys_brk(intptr_t increment) +static void *sys_brk(void *addr) { - Tasking::PCB *pcb = thisProcess; - Memory::MemMgr *mgr = pcb->Memory; - - stub; - size_t PagesToAllocate = increment ? TO_PAGES(increment) : 1; - return (void *)mgr->RequestPages(PagesToAllocate, true); + trace("Ignoring brk syscall..."); + return (void *)-ENOSYS; + // Tasking::PCB *pcb = thisProcess; + // void *ret = pcb->ProgramBreak->brk(addr); + // debug("brk(%#lx) = %#lx", addr, ret); + // return ret; } /* https://man7.org/linux/man-pages/man2/ioctl.2.html */ static int sys_ioctl(int fd, unsigned long request, void *argp) { - UNUSED(fd); - UNUSED(request); - UNUSED(argp); - return -ENOSYS; + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)argp, Memory::US)) + { + warn("Invalid address %#lx", argp); + return -EFAULT; + } + auto pArgp = pcb->PageTable->Get(argp); + + return ConvertErrno(fdt->_ioctl(fd, request, pArgp)); } /* https://man7.org/linux/man-pages/man3/readv.3p.html */ @@ -254,14 +387,20 @@ static ssize_t sys_readv(int fildes, const struct iovec *iov, int iovcnt) ssize_t Total = 0; for (int i = 0; i < iovcnt; i++) { + debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len); ssize_t n = sys_read(fildes, iov[i].iov_base, iov[i].iov_len); if (n < 0) return n; + debug("n: %d", n); Total += n; if (n < (ssize_t)iov[i].iov_len) + { + debug("break"); break; + } } + debug("readv: %d", Total); return Total; } @@ -271,17 +410,39 @@ static ssize_t sys_writev(int fildes, const struct iovec *iov, int iovcnt) ssize_t Total = 0; for (int i = 0; i < iovcnt; i++) { + debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len); ssize_t n = sys_write(fildes, iov[i].iov_base, iov[i].iov_len); if (n < 0) return n; + debug("n: %d", n); Total += n; if (n < (ssize_t)iov[i].iov_len) + { + debug("break"); break; + } } + debug("writev: %d", Total); return Total; } +/* https://man7.org/linux/man-pages/man2/dup.2.html */ +static int sys_dup(int oldfd) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_dup(oldfd)); +} + +/* https://man7.org/linux/man-pages/man2/dup.2.html */ +static int sys_dup2(int oldfd, int newfd) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_dup2(oldfd, newfd)); +} + /* https://man7.org/linux/man-pages/man3/exit.3.html */ static __noreturn void sys_exit(int status) { @@ -307,9 +468,24 @@ static int sys_creat(const char *pathname, mode_t mode) /* https://man7.org/linux/man-pages/man2/arch_prctl.2.html */ static int sys_arch_prctl(int code, unsigned long addr) { + Tasking::PCB *pcb = thisProcess; + Memory::Virtual vmm = Memory::Virtual(pcb->PageTable); + + if (!vmm.Check((void *)addr)) + { + warn("Invalid address %#lx", addr); + return -EFAULT; + } + + if (!vmm.Check((void *)addr, Memory::US)) + { + warn("Address %#lx is not user accessible", addr); + return -EPERM; + } + switch (code) { - case 0x1001: // ARCH_SET_GS + case ARCH_SET_GS: { #if defined(a64) CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); @@ -318,7 +494,7 @@ static int sys_arch_prctl(int code, unsigned long addr) #endif return 0; } - case 0x1002: // ARCH_SET_FS + case ARCH_SET_FS: { #if defined(a64) CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); @@ -327,7 +503,7 @@ static int sys_arch_prctl(int code, unsigned long addr) #endif return 0; } - case 0x1003: // ARCH_GET_FS + case ARCH_GET_FS: { #if defined(a64) *r_cst(uint64_t *, addr) = @@ -338,7 +514,7 @@ static int sys_arch_prctl(int code, unsigned long addr) #endif return 0; } - case 0x1004: // ARCH_GET_GS + case ARCH_GET_GS: { #if defined(a64) *r_cst(uint64_t *, addr) = @@ -349,17 +525,43 @@ static int sys_arch_prctl(int code, unsigned long addr) #endif return 0; } - default: - fixme("code=%d", code); + case ARCH_GET_CPUID: + case ARCH_SET_CPUID: + case ARCH_GET_XCOMP_SUPP: + case ARCH_GET_XCOMP_PERM: + case ARCH_REQ_XCOMP_PERM: + case ARCH_GET_XCOMP_GUEST_PERM: + case ARCH_REQ_XCOMP_GUEST_PERM: + case ARCH_XCOMP_TILECFG: + case ARCH_XCOMP_TILEDATA: + case ARCH_MAP_VDSO_X32: + case ARCH_MAP_VDSO_32: + case ARCH_MAP_VDSO_64: + case ARCH_GET_UNTAG_MASK: + case ARCH_ENABLE_TAGGED_ADDR: + case ARCH_GET_MAX_TAG_BITS: + case ARCH_FORCE_TAGGED_SVA: + { + fixme("Code %#lx not implemented", code); return -ENOSYS; } + default: + { + warn("Invalid code %#lx", code); + return -EINVAL; + } + } } /* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */ static pid_t sys_set_tid_address(int *tidptr) { + if (tidptr == nullptr) + return -EINVAL; + Tasking::TCB *tcb = thisThread; - *tidptr = tcb->ID; + + tcb->Linux.clear_child_tid = tidptr; return tcb->ID; } @@ -382,7 +584,7 @@ static SyscallData LinuxSyscallsTable[] = { [__NR_lseek] = {"lseek", (void *)sys_lseek}, [__NR_mmap] = {"mmap", (void *)sys_mmap}, [__NR_mprotect] = {"mprotect", (void *)sys_mprotect}, - [__NR_munmap] = {"munmap", (void *)nullptr}, + [__NR_munmap] = {"munmap", (void *)sys_munmap}, [__NR_brk] = {"brk", (void *)sys_brk}, [__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr}, [__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr}, @@ -403,8 +605,8 @@ static SyscallData LinuxSyscallsTable[] = { [__NR_shmget] = {"shmget", (void *)nullptr}, [__NR_shmat] = {"shmat", (void *)nullptr}, [__NR_shmctl] = {"shmctl", (void *)nullptr}, - [__NR_dup] = {"dup", (void *)nullptr}, - [__NR_dup2] = {"dup2", (void *)nullptr}, + [__NR_dup] = {"dup", (void *)sys_dup}, + [__NR_dup2] = {"dup2", (void *)sys_dup2}, [__NR_pause] = {"pause", (void *)nullptr}, [__NR_nanosleep] = {"nanosleep", (void *)nullptr}, [__NR_getitimer] = {"getitimer", (void *)nullptr}, @@ -837,7 +1039,7 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame) if (unlikely(!call)) { - error("Syscall %s(%d) not implemented.", + fixme("Syscall %s(%d) not implemented.", Syscall.Name, Frame->rax); return -ENOSYS; } diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index f8390af0..bd9fe9c8 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -224,6 +224,9 @@ static int sys_ipc(SysFrm *, enum IPCCommand Command, static long sys_local_thread_state(SysFrm *, int Code, unsigned long Address) { + /* TODO: return EFAULT if Address is not mapped */ + /* TODO: return EINVAL if Code is invalid */ + /* TODO: return EPERM if Address is outside of process address space */ #if defined(a64) || defined(aa64) switch (Code) { diff --git a/SystemCalls/Syscalls.cpp b/SystemCalls/Syscalls.cpp index 6c691424..e1ba8c40 100644 --- a/SystemCalls/Syscalls.cpp +++ b/SystemCalls/Syscalls.cpp @@ -21,44 +21,76 @@ #include "../kernel.h" +class AutoSwitchPageTable +{ +private: + uintptr_t Original; + +public: + AutoSwitchPageTable() + { +#if defined(a86) + asmv("mov %%cr3, %0" + : "=r"(Original)); + + asmv("mov %0, %%cr3" + : + : "r"(KernelPageTable)); +#endif + } + + ~AutoSwitchPageTable() + { +#if defined(a86) + asmv("mov %0, %%cr3" + : + : "r"(Original)); +#endif + } +}; + extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) { - Tasking::TaskInfo *Ptinfo = &thisProcess->Info; - Tasking::TaskInfo *Ttinfo = &thisThread->Info; - uint64_t TempTimeCalc = TimeManager->GetCounter(); + /* Automatically switch to kernel page table + and switch back when this function returns. */ + AutoSwitchPageTable PageSwitcher; - switch (Ttinfo->Compatibility) - { - case Tasking::TaskCompatibility::Native: - { - uintptr_t ret = 0; - if (Config.UseLinuxSyscalls) - ret = HandleLinuxSyscalls(Frame); - else - ret = HandleNativeSyscalls(Frame); - Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; - Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; - return ret; - } - case Tasking::TaskCompatibility::Linux: - { - uintptr_t ret = HandleLinuxSyscalls(Frame); - Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; - Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; - return ret; - } - case Tasking::TaskCompatibility::Windows: - { - error("Windows compatibility not implemented yet."); - break; - } - default: - { - error("Unknown compatibility mode! Killing thread..."); - TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL); - break; - } - } - assert(false); /* Should never reach here. */ - return 0; + uint64_t TempTimeCalc = TimeManager->GetCounter(); + Tasking::TaskInfo *Ptinfo = &thisProcess->Info; + Tasking::TaskInfo *Ttinfo = &thisThread->Info; + + switch (Ttinfo->Compatibility) + { + case Tasking::TaskCompatibility::Native: + { + uintptr_t ret = 0; + if (Config.UseLinuxSyscalls) + ret = HandleLinuxSyscalls(Frame); + else + ret = HandleNativeSyscalls(Frame); + Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; + Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; + return ret; + } + case Tasking::TaskCompatibility::Linux: + { + uintptr_t ret = HandleLinuxSyscalls(Frame); + Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; + Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; + return ret; + } + case Tasking::TaskCompatibility::Windows: + { + error("Windows compatibility not implemented yet."); + break; + } + default: + { + error("Unknown compatibility mode! Killing thread..."); + TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL); + break; + } + } + assert(false); /* Should never reach here. */ + return 0; } diff --git a/Tasking/Process.cpp b/Tasking/Process.cpp index 56ccf4fc..870b7ec8 100644 --- a/Tasking/Process.cpp +++ b/Tasking/Process.cpp @@ -55,16 +55,19 @@ namespace Tasking assert(name != nullptr); assert(strlen(name) > 0); - trace("Renaming thread %s to %s", this->Name, name); + trace("Renaming thread %s to %s", + this->Name, name); + if (this->Name) delete[] this->Name; + this->Name = new char[strlen(name) + 1]; strcpy((char *)this->Name, name); } void PCB::SetWorkingDirectory(VirtualFileSystem::Node *node) { - debug("Setting working directory of process %s to %#lx (%s)", + trace("Setting working directory of process %s to %#lx (%s)", this->Name, node, node->Name); CurrentWorkingDirectory = node; } @@ -75,94 +78,89 @@ namespace Tasking uint16_t UserID, uint16_t GroupID) { assert(ctx != nullptr); + assert(Name != nullptr); + assert(strlen(Name) > 0); assert(ExecutionMode >= _ExecuteModeMin); assert(ExecutionMode <= _ExecuteModeMax); this->ctx = ctx; this->ID = ctx->NextPID++; - if (this->Name) + + if (this->Name) /* Prevent memory leak */ delete[] this->Name; + this->Name = new char[strlen(Name) + 1]; strcpy((char *)this->Name, Name); this->ExitCode = KILL_CRASH; - this->Security.ExecutionMode = ExecutionMode; + /* Check parent */ if (Parent == nullptr) this->Parent = ctx->GetCurrentProcess(); else this->Parent = Parent; + /* Set uid & gid */ if (this->Parent && UserID == UINT16_MAX && GroupID == UINT16_MAX) { UserID = this->Parent->Security.Real.UserID; GroupID = this->Parent->Security.Real.GroupID; + debug("Inherited uid & gid from parent process %s(%d) with uid %d and gid %d", + this->Parent->Name, this->Parent->ID, UserID, GroupID); } this->Security.Real.UserID = UserID; this->Security.Real.GroupID = GroupID; this->Security.Effective.UserID = UserID; this->Security.Effective.GroupID = GroupID; + this->Security.ExecutionMode = ExecutionMode; - char ProcFSName[16]; + switch (ExecutionMode) + { + case TaskExecutionMode::System: + fixme("Mode not supported."); + [[fallthrough]]; + case TaskExecutionMode::Kernel: + { + this->Security.IsCritical = true; + break; + } + case TaskExecutionMode::User: + { + break; + } + default: + assert(false); + } + + char ProcFSName[12]; sprintf(ProcFSName, "%d", this->ID); this->ProcessDirectory = vfs->Create(ProcFSName, DIRECTORY, ProcFS); this->memDirectory = vfs->Create("mem", DIRECTORY, this->ProcessDirectory); - this->FileDescriptors = new FileDescriptorTable(this); - this->IPC = new class IPC((void *)this); - if (!DoNotCreatePageTable) + this->FileDescriptors = new FileDescriptorTable(this); + + /* If create page table */ + if (DoNotCreatePageTable == false) { OwnPageTable = true; - switch (ExecutionMode) - { - case TaskExecutionMode::System: - fixme("Mode not supported."); - [[fallthrough]]; - case TaskExecutionMode::Kernel: - { - this->Security.IsCritical = true; -#if defined(a64) - this->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw; -#elif defined(a32) - this->PageTable = (Memory::PageTable *)CPU::x32::readcr3().raw; -#elif defined(aa64) -#endif - debug("Process %s(%d) has page table at %#lx", - this->Name, this->ID, this->PageTable); - break; - } - case TaskExecutionMode::User: - { -#if defined(a64) - this->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(Memory::PageTable) + 1)); - memcpy(this->PageTable, - KernelPageTable, - sizeof(Memory::PageTable)); -#elif defined(a32) -#elif defined(aa64) -#endif - debug("Process %s(%d) has page table at %#lx", - this->Name, this->ID, this->PageTable); - break; - } - default: - assert(false); - } + + size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1); + this->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(PTPgs); + memcpy(this->PageTable, KernelPageTable, sizeof(Memory::PageTable)); + + debug("Process %s(%d) has page table at %#lx", + this->Name, this->ID, this->PageTable); } this->Memory = new Memory::MemMgr(this->PageTable, this->memDirectory); + this->ProgramBreak = new Memory::ProgramBreak(this->PageTable, this->Memory); + + this->IPC = new class IPC((void *)this); if (Image) - { this->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image); - } - else - { - debug("No image provided for process \"%s\"(%d)", - this->Name, this->ID); - } if (Parent) Parent->Children.push_back(this); @@ -182,32 +180,51 @@ namespace Tasking debug("Destroying process \"%s\"(%d)", this->Name, this->ID); + /* Remove us from the process list so we + don't get scheduled anymore */ ctx->ProcessList.erase(std::find(ctx->ProcessList.begin(), ctx->ProcessList.end(), this)); + /* If we have a symbol table allocated, + we need to free it */ if (this->ELFSymbolTable) delete this->ELFSymbolTable; + /* Free IPC */ delete this->IPC; - delete this->FileDescriptors; + + /* Free all allocated memory */ + delete this->ProgramBreak; delete this->Memory; + + /* Closing all open files */ + delete this->FileDescriptors; + + /* Free Name */ delete[] this->Name; + /* If we own the pointer to the + PageTable, we need to free it */ if (this->PageTable && OwnPageTable) { size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1); KernelAllocator.FreePages(this->PageTable, PTPgs); } + /* Exit all children processes */ foreach (auto pcb in this->Children) delete pcb; + /* Exit all threads */ foreach (auto tcb in this->Threads) delete tcb; + /* Delete /proc/{pid} directory */ vfs->Delete(this->ProcessDirectory, true); + /* If we have a Parent, remove us from + their children list */ if (this->Parent) { std::vector &pChild = this->Parent->Children; diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 1e543a41..6b4b216a 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -49,15 +49,15 @@ namespace Tasking #if defined(a86) __naked __used __no_stack_protector void IdleProcessLoop() { - asmv("IdleLoop:\n" - "hlt\n" - "jmp IdleLoop\n"); + asmv("IdleLoop:"); + asmv("hlt"); + asmv("jmp IdleLoop"); #elif defined(aa64) __used __no_stack_protector void IdleProcessLoop() { - asmv("IdleLoop:\n" - "wfe\n" - "b IdleLoop\n"); + asmv("IdleLoop:"); + asmv("wfe"); + asmv("b IdleLoop"); #endif } diff --git a/Tasking/Thread.cpp b/Tasking/Thread.cpp index 9b155e4b..fa4c18de 100644 --- a/Tasking/Thread.cpp +++ b/Tasking/Thread.cpp @@ -44,6 +44,7 @@ #define tskdbg(m, ...) #endif +/* For kernel threads only */ void ThreadDoExit() { CPUData *CPUData = GetCurrentCPU(); @@ -64,9 +65,12 @@ namespace Tasking assert(name != nullptr); assert(strlen(name) > 0); - trace("Renaming thread %s to %s", this->Name, name); + trace("Renaming thread %s to %s", + this->Name, name); + if (this->Name) delete[] this->Name; + this->Name = new char[strlen(name) + 1]; strcpy((char *)this->Name, name); } @@ -120,18 +124,182 @@ namespace Tasking this->Registers.r9 = Arg6; if (Function != nullptr) this->Registers.rip = (uint64_t)Function; +#elif defined(a32) + this->Registers.eax = Arg1; + this->Registers.ebx = Arg2; + this->Registers.ecx = Arg3; + this->Registers.edx = Arg4; + this->Registers.esi = Arg5; + this->Registers.edi = Arg6; + if (Function != nullptr) + this->Registers.eip = (uint32_t)Function; #else #warning "SYSV ABI not implemented for this architecture" #endif } - __no_sanitize("undefined") - TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint, - const char **argv, const char **envp, - const std::vector &auxv, - TaskArchitecture Architecture, - TaskCompatibility Compatibility, - bool ThreadNotReady) + __no_sanitize("undefined") void TCB::SetupUserStack_x86_64(const char **argv, + const char **envp, + const std::vector &auxv) + { + size_t ArgvSize = 0; + if (argv) + while (argv[ArgvSize] != nullptr) + ArgvSize++; + + size_t EnvpSize = 0; + if (envp) + while (envp[EnvpSize] != nullptr) + EnvpSize++; + + debug("ArgvSize: %d", ArgvSize); + debug("EnvpSize: %d", EnvpSize); + + /* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */ + /* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */ + // rsp is the top of the stack + char *Stack = (char *)this->Stack->GetStackPhysicalTop(); + // Temporary stack pointer for strings + char *StackStrings = (char *)Stack; + char *StackStringsVirtual = (char *)this->Stack->GetStackTop(); + + // Store string pointers for later + uintptr_t *ArgvStrings = nullptr; + uintptr_t *EnvpStrings = nullptr; + if (ArgvSize > 0) + ArgvStrings = new uintptr_t[ArgvSize]; + if (EnvpSize > 0) + EnvpStrings = new uintptr_t[EnvpSize]; + + for (size_t i = 0; i < ArgvSize; i++) + { + // Subtract the length of the string and the null terminator + StackStrings -= strlen(argv[i]) + 1; + StackStringsVirtual -= strlen(argv[i]) + 1; + // Store the pointer to the string + ArgvStrings[i] = (uintptr_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, argv[i]); + debug("argv[%d]: %s", i, argv[i]); + } + + for (size_t i = 0; i < EnvpSize; i++) + { + // Subtract the length of the string and the null terminator + StackStrings -= strlen(envp[i]) + 1; + StackStringsVirtual -= strlen(envp[i]) + 1; + // Store the pointer to the string + EnvpStrings[i] = (uintptr_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, envp[i]); + debug("envp[%d]: %s", i, envp[i]); + } + + // Align the stack to 16 bytes + StackStrings -= (uintptr_t)StackStrings & 0xF; + // Set "Stack" to the new stack pointer + Stack = (char *)StackStrings; + // If argv and envp sizes are odd then we need to align the stack + Stack -= (ArgvSize + EnvpSize) % 2; + + // We need 8 bit pointers for the stack from here + uintptr_t *Stack64 = (uintptr_t *)Stack; + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator + std::vector auxv_array = auxv; + if (auxv_array.size() == 0) + auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + + // Store auxillary vector + foreach (AuxiliaryVector var in auxv_array) + { + // Subtract the size of the auxillary vector + Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t); + // Store the auxillary vector + POKE(Elf64_auxv_t, Stack64) = var.archaux; + // TODO: Store strings to the stack + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store EnvpStrings[] to the stack + Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize) + for (size_t i = 0; i < EnvpSize; i++) + { + *(Stack64 + i) = (uintptr_t)EnvpStrings[i]; + debug("EnvpStrings[%d]: %#lx", + i, EnvpStrings[i]); + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store ArgvStrings[] to the stack + Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize) + for (size_t i = 0; i < ArgvSize; i++) + { + *(Stack64 + i) = (uintptr_t)ArgvStrings[i]; + debug("ArgvStrings[%d]: %#lx", + i, ArgvStrings[i]); + } + + // Store the argc + Stack64--; + *Stack64 = ArgvSize; + + // Set "Stack" to the new stack pointer + Stack = (char *)Stack64; + + /* We need the virtual address but because we are in the kernel we can't use the process page table. + So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */ + uintptr_t SubtractStack = (uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)Stack; + debug("SubtractStack: %#lx", SubtractStack); + + // Set the stack pointer to the new stack + this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack); + + if (ArgvSize > 0) + delete[] ArgvStrings; + if (EnvpSize > 0) + delete[] EnvpStrings; + +#ifdef DEBUG + DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack); +#endif + + this->Registers.rdi = (uintptr_t)ArgvSize; // argc + this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv + this->Registers.rcx = (uintptr_t)EnvpSize; // envc + this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp + } + + void TCB::SetupUserStack_x86_32(const char **argv, + const char **envp, + const std::vector &auxv) + { + fixme("Not implemented"); + } + + void TCB::SetupUserStack_aarch64(const char **argv, + const char **envp, + const std::vector &auxv) + { + fixme("Not implemented"); + } + + TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint, + const char **argv, const char **envp, + const std::vector &auxv, + TaskArchitecture Architecture, + TaskCompatibility Compatibility, + bool ThreadNotReady) { assert(ctx != nullptr); assert(Architecture >= _ArchitectureMin); @@ -152,42 +320,20 @@ namespace Tasking if (this->Name) delete[] this->Name; + this->Name = new char[strlen(this->Parent->Name) + 1]; strcpy((char *)this->Name, this->Parent->Name); this->EntryPoint = EntryPoint; this->ExitCode = KILL_CRASH; - this->Info.Architecture = Architecture; - this->Info.Compatibility = Compatibility; - this->Security.ExecutionMode = - this->Parent->Security.ExecutionMode; + if (ThreadNotReady) this->Status = TaskStatus::Zombie; else this->Status = TaskStatus::Ready; + this->Memory = new Memory::MemMgr(this->Parent->PageTable, this->Parent->memDirectory); - std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1); - this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs); - memset(this->FPU, 0, sizeof(CPU::x64::FXState)); - - // TODO: Is really a good idea to use the FPU in kernel mode? - this->FPU->mxcsr = 0b0001111110000000; - this->FPU->mxcsrmask = 0b1111111110111111; - this->FPU->fcw = 0b0000001100111111; - - // CPU::x64::fxrstor(this->FPU); - // uint16_t FCW = 0b1100111111; - // asmv("fldcw %0" - // : - // : "m"(FCW) - // : "memory"); - // uint32_t MXCSR = 0b1111110000000; - // asmv("ldmxcsr %0" - // : - // : "m"(MXCSR) - // : "memory"); - // CPU::x64::fxsave(this->FPU); #if defined(a64) this->Registers.rip = EntryPoint; @@ -221,7 +367,17 @@ namespace Tasking this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop()); POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit; #elif defined(a32) + this->Registers.cs = GDT_KERNEL_CODE; + this->Registers.ss = GDT_KERNEL_DATA; + this->Registers.eflags.AlwaysOne = 1; + this->Registers.eflags.IF = 1; + this->Registers.eflags.ID = 1; + this->Registers.esp = ((uintptr_t)this->Stack->GetStackTop()); + POKE(uintptr_t, this->Registers.esp) = (uintptr_t)ThreadDoExit; #elif defined(aa64) + this->Registers.pc = EntryPoint; + this->Registers.sp = ((uintptr_t)this->Stack->GetStackTop()); + POKE(uintptr_t, this->Registers.sp) = (uintptr_t)ThreadDoExit; #endif break; } @@ -250,150 +406,23 @@ namespace Tasking /* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get - GPF or PF exception. */ - -#pragma region - size_t ArgvSize = 0; - if (argv) - while (argv[ArgvSize] != nullptr) - ArgvSize++; - - size_t EnvpSize = 0; - if (envp) - while (envp[EnvpSize] != nullptr) - EnvpSize++; - - debug("ArgvSize: %d", ArgvSize); - debug("EnvpSize: %d", EnvpSize); - - /* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */ - /* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */ - // rsp is the top of the stack - char *Stack = (char *)this->Stack->GetStackPhysicalTop(); - // Temporary stack pointer for strings - char *StackStrings = (char *)Stack; - char *StackStringsVirtual = (char *)this->Stack->GetStackTop(); - - // Store string pointers for later - uintptr_t *ArgvStrings = nullptr; - uintptr_t *EnvpStrings = nullptr; - if (ArgvSize > 0) - ArgvStrings = new uintptr_t[ArgvSize]; - if (EnvpSize > 0) - EnvpStrings = new uintptr_t[EnvpSize]; - - for (size_t i = 0; i < ArgvSize; i++) - { - // Subtract the length of the string and the null terminator - StackStrings -= strlen(argv[i]) + 1; - StackStringsVirtual -= strlen(argv[i]) + 1; - // Store the pointer to the string - ArgvStrings[i] = (uintptr_t)StackStringsVirtual; - // Copy the string to the stack - strcpy(StackStrings, argv[i]); - debug("argv[%d]: %s", i, argv[i]); - } - - for (size_t i = 0; i < EnvpSize; i++) - { - // Subtract the length of the string and the null terminator - StackStrings -= strlen(envp[i]) + 1; - StackStringsVirtual -= strlen(envp[i]) + 1; - // Store the pointer to the string - EnvpStrings[i] = (uintptr_t)StackStringsVirtual; - // Copy the string to the stack - strcpy(StackStrings, envp[i]); - debug("envp[%d]: %s", i, envp[i]); - } - - // Align the stack to 16 bytes - StackStrings -= (uintptr_t)StackStrings & 0xF; - // Set "Stack" to the new stack pointer - Stack = (char *)StackStrings; - // If argv and envp sizes are odd then we need to align the stack - Stack -= (ArgvSize + EnvpSize) % 2; - - // We need 8 bit pointers for the stack from here - uintptr_t *Stack64 = (uintptr_t *)Stack; - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator - std::vector auxv_array = auxv; - if (auxv_array.size() == 0) - auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - - // Store auxillary vector - foreach (AuxiliaryVector var in auxv_array) - { - // Subtract the size of the auxillary vector - Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t); - // Store the auxillary vector - POKE(Elf64_auxv_t, Stack64) = var.archaux; - // TODO: Store strings to the stack - } - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // Store EnvpStrings[] to the stack - Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize) - for (size_t i = 0; i < EnvpSize; i++) - { - *(Stack64 + i) = (uintptr_t)EnvpStrings[i]; - debug("EnvpStrings[%d]: %#lx", - i, EnvpStrings[i]); - } - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // Store ArgvStrings[] to the stack - Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize) - for (size_t i = 0; i < ArgvSize; i++) - { - *(Stack64 + i) = (uintptr_t)ArgvStrings[i]; - debug("ArgvStrings[%d]: %#lx", - i, ArgvStrings[i]); - } - - // Store the argc - Stack64--; - *Stack64 = ArgvSize; - - // Set "Stack" to the new stack pointer - Stack = (char *)Stack64; - - /* We need the virtual address but because we are in the kernel we can't use the process page table. - So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */ - uintptr_t SubtractStack = (uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)Stack; - debug("SubtractStack: %#lx", SubtractStack); - - // Set the stack pointer to the new stack - this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack); - - if (ArgvSize > 0) - delete[] ArgvStrings; - if (EnvpSize > 0) - delete[] EnvpStrings; - -#ifdef DEBUG - DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack); -#endif - - this->Registers.rdi = (uintptr_t)ArgvSize; // argc - this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv - this->Registers.rcx = (uintptr_t)EnvpSize; // envc - this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp - -#pragma endregion + an exception. */ + this->SetupUserStack_x86_64(argv, envp, auxv); #elif defined(a32) + this->Registers.cs = GDT_USER_CODE; + this->Registers.ss = GDT_USER_DATA; + this->Registers.eflags.AlwaysOne = 1; + this->Registers.eflags.IF = 1; + this->Registers.eflags.ID = 1; + /* We need to leave the libc's crt + to make a syscall when the Thread + is exited or we are going to get + an exception. */ + + this->SetupUserStack_x86_32(argv, envp, auxv); #elif defined(aa64) + this->SetupUserStack_aarch64(argv, envp, auxv); #endif #ifdef DEBUG_TASKING DumpData(this->Name, this->Stack, STACK_SIZE); @@ -404,7 +433,32 @@ namespace Tasking assert(false); } - this->Info.SpawnTime = TimeManager->GetCounter(); + this->Info.Architecture = Architecture; + this->Info.Compatibility = Compatibility; + this->Security.ExecutionMode = + this->Parent->Security.ExecutionMode; + + std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1); + this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs); + memset(this->FPU, 0, sizeof(CPU::x64::FXState)); + + // TODO: Is really a good idea to use the FPU in kernel mode? + this->FPU->mxcsr = 0b0001111110000000; + this->FPU->mxcsrmask = 0b1111111110111111; + this->FPU->fcw = 0b0000001100111111; + + // CPU::x64::fxrstor(this->FPU); + // uint16_t FCW = 0b1100111111; + // asmv("fldcw %0" + // : + // : "m"(FCW) + // : "memory"); + // uint32_t MXCSR = 0b1111110000000; + // asmv("ldmxcsr %0" + // : + // : "m"(MXCSR) + // : "memory"); + // CPU::x64::fxsave(this->FPU); #ifdef DEBUG #ifdef a64 @@ -436,6 +490,8 @@ namespace Tasking this->Parent->ID); #endif + this->Info.SpawnTime = TimeManager->GetCounter(); + this->Parent->Threads.push_back(this); if (this->Parent->Threads.size() == 1 && @@ -448,13 +504,20 @@ namespace Tasking TCB::~TCB() { + /* Remove us from the process list so we + don't get scheduled anymore */ std::vector &Threads = this->Parent->Threads; Threads.erase(std::find(Threads.begin(), Threads.end(), this)); + /* Free Name */ delete[] this->Name; + + /* Free CPU Stack */ delete this->Stack; + + /* Free all allocated memory */ delete this->Memory; } } diff --git a/Tests/MemoryAllocation.cpp b/Tests/MemoryAllocation.cpp index f60abc1e..4be270f8 100644 --- a/Tests/MemoryAllocation.cpp +++ b/Tests/MemoryAllocation.cpp @@ -44,7 +44,6 @@ test_mem_new_delete::~test_mem_new_delete() ; } -extern bool EnableExternalMemoryTracer; extern bool DebuggerIsAttached; void TestMemoryAllocation() @@ -52,9 +51,9 @@ void TestMemoryAllocation() #ifdef a32 return; /* Not ready for now. */ #endif - if (EnableExternalMemoryTracer || DebuggerIsAttached) + if (DebuggerIsAttached) { - debug("The test is disabled when the external memory tracer or a debugger is enabled."); + debug("The test is disabled when the debugger is enabled."); return; } @@ -68,13 +67,13 @@ void TestMemoryAllocation() debug("Single Page Request Test"); { - uint64_t prq1 = (uint64_t)KernelAllocator.RequestPage(); + uintptr_t prq1 = (uintptr_t)KernelAllocator.RequestPage(); KernelAllocator.FreePage((void *)prq1); for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) KernelAllocator.FreePage(KernelAllocator.RequestPage()); - uint64_t prq2 = (uint64_t)KernelAllocator.RequestPage(); + uintptr_t prq2 = (uintptr_t)KernelAllocator.RequestPage(); KernelAllocator.FreePage((void *)prq2); debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); @@ -83,13 +82,13 @@ void TestMemoryAllocation() debug("Multiple Page Request Test"); { - uint64_t prq1 = (uint64_t)KernelAllocator.RequestPages(10); + uintptr_t prq1 = (uintptr_t)KernelAllocator.RequestPages(10); KernelAllocator.FreePages((void *)prq1, 10); for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) KernelAllocator.FreePages(KernelAllocator.RequestPages(20), 20); - uint64_t prq2 = (uint64_t)KernelAllocator.RequestPages(10); + uintptr_t prq2 = (uintptr_t)KernelAllocator.RequestPages(10); KernelAllocator.FreePages((void *)prq2, 10); debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); diff --git a/Tests/MemoryOperations.cpp b/Tests/MemoryOperations.cpp index e487cbda..3b16a085 100644 --- a/Tests/MemoryOperations.cpp +++ b/Tests/MemoryOperations.cpp @@ -21,15 +21,15 @@ #include #include -extern bool EnableExternalMemoryTracer; + extern bool DebuggerIsAttached; extern Memory::MemoryAllocatorType AllocatorType; __constructor void TestMemoryOperations() { - if (EnableExternalMemoryTracer || DebuggerIsAttached) + if (DebuggerIsAttached) { - debug("The test is disabled when the external memory tracer or a debugger is enabled."); + debug("The test is disabled when the debugger is enabled."); return; } diff --git a/include/exec.hpp b/include/exec.hpp index 0347fe6a..9eee9450 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -66,6 +66,18 @@ namespace Execute std::vector Elfauxv; Tasking::IP ip; + void GenerateAuxiliaryVector_x86_32(Memory::MemMgr *mm, + int fd, + Elf32_Ehdr ELFHeader, + uint32_t EntryPoint, + uint32_t BaseAddress); + + void GenerateAuxiliaryVector_x86_64(Memory::MemMgr *mm, + int fd, + Elf64_Ehdr ELFHeader, + uint64_t EntryPoint, + uint64_t BaseAddress); + void LoadExec_x86_32(int fd, Tasking::PCB *TargetProcess); @@ -99,7 +111,8 @@ namespace Execute int Spawn(char *Path, const char **argv, const char **envp, Tasking::PCB *Parent = nullptr, - Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); + Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native, + bool Critical = false); bool ELFIs64(void *Header); Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header); diff --git a/include/filesystem.hpp b/include/filesystem.hpp index 0d1e340a..976fbcee 100644 --- a/include/filesystem.hpp +++ b/include/filesystem.hpp @@ -357,7 +357,23 @@ namespace VirtualFileSystem class FileDescriptorTable { public: - struct FileDescriptor + struct winsize + { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; + }; + + struct Fildes + { + RefNode *Handle{}; + mode_t Mode = 0; + int Flags = 0; + int Descriptor = -1; + }; + + struct DupFildes { RefNode *Handle{}; mode_t Mode = 0; @@ -366,10 +382,13 @@ namespace VirtualFileSystem }; private: - std::vector FileDescriptors; + std::vector FileDescriptors; + std::vector FildesDuplicates; VirtualFileSystem::Node *fdDir = nullptr; - FileDescriptor GetFileDescriptor(int FileDescriptor); + Fildes GetFileDescriptor(int FileDescriptor); + FileDescriptorTable::DupFildes GetDupFildes(int FileDescriptor); + int ProbeMode(mode_t Mode, int Flags); int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags); int RemoveFileDescriptor(int FileDescriptor); @@ -377,7 +396,7 @@ namespace VirtualFileSystem public: std::string GetAbsolutePath(int FileDescriptor); - std::vector &GetFileDescriptors() { return FileDescriptors; } + std::vector &GetFileDescriptors() { return FileDescriptors; } int _open(const char *pathname, int flags, mode_t mode); int _creat(const char *pathname, mode_t mode); @@ -388,6 +407,9 @@ namespace VirtualFileSystem int _stat(const char *pathname, struct stat *statbuf); int _fstat(int fd, struct stat *statbuf); int _lstat(const char *pathname, struct stat *statbuf); + int _dup(int oldfd); + int _dup2(int oldfd, int newfd); + int _ioctl(int fd, unsigned long request, void *argp); FileDescriptorTable(void *Owner); ~FileDescriptorTable(); diff --git a/include/filesystem/mounts.hpp b/include/filesystem/mounts.hpp index b6f46e38..94f2e5fa 100644 --- a/include/filesystem/mounts.hpp +++ b/include/filesystem/mounts.hpp @@ -22,93 +22,9 @@ #include -namespace VirtualFileSystem -{ - /* Manage /dev */ - class Device - { - public: - Node *AddFileSystem(FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags); - Device(); - ~Device(); - }; - - /* Manage /mnt */ - class Mount - { - public: - Node *MountFileSystem(FileSystemOperations *Operator, uint64_t Mode, const char *Name); - void DetectAndMountFS(void *drive); - Mount(); - ~Mount(); - }; - - /* Manage /prc */ - class Process - { - public: - Process(); - ~Process(); - }; - - /* Manage /drv */ - class Driver - { - public: - Node *AddDriver(struct FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags); - Driver(); - ~Driver(); - }; - - /* Manage /net */ - class Network - { - public: - Node *AddNetworkCard(struct FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags); - Network(); - ~Network(); - }; - - /* Manage /dev/serialX */ - class Serial - { - public: - Serial(); - ~Serial(); - }; - - /* Manage /dev/random */ - class Random - { - public: - Random(); - ~Random(); - }; - - /* Manage /dev/null */ - class Null - { - public: - Null(); - ~Null(); - }; - - /* Manage /dev/zero */ - class Zero - { - public: - Zero(); - ~Zero(); - }; - - /* Manage /dev/fbX */ - class FB - { - public: - void SetFrameBufferData(uintptr_t Address, size_t Size, uint32_t Width, uint32_t Height, uint32_t PixelsPerScanLine); - FB(); - ~FB(); - }; -} +void Init_Null(VirtualFileSystem::Virtual *vfs_ctx); +void Init_Random(VirtualFileSystem::Virtual *vfs_ctx); +void Init_Teletype(VirtualFileSystem::Virtual *vfs_ctx); +void Init_Zero(VirtualFileSystem::Virtual *vfs_ctx); #endif // !__FENNIX_KERNEL_FILESYSTEM_DEV_H__ diff --git a/include/memory.hpp b/include/memory.hpp index e94f9628..66ba079f 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -66,16 +66,12 @@ extern uintptr_t _kernel_bss_start, _kernel_bss_end; #define FROM_PAGES(d) ((d)*PAGE_SIZE) #if defined(a64) || defined(aa64) -#define NORMAL_VMA_OFFSET 0xFFFF800000000000 #define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000 -#define KERNEL_HEAP_BASE 0xFFFFA00000000000 -#define USER_HEAP_BASE 0xFFFFB00000000000 +#define KERNEL_HEAP_BASE 0xFFFFFF0000000000 #define USER_STACK_BASE 0xFFFFEFFFFFFF0000 #elif defined(a32) -#define NORMAL_VMA_OFFSET 0x80000000 #define KERNEL_VMA_OFFSET 0xC0000000 #define KERNEL_HEAP_BASE 0xA0000000 -#define USER_HEAP_BASE 0xB0000000 #define USER_STACK_BASE 0xEFFFFFFF #endif @@ -86,6 +82,7 @@ namespace Memory None, Pages, XallocV1, + XallocV2, liballoc11 }; @@ -584,8 +581,35 @@ namespace Memory * @return A new PageTable with the same content */ PageTable Fork(); + + template + T Get(T Address); } __aligned(0x1000); + class TempSwitchPT + { + private: + PageTable *Replace = nullptr; + PageTable *Restore = nullptr; + + public: + TempSwitchPT(PageTable *ReplaceWith, + PageTable *RestoreWith = nullptr) + : Replace(ReplaceWith) + { + extern PageTable *KernelPageTable; + + if (RestoreWith) + Restore = RestoreWith; + else + Restore = KernelPageTable; + + Replace->Update(); + } + + ~TempSwitchPT() { Restore->Update(); } + }; + class Physical { private: @@ -1077,6 +1101,30 @@ namespace Memory std::vector AllocatedPagesList; }; + class ProgramBreak + { + private: + PageTable *Table = nullptr; + MemMgr *mm = nullptr; + + uintptr_t HeapStart = 0x0; + uintptr_t Break = 0x0; + + public: + /* Directly to syscall */ + void *brk(void *Address); + + void InitBrk(uintptr_t Address) + { + function("%#lx", Address); + HeapStart = Address; + Break = Address; + } + + ProgramBreak(PageTable *Table, MemMgr *mm); + ~ProgramBreak(); + }; + class SmartHeap { private: diff --git a/include/task.hpp b/include/task.hpp index 94997216..79906414 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -159,17 +159,35 @@ namespace Tasking private: class Task *ctx = nullptr; + void SetupUserStack_x86_64(const char **argv, + const char **envp, + const std::vector &auxv); + + void SetupUserStack_x86_32(const char **argv, + const char **envp, + const std::vector &auxv); + + void SetupUserStack_aarch64(const char **argv, + const char **envp, + const std::vector &auxv); + public: + /* Basic info */ TID ID = -1; - const char * Name = nullptr; + const char *Name = nullptr; class PCB *Parent = nullptr; IP EntryPoint = 0; + /* Statuses */ std::atomic_int ExitCode; - std::atomic Status = TaskStatus::UnknownStatus; - Memory::StackGuard *Stack; - Memory::MemMgr *Memory; + std::atomic Status = TaskStatus::Zombie; int ErrorNumber; + + /* Memory */ + Memory::MemMgr *Memory; + Memory::StackGuard *Stack; + + /* CPU state */ #if defined(a64) CPU::x64::TrapFrame Registers{}; uintptr_t ShadowGSBase, GSBase, FSBase; @@ -180,6 +198,9 @@ namespace Tasking uintptr_t Registers; // TODO #endif uintptr_t IPHistory[128]; + CPU::x64::FXState *FPU; + + /* Info & Security info */ struct { TaskExecutionMode ExecutionMode = UnknownExecutionMode; @@ -188,7 +209,13 @@ namespace Tasking bool IsKernelDebugEnabled = false; } Security{}; TaskInfo Info{}; - CPU::x64::FXState *FPU; + + /* Compatibility structures */ + struct + { + int *set_child_tid{}; + int *clear_child_tid{}; + } Linux{}; void Rename(const char *name); void SetPriority(TaskPriority priority); @@ -228,11 +255,16 @@ namespace Tasking bool OwnPageTable = false; public: + /* Basic info */ PID ID = -1; - const char * Name = nullptr; + const char *Name = nullptr; PCB *Parent = nullptr; + + /* Statuses */ std::atomic_int ExitCode; std::atomic Status = Zombie; + + /* Info & Security info */ struct { TaskExecutionMode ExecutionMode = UnknownExecutionMode; @@ -246,17 +278,26 @@ namespace Tasking } Real, Effective; } Security{}; TaskInfo Info{}; - std::vector Threads; - std::vector Children; - InterProcessCommunication::IPC *IPC; - Memory::PageTable *PageTable; - SymbolResolver::Symbols *ELFSymbolTable; + + /* Filesystem */ Node *CurrentWorkingDirectory; Node *ProcessDirectory; Node *memDirectory; - Memory::MemMgr *Memory; FileDescriptorTable *FileDescriptors; + /* Memory */ + Memory::PageTable *PageTable; + Memory::MemMgr *Memory; + Memory::ProgramBreak *ProgramBreak; + + /* Other */ + InterProcessCommunication::IPC *IPC; + SymbolResolver::Symbols *ELFSymbolTable; + + /* Threads & Children */ + std::vector Threads; + std::vector Children; + public: void Rename(const char *name); void SetWorkingDirectory(Node *node); diff --git a/include/types.h b/include/types.h index dfd761a4..9d02fc14 100644 --- a/include/types.h +++ b/include/types.h @@ -21,10 +21,10 @@ #ifdef __cplusplus #define EXTERNC extern "C" #define START_EXTERNC \ - EXTERNC \ - { + EXTERNC \ + { #define END_EXTERNC \ - } + } #else // __cplusplus #define EXTERNC #define START_EXTERNC @@ -52,8 +52,8 @@ #define in : #define forItr(itr, container) \ - for (auto itr = container.begin(); \ - itr != container.end(); ++itr) + for (auto itr = container.begin(); \ + itr != container.end(); ++itr) #define r_cst(t, v) reinterpret_cast(v) #define c_cst(t, v) const_cast(v) @@ -83,18 +83,18 @@ typedef __builtin_va_list va_list; #define offsetof(type, member) __builtin_offsetof(type, member) #define MAX(a, b) \ - ({ \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a > _b ? _a : _b; \ - }) + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) #define MIN(a, b) \ - ({ \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; \ - }) + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) #define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1)) #define ROUND_DOWN(x, y) ((x) & ~((y)-1)) @@ -291,19 +291,19 @@ typedef unsigned gid_t; #if defined(a64) #define BREAK __asm__ __volatile__("int $0x3" \ - : \ - : \ - : "memory"); + : \ + : \ + : "memory"); #elif defined(a32) #define BREAK __asm__ __volatile__("int $0x3" \ - : \ - : \ - : "memory"); + : \ + : \ + : "memory"); #elif defined(aa64) #define BREAK __asm__ __volatile__("brk #0" \ - : \ - : \ - : "memory"); + : \ + : \ + : "memory"); #endif #ifdef __INT48_TYPE__ @@ -327,11 +327,11 @@ typedef uint48_t uint_fast48_t; #define b16(x) __builtin_bswap16(x) #define b32(x) __builtin_bswap32(x) #define b48(x) (((((x)&0x0000000000ff) << 40) | \ - (((x)&0x00000000ff00) << 24) | \ - (((x)&0x000000ff0000) << 8) | \ - (((x)&0x0000ff000000) >> 8) | \ - (((x)&0x00ff00000000) >> 24) | \ - (((x)&0xff0000000000) >> 40))) + (((x)&0x00000000ff00) << 24) | \ + (((x)&0x000000ff0000) << 8) | \ + (((x)&0x0000ff000000) >> 8) | \ + (((x)&0x00ff00000000) >> 24) | \ + (((x)&0xff0000000000) >> 40))) #define b64(x) __builtin_bswap64(x) /* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */ @@ -411,16 +411,10 @@ typedef uint48_t uint_fast48_t; #define NIF __no_instrument_function -#define int1 \ - __asm__ __volatile__("int $0x1" \ - : \ - : \ - : "memory") - #define int3 \ - __asm__ __volatile__("int3" \ - : \ - : \ - : "memory") + __asm__ __volatile__("int3" \ + : \ + : \ + : "memory") #endif // !__FENNIX_KERNEL_TYPES_H__ diff --git a/include_std/std/string.hpp b/include_std/std/string.hpp index 2a9937bf..9bfab12e 100644 --- a/include_std/std/string.hpp +++ b/include_std/std/string.hpp @@ -22,7 +22,7 @@ #include #include -// show debug messages +// Show debug messages // #define DEBUG_CPP_STRING 1 // #define DEBUG_CPP_STRING_VERBOSE 1 @@ -62,48 +62,49 @@ namespace std this->Capacity = this->Length + 1; this->Data = new char[this->Capacity]; strcpy(this->Data, Str); - strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } ~string() { - strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); delete[] this->Data, this->Data = nullptr; } size_t length() const { - v_strdbg("String length: %d", - this->Length); + v_strdbg("%#lx: String length: %d", + this, this->Length); return this->Length; } size_t capacity() const { - v_strdbg("String capacity: %d", - this->Capacity); + v_strdbg("%#lx: String capacity: %d", + this, this->Capacity); return this->Capacity; } const char *c_str() const { - v_strdbg("String data: \"%s\"", - this->Data); + v_strdbg("%#lx: String data: \"%s\"", + this, this->Data); return this->Data; } void resize(size_t NewLength) { - strdbg("String resize: %d", NewLength); + strdbg("%#lx: String resize: %d", + this, NewLength); if (NewLength < this->Capacity) { this->Length = NewLength; this->Data[this->Length] = '\0'; - strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return; } @@ -111,16 +112,16 @@ namespace std char *newData = new char[newCapacity]; strcpy(newData, this->Data); - strdbg("old: %#lx, new: %#lx", - this->Data, newData); + strdbg("%#lx: old: %#lx, new: %#lx", + this, this->Data, newData); delete[] this->Data; this->Data = newData; this->Length = NewLength; this->Capacity = newCapacity; - strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } void concat(const string &Other) @@ -129,31 +130,34 @@ namespace std this->resize(NewLength); strcat(this->Data, Other.Data); - strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } bool empty() const { - strdbg("String empty: %d", this->Length == 0); + strdbg("%#lx: String empty: %d", + this, this->Length == 0); return this->Length == 0; } size_t size() const { - strdbg("String size: %d", this->Length); + strdbg("%#lx: String size: %d", + this, this->Length); return this->Length; } void clear() { - strdbg("String clear"); + strdbg("%#lx: String clear", this); this->resize(0); } size_t find(const char *Str, size_t Pos = 0) const { - strdbg("String find: \"%s\", %d", Str, Pos); + strdbg("%#lx: String find: \"%s\", %d", + this, Str, Pos); if (Pos >= this->Length) return npos; @@ -176,13 +180,15 @@ namespace std size_t find(const string &Str, size_t Pos = 0) const { - strdbg("String find: \"%s\", %d", Str.c_str(), Pos); + strdbg("%#lx: String find: \"%s\", %d", + this, Str.c_str(), Pos); return this->find(Str.c_str(), Pos); } void erase(int Index, int Count = 1) { - strdbg("String erase: %d, %d", Index, Count); + strdbg("%#lx: String erase: %d, %d", + this, Index, Count); if (Index < 0 || (size_t)Index >= this->Length) return; @@ -197,12 +203,14 @@ namespace std this->Length -= Count; this->Data[this->Length] = '\0'; - strdbg("String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } size_t find_last_not_of(const char *Str, size_t Pos = npos) const { - strdbg("String find_last_not_of: \"%s\", %d", Str, Pos); + strdbg("%#lx: String find_last_not_of: \"%s\", %d", + this, Str, Pos); if (Pos == npos) Pos = this->Length - 1; @@ -225,7 +233,8 @@ namespace std size_t find_first_not_of(const char *Str, size_t Pos = 0) const { - strdbg("String find_first_not_of: \"%s\", %d", Str, Pos); + strdbg("%#lx: String find_first_not_of: \"%s\", %d", + this, Str, Pos); if (Pos >= this->Length) return npos; @@ -248,7 +257,8 @@ namespace std size_t find_first_of(const char *Str, size_t Pos = 0) const { - strdbg("String find_first_of: \"%s\", %d", Str, Pos); + strdbg("%#lx: String find_first_of: \"%s\", %d", + this, Str, Pos); if (Pos >= this->Length) return npos; @@ -271,7 +281,8 @@ namespace std size_t find_last_of(const char *Str, size_t Pos = npos) const { - strdbg("String find_last_of: \"%s\", %d", Str, Pos); + strdbg("%#lx: String find_last_of: \"%s\", %d", + this, Str, Pos); if (Pos == npos) Pos = this->Length - 1; @@ -294,7 +305,8 @@ namespace std size_t find_first_of(char C, size_t Pos = 0) const { - strdbg("String find_first_of: '%c', %d", C, Pos); + strdbg("%#lx: String find_first_of: '%c', %d", + this, C, Pos); if (Pos >= this->Length) return npos; @@ -308,7 +320,8 @@ namespace std size_t find_last_of(char C, size_t Pos = npos) const { - strdbg("String find_last_of: '%c', %d", C, Pos); + strdbg("%#lx: String find_last_of: '%c', %d", + this, C, Pos); if (Pos == npos) Pos = this->Length - 1; @@ -322,7 +335,8 @@ namespace std size_t substr(const char *Str, size_t Pos = 0) const { - strdbg("String substr: \"%s\", %d", Str, Pos); + strdbg("%#lx: String substr: \"%s\", %d", + this, Str, Pos); if (Pos >= this->Length) return npos; @@ -345,13 +359,15 @@ namespace std size_t substr(const string &Str, size_t Pos = 0) const { - strdbg("String substr: \"%s\", %d", Str.c_str(), Pos); + strdbg("%#lx: String substr: \"%s\", %d", + this, Str.c_str(), Pos); return this->substr(Str.c_str(), Pos); } string substr(size_t Pos = 0, size_t Count = npos) const { - strdbg("String substr: %d, %d", Pos, Count); + strdbg("%#lx: String substr: %d, %d", + this, Pos, Count); if (Pos >= this->Length) return string(); @@ -371,7 +387,8 @@ namespace std void replace(size_t Pos, size_t Count, const char *Str) { - strdbg("String replace: %d, %d, \"%s\"", Pos, Count, Str); + strdbg("%#lx: String replace: %d, %d, \"%s\"", + this, Pos, Count, Str); if (Pos >= this->Length) return; @@ -390,12 +407,14 @@ namespace std for (unsigned long i = 0; i < strlen(Str); i++) this->Data[Pos + i] = Str[i]; - strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } void replace(size_t Pos, size_t Count, const string &Str) { - strdbg("String replace: %d, %d, \"%s\"", Pos, Count, Str.Data); + strdbg("%#lx: String replace: %d, %d, \"%s\"", + this, Pos, Count, Str.Data); if (Pos >= this->Length) return; @@ -414,13 +433,13 @@ namespace std for (size_t i = 0; i < Str.Length; i++) this->Data[Pos + i] = Str.Data[i]; - strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); } void pop_back() { - strdbg("String pop_back"); + strdbg("%#lx: String pop_back", this); if (this->Length > 0) { this->Data[this->Length - 1] = '\0'; @@ -432,8 +451,8 @@ namespace std { string result = *this; result.concat(Other); - strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", - result.Data, result.Data, result.Length, result.Capacity); + strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, result.Data, result.Data, result.Length, result.Capacity); return result; } @@ -441,24 +460,24 @@ namespace std { string result = *this; result.concat(Other); - strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", - result.Data, result.Data, result.Length, result.Capacity); + strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, result.Data, result.Data, result.Length, result.Capacity); return result; } string &operator+=(const string &Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator+=(const char *Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } @@ -466,8 +485,8 @@ namespace std { const char str[2] = {Other, '\0'}; this->concat(str); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } @@ -482,8 +501,8 @@ namespace std // this->Data = Other.Data; // this->Length = Other.Length; // this->Capacity = Other.Capacity; - // strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", - // this->Data, this->Data, this->Length, this->Capacity); + // strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + // this, this->Data, this->Data, this->Length, this->Capacity); // } // return *this; // } @@ -495,72 +514,76 @@ namespace std delete[] this->Data; this->Data = new char[this->Capacity]; strcpy(this->Data, Other); - strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator<<(const string &Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator<<(const char *Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this->Data, this->Data, this->Length, this->Capacity); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); return *this; } char &operator[](int Index) { - strdbg("String index: %d", Index); + strdbg("%#lx: String index: %d", this, Index); return this->Data[Index]; } const char &operator[](int Index) const { - strdbg("String index: %d", Index); + strdbg("%#lx: String index: %d", this, Index); return this->Data[Index]; } char &operator[](size_t Index) { - strdbg("String index: %d", Index); + strdbg("%#lx: String index: %d", this, Index); return this->Data[Index]; } const char &operator[](size_t Index) const { - strdbg("String index: %d", Index); + strdbg("%#lx: String index: %d", this, Index); return this->Data[Index]; } bool operator==(const string &Other) const { - strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other.Data); + strdbg("%#lx: String compared: \"%s\" == \"%s\"", + this, this->Data, Other.Data); return strcmp(this->Data, Other.Data) == 0; } bool operator!=(const char *Other) const { - strdbg("String compared: \"%s\" != \"%s\"", this->Data, Other); + strdbg("%#lx: String compared: \"%s\" != \"%s\"", + this, this->Data, Other); return strcmp(this->Data, Other) != 0; } bool operator!=(const string &Other) const { - strdbg("String compared: \"%s\" != \"%s\"", this->Data, Other.Data); + strdbg("%#lx: String compared: \"%s\" != \"%s\"", + this, this->Data, Other.Data); return strcmp(this->Data, Other.Data) != 0; } bool operator==(const char *Other) const { - strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other); + strdbg("%#lx: String compared: \"%s\" == \"%s\"", + this, this->Data, Other); return strcmp(this->Data, Other) == 0; } @@ -575,42 +598,44 @@ namespace std iterator &operator++() { ++this->Pointer; - strdbg("String iterator incremented: %#lx", - this->Pointer); + strdbg("%#lx: String iterator incremented: %#lx", + this, this->Pointer); return *this; } char &operator*() { - strdbg("String iterator dereferenced: %#lx", - this->Pointer); + strdbg("%#lx: String iterator dereferenced: %#lx", + this, this->Pointer); return *this->Pointer; } bool operator!=(const iterator &Other) const { - strdbg("String iterator compared: %#lx != %#lx", - this->Pointer, Other.Pointer); + strdbg("%#lx: String iterator compared: %#lx != %#lx", + this, this->Pointer, Other.Pointer); return this->Pointer != Other.Pointer; } bool operator==(const iterator &Other) const { - strdbg("String iterator compared: %#lx == %#lx", - this->Pointer, Other.Pointer); + strdbg("%#lx: String iterator compared: %#lx == %#lx", + this, this->Pointer, Other.Pointer); return this->Pointer == Other.Pointer; } }; iterator begin() { - strdbg("String iterator begin: %#lx", this->Data); + strdbg("%#lx: String iterator begin: %#lx", + this, this->Data); return iterator(this->Data); } iterator end() { - strdbg("String iterator end: %#lx", this->Data + this->Length); + strdbg("%#lx: String iterator end: %#lx", + this, this->Data + this->Length); return iterator(this->Data + this->Length); } }; diff --git a/include_std/stropts.h b/include_std/stropts.h new file mode 100644 index 00000000..bc6c48f7 --- /dev/null +++ b/include_std/stropts.h @@ -0,0 +1,78 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef _STROPTS_H +#define _STROPTS_H + +#define __SID ('S' << 8) + +#define I_NREAD (__SID | 1) +#define I_PUSH (__SID | 2) +#define I_POP (__SID | 3) +#define I_LOOK (__SID | 4) +#define I_FLUSH (__SID | 5) +#define I_SRDOPT (__SID | 6) +#define I_GRDOPT (__SID | 7) +#define I_STR (__SID | 8) +#define I_SETSIG (__SID | 9) +#define I_GETSIG (__SID | 10) +#define I_FIND (__SID | 11) +#define I_LINK (__SID | 12) +#define I_UNLINK (__SID | 13) +#define I_PEEK (__SID | 15) +#define I_FDINSERT (__SID | 16) +#define I_SENDFD (__SID | 17) +#define I_RECVFD (__SID | 14) +#define I_SWROPT (__SID | 19) +#define I_GWROPT (__SID | 20) +#define I_LIST (__SID | 21) +#define I_PLINK (__SID | 22) +#define I_PUNLINK (__SID | 23) +#define I_FLUSHBAND (__SID | 28) +#define I_CKBAND (__SID | 29) +#define I_GETBAND (__SID | 30) +#define I_ATMARK (__SID | 31) +#define I_SETCLTIME (__SID | 32) +#define I_GETCLTIME (__SID | 33) +#define I_CANPUT (__SID | 34) + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 + +#endif diff --git a/kernel.h b/kernel.h index 9d78006e..05f57fc5 100644 --- a/kernel.h +++ b/kernel.h @@ -39,13 +39,6 @@ extern struct BootInfo bInfo; extern bool DebuggerIsAttached; #ifdef __cplusplus -#ifdef DEBUG -#define MEM_TRK_MAX_SIZE 0x100 -extern bool EnableExternalMemoryTracer; -extern char mExtTrkLog[]; -extern LockClass mExtTrkLock; -#endif - extern Video::Display *Display; extern SymbolResolver::Symbols *KernelSymbolTable; extern Power::Power *PowerManager;