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" #include "../kernel.h"
#ifdef DEBUG #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 #endif
#ifdef PRINT_BACKTRACE #ifdef PRINT_BACKTRACE

View File

@ -1,6 +1,7 @@
# Xalloc # 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. ❗ #### ❗ 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 ## 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) 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) extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
{ {
// ... // ...
@ -45,13 +50,21 @@ extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
##### Xalloc.hpp ##### Xalloc.hpp
```cpp ```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_PAGE_SIZE <page size> /* <-- Replace with your page size */
#define Xalloc_trace(m, ...) <trace function> #define Xalloc_trace(m, ...) <trace function>
#define Xalloc_warn(m, ...) <warning function> #define Xalloc_warn(m, ...) <warning function>
#define Xalloc_err(m, ...) <error function> #define Xalloc_err(m, ...) <error function>
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
#define Xalloc_lock <lock function> #define XallocV1_def <define a lock> /* eg. std::mutex Xalloc_lock; */
#define Xalloc_unlock <unlock function> #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 ### 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. - `Size` - The new size of the memory block in bytes.
--- ---
## To-do
- [ ] Multiple free-lists for different block sizes

View File

@ -22,17 +22,24 @@
#include <lock.hpp> #include <lock.hpp>
#include <debug.h> #include <debug.h>
typedef long unsigned Xuint64_t; typedef __UINT8_TYPE__ Xuint8_t;
typedef long unsigned Xsize_t; typedef __SIZE_TYPE__ Xsize_t;
typedef __UINTPTR_TYPE__ Xuintptr_t;
#define Xalloc_StopOnFail true #define Xalloc_StopOnFail true
#define Xalloc_MapPages true
#define Xalloc_PAGE_SIZE PAGE_SIZE #define Xalloc_PAGE_SIZE PAGE_SIZE
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__) #define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__) #define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__) #define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
#define Xalloc_def NewLock(XallocLock)
#define Xalloc_lock XallocLock.Lock(__FUNCTION__) #define XallocV1_def NewLock(XallocV1Lock)
#define Xalloc_unlock XallocLock.Unlock() #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 namespace Xalloc
{ {
@ -114,6 +121,116 @@ namespace Xalloc
*/ */
~V1(); ~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__ #endif // !__FENNIX_KERNEL_Xalloc_H__

View File

@ -17,7 +17,7 @@
#include "Xalloc.hpp" #include "Xalloc.hpp"
Xalloc_def; XallocV1_def;
#define XALLOC_CONCAT(x, y) x##y #define XALLOC_CONCAT(x, y) x##y
#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE) #define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
@ -30,20 +30,20 @@ extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, X
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress); extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
// TODO: Change memcpy with an optimized version // 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; unsigned char *dst = (unsigned char *)Destination;
const unsigned char *src = (const unsigned char *)Source; const unsigned char *src = (const unsigned char *)Source;
for (Xuint64_t i = 0; i < Length; i++) for (Xsize_t i = 0; i < Length; i++)
dst[i] = src[i]; dst[i] = src[i];
return Destination; return Destination;
} }
// TODO: Change memset with an optimized version // 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; unsigned char *Buffer = (unsigned char *)Destination;
for (Xuint64_t i = 0; i < Length; i++) for (Xsize_t i = 0; i < Length; i++)
Buffer[i] = (unsigned char)Data; Buffer[i] = (unsigned char)Data;
return Destination; return Destination;
} }
@ -153,13 +153,13 @@ namespace Xalloc
} }
SmartSMAP; SmartSMAP;
Xalloc_lock; XallocV1_lock;
if (this->FirstBlock == nullptr) if (this->FirstBlock == nullptr)
{ {
this->FirstBlock = new Block(Size); this->FirstBlock = new Block(Size);
((Block *)this->FirstBlock)->IsFree = false; ((Block *)this->FirstBlock)->IsFree = false;
Xalloc_unlock; XallocV1_unlock;
return ((Block *)this->FirstBlock)->Address; return ((Block *)this->FirstBlock)->Address;
} }
@ -169,7 +169,7 @@ namespace Xalloc
if (!CurrentBlock->Check()) if (!CurrentBlock->Check())
{ {
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); (Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
while (Xalloc_StopOnFail) while (Xalloc_StopOnFail)
; ;
} }
@ -177,7 +177,7 @@ namespace Xalloc
{ {
CurrentBlock->IsFree = false; CurrentBlock->IsFree = false;
Xmemset(CurrentBlock->Address, 0, Size); Xmemset(CurrentBlock->Address, 0, Size);
Xalloc_unlock; XallocV1_unlock;
return CurrentBlock->Address; return CurrentBlock->Address;
} }
CurrentBlock = CurrentBlock->Next; CurrentBlock = CurrentBlock->Next;
@ -190,7 +190,7 @@ namespace Xalloc
CurrentBlock->Next = new Block(Size); CurrentBlock->Next = new Block(Size);
((Block *)CurrentBlock->Next)->Last = CurrentBlock; ((Block *)CurrentBlock->Next)->Last = CurrentBlock;
((Block *)CurrentBlock->Next)->IsFree = false; ((Block *)CurrentBlock->Next)->IsFree = false;
Xalloc_unlock; XallocV1_unlock;
return ((Block *)CurrentBlock->Next)->Address; return ((Block *)CurrentBlock->Next)->Address;
} }
@ -203,7 +203,7 @@ namespace Xalloc
} }
SmartSMAP; SmartSMAP;
Xalloc_lock; XallocV1_lock;
Block *CurrentBlock = ((Block *)this->FirstBlock); Block *CurrentBlock = ((Block *)this->FirstBlock);
while (CurrentBlock != nullptr) while (CurrentBlock != nullptr)
@ -211,7 +211,7 @@ namespace Xalloc
if (!CurrentBlock->Check()) if (!CurrentBlock->Check())
{ {
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); (Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
while (Xalloc_StopOnFail) while (Xalloc_StopOnFail)
; ;
} }
@ -220,19 +220,19 @@ namespace Xalloc
if (CurrentBlock->IsFree) if (CurrentBlock->IsFree)
{ {
Xalloc_warn("Attempted to free an already freed pointer!"); Xalloc_warn("Attempted to free an already freed pointer!");
Xalloc_unlock; XallocV1_unlock;
return; return;
} }
CurrentBlock->IsFree = true; CurrentBlock->IsFree = true;
Xalloc_unlock; XallocV1_unlock;
return; return;
} }
CurrentBlock = CurrentBlock->Next; CurrentBlock = CurrentBlock->Next;
} }
Xalloc_err("Invalid address %#lx.", Address); Xalloc_err("Invalid address %#lx.", Address);
Xalloc_unlock; XallocV1_unlock;
} }
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size) void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
@ -261,9 +261,9 @@ namespace Xalloc
} }
// SmartSMAP; // SmartSMAP;
// Xalloc_lock; // XallocV1_lock;
// ... // ...
// Xalloc_unlock; // XallocV1_unlock;
// TODO: Implement realloc // TODO: Implement realloc
this->free(Address); this->free(Address);
@ -273,18 +273,18 @@ namespace Xalloc
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled) V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
{ {
SmartSMAP; SmartSMAP;
Xalloc_lock; XallocV1_lock;
this->SMAPUsed = SMAPEnabled; this->SMAPUsed = SMAPEnabled;
this->UserMapping = UserMode; this->UserMapping = UserMode;
this->BaseVirtualAddress = BaseVirtualAddress; this->BaseVirtualAddress = BaseVirtualAddress;
Xalloc_unlock; XallocV1_unlock;
} }
V1::~V1() V1::~V1()
{ {
SmartSMAP; SmartSMAP;
Xalloc_lock; XallocV1_lock;
Xalloc_trace("Destructor not implemented yet."); Xalloc_trace("Destructor not implemented yet.");
Xalloc_unlock; 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 #endif
#include "HeapAllocators/Xalloc/Xalloc.hpp" #include "HeapAllocators/Xalloc/Xalloc.hpp"
#include "../Library/liballoc_1_1.h" #include "HeapAllocators/liballoc_1_1/liballoc_1_1.h"
#include "../../kernel.h" #include "../../kernel.h"
// #define DEBUG_ALLOCATIONS_SL 1
// #define DEBUG_ALLOCATIONS 1 // #define DEBUG_ALLOCATIONS 1
#ifdef DEBUG_ALLOCATIONS #ifdef DEBUG_ALLOCATIONS
@ -39,11 +38,6 @@
#define memdbg(m, ...) #define memdbg(m, ...)
#endif #endif
#ifdef DEBUG_ALLOCATIONS_SL
NewLock(AllocatorLock);
NewLock(OperatorAllocatorLock);
#endif
using namespace Memory; using namespace Memory;
Physical KernelAllocator; Physical KernelAllocator;
@ -53,6 +47,7 @@ bool PSESupport = false;
MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages; MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages;
Xalloc::V1 *XallocV1Allocator = nullptr; Xalloc::V1 *XallocV1Allocator = nullptr;
Xalloc::V2 *XallocV2Allocator = nullptr;
#ifdef DEBUG #ifdef DEBUG
NIF void tracepagetable(PageTable *pt) NIF void tracepagetable(PageTable *pt)
@ -119,27 +114,6 @@ NIF void MapFramebuffer(PageTable *PT)
(size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height), (size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height),
PTFlag::RW | PTFlag::US | PTFlag::G); PTFlag::RW | PTFlag::US | PTFlag::G);
itrfb++; 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); 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() NIF void InitializeMemoryManagement()
@ -404,20 +347,22 @@ NIF void InitializeMemoryManagement()
CPU::PageTable(KernelPageTable); CPU::PageTable(KernelPageTable);
debug("Page table updated."); debug("Page table updated.");
/* FIXME: Read kernel config */
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false); XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
AllocatorType = MemoryAllocatorType::XallocV1; XallocV2Allocator = new Xalloc::V2((void *)KERNEL_HEAP_BASE);
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator); 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) void *malloc(size_t Size)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("malloc(%d)->[%s]", Size,
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr; void *ret = nullptr;
switch (AllocatorType) switch (AllocatorType)
@ -425,7 +370,6 @@ void *malloc(size_t Size)
case MemoryAllocatorType::Pages: case MemoryAllocatorType::Pages:
{ {
ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1));
memset(ret, 0, Size);
break; break;
} }
case MemoryAllocatorType::XallocV1: case MemoryAllocatorType::XallocV1:
@ -433,10 +377,14 @@ void *malloc(size_t Size)
ret = XallocV1Allocator->malloc(Size); ret = XallocV1Allocator->malloc(Size);
break; break;
} }
case MemoryAllocatorType::XallocV2:
{
ret = XallocV2Allocator->malloc(Size);
break;
}
case MemoryAllocatorType::liballoc11: case MemoryAllocatorType::liballoc11:
{ {
ret = PREFIX(malloc)(Size); ret = PREFIX(malloc)(Size);
memset(ret, 0, Size);
break; break;
} }
default: default:
@ -445,26 +393,8 @@ void *malloc(size_t Size)
CPU::Stop(); CPU::Stop();
} }
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer) memset(ret, 0, Size);
{
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
return ret; return ret;
} }
@ -472,10 +402,9 @@ void *calloc(size_t n, size_t Size)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("calloc(%d, %d)->[%s]", n, Size,
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr; void *ret = nullptr;
switch (AllocatorType) switch (AllocatorType)
@ -483,7 +412,6 @@ void *calloc(size_t n, size_t Size)
case MemoryAllocatorType::Pages: case MemoryAllocatorType::Pages:
{ {
ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1)); ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1));
memset(ret, 0, n * Size);
break; break;
} }
case MemoryAllocatorType::XallocV1: case MemoryAllocatorType::XallocV1:
@ -491,10 +419,14 @@ void *calloc(size_t n, size_t Size)
ret = XallocV1Allocator->calloc(n, Size); ret = XallocV1Allocator->calloc(n, Size);
break; break;
} }
case MemoryAllocatorType::XallocV2:
{
ret = XallocV2Allocator->calloc(n, Size);
break;
}
case MemoryAllocatorType::liballoc11: case MemoryAllocatorType::liballoc11:
{ {
void *ret = PREFIX(calloc)(n, Size); void *ret = PREFIX(calloc)(n, Size);
memset(ret, 0, Size);
return ret; return ret;
} }
default: default:
@ -503,26 +435,8 @@ void *calloc(size_t n, size_t Size)
CPU::Stop(); CPU::Stop();
} }
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer) memset(ret, 0, n * Size);
{
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
return ret; return ret;
} }
@ -530,10 +444,9 @@ void *realloc(void *Address, size_t Size)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr; void *ret = nullptr;
switch (AllocatorType) switch (AllocatorType)
@ -541,7 +454,6 @@ void *realloc(void *Address, size_t Size)
case unlikely(MemoryAllocatorType::Pages): case unlikely(MemoryAllocatorType::Pages):
{ {
ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak
memset(ret, 0, Size);
break; break;
} }
case MemoryAllocatorType::XallocV1: case MemoryAllocatorType::XallocV1:
@ -549,10 +461,14 @@ void *realloc(void *Address, size_t Size)
ret = XallocV1Allocator->realloc(Address, Size); ret = XallocV1Allocator->realloc(Address, Size);
break; break;
} }
case MemoryAllocatorType::XallocV2:
{
ret = XallocV2Allocator->realloc(Address, Size);
break;
}
case MemoryAllocatorType::liballoc11: case MemoryAllocatorType::liballoc11:
{ {
void *ret = PREFIX(realloc)(Address, Size); void *ret = PREFIX(realloc)(Address, Size);
memset(ret, 0, Size);
return ret; return ret;
} }
default: default:
@ -561,26 +477,8 @@ void *realloc(void *Address, size_t Size)
CPU::Stop(); CPU::Stop();
} }
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer) memset(ret, 0, Size);
{
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
return ret; return ret;
} }
@ -588,10 +486,9 @@ void free(void *Address)
{ {
assert(Address != nullptr); assert(Address != nullptr);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("free(%#lx)->[%s]", Address,
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
switch (AllocatorType) switch (AllocatorType)
{ {
@ -605,6 +502,11 @@ void free(void *Address)
XallocV1Allocator->free(Address); XallocV1Allocator->free(Address);
break; break;
} }
case MemoryAllocatorType::XallocV2:
{
XallocV2Allocator->free(Address);
break;
}
case MemoryAllocatorType::liballoc11: case MemoryAllocatorType::liballoc11:
{ {
PREFIX(free) PREFIX(free)
@ -617,58 +519,17 @@ void free(void *Address)
CPU::Stop(); 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) void *operator new(std::size_t Size)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("new(%d)->[%s]", Size,
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = malloc(Size); 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; return ret;
} }
@ -676,32 +537,11 @@ void *operator new[](std::size_t Size)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("new[](%d)->[%s]", Size,
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = malloc(Size); 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; return ret;
} }
@ -709,39 +549,14 @@ void *operator new(std::size_t Size, std::align_val_t Alignment)
{ {
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("new(%d, %d)->[%s]", Size, Alignment,
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
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); fixme("operator new with alignment(%#lx) is not implemented",
Alignment);
void *ret = malloc(Size); 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; return ret;
} }
@ -749,64 +564,22 @@ void operator delete(void *Pointer)
{ {
assert(Pointer != nullptr); assert(Pointer != nullptr);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("delete(%#lx)->[%s]", Pointer,
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
free(Pointer); 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) void operator delete[](void *Pointer)
{ {
assert(Pointer != nullptr); assert(Pointer != nullptr);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("delete[](%#lx)->[%s]", Pointer,
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
#endif : "Unknown");
memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
free(Pointer); 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) 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(Pointer != nullptr);
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("delete(%#lx, %d)->[%s]",
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); Pointer, Size,
#endif KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); : "Unknown");
free(Pointer); 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) 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(Pointer != nullptr);
assert(Size > 0); assert(Size > 0);
#ifdef DEBUG_ALLOCATIONS_SL memdbg("delete[](%#lx, %d)->[%s]",
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); Pointer, Size,
#endif KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); : "Unknown");
free(Pointer); 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) ReadFSFunction(MEM_Read)
{ {
if (!Size) if (Size <= 0)
Size = node->Length; Size = node->Length;
if (RefOffset > node->Length) if (RefOffset > node->Length)
@ -39,7 +39,7 @@ namespace Memory
WriteFSFunction(MEM_Write) WriteFSFunction(MEM_Write)
{ {
if (!Size) if (Size <= 0)
Size = node->Length; Size = node->Length;
if (RefOffset > node->Length) if (RefOffset > node->Length)

View File

@ -21,8 +21,8 @@ namespace Memory
{ {
Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress) Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
{ {
#if defined(a64)
uintptr_t Address = VirtualAddress; uintptr_t Address = VirtualAddress;
#if defined(a64)
Address >>= 12; Address >>= 12;
this->PTEIndex = Address & 0x1FF; this->PTEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
@ -32,12 +32,23 @@ namespace Memory
Address >>= 9; Address >>= 9;
this->PMLIndex = Address & 0x1FF; this->PMLIndex = Address & 0x1FF;
#elif defined(a32) #elif defined(a32)
uintptr_t Address = VirtualAddress;
Address >>= 12; Address >>= 12;
this->PTEIndex = Address & 0x3FF; this->PTEIndex = Address & 0x3FF;
Address >>= 10; Address >>= 10;
this->PDEIndex = Address & 0x3FF; this->PDEIndex = Address & 0x3FF;
#elif defined(aa64) #elif defined(aa64)
#endif #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,5 +1,7 @@
#include <memory.hpp> #include <memory.hpp>
#include <filesystem.hpp>
namespace Memory namespace Memory
{ {
void PageTable::Update() void PageTable::Update()
@ -17,4 +19,23 @@ namespace Memory
memcpy(&NewTable, this, sizeof(PageTable)); memcpy(&NewTable, this, sizeof(PageTable));
return NewTable; 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; continue;
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); 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); return (void *)(PageBitmapIndex * PAGE_SIZE);
} }
@ -152,26 +133,6 @@ namespace Memory
} }
this->LockPages((void *)(Index * PAGE_SIZE), Count); 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); return (void *)(Index * PAGE_SIZE);
NextPage: NextPage:
@ -228,26 +189,6 @@ namespace Memory
PageBitmapIndex = Index; 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) 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" : ""); warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
return; 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++) for (size_t t = 0; t < Count; t++)
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE))); 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) #if defined(a86)
fixme(""); // FIXME: This is not a good way to measure the clock speed 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); TimeManager->Sleep(1, Units::Milliseconds);
size_t End = CPU::Counter(); uint64_t End = CPU::Counter();
this->clk = End - Start; this->clk = End - Start;
this->ClassCreationTime = this->GetCounter(); this->ClassCreationTime = this->GetCounter();

View File

@ -253,28 +253,22 @@ namespace Video
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10); this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10);
else else
this->Buffers[Index].Color = 0xFFFFFF; this->Buffers[Index].Color = 0xFFFFFF;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
this->ColorPickerIteration++; this->ColorPickerIteration++;
if (this->ColorPickerIteration == 6) if (this->ColorPickerIteration == 6)
{ {
this->ColorPickerIteration = 0; this->ColorPickerIteration = 0;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']');
this->ColorIteration = false; this->ColorIteration = false;
} }
return Char; return Char;
} }
if (WriteToUART) if (WriteToUART && Char != '\e')
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
switch (Char) switch (Char)
{ {
case '\e': case '\e':
{ {
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('[');
this->ColorIteration = true; this->ColorIteration = true;
return Char; return Char;
} }

View File

@ -20,6 +20,7 @@
#include <memory.hpp> #include <memory.hpp>
#include <lock.hpp> #include <lock.hpp>
#include <msexec.h> #include <msexec.h>
#include <rand.hpp>
#include <cwalk.h> #include <cwalk.h>
#include <elf.h> #include <elf.h>
#include <abi.h> #include <abi.h>
@ -32,6 +33,57 @@ using namespace VirtualFileSystem;
namespace Execute 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) void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess)
{ {
stub; stub;
@ -104,10 +156,10 @@ namespace Execute
Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable); Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable);
Memory::MemMgr *mm = TargetProcess->Memory; Memory::MemMgr *mm = TargetProcess->Memory;
uint64_t BaseAddress = 0;
/* Copy segments into memory */ /* Copy segments into memory */
{ {
Elf64_Phdr ProgramBreakHeader{};
Elf64_Phdr ProgramHeader; Elf64_Phdr ProgramHeader;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{ {
@ -129,9 +181,6 @@ namespace Execute
debug("Mapped %#lx to %#lx", SegmentDestination, pAddr); 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)", debug("Copying segment to p: %#lx-%#lx; v: %#lx-%#lx (%ld file bytes, %ld mem bytes)",
pAddr, uintptr_t(pAddr) + ProgramHeader.p_memsz, pAddr, uintptr_t(pAddr) + ProgramHeader.p_memsz,
SegmentDestination, uintptr_t(SegmentDestination) + 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); void *zAddr = (void *)(uintptr_t(pAddr) + ProgramHeader.p_filesz);
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
} }
ProgramBreakHeader = ProgramHeader;
break; break;
} }
default: 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; struct stat statbuf;
@ -169,39 +226,8 @@ namespace Execute
debug("Entry Point: %#lx", EntryPoint); debug("Entry Point: %#lx", EntryPoint);
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader,
strcpy(aux_platform, "x86_64"); EntryPoint, 0);
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->ip = EntryPoint; this->ip = EntryPoint;
this->IsElfValid = true; this->IsElfValid = true;
@ -282,6 +308,7 @@ namespace Execute
/* Copy segments into memory */ /* Copy segments into memory */
{ {
Elf64_Phdr ProgramBreakHeader{};
Elf64_Phdr ProgramHeader; Elf64_Phdr ProgramHeader;
std::size_t SegmentsSize = 0; std::size_t SegmentsSize = 0;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
@ -336,6 +363,7 @@ namespace Execute
void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz); void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz);
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
} }
ProgramBreakHeader = ProgramHeader;
break; break;
} }
case PT_DYNAMIC: 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; EntryPoint += BaseAddress;
@ -578,39 +614,8 @@ namespace Execute
debug("Entry Point: %#lx", EntryPoint); debug("Entry Point: %#lx", EntryPoint);
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader,
strcpy(aux_platform, "x86_64"); EntryPoint, BaseAddress);
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->ip = EntryPoint; this->ip = EntryPoint;
this->IsElfValid = true; this->IsElfValid = true;

View File

@ -33,7 +33,8 @@ namespace Execute
{ {
int Spawn(char *Path, const char **argv, const char **envp, int Spawn(char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent, Tasking::PCB *Parent,
Tasking::TaskCompatibility Compatibility) Tasking::TaskCompatibility Compatibility,
bool Critical)
{ {
int fd = fopen(Path, "r"); int fd = fopen(Path, "r");
if (fd < 0) if (fd < 0)
@ -141,11 +142,16 @@ namespace Execute
return -ENOEXEC; return -ENOEXEC;
} }
TCB *Thread = TaskManager->CreateThread(Process, TCB *Thread = nullptr;
{
CriticalSection cs;
Thread = TaskManager->CreateThread(Process,
obj->InstructionPointer, obj->InstructionPointer,
obj->argv, obj->envp, obj->auxv, obj->argv, obj->envp, obj->auxv,
Arch, Arch,
Compatibility); Compatibility);
Thread->SetCritical(true);
}
fclose(fd); fclose(fd);
return Thread->ID; return Thread->ID;
} }

View File

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

View File

@ -19,6 +19,7 @@
#include <smart_ptr.hpp> #include <smart_ptr.hpp>
#include <convert.h> #include <convert.h>
#include <stropts.h>
#include <task.hpp> #include <task.hpp>
#include <printf.h> #include <printf.h>
#include <lock.hpp> #include <lock.hpp>
@ -30,7 +31,7 @@ namespace VirtualFileSystem
{ {
ReadFSFunction(fd_Read) ReadFSFunction(fd_Read)
{ {
if (!Size) if (Size <= 0)
Size = node->Length; Size = node->Length;
if (RefOffset > node->Length) if (RefOffset > node->Length)
@ -45,7 +46,7 @@ namespace VirtualFileSystem
WriteFSFunction(fd_Write) WriteFSFunction(fd_Write)
{ {
if (!Size) if (Size <= 0)
Size = node->Length; Size = node->Length;
if (RefOffset > node->Length) if (RefOffset > node->Length)
@ -64,15 +65,32 @@ namespace VirtualFileSystem
// .Write = fd_Write, // .Write = fd_Write,
}; };
FileDescriptorTable::FileDescriptor FileDescriptorTable::Fildes
FileDescriptorTable::GetFileDescriptor(int FileDescriptor) FileDescriptorTable::GetFileDescriptor(int FileDescriptor)
{ {
foreach (auto fd in FileDescriptors) foreach (auto fd in FileDescriptors)
{ {
if (fd.Descriptor == FileDescriptor) if (fd.Descriptor == FileDescriptor)
{
debug("Found file descriptor %d", FileDescriptor);
return fd; 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) int FileDescriptorTable::ProbeMode(mode_t Mode, int Flags)
@ -118,9 +136,8 @@ namespace VirtualFileSystem
if (!n) if (!n)
{ {
error("Failed to create file %s: %d", debug("%s: File already exists, continuing...",
AbsolutePath, errno); AbsolutePath);
return -1;
} }
} }
@ -132,23 +149,25 @@ namespace VirtualFileSystem
if (!File) if (!File)
{ {
errno = EEXIST; errno = EEXIST;
error("Failed to open file %s: %d",
AbsolutePath, errno);
return -1; return -1;
} }
} }
if (Flags & O_TRUNC) if (Flags & O_TRUNC)
{ {
fixme("Implement O_TRUNC"); fixme("O_TRUNC");
} }
if (Flags & O_APPEND) if (Flags & O_APPEND)
{ {
fixme("Implement O_APPEND"); fixme("O_APPEND");
} }
if (Flags & O_CLOEXEC) if (Flags & O_CLOEXEC)
{ {
fixme("Implement O_CLOEXEC"); fixme("O_CLOEXEC");
} }
RefNode *File = vfs->Open(AbsolutePath, RefNode *File = vfs->Open(AbsolutePath,
@ -161,8 +180,7 @@ namespace VirtualFileSystem
return -1; return -1;
} }
FileDescriptorTable::FileDescriptor fd; Fildes fd = {.Descriptor = GetFreeFileDescriptor()};
fd.Descriptor = GetFreeFileDescriptor();
if (fd.Descriptor < 0) 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; errno = EBADF;
return -1; return -1;
} }
@ -223,6 +254,19 @@ namespace VirtualFileSystem
break; break;
} }
} }
if (!Found)
{
foreach (auto fd in FildesDuplicates)
{
if (fd.Descriptor == i)
{
Found = true;
break;
}
}
}
if (!Found) if (!Found)
return i; return i;
i++; i++;
@ -234,12 +278,20 @@ namespace VirtualFileSystem
std::string FileDescriptorTable::GetAbsolutePath(int FileDescriptor) std::string FileDescriptorTable::GetAbsolutePath(int FileDescriptor)
{ {
FileDescriptorTable::FileDescriptor fd = Fildes fd = this->GetFileDescriptor(FileDescriptor);
this->GetFileDescriptor(FileDescriptor); DupFildes dfd = this->GetDupFildes(FileDescriptor);
if (fd.Descriptor == -1)
if (fd.Descriptor == -1 &&
dfd.Descriptor == -1)
return ""; 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 absolutePath = vfs->GetPathFromNode(node);
std::string path = absolutePath.c_str(); std::string path = absolutePath.c_str();
return path; return path;
@ -264,36 +316,52 @@ namespace VirtualFileSystem
ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count) ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count)
{ {
FileDescriptor fdesc; Fildes fdesc = this->GetFileDescriptor(fd);
fdesc = this->GetFileDescriptor(fd); DupFildes dfdesc = this->GetDupFildes(fd);
if (fdesc.Descriptor < 0 &&
if (fdesc.Descriptor < 0) dfdesc.Descriptor < 0)
{ {
errno = EBADF; errno = EBADF;
return -1; 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, ssize_t FileDescriptorTable::_write(int fd, const void *buf,
size_t count) size_t count)
{ {
FileDescriptor fdesc; Fildes fdesc = this->GetFileDescriptor(fd);
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 -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) int FileDescriptorTable::_close(int fd)
{ {
FileDescriptor fdesc; Fildes fdesc = this->GetFileDescriptor(fd);
fdesc = this->GetFileDescriptor(fd); DupFildes dfdesc = this->GetDupFildes(fd);
if (fdesc.Descriptor < 0) if (fdesc.Descriptor < 0 &&
dfdesc.Descriptor < 0)
{ {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -305,22 +373,61 @@ namespace VirtualFileSystem
return -1; 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; return 0;
} }
off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence) off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence)
{ {
FileDescriptor fdesc; Fildes fdesc = this->GetFileDescriptor(fd);
fdesc = this->GetFileDescriptor(fd); DupFildes dfdesc = this->GetDupFildes(fd);
if (fdesc.Descriptor < 0) if (fdesc.Descriptor < 0 &&
dfdesc.Descriptor < 0)
{ {
errno = EBADF; errno = EBADF;
return -1; 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, int FileDescriptorTable::_stat(const char *pathname,
@ -359,16 +466,23 @@ namespace VirtualFileSystem
int FileDescriptorTable::_fstat(int fd, struct stat *statbuf) int FileDescriptorTable::_fstat(int fd, struct stat *statbuf)
{ {
FileDescriptor fdesc; Fildes fdesc = this->GetFileDescriptor(fd);
fdesc = this->GetFileDescriptor(fd); DupFildes dfdesc = this->GetDupFildes(fd);
if (fdesc.Descriptor < 0) if (fdesc.Descriptor < 0 &&
dfdesc.Descriptor < 0)
{ {
errno = EBADF; errno = EBADF;
return -1; 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_dev = 0; /* FIXME: stub */
statbuf->st_ino = node->IndexNode; statbuf->st_ino = node->IndexNode;
statbuf->st_mode = node->Flags | node->Mode; statbuf->st_mode = node->Flags | node->Mode;
@ -417,6 +531,111 @@ namespace VirtualFileSystem
return 0; 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;
}
FileDescriptorTable::FileDescriptorTable(void *Owner) FileDescriptorTable::FileDescriptorTable(void *Owner)
{ {
this->fdDir = vfs->Create("fd", VirtualFileSystem::NodeFlags::DIRECTORY, this->fdDir = vfs->Create("fd", VirtualFileSystem::NodeFlags::DIRECTORY,

View File

@ -17,6 +17,13 @@
#include <filesystem.hpp> #include <filesystem.hpp>
#ifdef DEBUG
const char *SeekStrings[] =
{"SEEK_SET",
"SEEK_CUR",
"SEEK_END"};
#endif
namespace VirtualFileSystem namespace VirtualFileSystem
{ {
ReferenceNode *Node::CreateReference() ReferenceNode *Node::CreateReference()
@ -83,10 +90,10 @@ namespace VirtualFileSystem
return -1; return -1;
} }
off_t ReferenceNode::Seek(off_t Offset, int Whence) off_t ReferenceNode::Seek(off_t _Offset, int Whence)
{ {
if (this->SymlinkTo) if (this->SymlinkTo)
return this->SymlinkTo->Seek(Offset, Whence); return this->SymlinkTo->Seek(_Offset, Whence);
if (!this->node->Operator) if (!this->node->Operator)
{ {
@ -99,25 +106,40 @@ namespace VirtualFileSystem
if (this->node->Operator->Seek) if (this->node->Operator->Seek)
{ {
off_t RefOffset = off_t(this->Offset.load()); 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) switch (Whence)
{ {
case SEEK_SET: case SEEK_SET:
{ {
if (Offset > this->node->Length) if (_Offset > this->node->Length)
{ {
errno = EINVAL; errno = EINVAL;
return -1; 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; break;
} }
case SEEK_CUR: 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 || if (NewOffset > this->node->Length ||
NewOffset < 0) NewOffset < 0)
{ {
@ -130,7 +152,7 @@ namespace VirtualFileSystem
} }
case SEEK_END: case SEEK_END:
{ {
off_t NewOffset = this->node->Length + Offset; off_t NewOffset = this->node->Length + _Offset;
if (NewOffset > this->node->Length || if (NewOffset > this->node->Length ||
NewOffset < 0) 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) 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 "kernel.h"
#include <filesystem/mounts.hpp>
#include <filesystem/ustar.hpp> #include <filesystem/ustar.hpp>
#include <ints.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <convert.h> #include <convert.h>
#include <ints.hpp>
#include <printf.h> #include <printf.h>
#include <lock.hpp> #include <lock.hpp>
#include <uart.hpp> #include <uart.hpp>
@ -34,12 +35,6 @@
bool DebuggerIsAttached = false; 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 * Fennix Kernel
* ------------- * -------------
@ -223,7 +218,7 @@ Time::time *TimeManager = nullptr;
VirtualFileSystem::Virtual *vfs = nullptr; VirtualFileSystem::Virtual *vfs = nullptr;
KernelConfig Config = { KernelConfig Config = {
.AllocatorType = Memory::MemoryAllocatorType::XallocV1, .AllocatorType = Memory::MemoryAllocatorType::liballoc11,
.SchedulerType = Multi, .SchedulerType = Multi,
.DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'}, .DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'},
.InitPath = {'/', 'b', 'i', 'n', '/', 'i', 'n', 'i', 't', '\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################################"); KPrint("\e058C19################################");
TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread)); TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread));
CPU::Halt(true); CPU::Halt(true);
@ -574,9 +574,9 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
* is a global constructor but we need * is a global constructor but we need
* memory management to be initialized first. * memory management to be initialized first.
*/ */
TestMemoryAllocation();
TestString(); TestString();
Test_std(); Test_std();
TestMemoryAllocation();
#endif #endif
EnableProfiler = true; EnableProfiler = true;
Main(); Main();

View File

@ -162,6 +162,11 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
KPrint("\eAAFFAAUsing XallocV1 as memory allocator"); KPrint("\eAAFFAAUsing XallocV1 as memory allocator");
ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV1; 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) else if (strcmp(value, "liballoc11") == 0)
{ {
KPrint("\eAAFFAAUsing Liballoc11 as memory allocator"); KPrint("\eAAFFAAUsing Liballoc11 as memory allocator");

View File

@ -27,7 +27,8 @@ void cmd_lsof(const char *)
if (!Proc) if (!Proc)
continue; 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) foreach (auto fd in fds_array)
printf("%s %d: %s\n", Proc->Name, fd.Descriptor, printf("%s %d: %s\n", Proc->Name, fd.Descriptor,
fd.Handle->AbsolutePath.c_str()); fd.Handle->AbsolutePath.c_str());

View File

@ -254,7 +254,8 @@ void lsof()
printf("%s:\n", Proc->Name); 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) foreach (auto fd in fds_array)
printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str()); printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str());
} }
@ -307,7 +308,10 @@ int SpawnInit()
"--critical", "--critical",
nullptr}; 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 */ /* Files: 0.tga 1.tga ... 26.tga */
@ -451,7 +455,10 @@ void ExitLogoAnimationThread()
} }
} }
void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); } void CleanupProcessesThreadWrapper()
{
TaskManager->CleanupProcessesThread();
}
void KernelMainThread() void KernelMainThread()
{ {
@ -530,11 +537,10 @@ void KernelMainThread()
goto Exit; goto Exit;
} }
initThread = TaskManager->GetThreadByID(tid);
initThread->SetCritical(true);
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath); KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
thisThread->SetPriority(Tasking::Idle); thisThread->SetPriority(Tasking::Idle);
initThread = TaskManager->GetThreadByID(tid);
TaskManager->WaitForThread(initThread); TaskManager->WaitForThread(initThread);
ExitCode = initThread->GetExitCode(); ExitCode = initThread->GetExitCode();
Exit: Exit:

View File

@ -74,15 +74,14 @@ EXTERNC char *strcat_unsafe(char *destination, const char *source)
{ {
if ((destination == NULL) || (source == NULL)) if ((destination == NULL) || (source == NULL))
return NULL; return NULL;
char *start = destination; char *start = destination;
while (*start != '\0') while (*start != '\0')
{
start++; start++;
}
while (*source != '\0') while (*source != '\0')
{
*start++ = *source++; *start++ = *source++;
}
*start = '\0'; *start = '\0';
return destination; return destination;
} }
@ -91,6 +90,7 @@ EXTERNC char *strcpy_unsafe(char *destination, const char *source)
{ {
if (destination == NULL) if (destination == NULL)
return NULL; return NULL;
char *ptr = destination; char *ptr = destination;
while (*source != '\0') while (*source != '\0')
{ {
@ -98,6 +98,7 @@ EXTERNC char *strcpy_unsafe(char *destination, const char *source)
destination++; destination++;
source++; source++;
} }
*destination = '\0'; *destination = '\0';
return ptr; return ptr;
} }
@ -106,6 +107,7 @@ EXTERNC char *strncpy(char *destination, const char *source, unsigned long num)
{ {
if (destination == NULL) if (destination == NULL)
return NULL; return NULL;
char *ptr = destination; char *ptr = destination;
while (*source && num--) while (*source && num--)
{ {
@ -113,6 +115,7 @@ EXTERNC char *strncpy(char *destination, const char *source, unsigned long num)
destination++; destination++;
source++; source++;
} }
*destination = '\0'; *destination = '\0';
return ptr; return ptr;
} }
@ -121,6 +124,7 @@ EXTERNC int strcmp(const char *l, const char *r)
{ {
for (; *l == *r && *l; l++, r++) for (; *l == *r && *l; l++, r++)
; ;
return *(unsigned char *)l - *(unsigned char *)r; return *(unsigned char *)l - *(unsigned char *)r;
} }
@ -763,29 +767,42 @@ __noreturn __always_inline static inline void __convert_chk_fail(void)
EXTERNC __no_stack_protector void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen) EXTERNC __no_stack_protector void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen)
{ {
#ifdef DBG_CHK #ifdef DBG_CHK
debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", dest, src, len, slen); debug("( dest:%#lx src:%#lx len:%llu slen:%llu )",
dest, src, len, slen);
#endif #endif
if (unlikely(dest == NULL)) if (unlikely(dest == NULL))
{ {
error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("dest is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(src == NULL)) if (unlikely(src == NULL))
{ {
error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("src is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(len == 0)) if (unlikely(len == 0))
{ {
error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("len is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(slen == 0)) if (unlikely(slen == 0))
{ {
error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("slen is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
@ -818,26 +835,6 @@ EXTERNC __no_stack_protector void *__memcpy_chk(void *dest, const void *src, siz
fixme("SIMD memcpy disabled"); fixme("SIMD memcpy disabled");
ret = memcpy_unsafe(dest, src, len); ret = memcpy_unsafe(dest, src, len);
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "memcpy( %p %p %ld %ld )=%p~%p\n\r",
dest, src, len, slen,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret; return ret;
} }
@ -848,19 +845,28 @@ EXTERNC __no_stack_protector void *__memset_chk(void *dest, int val, size_t len,
#endif #endif
if (unlikely(dest == NULL)) if (unlikely(dest == NULL))
{ {
error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("dest is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(len == 0)) if (unlikely(len == 0))
{ {
error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("len is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(slen == 0)) if (unlikely(slen == 0))
{ {
error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("slen is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
@ -893,55 +899,48 @@ EXTERNC __no_stack_protector void *__memset_chk(void *dest, int val, size_t len,
fixme("SIMD memset disabled"); fixme("SIMD memset disabled");
ret = memset_unsafe(dest, val, len); ret = memset_unsafe(dest, val, len);
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "memset( %p %d %ld %ld )=%p~%p\n\r",
dest, val, len, slen,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret; return ret;
} }
EXTERNC __no_stack_protector void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen) EXTERNC __no_stack_protector void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen)
{ {
#ifdef DBG_CHK #ifdef DBG_CHK
debug("( dest:%#lx src:%#lx len:%llu slen:%llu )", dest, src, len, slen); debug("( dest:%#lx src:%#lx len:%llu slen:%llu )",
dest, src, len, slen);
#endif #endif
if (unlikely(dest == NULL)) if (unlikely(dest == NULL))
{ {
error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("dest is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(src == NULL)) if (unlikely(src == NULL))
{ {
error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("src is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(len == 0)) if (unlikely(len == 0))
{ {
error("len is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("len is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(slen == 0)) if (unlikely(slen == 0))
{ {
error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("slen is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
@ -974,49 +973,39 @@ EXTERNC __no_stack_protector void *__memmove_chk(void *dest, const void *src, si
fixme("SIMD memmove disabled"); fixme("SIMD memmove disabled");
ret = memmove_unsafe(dest, src, len); ret = memmove_unsafe(dest, src, len);
} }
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "memmove( %p %p %ld %ld )=%p~%p\n\r",
dest, src, len, slen,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret; return ret;
} }
EXTERNC __no_stack_protector char *__strcat_chk(char *dest, const char *src, size_t slen) EXTERNC __no_stack_protector char *__strcat_chk(char *dest, const char *src, size_t slen)
{ {
#ifdef DBG_CHK #ifdef DBG_CHK
debug("( dest:%#lx src:%#lx slen:%llu )", dest, src, slen); debug("( dest:%#lx src:%#lx slen:%llu )",
dest, src, slen);
#endif #endif
if (unlikely(dest == NULL)) if (unlikely(dest == NULL))
{ {
error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("dest is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(src == NULL)) if (unlikely(src == NULL))
{ {
error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("src is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(slen == 0)) if (unlikely(slen == 0))
{ {
error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("slen is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
@ -1029,23 +1018,33 @@ EXTERNC __no_stack_protector char *__strcat_chk(char *dest, const char *src, siz
EXTERNC __no_stack_protector char *__strcpy_chk(char *dest, const char *src, size_t slen) EXTERNC __no_stack_protector char *__strcpy_chk(char *dest, const char *src, size_t slen)
{ {
#ifdef DBG_CHK #ifdef DBG_CHK
debug("( dest:%#lx src:%#lx slen:%llu )", dest, src, slen); debug("( dest:%#lx src:%#lx slen:%llu )",
dest, src, slen);
#endif #endif
if (unlikely(dest == NULL)) if (unlikely(dest == NULL))
{ {
error("dest is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("dest is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(src == NULL)) if (unlikely(src == NULL))
{ {
error("src is NULL (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("src is NULL (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
if (unlikely(slen == 0)) if (unlikely(slen == 0))
{ {
error("slen is 0 (for %#lx %s)", __builtin_return_address(0), KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); error("slen is 0 (for %#lx %s)",
__builtin_return_address(0),
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
: "Unknown");
__convert_chk_fail(); __convert_chk_fail();
} }
@ -1061,26 +1060,6 @@ EXTERNC __no_stack_protector char *__strcpy_chk(char *dest, const char *src, siz
EXTERNC __no_stack_protector void *memcpy(void *dest, const void *src, size_t len) EXTERNC __no_stack_protector void *memcpy(void *dest, const void *src, size_t len)
{ {
void *ret = __memcpy_chk(dest, src, len, __builtin_object_size(dest, 0)); void *ret = __memcpy_chk(dest, src, len, __builtin_object_size(dest, 0));
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "!memcpy( %p %p %ld )=%p~%p\n\r",
dest, src, len,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret; return ret;
} }
@ -1088,25 +1067,5 @@ EXTERNC __no_stack_protector void *memcpy(void *dest, const void *src, size_t le
EXTERNC __no_stack_protector void *memset(void *dest, int val, size_t len) EXTERNC __no_stack_protector void *memset(void *dest, int val, size_t len)
{ {
void *ret = __memset_chk(dest, val, len, __builtin_object_size(dest, 0)); void *ret = __memset_chk(dest, val, len, __builtin_object_size(dest, 0));
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "!memset( %p %d %ld )=%p~%p\n\r",
dest, val, len,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret; return ret;
} }

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_FS 0x1003
#define ARCH_GET_GS 0x1004 #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_NONE 0
#define PROT_READ 1 #define PROT_READ 1
#define PROT_WRITE 2 #define PROT_WRITE 2
@ -47,16 +68,14 @@ using Tasking::TaskStatus::Terminated;
#define PROT_GROWSDOWN 0x01000000 #define PROT_GROWSDOWN 0x01000000
#define PROT_GROWSUP 0x02000000 #define PROT_GROWSUP 0x02000000
#define MAP_FAILED ((void *)-1) #define MAP_TYPE 0x0f
#define MAP_FILE 0 #define MAP_FILE 0
#define MAP_SHARED 0x01 #define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02 #define MAP_PRIVATE 0x02
#define MAP_SHARED_VALIDATE 0x03 #define MAP_SHARED_VALIDATE 0x03
#define MAP_TYPE 0x0f
#define MAP_FIXED 0x10 #define MAP_FIXED 0x10
#define MAP_ANON 0x20 #define MAP_ANONYMOUS 0x20
#define MAP_ANONYMOUS MAP_ANON
#define MAP_NORESERVE 0x4000 #define MAP_NORESERVE 0x4000
#define MAP_GROWSDOWN 0x0100 #define MAP_GROWSDOWN 0x0100
#define MAP_DENYWRITE 0x0800 #define MAP_DENYWRITE 0x0800
@ -96,17 +115,41 @@ static int ConvertErrno(int r)
/* https://man7.org/linux/man-pages/man2/read.2.html */ /* https://man7.org/linux/man-pages/man2/read.2.html */
static ssize_t sys_read(int fd, void *buf, size_t count) 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; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* https://man7.org/linux/man-pages/man2/write.2.html */
static ssize_t sys_write(int fd, const void *buf, size_t count) 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; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* https://man7.org/linux/man-pages/man2/close.2.html */
@ -122,7 +177,9 @@ static int sys_close(int fd)
{ {
Tasking::PCB *pcb = thisProcess; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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 #undef fstat
Tasking::PCB *pcb = thisProcess; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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 #undef lstat
Tasking::PCB *pcb = thisProcess; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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; Tasking::PCB *pcb = thisProcess;
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; 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 */ /* 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 */ UNUSED(offset); /* FIXME */
Tasking::PCB *pcb = thisProcess; Tasking::PCB *pcb = thisProcess;
Memory::MemMgr *mgr = pcb->Memory; Memory::MemMgr *mm = pcb->Memory;
if (!addr) void *newPages = mm->RequestPages(TO_PAGES(length));
{
void *newPages = mgr->RequestPages(TO_PAGES(length));
if (newPages == nullptr) if (newPages == nullptr)
return MAP_FAILED; return (void *)-ENOMEM;
Memory::Virtual vma = Memory::Virtual(pcb->PageTable); bool MustUseAddr = (flags & MAP_FIXED) != 0;
if (addr == NULL && !MustUseAddr)
addr = newPages;
if (MustUseAddr)
{
debug("Using fixed address %#lx", addr);
}
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
uint64_t MapFlags = Memory::P;
if (prot & PROT_READ) if (prot & PROT_READ)
vma.Map(newPages, newPages, length, Memory::P | Memory::US, Memory::Virtual::FourKiB); MapFlags |= Memory::US;
if (prot & PROT_WRITE) if (prot & PROT_WRITE)
vma.Map(newPages, newPages, length, Memory::RW, Memory::Virtual::FourKiB); MapFlags |= Memory::RW;
if (prot & PROT_EXEC) if (prot & PROT_EXEC)
fixme("PROT_EXEC not implemented"); debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */
if (flags & MAP_FILE) switch (flags & MAP_TYPE)
fixme("MAP_FILE not implemented"); {
if (flags & MAP_SHARED) case MAP_FILE:
debug("MAP_FILE ignored");
[[fallthrough]];
case MAP_SHARED:
fixme("MAP_SHARED not implemented"); fixme("MAP_SHARED not implemented");
if (flags & MAP_PRIVATE) [[fallthrough]];
fixme("MAP_PRIVATE not implemented"); case MAP_SHARED_VALIDATE:
if (flags & MAP_SHARED_VALIDATE)
fixme("MAP_SHARED_VALIDATE not implemented"); fixme("MAP_SHARED_VALIDATE not implemented");
if (flags & MAP_TYPE) [[fallthrough]];
fixme("MAP_TYPE not implemented"); case MAP_PRIVATE:
if (flags & MAP_FIXED) debug("MAP_PRIVATE ignored");
fixme("MAP_FIXED not implemented"); [[fallthrough]];
if (flags & MAP_ANONYMOUS) case MAP_ANONYMOUS:
fixme("MAP_ANONYMOUS not implemented"); 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) if (fildes != -1)
{ {
fixme("File mapping not implemented"); fixme("File mapping not implemented");
return MAP_FAILED; mm->FreePages(newPages, TO_PAGES(length));
return (void *)-ENOSYS;
} }
return newPages; return addr;
}
stub;
return MAP_FAILED;
} }
/* https://man7.org/linux/man-pages/man3/mprotect.3p.html */ /* 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; Tasking::PCB *pcb = thisProcess;
Memory::Virtual vma = Memory::Virtual(pcb->PageTable); Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
vma.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB); vmm.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB);
if (prot & PROT_READ) 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) 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) 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; return 0;
} }
/* https://man7.org/linux/man-pages/man2/brk.2.html */ /* 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; trace("Ignoring brk syscall...");
Memory::MemMgr *mgr = pcb->Memory; return (void *)-ENOSYS;
// Tasking::PCB *pcb = thisProcess;
stub; // void *ret = pcb->ProgramBreak->brk(addr);
size_t PagesToAllocate = increment ? TO_PAGES(increment) : 1; // debug("brk(%#lx) = %#lx", addr, ret);
return (void *)mgr->RequestPages(PagesToAllocate, true); // return ret;
} }
/* https://man7.org/linux/man-pages/man2/ioctl.2.html */ /* https://man7.org/linux/man-pages/man2/ioctl.2.html */
static int sys_ioctl(int fd, unsigned long request, void *argp) static int sys_ioctl(int fd, unsigned long request, void *argp)
{ {
UNUSED(fd); Tasking::PCB *pcb = thisProcess;
UNUSED(request); VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
UNUSED(argp); Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
return -ENOSYS;
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 */ /* 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; ssize_t Total = 0;
for (int i = 0; i < iovcnt; i++) 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); ssize_t n = sys_read(fildes, iov[i].iov_base, iov[i].iov_len);
if (n < 0) if (n < 0)
return n; return n;
debug("n: %d", n);
Total += n; Total += n;
if (n < (ssize_t)iov[i].iov_len) if (n < (ssize_t)iov[i].iov_len)
{
debug("break");
break; break;
} }
}
debug("readv: %d", Total);
return Total; return Total;
} }
@ -271,17 +410,39 @@ static ssize_t sys_writev(int fildes, const struct iovec *iov, int iovcnt)
ssize_t Total = 0; ssize_t Total = 0;
for (int i = 0; i < iovcnt; i++) 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); ssize_t n = sys_write(fildes, iov[i].iov_base, iov[i].iov_len);
if (n < 0) if (n < 0)
return n; return n;
debug("n: %d", n);
Total += n; Total += n;
if (n < (ssize_t)iov[i].iov_len) if (n < (ssize_t)iov[i].iov_len)
{
debug("break");
break; break;
} }
}
debug("writev: %d", Total);
return 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 */ /* https://man7.org/linux/man-pages/man3/exit.3.html */
static __noreturn void sys_exit(int status) 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 */ /* https://man7.org/linux/man-pages/man2/arch_prctl.2.html */
static int sys_arch_prctl(int code, unsigned long addr) 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) switch (code)
{ {
case 0x1001: // ARCH_SET_GS case ARCH_SET_GS:
{ {
#if defined(a64) #if defined(a64)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); 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 #endif
return 0; return 0;
} }
case 0x1002: // ARCH_SET_FS case ARCH_SET_FS:
{ {
#if defined(a64) #if defined(a64)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); 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 #endif
return 0; return 0;
} }
case 0x1003: // ARCH_GET_FS case ARCH_GET_FS:
{ {
#if defined(a64) #if defined(a64)
*r_cst(uint64_t *, addr) = *r_cst(uint64_t *, addr) =
@ -338,7 +514,7 @@ static int sys_arch_prctl(int code, unsigned long addr)
#endif #endif
return 0; return 0;
} }
case 0x1004: // ARCH_GET_GS case ARCH_GET_GS:
{ {
#if defined(a64) #if defined(a64)
*r_cst(uint64_t *, addr) = *r_cst(uint64_t *, addr) =
@ -349,17 +525,43 @@ static int sys_arch_prctl(int code, unsigned long addr)
#endif #endif
return 0; return 0;
} }
default: case ARCH_GET_CPUID:
fixme("code=%d", code); 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; return -ENOSYS;
} }
default:
{
warn("Invalid code %#lx", code);
return -EINVAL;
}
}
} }
/* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */ /* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */
static pid_t sys_set_tid_address(int *tidptr) static pid_t sys_set_tid_address(int *tidptr)
{ {
if (tidptr == nullptr)
return -EINVAL;
Tasking::TCB *tcb = thisThread; Tasking::TCB *tcb = thisThread;
*tidptr = tcb->ID;
tcb->Linux.clear_child_tid = tidptr;
return tcb->ID; return tcb->ID;
} }
@ -382,7 +584,7 @@ static SyscallData LinuxSyscallsTable[] = {
[__NR_lseek] = {"lseek", (void *)sys_lseek}, [__NR_lseek] = {"lseek", (void *)sys_lseek},
[__NR_mmap] = {"mmap", (void *)sys_mmap}, [__NR_mmap] = {"mmap", (void *)sys_mmap},
[__NR_mprotect] = {"mprotect", (void *)sys_mprotect}, [__NR_mprotect] = {"mprotect", (void *)sys_mprotect},
[__NR_munmap] = {"munmap", (void *)nullptr}, [__NR_munmap] = {"munmap", (void *)sys_munmap},
[__NR_brk] = {"brk", (void *)sys_brk}, [__NR_brk] = {"brk", (void *)sys_brk},
[__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr}, [__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr},
[__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr}, [__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr},
@ -403,8 +605,8 @@ static SyscallData LinuxSyscallsTable[] = {
[__NR_shmget] = {"shmget", (void *)nullptr}, [__NR_shmget] = {"shmget", (void *)nullptr},
[__NR_shmat] = {"shmat", (void *)nullptr}, [__NR_shmat] = {"shmat", (void *)nullptr},
[__NR_shmctl] = {"shmctl", (void *)nullptr}, [__NR_shmctl] = {"shmctl", (void *)nullptr},
[__NR_dup] = {"dup", (void *)nullptr}, [__NR_dup] = {"dup", (void *)sys_dup},
[__NR_dup2] = {"dup2", (void *)nullptr}, [__NR_dup2] = {"dup2", (void *)sys_dup2},
[__NR_pause] = {"pause", (void *)nullptr}, [__NR_pause] = {"pause", (void *)nullptr},
[__NR_nanosleep] = {"nanosleep", (void *)nullptr}, [__NR_nanosleep] = {"nanosleep", (void *)nullptr},
[__NR_getitimer] = {"getitimer", (void *)nullptr}, [__NR_getitimer] = {"getitimer", (void *)nullptr},
@ -837,7 +1039,7 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame)
if (unlikely(!call)) if (unlikely(!call))
{ {
error("Syscall %s(%d) not implemented.", fixme("Syscall %s(%d) not implemented.",
Syscall.Name, Frame->rax); Syscall.Name, Frame->rax);
return -ENOSYS; 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, static long sys_local_thread_state(SysFrm *, int Code,
unsigned long Address) 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) #if defined(a64) || defined(aa64)
switch (Code) switch (Code)
{ {

View File

@ -21,11 +21,43 @@
#include "../kernel.h" #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) extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
{ {
/* Automatically switch to kernel page table
and switch back when this function returns. */
AutoSwitchPageTable PageSwitcher;
uint64_t TempTimeCalc = TimeManager->GetCounter();
Tasking::TaskInfo *Ptinfo = &thisProcess->Info; Tasking::TaskInfo *Ptinfo = &thisProcess->Info;
Tasking::TaskInfo *Ttinfo = &thisThread->Info; Tasking::TaskInfo *Ttinfo = &thisThread->Info;
uint64_t TempTimeCalc = TimeManager->GetCounter();
switch (Ttinfo->Compatibility) switch (Ttinfo->Compatibility)
{ {

View File

@ -55,16 +55,19 @@ namespace Tasking
assert(name != nullptr); assert(name != nullptr);
assert(strlen(name) > 0); 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) if (this->Name)
delete[] this->Name; delete[] this->Name;
this->Name = new char[strlen(name) + 1]; this->Name = new char[strlen(name) + 1];
strcpy((char *)this->Name, name); strcpy((char *)this->Name, name);
} }
void PCB::SetWorkingDirectory(VirtualFileSystem::Node *node) 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); this->Name, node, node->Name);
CurrentWorkingDirectory = node; CurrentWorkingDirectory = node;
} }
@ -75,46 +78,44 @@ namespace Tasking
uint16_t UserID, uint16_t GroupID) uint16_t UserID, uint16_t GroupID)
{ {
assert(ctx != nullptr); assert(ctx != nullptr);
assert(Name != nullptr);
assert(strlen(Name) > 0);
assert(ExecutionMode >= _ExecuteModeMin); assert(ExecutionMode >= _ExecuteModeMin);
assert(ExecutionMode <= _ExecuteModeMax); assert(ExecutionMode <= _ExecuteModeMax);
this->ctx = ctx; this->ctx = ctx;
this->ID = ctx->NextPID++; this->ID = ctx->NextPID++;
if (this->Name)
if (this->Name) /* Prevent memory leak */
delete[] this->Name; delete[] this->Name;
this->Name = new char[strlen(Name) + 1]; this->Name = new char[strlen(Name) + 1];
strcpy((char *)this->Name, Name); strcpy((char *)this->Name, Name);
this->ExitCode = KILL_CRASH; this->ExitCode = KILL_CRASH;
this->Security.ExecutionMode = ExecutionMode;
/* Check parent */
if (Parent == nullptr) if (Parent == nullptr)
this->Parent = ctx->GetCurrentProcess(); this->Parent = ctx->GetCurrentProcess();
else else
this->Parent = Parent; this->Parent = Parent;
/* Set uid & gid */
if (this->Parent && if (this->Parent &&
UserID == UINT16_MAX && UserID == UINT16_MAX &&
GroupID == UINT16_MAX) GroupID == UINT16_MAX)
{ {
UserID = this->Parent->Security.Real.UserID; UserID = this->Parent->Security.Real.UserID;
GroupID = this->Parent->Security.Real.GroupID; 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.UserID = UserID;
this->Security.Real.GroupID = GroupID; this->Security.Real.GroupID = GroupID;
this->Security.Effective.UserID = UserID; this->Security.Effective.UserID = UserID;
this->Security.Effective.GroupID = GroupID; this->Security.Effective.GroupID = GroupID;
this->Security.ExecutionMode = ExecutionMode;
char ProcFSName[16];
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)
{
OwnPageTable = true;
switch (ExecutionMode) switch (ExecutionMode)
{ {
case TaskExecutionMode::System: case TaskExecutionMode::System:
@ -123,46 +124,43 @@ namespace Tasking
case TaskExecutionMode::Kernel: case TaskExecutionMode::Kernel:
{ {
this->Security.IsCritical = true; 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; break;
} }
case TaskExecutionMode::User: 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; break;
} }
default: default:
assert(false); 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);
/* If create page table */
if (DoNotCreatePageTable == false)
{
OwnPageTable = true;
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->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) if (Image)
{
this->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image); this->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image);
}
else
{
debug("No image provided for process \"%s\"(%d)",
this->Name, this->ID);
}
if (Parent) if (Parent)
Parent->Children.push_back(this); Parent->Children.push_back(this);
@ -182,32 +180,51 @@ namespace Tasking
debug("Destroying process \"%s\"(%d)", debug("Destroying process \"%s\"(%d)",
this->Name, this->ID); 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.erase(std::find(ctx->ProcessList.begin(),
ctx->ProcessList.end(), ctx->ProcessList.end(),
this)); this));
/* If we have a symbol table allocated,
we need to free it */
if (this->ELFSymbolTable) if (this->ELFSymbolTable)
delete this->ELFSymbolTable; delete this->ELFSymbolTable;
/* Free IPC */
delete this->IPC; delete this->IPC;
delete this->FileDescriptors;
/* Free all allocated memory */
delete this->ProgramBreak;
delete this->Memory; delete this->Memory;
/* Closing all open files */
delete this->FileDescriptors;
/* Free Name */
delete[] this->Name; delete[] this->Name;
/* If we own the pointer to the
PageTable, we need to free it */
if (this->PageTable && OwnPageTable) if (this->PageTable && OwnPageTable)
{ {
size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1); size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1);
KernelAllocator.FreePages(this->PageTable, PTPgs); KernelAllocator.FreePages(this->PageTable, PTPgs);
} }
/* Exit all children processes */
foreach (auto pcb in this->Children) foreach (auto pcb in this->Children)
delete pcb; delete pcb;
/* Exit all threads */
foreach (auto tcb in this->Threads) foreach (auto tcb in this->Threads)
delete tcb; delete tcb;
/* Delete /proc/{pid} directory */
vfs->Delete(this->ProcessDirectory, true); vfs->Delete(this->ProcessDirectory, true);
/* If we have a Parent, remove us from
their children list */
if (this->Parent) if (this->Parent)
{ {
std::vector<Tasking::PCB *> &pChild = this->Parent->Children; std::vector<Tasking::PCB *> &pChild = this->Parent->Children;

View File

@ -49,15 +49,15 @@ namespace Tasking
#if defined(a86) #if defined(a86)
__naked __used __no_stack_protector void IdleProcessLoop() __naked __used __no_stack_protector void IdleProcessLoop()
{ {
asmv("IdleLoop:\n" asmv("IdleLoop:");
"hlt\n" asmv("hlt");
"jmp IdleLoop\n"); asmv("jmp IdleLoop");
#elif defined(aa64) #elif defined(aa64)
__used __no_stack_protector void IdleProcessLoop() __used __no_stack_protector void IdleProcessLoop()
{ {
asmv("IdleLoop:\n" asmv("IdleLoop:");
"wfe\n" asmv("wfe");
"b IdleLoop\n"); asmv("b IdleLoop");
#endif #endif
} }

View File

@ -44,6 +44,7 @@
#define tskdbg(m, ...) #define tskdbg(m, ...)
#endif #endif
/* For kernel threads only */
void ThreadDoExit() void ThreadDoExit()
{ {
CPUData *CPUData = GetCurrentCPU(); CPUData *CPUData = GetCurrentCPU();
@ -64,9 +65,12 @@ namespace Tasking
assert(name != nullptr); assert(name != nullptr);
assert(strlen(name) > 0); 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) if (this->Name)
delete[] this->Name; delete[] this->Name;
this->Name = new char[strlen(name) + 1]; this->Name = new char[strlen(name) + 1];
strcpy((char *)this->Name, name); strcpy((char *)this->Name, name);
} }
@ -120,139 +124,24 @@ namespace Tasking
this->Registers.r9 = Arg6; this->Registers.r9 = Arg6;
if (Function != nullptr) if (Function != nullptr)
this->Registers.rip = (uint64_t)Function; 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 #else
#warning "SYSV ABI not implemented for this architecture" #warning "SYSV ABI not implemented for this architecture"
#endif #endif
} }
__no_sanitize("undefined") __no_sanitize("undefined") void TCB::SetupUserStack_x86_64(const char **argv,
TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint, const char **envp,
const char **argv, const char **envp, const std::vector<AuxiliaryVector> &auxv)
const std::vector<AuxiliaryVector> &auxv,
TaskArchitecture Architecture,
TaskCompatibility Compatibility,
bool ThreadNotReady)
{ {
assert(ctx != nullptr);
assert(Architecture >= _ArchitectureMin);
assert(Architecture <= _ArchitectureMax);
assert(Compatibility >= _CompatibilityMin);
assert(Compatibility <= _CompatibilityMax);
if (Parent == nullptr)
{
this->Parent = ctx->GetCurrentProcess();
assert(this->Parent != nullptr);
}
else
this->Parent = Parent;
this->ctx = ctx;
this->ID = ctx->NextTID++;
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;
#elif defined(a32)
this->Registers.eip = EntryPoint;
#elif defined(aa64)
this->Registers.pc = EntryPoint;
#endif
switch (this->Parent->Security.ExecutionMode)
{
case TaskExecutionMode::System:
fixme("System mode not supported.");
[[fallthrough]];
case TaskExecutionMode::Kernel:
{
this->Security.IsCritical = true;
this->Stack = new Memory::StackGuard(false,
this->Parent->PageTable);
#if defined(a64)
this->ShadowGSBase =
CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE);
this->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE);
this->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE);
this->Registers.cs = GDT_KERNEL_CODE;
this->Registers.ss = GDT_KERNEL_DATA;
this->Registers.rflags.AlwaysOne = 1;
this->Registers.rflags.IF = 1;
this->Registers.rflags.ID = 1;
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop());
POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit;
#elif defined(a32)
#elif defined(aa64)
#endif
break;
}
case TaskExecutionMode::User:
{
this->Stack = new Memory::StackGuard(true,
this->Parent->PageTable);
gsTCB *gsT = (gsTCB *)this->Memory->RequestPages(TO_PAGES(sizeof(gsTCB)));
gsT->SyscallStack =
(uintptr_t)this->Memory->RequestPages(TO_PAGES(STACK_SIZE)) +
STACK_SIZE - 0x10;
gsT->TempStack = 0x0;
gsT->t = this;
#if defined(a64)
this->ShadowGSBase = (uintptr_t)gsT;
this->GSBase = 0;
this->FSBase = 0;
this->Registers.cs = GDT_USER_CODE;
this->Registers.ss = GDT_USER_DATA;
this->Registers.rflags.AlwaysOne = 1;
this->Registers.rflags.IF = 1;
this->Registers.rflags.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
GPF or PF exception. */
#pragma region
size_t ArgvSize = 0; size_t ArgvSize = 0;
if (argv) if (argv)
while (argv[ArgvSize] != nullptr) while (argv[ArgvSize] != nullptr)
@ -389,11 +278,151 @@ namespace Tasking
this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv
this->Registers.rcx = (uintptr_t)EnvpSize; // envc this->Registers.rcx = (uintptr_t)EnvpSize; // envc
this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp
}
#pragma endregion 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);
assert(Architecture <= _ArchitectureMax);
assert(Compatibility >= _CompatibilityMin);
assert(Compatibility <= _CompatibilityMax);
if (Parent == nullptr)
{
this->Parent = ctx->GetCurrentProcess();
assert(this->Parent != nullptr);
}
else
this->Parent = Parent;
this->ctx = ctx;
this->ID = ctx->NextTID++;
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;
if (ThreadNotReady)
this->Status = TaskStatus::Zombie;
else
this->Status = TaskStatus::Ready;
this->Memory = new Memory::MemMgr(this->Parent->PageTable,
this->Parent->memDirectory);
#if defined(a64)
this->Registers.rip = EntryPoint;
#elif defined(a32) #elif defined(a32)
this->Registers.eip = EntryPoint;
#elif defined(aa64) #elif defined(aa64)
this->Registers.pc = EntryPoint;
#endif
switch (this->Parent->Security.ExecutionMode)
{
case TaskExecutionMode::System:
fixme("System mode not supported.");
[[fallthrough]];
case TaskExecutionMode::Kernel:
{
this->Security.IsCritical = true;
this->Stack = new Memory::StackGuard(false,
this->Parent->PageTable);
#if defined(a64)
this->ShadowGSBase =
CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE);
this->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE);
this->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE);
this->Registers.cs = GDT_KERNEL_CODE;
this->Registers.ss = GDT_KERNEL_DATA;
this->Registers.rflags.AlwaysOne = 1;
this->Registers.rflags.IF = 1;
this->Registers.rflags.ID = 1;
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;
}
case TaskExecutionMode::User:
{
this->Stack = new Memory::StackGuard(true,
this->Parent->PageTable);
gsTCB *gsT = (gsTCB *)this->Memory->RequestPages(TO_PAGES(sizeof(gsTCB)));
gsT->SyscallStack =
(uintptr_t)this->Memory->RequestPages(TO_PAGES(STACK_SIZE)) +
STACK_SIZE - 0x10;
gsT->TempStack = 0x0;
gsT->t = this;
#if defined(a64)
this->ShadowGSBase = (uintptr_t)gsT;
this->GSBase = 0;
this->FSBase = 0;
this->Registers.cs = GDT_USER_CODE;
this->Registers.ss = GDT_USER_DATA;
this->Registers.rflags.AlwaysOne = 1;
this->Registers.rflags.IF = 1;
this->Registers.rflags.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_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 #endif
#ifdef DEBUG_TASKING #ifdef DEBUG_TASKING
DumpData(this->Name, this->Stack, STACK_SIZE); DumpData(this->Name, this->Stack, STACK_SIZE);
@ -404,7 +433,32 @@ namespace Tasking
assert(false); 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 DEBUG
#ifdef a64 #ifdef a64
@ -436,6 +490,8 @@ namespace Tasking
this->Parent->ID); this->Parent->ID);
#endif #endif
this->Info.SpawnTime = TimeManager->GetCounter();
this->Parent->Threads.push_back(this); this->Parent->Threads.push_back(this);
if (this->Parent->Threads.size() == 1 && if (this->Parent->Threads.size() == 1 &&
@ -448,13 +504,20 @@ namespace Tasking
TCB::~TCB() TCB::~TCB()
{ {
/* Remove us from the process list so we
don't get scheduled anymore */
std::vector<Tasking::TCB *> &Threads = this->Parent->Threads; std::vector<Tasking::TCB *> &Threads = this->Parent->Threads;
Threads.erase(std::find(Threads.begin(), Threads.erase(std::find(Threads.begin(),
Threads.end(), Threads.end(),
this)); this));
/* Free Name */
delete[] this->Name; delete[] this->Name;
/* Free CPU Stack */
delete this->Stack; delete this->Stack;
/* Free all allocated memory */
delete this->Memory; delete this->Memory;
} }
} }

View File

@ -44,7 +44,6 @@ test_mem_new_delete::~test_mem_new_delete()
; ;
} }
extern bool EnableExternalMemoryTracer;
extern bool DebuggerIsAttached; extern bool DebuggerIsAttached;
void TestMemoryAllocation() void TestMemoryAllocation()
@ -52,9 +51,9 @@ void TestMemoryAllocation()
#ifdef a32 #ifdef a32
return; /* Not ready for now. */ return; /* Not ready for now. */
#endif #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; return;
} }
@ -68,13 +67,13 @@ void TestMemoryAllocation()
debug("Single Page Request Test"); debug("Single Page Request Test");
{ {
uint64_t prq1 = (uint64_t)KernelAllocator.RequestPage(); uintptr_t prq1 = (uintptr_t)KernelAllocator.RequestPage();
KernelAllocator.FreePage((void *)prq1); KernelAllocator.FreePage((void *)prq1);
for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) for (size_t i = 0; i < MEMTEST_ITERATIONS; i++)
KernelAllocator.FreePage(KernelAllocator.RequestPage()); KernelAllocator.FreePage(KernelAllocator.RequestPage());
uint64_t prq2 = (uint64_t)KernelAllocator.RequestPage(); uintptr_t prq2 = (uintptr_t)KernelAllocator.RequestPage();
KernelAllocator.FreePage((void *)prq2); KernelAllocator.FreePage((void *)prq2);
debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
@ -83,13 +82,13 @@ void TestMemoryAllocation()
debug("Multiple Page Request Test"); 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); KernelAllocator.FreePages((void *)prq1, 10);
for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) for (size_t i = 0; i < MEMTEST_ITERATIONS; i++)
KernelAllocator.FreePages(KernelAllocator.RequestPages(20), 20); 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); KernelAllocator.FreePages((void *)prq2, 10);
debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);

View File

@ -21,15 +21,15 @@
#include <memory.hpp> #include <memory.hpp>
#include <convert.h> #include <convert.h>
extern bool EnableExternalMemoryTracer;
extern bool DebuggerIsAttached; extern bool DebuggerIsAttached;
extern Memory::MemoryAllocatorType AllocatorType; extern Memory::MemoryAllocatorType AllocatorType;
__constructor void TestMemoryOperations() __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; return;
} }

View File

@ -66,6 +66,18 @@ namespace Execute
std::vector<AuxiliaryVector> Elfauxv; std::vector<AuxiliaryVector> Elfauxv;
Tasking::IP ip; 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, void LoadExec_x86_32(int fd,
Tasking::PCB *TargetProcess); Tasking::PCB *TargetProcess);
@ -99,7 +111,8 @@ namespace Execute
int Spawn(char *Path, const char **argv, const char **envp, int Spawn(char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent = nullptr, Tasking::PCB *Parent = nullptr,
Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native,
bool Critical = false);
bool ELFIs64(void *Header); bool ELFIs64(void *Header);
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header); Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);

View File

@ -357,7 +357,23 @@ namespace VirtualFileSystem
class FileDescriptorTable class FileDescriptorTable
{ {
public: 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{}; RefNode *Handle{};
mode_t Mode = 0; mode_t Mode = 0;
@ -366,10 +382,13 @@ namespace VirtualFileSystem
}; };
private: private:
std::vector<FileDescriptor> FileDescriptors; std::vector<Fildes> FileDescriptors;
std::vector<DupFildes> FildesDuplicates;
VirtualFileSystem::Node *fdDir = nullptr; 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 ProbeMode(mode_t Mode, int Flags);
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags); int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
int RemoveFileDescriptor(int FileDescriptor); int RemoveFileDescriptor(int FileDescriptor);
@ -377,7 +396,7 @@ namespace VirtualFileSystem
public: public:
std::string GetAbsolutePath(int FileDescriptor); 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 _open(const char *pathname, int flags, mode_t mode);
int _creat(const char *pathname, 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 _stat(const char *pathname, struct stat *statbuf);
int _fstat(int fd, struct stat *statbuf); int _fstat(int fd, struct stat *statbuf);
int _lstat(const char *pathname, 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(void *Owner);
~FileDescriptorTable(); ~FileDescriptorTable();

View File

@ -22,93 +22,9 @@
#include <filesystem.hpp> #include <filesystem.hpp>
namespace VirtualFileSystem void Init_Null(VirtualFileSystem::Virtual *vfs_ctx);
{ void Init_Random(VirtualFileSystem::Virtual *vfs_ctx);
/* Manage /dev */ void Init_Teletype(VirtualFileSystem::Virtual *vfs_ctx);
class Device void Init_Zero(VirtualFileSystem::Virtual *vfs_ctx);
{
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();
};
}
#endif // !__FENNIX_KERNEL_FILESYSTEM_DEV_H__ #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) #define FROM_PAGES(d) ((d)*PAGE_SIZE)
#if defined(a64) || defined(aa64) #if defined(a64) || defined(aa64)
#define NORMAL_VMA_OFFSET 0xFFFF800000000000
#define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000 #define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000
#define KERNEL_HEAP_BASE 0xFFFFA00000000000 #define KERNEL_HEAP_BASE 0xFFFFFF0000000000
#define USER_HEAP_BASE 0xFFFFB00000000000
#define USER_STACK_BASE 0xFFFFEFFFFFFF0000 #define USER_STACK_BASE 0xFFFFEFFFFFFF0000
#elif defined(a32) #elif defined(a32)
#define NORMAL_VMA_OFFSET 0x80000000
#define KERNEL_VMA_OFFSET 0xC0000000 #define KERNEL_VMA_OFFSET 0xC0000000
#define KERNEL_HEAP_BASE 0xA0000000 #define KERNEL_HEAP_BASE 0xA0000000
#define USER_HEAP_BASE 0xB0000000
#define USER_STACK_BASE 0xEFFFFFFF #define USER_STACK_BASE 0xEFFFFFFF
#endif #endif
@ -86,6 +82,7 @@ namespace Memory
None, None,
Pages, Pages,
XallocV1, XallocV1,
XallocV2,
liballoc11 liballoc11
}; };
@ -584,8 +581,35 @@ namespace Memory
* @return A new PageTable with the same content * @return A new PageTable with the same content
*/ */
PageTable Fork(); PageTable Fork();
template <typename T>
T Get(T Address);
} __aligned(0x1000); } __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 class Physical
{ {
private: private:
@ -1077,6 +1101,30 @@ namespace Memory
std::vector<AllocatedPages> AllocatedPagesList; 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 class SmartHeap
{ {
private: private:

View File

@ -159,17 +159,35 @@ namespace Tasking
private: private:
class Task *ctx = nullptr; 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: public:
/* Basic info */
TID ID = -1; TID ID = -1;
const char *Name = nullptr; const char *Name = nullptr;
class PCB *Parent = nullptr; class PCB *Parent = nullptr;
IP EntryPoint = 0; IP EntryPoint = 0;
/* Statuses */
std::atomic_int ExitCode; std::atomic_int ExitCode;
std::atomic<TaskStatus> Status = TaskStatus::UnknownStatus; std::atomic<TaskStatus> Status = TaskStatus::Zombie;
Memory::StackGuard *Stack;
Memory::MemMgr *Memory;
int ErrorNumber; int ErrorNumber;
/* Memory */
Memory::MemMgr *Memory;
Memory::StackGuard *Stack;
/* CPU state */
#if defined(a64) #if defined(a64)
CPU::x64::TrapFrame Registers{}; CPU::x64::TrapFrame Registers{};
uintptr_t ShadowGSBase, GSBase, FSBase; uintptr_t ShadowGSBase, GSBase, FSBase;
@ -180,6 +198,9 @@ namespace Tasking
uintptr_t Registers; // TODO uintptr_t Registers; // TODO
#endif #endif
uintptr_t IPHistory[128]; uintptr_t IPHistory[128];
CPU::x64::FXState *FPU;
/* Info & Security info */
struct struct
{ {
TaskExecutionMode ExecutionMode = UnknownExecutionMode; TaskExecutionMode ExecutionMode = UnknownExecutionMode;
@ -188,7 +209,13 @@ namespace Tasking
bool IsKernelDebugEnabled = false; bool IsKernelDebugEnabled = false;
} Security{}; } Security{};
TaskInfo Info{}; TaskInfo Info{};
CPU::x64::FXState *FPU;
/* Compatibility structures */
struct
{
int *set_child_tid{};
int *clear_child_tid{};
} Linux{};
void Rename(const char *name); void Rename(const char *name);
void SetPriority(TaskPriority priority); void SetPriority(TaskPriority priority);
@ -228,11 +255,16 @@ namespace Tasking
bool OwnPageTable = false; bool OwnPageTable = false;
public: public:
/* Basic info */
PID ID = -1; PID ID = -1;
const char *Name = nullptr; const char *Name = nullptr;
PCB *Parent = nullptr; PCB *Parent = nullptr;
/* Statuses */
std::atomic_int ExitCode; std::atomic_int ExitCode;
std::atomic<TaskStatus> Status = Zombie; std::atomic<TaskStatus> Status = Zombie;
/* Info & Security info */
struct struct
{ {
TaskExecutionMode ExecutionMode = UnknownExecutionMode; TaskExecutionMode ExecutionMode = UnknownExecutionMode;
@ -246,17 +278,26 @@ namespace Tasking
} Real, Effective; } Real, Effective;
} Security{}; } Security{};
TaskInfo Info{}; TaskInfo Info{};
std::vector<TCB *> Threads;
std::vector<PCB *> Children; /* Filesystem */
InterProcessCommunication::IPC *IPC;
Memory::PageTable *PageTable;
SymbolResolver::Symbols *ELFSymbolTable;
Node *CurrentWorkingDirectory; Node *CurrentWorkingDirectory;
Node *ProcessDirectory; Node *ProcessDirectory;
Node *memDirectory; Node *memDirectory;
Memory::MemMgr *Memory;
FileDescriptorTable *FileDescriptors; 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: public:
void Rename(const char *name); void Rename(const char *name);
void SetWorkingDirectory(Node *node); void SetWorkingDirectory(Node *node);

View File

@ -411,12 +411,6 @@ typedef uint48_t uint_fast48_t;
#define NIF __no_instrument_function #define NIF __no_instrument_function
#define int1 \
__asm__ __volatile__("int $0x1" \
: \
: \
: "memory")
#define int3 \ #define int3 \
__asm__ __volatile__("int3" \ __asm__ __volatile__("int3" \
: \ : \

View File

@ -22,7 +22,7 @@
#include <convert.h> #include <convert.h>
#include <debug.h> #include <debug.h>
// show debug messages // Show debug messages
// #define DEBUG_CPP_STRING 1 // #define DEBUG_CPP_STRING 1
// #define DEBUG_CPP_STRING_VERBOSE 1 // #define DEBUG_CPP_STRING_VERBOSE 1
@ -62,48 +62,49 @@ namespace std
this->Capacity = this->Length + 1; this->Capacity = this->Length + 1;
this->Data = new char[this->Capacity]; this->Data = new char[this->Capacity];
strcpy(this->Data, Str); strcpy(this->Data, Str);
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
} }
~string() ~string()
{ {
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
delete[] this->Data, this->Data = nullptr; delete[] this->Data, this->Data = nullptr;
} }
size_t length() const size_t length() const
{ {
v_strdbg("String length: %d", v_strdbg("%#lx: String length: %d",
this->Length); this, this->Length);
return this->Length; return this->Length;
} }
size_t capacity() const size_t capacity() const
{ {
v_strdbg("String capacity: %d", v_strdbg("%#lx: String capacity: %d",
this->Capacity); this, this->Capacity);
return this->Capacity; return this->Capacity;
} }
const char *c_str() const const char *c_str() const
{ {
v_strdbg("String data: \"%s\"", v_strdbg("%#lx: String data: \"%s\"",
this->Data); this, this->Data);
return this->Data; return this->Data;
} }
void resize(size_t NewLength) void resize(size_t NewLength)
{ {
strdbg("String resize: %d", NewLength); strdbg("%#lx: String resize: %d",
this, NewLength);
if (NewLength < this->Capacity) if (NewLength < this->Capacity)
{ {
this->Length = NewLength; this->Length = NewLength;
this->Data[this->Length] = '\0'; this->Data[this->Length] = '\0';
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return; return;
} }
@ -111,16 +112,16 @@ namespace std
char *newData = new char[newCapacity]; char *newData = new char[newCapacity];
strcpy(newData, this->Data); strcpy(newData, this->Data);
strdbg("old: %#lx, new: %#lx", strdbg("%#lx: old: %#lx, new: %#lx",
this->Data, newData); this, this->Data, newData);
delete[] this->Data; delete[] this->Data;
this->Data = newData; this->Data = newData;
this->Length = NewLength; this->Length = NewLength;
this->Capacity = newCapacity; this->Capacity = newCapacity;
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
} }
void concat(const string &Other) void concat(const string &Other)
@ -129,31 +130,34 @@ namespace std
this->resize(NewLength); this->resize(NewLength);
strcat(this->Data, Other.Data); strcat(this->Data, Other.Data);
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
} }
bool empty() const bool empty() const
{ {
strdbg("String empty: %d", this->Length == 0); strdbg("%#lx: String empty: %d",
this, this->Length == 0);
return this->Length == 0; return this->Length == 0;
} }
size_t size() const size_t size() const
{ {
strdbg("String size: %d", this->Length); strdbg("%#lx: String size: %d",
this, this->Length);
return this->Length; return this->Length;
} }
void clear() void clear()
{ {
strdbg("String clear"); strdbg("%#lx: String clear", this);
this->resize(0); this->resize(0);
} }
size_t find(const char *Str, size_t Pos = 0) const 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) if (Pos >= this->Length)
return npos; return npos;
@ -176,13 +180,15 @@ namespace std
size_t find(const string &Str, size_t Pos = 0) const 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); return this->find(Str.c_str(), Pos);
} }
void erase(int Index, int Count = 1) 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) if (Index < 0 || (size_t)Index >= this->Length)
return; return;
@ -197,12 +203,14 @@ namespace std
this->Length -= Count; this->Length -= Count;
this->Data[this->Length] = '\0'; 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 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) if (Pos == npos)
Pos = this->Length - 1; Pos = this->Length - 1;
@ -225,7 +233,8 @@ namespace std
size_t find_first_not_of(const char *Str, size_t Pos = 0) const 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) if (Pos >= this->Length)
return npos; return npos;
@ -248,7 +257,8 @@ namespace std
size_t find_first_of(const char *Str, size_t Pos = 0) const 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) if (Pos >= this->Length)
return npos; return npos;
@ -271,7 +281,8 @@ namespace std
size_t find_last_of(const char *Str, size_t Pos = npos) const 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) if (Pos == npos)
Pos = this->Length - 1; Pos = this->Length - 1;
@ -294,7 +305,8 @@ namespace std
size_t find_first_of(char C, size_t Pos = 0) const 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) if (Pos >= this->Length)
return npos; return npos;
@ -308,7 +320,8 @@ namespace std
size_t find_last_of(char C, size_t Pos = npos) const 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) if (Pos == npos)
Pos = this->Length - 1; Pos = this->Length - 1;
@ -322,7 +335,8 @@ namespace std
size_t substr(const char *Str, size_t Pos = 0) const 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) if (Pos >= this->Length)
return npos; return npos;
@ -345,13 +359,15 @@ namespace std
size_t substr(const string &Str, size_t Pos = 0) const 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); return this->substr(Str.c_str(), Pos);
} }
string substr(size_t Pos = 0, size_t Count = npos) const 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) if (Pos >= this->Length)
return string(); return string();
@ -371,7 +387,8 @@ namespace std
void replace(size_t Pos, size_t Count, const char *Str) 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) if (Pos >= this->Length)
return; return;
@ -390,12 +407,14 @@ namespace std
for (unsigned long i = 0; i < strlen(Str); i++) for (unsigned long i = 0; i < strlen(Str); i++)
this->Data[Pos + i] = 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) 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) if (Pos >= this->Length)
return; return;
@ -414,13 +433,13 @@ namespace std
for (size_t i = 0; i < Str.Length; i++) for (size_t i = 0; i < Str.Length; i++)
this->Data[Pos + i] = Str.Data[i]; this->Data[Pos + i] = Str.Data[i];
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
} }
void pop_back() void pop_back()
{ {
strdbg("String pop_back"); strdbg("%#lx: String pop_back", this);
if (this->Length > 0) if (this->Length > 0)
{ {
this->Data[this->Length - 1] = '\0'; this->Data[this->Length - 1] = '\0';
@ -432,8 +451,8 @@ namespace std
{ {
string result = *this; string result = *this;
result.concat(Other); result.concat(Other);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
result.Data, result.Data, result.Length, result.Capacity); this, result.Data, result.Data, result.Length, result.Capacity);
return result; return result;
} }
@ -441,24 +460,24 @@ namespace std
{ {
string result = *this; string result = *this;
result.concat(Other); result.concat(Other);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
result.Data, result.Data, result.Length, result.Capacity); this, result.Data, result.Data, result.Length, result.Capacity);
return result; return result;
} }
string &operator+=(const string &Other) string &operator+=(const string &Other)
{ {
this->concat(Other); this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
string &operator+=(const char *Other) string &operator+=(const char *Other)
{ {
this->concat(Other); this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
@ -466,8 +485,8 @@ namespace std
{ {
const char str[2] = {Other, '\0'}; const char str[2] = {Other, '\0'};
this->concat(str); this->concat(str);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
@ -482,8 +501,8 @@ namespace std
// this->Data = Other.Data; // this->Data = Other.Data;
// this->Length = Other.Length; // this->Length = Other.Length;
// this->Capacity = Other.Capacity; // this->Capacity = Other.Capacity;
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", // strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
// this->Data, this->Data, this->Length, this->Capacity); // this, this->Data, this->Data, this->Length, this->Capacity);
// } // }
// return *this; // return *this;
// } // }
@ -495,72 +514,76 @@ namespace std
delete[] this->Data; delete[] this->Data;
this->Data = new char[this->Capacity]; this->Data = new char[this->Capacity];
strcpy(this->Data, Other); strcpy(this->Data, Other);
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
string &operator<<(const string &Other) string &operator<<(const string &Other)
{ {
this->concat(Other); this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
string &operator<<(const char *Other) string &operator<<(const char *Other)
{ {
this->concat(Other); this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity); this, this->Data, this->Data, this->Length, this->Capacity);
return *this; return *this;
} }
char &operator[](int Index) char &operator[](int Index)
{ {
strdbg("String index: %d", Index); strdbg("%#lx: String index: %d", this, Index);
return this->Data[Index]; return this->Data[Index];
} }
const char &operator[](int Index) const const char &operator[](int Index) const
{ {
strdbg("String index: %d", Index); strdbg("%#lx: String index: %d", this, Index);
return this->Data[Index]; return this->Data[Index];
} }
char &operator[](size_t Index) char &operator[](size_t Index)
{ {
strdbg("String index: %d", Index); strdbg("%#lx: String index: %d", this, Index);
return this->Data[Index]; return this->Data[Index];
} }
const char &operator[](size_t Index) const const char &operator[](size_t Index) const
{ {
strdbg("String index: %d", Index); strdbg("%#lx: String index: %d", this, Index);
return this->Data[Index]; return this->Data[Index];
} }
bool operator==(const string &Other) const 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; return strcmp(this->Data, Other.Data) == 0;
} }
bool operator!=(const char *Other) const 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; return strcmp(this->Data, Other) != 0;
} }
bool operator!=(const string &Other) const 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; return strcmp(this->Data, Other.Data) != 0;
} }
bool operator==(const char *Other) const 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; return strcmp(this->Data, Other) == 0;
} }
@ -575,42 +598,44 @@ namespace std
iterator &operator++() iterator &operator++()
{ {
++this->Pointer; ++this->Pointer;
strdbg("String iterator incremented: %#lx", strdbg("%#lx: String iterator incremented: %#lx",
this->Pointer); this, this->Pointer);
return *this; return *this;
} }
char &operator*() char &operator*()
{ {
strdbg("String iterator dereferenced: %#lx", strdbg("%#lx: String iterator dereferenced: %#lx",
this->Pointer); this, this->Pointer);
return *this->Pointer; return *this->Pointer;
} }
bool operator!=(const iterator &Other) const bool operator!=(const iterator &Other) const
{ {
strdbg("String iterator compared: %#lx != %#lx", strdbg("%#lx: String iterator compared: %#lx != %#lx",
this->Pointer, Other.Pointer); this, this->Pointer, Other.Pointer);
return this->Pointer != Other.Pointer; return this->Pointer != Other.Pointer;
} }
bool operator==(const iterator &Other) const bool operator==(const iterator &Other) const
{ {
strdbg("String iterator compared: %#lx == %#lx", strdbg("%#lx: String iterator compared: %#lx == %#lx",
this->Pointer, Other.Pointer); this, this->Pointer, Other.Pointer);
return this->Pointer == Other.Pointer; return this->Pointer == Other.Pointer;
} }
}; };
iterator begin() iterator begin()
{ {
strdbg("String iterator begin: %#lx", this->Data); strdbg("%#lx: String iterator begin: %#lx",
this, this->Data);
return iterator(this->Data); return iterator(this->Data);
} }
iterator end() 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); 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; extern bool DebuggerIsAttached;
#ifdef __cplusplus #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 Video::Display *Display;
extern SymbolResolver::Symbols *KernelSymbolTable; extern SymbolResolver::Symbols *KernelSymbolTable;
extern Power::Power *PowerManager; extern Power::Power *PowerManager;