Update kernel code

This commit is contained in:
Alex 2023-08-22 06:21:17 +03:00
parent ef3b761d4f
commit 8898791257
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
49 changed files with 3389 additions and 2313 deletions

View File

@ -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

View File

@ -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 <bool> /* Infinite loop on failure */
#define Xalloc_MapPages <bool> /* Map pages on allocation */
#define Xalloc_PAGE_SIZE <page size> /* <-- Replace with your page size */
#define Xalloc_trace(m, ...) <trace function>
#define Xalloc_warn(m, ...) <warning function>
#define Xalloc_err(m, ...) <error function>
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
#define Xalloc_lock <lock function>
#define Xalloc_unlock <unlock function>
#define XallocV1_def <define a lock> /* eg. std::mutex Xalloc_lock; */
#define XallocV1_lock <lock function>
#define XallocV1_unlock <unlock function>
/* Same as above */
#define XallocV2_def <define a lock>
#define XallocV2_lock <lock function>
#define XallocV2_unlock <unlock function>
```
### 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

View File

@ -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);
}

View File

@ -22,98 +22,215 @@
#include <lock.hpp>
#include <debug.h>
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__

View File

@ -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;
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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;
}
}

View File

@ -0,0 +1,26 @@
#include <types.h>
#include <lock.hpp>
#include <memory.hpp>
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;
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
);
}
}
}

View File

@ -1,20 +1,41 @@
#include <memory.hpp>
#include <filesystem.hpp>
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 <typename T>
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 *>(struct stat *);
template const char *PageTable::Get<const char *>(const char *);
template const void *PageTable::Get<const void *>(const void *);
template uintptr_t PageTable::Get<uintptr_t>(uintptr_t);
template void *PageTable::Get<void *>(void *);
/* ... */
}

View File

@ -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)));
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <memory.hpp>
#include <assert.h>
#include <errno.h>
#include <debug.h>
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. */
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -20,6 +20,7 @@
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <rand.hpp>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
@ -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;

View File

@ -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;
}

View File

@ -26,7 +26,7 @@ namespace VirtualFileSystem
{
ReadFSFunction(USTAR_Read)
{
if (!Size)
if (Size <= 0)
Size = node->Length;
if (RefOffset > node->Length)

View File

@ -19,6 +19,7 @@
#include <smart_ptr.hpp>
#include <convert.h>
#include <stropts.h>
#include <task.hpp>
#include <printf.h>
#include <lock.hpp>
@ -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;
}

View File

@ -17,6 +17,13 @@
#include <filesystem.hpp>
#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)

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <filesystem.hpp>
#include <errno.h>
#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;
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <filesystem.hpp>
#include <rand.hpp>
#include <errno.h>
#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;
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <filesystem.hpp>
#include <errno.h>
#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;
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <filesystem.hpp>
#include <errno.h>
#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;
}

View File

@ -17,10 +17,11 @@
#include "kernel.h"
#include <filesystem/mounts.hpp>
#include <filesystem/ustar.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <convert.h>
#include <ints.hpp>
#include <printf.h>
#include <lock.hpp>
#include <uart.hpp>
@ -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();

View File

@ -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");

View File

@ -27,7 +27,8 @@ void cmd_lsof(const char *)
if (!Proc)
continue;
std::vector<VirtualFileSystem::FileDescriptorTable::FileDescriptor> fds_array = Proc->FileDescriptors->GetFileDescriptors();
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> 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());

View File

@ -254,7 +254,8 @@ void lsof()
printf("%s:\n", Proc->Name);
std::vector<VirtualFileSystem::FileDescriptorTable::FileDescriptor> fds_array = Proc->FileDescriptors->GetFileDescriptors();
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> 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:

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
#include <types.h>
#include <lock.hpp>
#include <memory.hpp>
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;
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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<Tasking::PCB *> &pChild = this->Parent->Children;

View File

@ -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
}

View File

@ -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<AuxiliaryVector> &auxv,
TaskArchitecture Architecture,
TaskCompatibility Compatibility,
bool ThreadNotReady)
__no_sanitize("undefined") void TCB::SetupUserStack_x86_64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &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<AuxiliaryVector> 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<AuxiliaryVector> &auxv)
{
fixme("Not implemented");
}
void TCB::SetupUserStack_aarch64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv)
{
fixme("Not implemented");
}
TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint,
const char **argv, const char **envp,
const std::vector<AuxiliaryVector> &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<AuxiliaryVector> 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<Tasking::TCB *> &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;
}
}

View File

@ -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);

View File

@ -21,15 +21,15 @@
#include <memory.hpp>
#include <convert.h>
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;
}

View File

@ -66,6 +66,18 @@ namespace Execute
std::vector<AuxiliaryVector> 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);

View File

@ -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<FileDescriptor> FileDescriptors;
std::vector<Fildes> FileDescriptors;
std::vector<DupFildes> 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<FileDescriptor> &GetFileDescriptors() { return FileDescriptors; }
std::vector<Fildes> &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();

View File

@ -22,93 +22,9 @@
#include <filesystem.hpp>
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__

View File

@ -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 <typename T>
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<AllocatedPages> 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:

View File

@ -159,17 +159,35 @@ namespace Tasking
private:
class Task *ctx = nullptr;
void SetupUserStack_x86_64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv);
void SetupUserStack_x86_32(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &auxv);
void SetupUserStack_aarch64(const char **argv,
const char **envp,
const std::vector<AuxiliaryVector> &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<TaskStatus> Status = TaskStatus::UnknownStatus;
Memory::StackGuard *Stack;
Memory::MemMgr *Memory;
std::atomic<TaskStatus> 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<TaskStatus> Status = Zombie;
/* Info & Security info */
struct
{
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
@ -246,17 +278,26 @@ namespace Tasking
} Real, Effective;
} Security{};
TaskInfo Info{};
std::vector<TCB *> Threads;
std::vector<PCB *> 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<TCB *> Threads;
std::vector<PCB *> Children;
public:
void Rename(const char *name);
void SetWorkingDirectory(Node *node);

View File

@ -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<t>(v)
#define c_cst(t, v) const_cast<t>(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__

View File

@ -22,7 +22,7 @@
#include <convert.h>
#include <debug.h>
// 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);
}
};

78
include_std/stropts.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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

View File

@ -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;