mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Update kernel code
This commit is contained in:
parent
ef3b761d4f
commit
8898791257
@ -23,7 +23,11 @@
|
||||
#include "../kernel.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PRINT_BACKTRACE
|
||||
/* This might end up in a deadlock in the deadlock handler.
|
||||
Nobody can escape the deadlock, not even the
|
||||
deadlock handler itself. */
|
||||
|
||||
// #define PRINT_BACKTRACE
|
||||
#endif
|
||||
|
||||
#ifdef PRINT_BACKTRACE
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Xalloc
|
||||
|
||||
Xalloc is a custom memory allocator designed for hobby operating systems. It is written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
|
||||
Xalloc is a custom memory allocator designed for hobby operating systems.
|
||||
Written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
|
||||
|
||||
#### ❗ This project is still in development and is not ready for use in production environments. ❗
|
||||
|
||||
@ -8,9 +9,11 @@ Xalloc is a custom memory allocator designed for hobby operating systems. It is
|
||||
|
||||
## Features
|
||||
|
||||
- **Simple API** - Xalloc provides a simple API for allocating and freeing memory. It is designed to be easy to use and understand.
|
||||
- **Simple API** - Simple API for allocating and freeing memory.
|
||||
|
||||
- [ ] todo complete this
|
||||
- **Efficient** - Uses a free-list to manage memory and is designed to be fast.
|
||||
|
||||
- **No dependencies** - No dependencies and is designed to be easy to integrate into your OS.
|
||||
|
||||
---
|
||||
|
||||
@ -32,11 +35,13 @@ extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
||||
// ...
|
||||
}
|
||||
|
||||
/* Mandatory only if Xalloc_MapPages is set to true */
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
/* Mandatory only if Xalloc_MapPages is set to true */
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
{
|
||||
// ...
|
||||
@ -45,13 +50,21 @@ extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
|
||||
##### Xalloc.hpp
|
||||
```cpp
|
||||
#define Xalloc_StopOnFail <bool> /* Infinite loop on failure */
|
||||
#define Xalloc_MapPages <bool> /* Map pages on allocation */
|
||||
#define Xalloc_PAGE_SIZE <page size> /* <-- Replace with your page size */
|
||||
#define Xalloc_trace(m, ...) <trace function>
|
||||
#define Xalloc_warn(m, ...) <warning function>
|
||||
#define Xalloc_err(m, ...) <error function>
|
||||
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
|
||||
#define Xalloc_lock <lock function>
|
||||
#define Xalloc_unlock <unlock function>
|
||||
|
||||
#define XallocV1_def <define a lock> /* eg. std::mutex Xalloc_lock; */
|
||||
#define XallocV1_lock <lock function>
|
||||
#define XallocV1_unlock <unlock function>
|
||||
|
||||
/* Same as above */
|
||||
#define XallocV2_def <define a lock>
|
||||
#define XallocV2_lock <lock function>
|
||||
#define XallocV2_unlock <unlock function>
|
||||
```
|
||||
|
||||
### Typical usage
|
||||
@ -135,3 +148,7 @@ If `Size` is equal to zero, and `Address` is not `nullptr`, then the call is equ
|
||||
- `Size` - The new size of the memory block in bytes.
|
||||
|
||||
---
|
||||
|
||||
## To-do
|
||||
|
||||
- [ ] Multiple free-lists for different block sizes
|
||||
|
@ -21,20 +21,20 @@
|
||||
|
||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
|
||||
{
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
||||
{
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
@ -22,98 +22,215 @@
|
||||
#include <lock.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
typedef long unsigned Xuint64_t;
|
||||
typedef long unsigned Xsize_t;
|
||||
typedef __UINT8_TYPE__ Xuint8_t;
|
||||
typedef __SIZE_TYPE__ Xsize_t;
|
||||
typedef __UINTPTR_TYPE__ Xuintptr_t;
|
||||
|
||||
#define Xalloc_StopOnFail true
|
||||
#define Xalloc_MapPages true
|
||||
#define Xalloc_PAGE_SIZE PAGE_SIZE
|
||||
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
|
||||
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
|
||||
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
|
||||
#define Xalloc_def NewLock(XallocLock)
|
||||
#define Xalloc_lock XallocLock.Lock(__FUNCTION__)
|
||||
#define Xalloc_unlock XallocLock.Unlock()
|
||||
|
||||
#define XallocV1_def NewLock(XallocV1Lock)
|
||||
#define XallocV1_lock XallocV1Lock.Lock(__FUNCTION__)
|
||||
#define XallocV1_unlock XallocV1Lock.Unlock()
|
||||
|
||||
#define XallocV2_def NewLock(XallocV2Lock)
|
||||
#define XallocV2_lock XallocV2Lock.Lock(__FUNCTION__)
|
||||
#define XallocV2_unlock XallocV2Lock.Unlock()
|
||||
|
||||
namespace Xalloc
|
||||
{
|
||||
class V1
|
||||
{
|
||||
private:
|
||||
void *BaseVirtualAddress = nullptr;
|
||||
void *FirstBlock = nullptr;
|
||||
void *LastBlock = nullptr;
|
||||
class V1
|
||||
{
|
||||
private:
|
||||
void *BaseVirtualAddress = nullptr;
|
||||
void *FirstBlock = nullptr;
|
||||
void *LastBlock = nullptr;
|
||||
|
||||
bool UserMapping = false;
|
||||
bool SMAPUsed = false;
|
||||
bool UserMapping = false;
|
||||
bool SMAPUsed = false;
|
||||
|
||||
public:
|
||||
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
|
||||
void Xstac();
|
||||
public:
|
||||
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
|
||||
void Xstac();
|
||||
|
||||
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
|
||||
void Xclac();
|
||||
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
|
||||
void Xclac();
|
||||
|
||||
/**
|
||||
* @brief Arrange the blocks to optimize the memory usage
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using
|
||||
* the allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
/**
|
||||
* @brief Arrange the blocks to optimize the memory usage
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using
|
||||
* the allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
/**
|
||||
* @brief Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
/**
|
||||
* @brief Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Construct a new Allocator object
|
||||
*
|
||||
* @param BaseVirtualAddress Virtual address to map the pages.
|
||||
* @param UserMode Map the new pages with USER flag?
|
||||
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
||||
*/
|
||||
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
|
||||
/**
|
||||
* @brief Construct a new Allocator object
|
||||
*
|
||||
* @param BaseVirtualAddress Virtual address to map the pages.
|
||||
* @param UserMode Map the new pages with USER flag?
|
||||
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
||||
*/
|
||||
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
|
||||
|
||||
/**
|
||||
* @brief Destroy the Allocator object
|
||||
*
|
||||
*/
|
||||
~V1();
|
||||
};
|
||||
/**
|
||||
* @brief Destroy the Allocator object
|
||||
*
|
||||
*/
|
||||
~V1();
|
||||
};
|
||||
|
||||
class V2
|
||||
{
|
||||
private:
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
int Sanity = 0xA110C;
|
||||
Block *Next = nullptr;
|
||||
bool IsFree = true;
|
||||
V2 *ctx = nullptr;
|
||||
|
||||
Xuint8_t *Data = nullptr;
|
||||
Xsize_t DataSize = 0;
|
||||
|
||||
void Check();
|
||||
Block(Xsize_t Size, V2 *ctx);
|
||||
~Block();
|
||||
void *operator new(Xsize_t);
|
||||
void operator delete(void *Address);
|
||||
} __attribute__((packed, aligned((16))));
|
||||
|
||||
/* The base address of the virtual memory */
|
||||
Xuintptr_t BaseVirtualAddress = 0x0;
|
||||
|
||||
/* The size of the heap */
|
||||
Xsize_t HeapSize = 0x0;
|
||||
|
||||
/* The used size of the heap */
|
||||
Xsize_t HeapUsed = 0x0;
|
||||
|
||||
Block *FirstBlock = nullptr;
|
||||
|
||||
Xuint8_t *AllocateHeap(Xsize_t Size);
|
||||
void FreeHeap(Xuint8_t *At, Xsize_t Size);
|
||||
|
||||
Xsize_t Align(Xsize_t Size);
|
||||
void *FindFreeBlock(Xsize_t Size,
|
||||
Block *&CurrentBlock);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Arrange the blocks to optimize the memory
|
||||
* usage.
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using the
|
||||
* allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
|
||||
/**
|
||||
* Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated
|
||||
* block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to
|
||||
* free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
|
||||
/**
|
||||
* Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks
|
||||
* to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated
|
||||
* block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks,
|
||||
Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block
|
||||
* to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated
|
||||
* block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Construct a new Allocator object
|
||||
*
|
||||
* @param VirtualBase Virtual address
|
||||
* to map the pages.
|
||||
*/
|
||||
V2(void *VirtualBase);
|
||||
|
||||
/**
|
||||
* Destroy the Allocator object
|
||||
*/
|
||||
~V2();
|
||||
|
||||
friend class Block;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_Xalloc_H__
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "Xalloc.hpp"
|
||||
|
||||
Xalloc_def;
|
||||
XallocV1_def;
|
||||
|
||||
#define XALLOC_CONCAT(x, y) x##y
|
||||
#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
@ -30,261 +30,261 @@ extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, X
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
|
||||
|
||||
// TODO: Change memcpy with an optimized version
|
||||
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
|
||||
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xsize_t Length)
|
||||
{
|
||||
unsigned char *dst = (unsigned char *)Destination;
|
||||
const unsigned char *src = (const unsigned char *)Source;
|
||||
for (Xuint64_t i = 0; i < Length; i++)
|
||||
dst[i] = src[i];
|
||||
return Destination;
|
||||
unsigned char *dst = (unsigned char *)Destination;
|
||||
const unsigned char *src = (const unsigned char *)Source;
|
||||
for (Xsize_t i = 0; i < Length; i++)
|
||||
dst[i] = src[i];
|
||||
return Destination;
|
||||
}
|
||||
|
||||
// TODO: Change memset with an optimized version
|
||||
void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
|
||||
void *Xmemset(void *__restrict__ Destination, int Data, Xsize_t Length)
|
||||
{
|
||||
unsigned char *Buffer = (unsigned char *)Destination;
|
||||
for (Xuint64_t i = 0; i < Length; i++)
|
||||
Buffer[i] = (unsigned char)Data;
|
||||
return Destination;
|
||||
unsigned char *Buffer = (unsigned char *)Destination;
|
||||
for (Xsize_t i = 0; i < Length; i++)
|
||||
Buffer[i] = (unsigned char)Data;
|
||||
return Destination;
|
||||
}
|
||||
|
||||
namespace Xalloc
|
||||
{
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
void *Address = nullptr;
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
void *Address = nullptr;
|
||||
|
||||
int Sanity = Xalloc_BlockSanityKey;
|
||||
Xsize_t Size = 0;
|
||||
Block *Next = nullptr;
|
||||
Block *Last = nullptr;
|
||||
bool IsFree = true;
|
||||
int Sanity = Xalloc_BlockSanityKey;
|
||||
Xsize_t Size = 0;
|
||||
Block *Next = nullptr;
|
||||
Block *Last = nullptr;
|
||||
bool IsFree = true;
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (this->Sanity != Xalloc_BlockSanityKey)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool Check()
|
||||
{
|
||||
if (this->Sanity != Xalloc_BlockSanityKey)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Block(Xsize_t Size)
|
||||
{
|
||||
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1));
|
||||
this->Size = Size;
|
||||
Xmemset(this->Address, 0, Size);
|
||||
}
|
||||
Block(Xsize_t Size)
|
||||
{
|
||||
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1));
|
||||
this->Size = Size;
|
||||
Xmemset(this->Address, 0, Size);
|
||||
}
|
||||
|
||||
~Block()
|
||||
{
|
||||
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1));
|
||||
}
|
||||
~Block()
|
||||
{
|
||||
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overload new operator to allocate memory from the heap
|
||||
* @param Size Unused
|
||||
* @return void* Pointer to the allocated memory
|
||||
*/
|
||||
void *operator new(Xsize_t Size)
|
||||
{
|
||||
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
|
||||
return ptr;
|
||||
(void)(Size);
|
||||
}
|
||||
/**
|
||||
* @brief Overload new operator to allocate memory from the heap
|
||||
* @param Size Unused
|
||||
* @return void* Pointer to the allocated memory
|
||||
*/
|
||||
void *operator new(Xsize_t Size)
|
||||
{
|
||||
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
|
||||
return ptr;
|
||||
(void)(Size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overload delete operator to free memory from the heap
|
||||
* @param Address Pointer to the memory to free
|
||||
*/
|
||||
void operator delete(void *Address)
|
||||
{
|
||||
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
|
||||
}
|
||||
} __attribute__((packed, aligned((16))));
|
||||
/**
|
||||
* @brief Overload delete operator to free memory from the heap
|
||||
* @param Address Pointer to the memory to free
|
||||
*/
|
||||
void operator delete(void *Address)
|
||||
{
|
||||
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
|
||||
}
|
||||
} __attribute__((packed, aligned((16))));
|
||||
|
||||
class SmartSMAPClass
|
||||
{
|
||||
private:
|
||||
V1 *allocator = nullptr;
|
||||
class SmartSMAPClass
|
||||
{
|
||||
private:
|
||||
V1 *allocator = nullptr;
|
||||
|
||||
public:
|
||||
SmartSMAPClass(V1 *allocator)
|
||||
{
|
||||
this->allocator = allocator;
|
||||
this->allocator->Xstac();
|
||||
}
|
||||
~SmartSMAPClass() { this->allocator->Xclac(); }
|
||||
};
|
||||
public:
|
||||
SmartSMAPClass(V1 *allocator)
|
||||
{
|
||||
this->allocator = allocator;
|
||||
this->allocator->Xstac();
|
||||
}
|
||||
~SmartSMAPClass() { this->allocator->Xclac(); }
|
||||
};
|
||||
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
|
||||
|
||||
void V1::Xstac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
void V1::Xstac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
#if defined(a86)
|
||||
asm volatile("stac" ::
|
||||
: "cc");
|
||||
asm volatile("stac" ::
|
||||
: "cc");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V1::Xclac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
void V1::Xclac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
#if defined(a86)
|
||||
asm volatile("clac" ::
|
||||
: "cc");
|
||||
asm volatile("clac" ::
|
||||
: "cc");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V1::Arrange()
|
||||
{
|
||||
Xalloc_err("Arrange() is not implemented yet!");
|
||||
}
|
||||
void V1::Arrange()
|
||||
{
|
||||
Xalloc_err("Arrange() is not implemented yet!");
|
||||
}
|
||||
|
||||
void *V1::malloc(Xsize_t Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
||||
return nullptr;
|
||||
}
|
||||
void *V1::malloc(Xsize_t Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
|
||||
if (this->FirstBlock == nullptr)
|
||||
{
|
||||
this->FirstBlock = new Block(Size);
|
||||
((Block *)this->FirstBlock)->IsFree = false;
|
||||
Xalloc_unlock;
|
||||
return ((Block *)this->FirstBlock)->Address;
|
||||
}
|
||||
if (this->FirstBlock == nullptr)
|
||||
{
|
||||
this->FirstBlock = new Block(Size);
|
||||
((Block *)this->FirstBlock)->IsFree = false;
|
||||
XallocV1_unlock;
|
||||
return ((Block *)this->FirstBlock)->Address;
|
||||
}
|
||||
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
|
||||
{
|
||||
CurrentBlock->IsFree = false;
|
||||
Xmemset(CurrentBlock->Address, 0, Size);
|
||||
Xalloc_unlock;
|
||||
return CurrentBlock->Address;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
|
||||
{
|
||||
CurrentBlock->IsFree = false;
|
||||
Xmemset(CurrentBlock->Address, 0, Size);
|
||||
XallocV1_unlock;
|
||||
return CurrentBlock->Address;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock->Next != nullptr)
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock->Next != nullptr)
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
|
||||
CurrentBlock->Next = new Block(Size);
|
||||
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
|
||||
((Block *)CurrentBlock->Next)->IsFree = false;
|
||||
Xalloc_unlock;
|
||||
return ((Block *)CurrentBlock->Next)->Address;
|
||||
}
|
||||
CurrentBlock->Next = new Block(Size);
|
||||
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
|
||||
((Block *)CurrentBlock->Next)->IsFree = false;
|
||||
XallocV1_unlock;
|
||||
return ((Block *)CurrentBlock->Next)->Address;
|
||||
}
|
||||
|
||||
void V1::free(void *Address)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
Xalloc_warn("Attempted to free a null pointer!");
|
||||
return;
|
||||
}
|
||||
void V1::free(void *Address)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
Xalloc_warn("Attempted to free a null pointer!");
|
||||
return;
|
||||
}
|
||||
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->Address == Address)
|
||||
{
|
||||
if (CurrentBlock->IsFree)
|
||||
{
|
||||
Xalloc_warn("Attempted to free an already freed pointer!");
|
||||
Xalloc_unlock;
|
||||
return;
|
||||
}
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->Address == Address)
|
||||
{
|
||||
if (CurrentBlock->IsFree)
|
||||
{
|
||||
Xalloc_warn("Attempted to free an already freed pointer!");
|
||||
XallocV1_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentBlock->IsFree = true;
|
||||
Xalloc_unlock;
|
||||
return;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
CurrentBlock->IsFree = true;
|
||||
XallocV1_unlock;
|
||||
return;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
Xalloc_err("Invalid address %#lx.", Address);
|
||||
Xalloc_unlock;
|
||||
}
|
||||
Xalloc_err("Invalid address %#lx.", Address);
|
||||
XallocV1_unlock;
|
||||
}
|
||||
|
||||
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
||||
{
|
||||
if (NumberOfBlocks == 0 || Size == 0)
|
||||
{
|
||||
Xalloc_warn("The %s%s%s is 0!",
|
||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
||||
Size == 0 ? "Size" : "");
|
||||
return nullptr;
|
||||
}
|
||||
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
||||
{
|
||||
if (NumberOfBlocks == 0 || Size == 0)
|
||||
{
|
||||
Xalloc_warn("The %s%s%s is 0!",
|
||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
||||
Size == 0 ? "Size" : "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->malloc(NumberOfBlocks * Size);
|
||||
}
|
||||
return this->malloc(NumberOfBlocks * Size);
|
||||
}
|
||||
|
||||
void *V1::realloc(void *Address, Xsize_t Size)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
return this->malloc(Size);
|
||||
void *V1::realloc(void *Address, Xsize_t Size)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
return this->malloc(Size);
|
||||
|
||||
if (Size == 0)
|
||||
{
|
||||
this->free(Address);
|
||||
return nullptr;
|
||||
}
|
||||
if (Size == 0)
|
||||
{
|
||||
this->free(Address);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// SmartSMAP;
|
||||
// Xalloc_lock;
|
||||
// ...
|
||||
// Xalloc_unlock;
|
||||
// SmartSMAP;
|
||||
// XallocV1_lock;
|
||||
// ...
|
||||
// XallocV1_unlock;
|
||||
|
||||
// TODO: Implement realloc
|
||||
this->free(Address);
|
||||
return this->malloc(Size);
|
||||
}
|
||||
// TODO: Implement realloc
|
||||
this->free(Address);
|
||||
return this->malloc(Size);
|
||||
}
|
||||
|
||||
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
|
||||
{
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
this->SMAPUsed = SMAPEnabled;
|
||||
this->UserMapping = UserMode;
|
||||
this->BaseVirtualAddress = BaseVirtualAddress;
|
||||
Xalloc_unlock;
|
||||
}
|
||||
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
|
||||
{
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
this->SMAPUsed = SMAPEnabled;
|
||||
this->UserMapping = UserMode;
|
||||
this->BaseVirtualAddress = BaseVirtualAddress;
|
||||
XallocV1_unlock;
|
||||
}
|
||||
|
||||
V1::~V1()
|
||||
{
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
Xalloc_trace("Destructor not implemented yet.");
|
||||
Xalloc_unlock;
|
||||
}
|
||||
V1::~V1()
|
||||
{
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
Xalloc_trace("Destructor not implemented yet.");
|
||||
XallocV1_unlock;
|
||||
}
|
||||
}
|
||||
|
281
Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp
Normal file
281
Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp
Normal 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;
|
||||
}
|
||||
}
|
26
Core/Memory/HeapAllocators/liballoc_1_1/liballoc_hooks.cpp
Normal file
26
Core/Memory/HeapAllocators/liballoc_1_1/liballoc_hooks.cpp
Normal 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;
|
||||
}
|
@ -25,10 +25,9 @@
|
||||
#endif
|
||||
|
||||
#include "HeapAllocators/Xalloc/Xalloc.hpp"
|
||||
#include "../Library/liballoc_1_1.h"
|
||||
#include "HeapAllocators/liballoc_1_1/liballoc_1_1.h"
|
||||
#include "../../kernel.h"
|
||||
|
||||
// #define DEBUG_ALLOCATIONS_SL 1
|
||||
// #define DEBUG_ALLOCATIONS 1
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS
|
||||
@ -39,11 +38,6 @@
|
||||
#define memdbg(m, ...)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
NewLock(AllocatorLock);
|
||||
NewLock(OperatorAllocatorLock);
|
||||
#endif
|
||||
|
||||
using namespace Memory;
|
||||
|
||||
Physical KernelAllocator;
|
||||
@ -53,6 +47,7 @@ bool PSESupport = false;
|
||||
|
||||
MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages;
|
||||
Xalloc::V1 *XallocV1Allocator = nullptr;
|
||||
Xalloc::V2 *XallocV2Allocator = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
NIF void tracepagetable(PageTable *pt)
|
||||
@ -119,27 +114,6 @@ NIF void MapFramebuffer(PageTable *PT)
|
||||
(size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height),
|
||||
PTFlag::RW | PTFlag::US | PTFlag::G);
|
||||
itrfb++;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r",
|
||||
bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height) + PAGE_SIZE);
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,37 +227,6 @@ NIF void MapKernel(PageTable *PT)
|
||||
KernelAllocator.ReservePage((void *)k);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r",
|
||||
bInfo.Kernel.PhysicalBase,
|
||||
bInfo.Kernel.Size);
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
|
||||
sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r",
|
||||
bInfo.Kernel.VirtualBase,
|
||||
bInfo.Kernel.Size);
|
||||
mExtTrkLock.Unlock();
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NIF void InitializeMemoryManagement()
|
||||
@ -404,20 +347,22 @@ NIF void InitializeMemoryManagement()
|
||||
CPU::PageTable(KernelPageTable);
|
||||
debug("Page table updated.");
|
||||
|
||||
/* FIXME: Read kernel config */
|
||||
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
|
||||
AllocatorType = MemoryAllocatorType::XallocV1;
|
||||
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator);
|
||||
XallocV2Allocator = new Xalloc::V2((void *)KERNEL_HEAP_BASE);
|
||||
trace("XallocV1 Allocator initialized at %#lx", XallocV1Allocator);
|
||||
trace("XallocV2 Allocator initialized at %#lx", XallocV2Allocator);
|
||||
|
||||
/* FIXME: Read kernel config */
|
||||
AllocatorType = MemoryAllocatorType::liballoc11;
|
||||
}
|
||||
|
||||
void *malloc(size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("malloc(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
switch (AllocatorType)
|
||||
@ -425,7 +370,6 @@ void *malloc(size_t Size)
|
||||
case MemoryAllocatorType::Pages:
|
||||
{
|
||||
ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1));
|
||||
memset(ret, 0, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV1:
|
||||
@ -433,10 +377,14 @@ void *malloc(size_t Size)
|
||||
ret = XallocV1Allocator->malloc(Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV2:
|
||||
{
|
||||
ret = XallocV2Allocator->malloc(Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::liballoc11:
|
||||
{
|
||||
ret = PREFIX(malloc)(Size);
|
||||
memset(ret, 0, Size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -445,26 +393,8 @@ void *malloc(size_t Size)
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r",
|
||||
Size,
|
||||
ret, __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(ret, 0, Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -472,10 +402,9 @@ void *calloc(size_t n, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("calloc(%d, %d)->[%s]", n, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
switch (AllocatorType)
|
||||
@ -483,7 +412,6 @@ void *calloc(size_t n, size_t Size)
|
||||
case MemoryAllocatorType::Pages:
|
||||
{
|
||||
ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1));
|
||||
memset(ret, 0, n * Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV1:
|
||||
@ -491,10 +419,14 @@ void *calloc(size_t n, size_t Size)
|
||||
ret = XallocV1Allocator->calloc(n, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV2:
|
||||
{
|
||||
ret = XallocV2Allocator->calloc(n, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::liballoc11:
|
||||
{
|
||||
void *ret = PREFIX(calloc)(n, Size);
|
||||
memset(ret, 0, Size);
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
@ -503,26 +435,8 @@ void *calloc(size_t n, size_t Size)
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r",
|
||||
n, Size,
|
||||
ret, __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(ret, 0, n * Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -530,10 +444,9 @@ void *realloc(void *Address, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
switch (AllocatorType)
|
||||
@ -541,7 +454,6 @@ void *realloc(void *Address, size_t Size)
|
||||
case unlikely(MemoryAllocatorType::Pages):
|
||||
{
|
||||
ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak
|
||||
memset(ret, 0, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV1:
|
||||
@ -549,10 +461,14 @@ void *realloc(void *Address, size_t Size)
|
||||
ret = XallocV1Allocator->realloc(Address, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV2:
|
||||
{
|
||||
ret = XallocV2Allocator->realloc(Address, Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::liballoc11:
|
||||
{
|
||||
void *ret = PREFIX(realloc)(Address, Size);
|
||||
memset(ret, 0, Size);
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
@ -561,26 +477,8 @@ void *realloc(void *Address, size_t Size)
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r",
|
||||
Address, Size,
|
||||
ret, __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(ret, 0, Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -588,10 +486,9 @@ void free(void *Address)
|
||||
{
|
||||
assert(Address != nullptr);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("free(%#lx)->[%s]", Address,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
switch (AllocatorType)
|
||||
{
|
||||
@ -605,6 +502,11 @@ void free(void *Address)
|
||||
XallocV1Allocator->free(Address);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV2:
|
||||
{
|
||||
XallocV2Allocator->free(Address);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::liballoc11:
|
||||
{
|
||||
PREFIX(free)
|
||||
@ -617,58 +519,17 @@ void free(void *Address)
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "free( %p )~%p\n\r",
|
||||
Address,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void *operator new(std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("new(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r",
|
||||
Size,
|
||||
ret, __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -676,32 +537,11 @@ void *operator new[](std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("new[](%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r",
|
||||
Size,
|
||||
ret, __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -709,39 +549,14 @@ void *operator new(std::size_t Size, std::align_val_t Alignment)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
|
||||
memdbg("new(%d, %d)->[%s]", Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator new with alignment(%#lx) is not implemented",
|
||||
Alignment);
|
||||
|
||||
void *ret = malloc(Size);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
#if defined(a64) || defined(aa64)
|
||||
sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r",
|
||||
Size, (uintptr_t)Alignment,
|
||||
ret, __builtin_return_address(0));
|
||||
#elif defined(a32)
|
||||
sprintf(mExtTrkLog, "new( %ld %#x )=%p~%p\n\r",
|
||||
Size, (uintptr_t)Alignment,
|
||||
ret, __builtin_return_address(0));
|
||||
#endif
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -749,64 +564,22 @@ void operator delete(void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("delete(%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "delete( %p )~%p\n\r",
|
||||
Pointer,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("delete[](%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r",
|
||||
Pointer,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, long unsigned int Size)
|
||||
@ -814,32 +587,12 @@ void operator delete(void *Pointer, long unsigned int Size)
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("delete(%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r",
|
||||
Pointer, Size,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer, long unsigned int Size)
|
||||
@ -847,30 +600,10 @@ void operator delete[](void *Pointer, long unsigned int Size)
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
#ifdef DEBUG_ALLOCATIONS_SL
|
||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||
#endif
|
||||
memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
||||
memdbg("delete[](%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r",
|
||||
Pointer, Size,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace Memory
|
||||
{
|
||||
ReadFSFunction(MEM_Read)
|
||||
{
|
||||
if (!Size)
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
@ -39,7 +39,7 @@ namespace Memory
|
||||
|
||||
WriteFSFunction(MEM_Write)
|
||||
{
|
||||
if (!Size)
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
|
@ -19,25 +19,36 @@
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
|
||||
{
|
||||
Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
|
||||
{
|
||||
uintptr_t Address = VirtualAddress;
|
||||
#if defined(a64)
|
||||
uintptr_t Address = VirtualAddress;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDPTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PMLIndex = Address & 0x1FF;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDPTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PMLIndex = Address & 0x1FF;
|
||||
#elif defined(a32)
|
||||
uintptr_t Address = VirtualAddress;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x3FF;
|
||||
Address >>= 10;
|
||||
this->PDEIndex = Address & 0x3FF;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x3FF;
|
||||
Address >>= 10;
|
||||
this->PDEIndex = Address & 0x3FF;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (VirtualAddress > PAGE_SIZE)
|
||||
{
|
||||
assert(
|
||||
this->PTEIndex != 0 ||
|
||||
this->PDEIndex != 0
|
||||
#if defined(a64)
|
||||
|| this->PDPTEIndex != 0 ||
|
||||
this->PMLIndex != 0
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,41 @@
|
||||
#include <memory.hpp>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
void PageTable::Update()
|
||||
{
|
||||
void PageTable::Update()
|
||||
{
|
||||
#if defined(a86)
|
||||
asmv("mov %0, %%cr3" ::"r"(this));
|
||||
asmv("mov %0, %%cr3" ::"r"(this));
|
||||
#elif defined(aa64)
|
||||
asmv("msr ttbr0_el1, %0" ::"r"(this));
|
||||
asmv("msr ttbr0_el1, %0" ::"r"(this));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
PageTable PageTable::Fork()
|
||||
{
|
||||
PageTable NewTable;
|
||||
memcpy(&NewTable, this, sizeof(PageTable));
|
||||
return NewTable;
|
||||
}
|
||||
PageTable PageTable::Fork()
|
||||
{
|
||||
PageTable NewTable;
|
||||
memcpy(&NewTable, this, sizeof(PageTable));
|
||||
return NewTable;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T PageTable::Get(T Address)
|
||||
{
|
||||
Virtual vmm = Virtual(this);
|
||||
void *PhysAddr = vmm.GetPhysical((void *)Address);
|
||||
uintptr_t Diff = uintptr_t(Address);
|
||||
Diff &= 0xFFF;
|
||||
Diff = uintptr_t(PhysAddr) + Diff;
|
||||
return (T)Diff;
|
||||
}
|
||||
|
||||
/* Templates */
|
||||
template struct stat *PageTable::Get<struct stat *>(struct stat *);
|
||||
template const char *PageTable::Get<const char *>(const char *);
|
||||
template const void *PageTable::Get<const void *>(const void *);
|
||||
template uintptr_t PageTable::Get<uintptr_t>(uintptr_t);
|
||||
template void *PageTable::Get<void *>(void *);
|
||||
/* ... */
|
||||
}
|
||||
|
@ -88,25 +88,6 @@ namespace Memory
|
||||
continue;
|
||||
|
||||
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r",
|
||||
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
||||
}
|
||||
|
||||
@ -152,26 +133,6 @@ namespace Memory
|
||||
}
|
||||
|
||||
this->LockPages((void *)(Index * PAGE_SIZE), Count);
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
|
||||
Count,
|
||||
(void *)(Index * PAGE_SIZE), __builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
return (void *)(Index * PAGE_SIZE);
|
||||
|
||||
NextPage:
|
||||
@ -228,26 +189,6 @@ namespace Memory
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r",
|
||||
Address,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Physical::FreePages(void *Address, size_t Count)
|
||||
@ -257,26 +198,6 @@ namespace Memory
|
||||
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (EnableExternalMemoryTracer)
|
||||
{
|
||||
char LockTmpStr[64];
|
||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
||||
sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r",
|
||||
Address, Count,
|
||||
__builtin_return_address(0));
|
||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
||||
{
|
||||
if (mExtTrkLog[i] == '\r')
|
||||
break;
|
||||
mTrkUART.Write(mExtTrkLog[i]);
|
||||
}
|
||||
mExtTrkLock.Unlock();
|
||||
}
|
||||
#endif
|
||||
for (size_t t = 0; t < Count; t++)
|
||||
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
||||
}
|
||||
|
98
Core/Memory/ProgramBreak.cpp
Normal file
98
Core/Memory/ProgramBreak.cpp
Normal 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. */
|
||||
}
|
||||
}
|
@ -66,9 +66,9 @@ namespace Time
|
||||
{
|
||||
#if defined(a86)
|
||||
fixme(""); // FIXME: This is not a good way to measure the clock speed
|
||||
size_t Start = CPU::Counter();
|
||||
uint64_t Start = CPU::Counter();
|
||||
TimeManager->Sleep(1, Units::Milliseconds);
|
||||
size_t End = CPU::Counter();
|
||||
uint64_t End = CPU::Counter();
|
||||
|
||||
this->clk = End - Start;
|
||||
this->ClassCreationTime = this->GetCounter();
|
||||
|
@ -253,28 +253,22 @@ namespace Video
|
||||
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10);
|
||||
else
|
||||
this->Buffers[Index].Color = 0xFFFFFF;
|
||||
if (WriteToUART)
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
|
||||
this->ColorPickerIteration++;
|
||||
if (this->ColorPickerIteration == 6)
|
||||
{
|
||||
this->ColorPickerIteration = 0;
|
||||
if (WriteToUART)
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']');
|
||||
this->ColorIteration = false;
|
||||
}
|
||||
return Char;
|
||||
}
|
||||
|
||||
if (WriteToUART)
|
||||
if (WriteToUART && Char != '\e')
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
|
||||
|
||||
switch (Char)
|
||||
{
|
||||
case '\e':
|
||||
{
|
||||
if (WriteToUART)
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('[');
|
||||
this->ColorIteration = true;
|
||||
return Char;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <memory.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <msexec.h>
|
||||
#include <rand.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <elf.h>
|
||||
#include <abi.h>
|
||||
@ -32,6 +33,57 @@ using namespace VirtualFileSystem;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
void ELFObject::GenerateAuxiliaryVector_x86_32(Memory::MemMgr *mm,
|
||||
int fd,
|
||||
Elf32_Ehdr ELFHeader,
|
||||
uint32_t EntryPoint,
|
||||
uint32_t BaseAddress)
|
||||
{
|
||||
}
|
||||
|
||||
void ELFObject::GenerateAuxiliaryVector_x86_64(Memory::MemMgr *mm,
|
||||
int fd,
|
||||
Elf64_Ehdr ELFHeader,
|
||||
uint64_t EntryPoint,
|
||||
uint64_t BaseAddress)
|
||||
{
|
||||
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd);
|
||||
void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true);
|
||||
strcpy((char *)execfn_str, execfn.c_str());
|
||||
void *at_random = mm->RequestPages(1, true);
|
||||
*(uint64_t *)at_random = Random::rand16();
|
||||
|
||||
// prep. for AT_PHDR
|
||||
void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true);
|
||||
lseek(fd, ELFHeader.e_phoff, SEEK_SET);
|
||||
fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr));
|
||||
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}});
|
||||
// AT_HWCAP2 26
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_RANDOM, .a_un = {.a_val = (uint64_t)at_random}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_SECURE, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||
// AT_FLAGS 8
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}});
|
||||
// AT_CLKTCK 17
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||
// AT_HWCAP 16
|
||||
// AT_MINSIGSTKSZ 51
|
||||
// AT_SYSINFO_EHDR 33
|
||||
}
|
||||
|
||||
void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess)
|
||||
{
|
||||
stub;
|
||||
@ -104,10 +156,10 @@ namespace Execute
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable);
|
||||
Memory::MemMgr *mm = TargetProcess->Memory;
|
||||
uint64_t BaseAddress = 0;
|
||||
|
||||
/* Copy segments into memory */
|
||||
{
|
||||
Elf64_Phdr ProgramBreakHeader{};
|
||||
Elf64_Phdr ProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
@ -129,9 +181,6 @@ namespace Execute
|
||||
|
||||
debug("Mapped %#lx to %#lx", SegmentDestination, pAddr);
|
||||
|
||||
if (BaseAddress == 0)
|
||||
BaseAddress = (uintptr_t)SegmentDestination;
|
||||
|
||||
debug("Copying segment to p: %#lx-%#lx; v: %#lx-%#lx (%ld file bytes, %ld mem bytes)",
|
||||
pAddr, uintptr_t(pAddr) + ProgramHeader.p_memsz,
|
||||
SegmentDestination, uintptr_t(SegmentDestination) + ProgramHeader.p_memsz,
|
||||
@ -148,6 +197,7 @@ namespace Execute
|
||||
void *zAddr = (void *)(uintptr_t(pAddr) + ProgramHeader.p_filesz);
|
||||
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
|
||||
}
|
||||
ProgramBreakHeader = ProgramHeader;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -158,6 +208,13 @@ namespace Execute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set program break */
|
||||
uintptr_t ProgramBreak = ROUND_UP(ProgramBreakHeader.p_vaddr +
|
||||
ProgramBreakHeader.p_memsz,
|
||||
PAGE_SIZE);
|
||||
|
||||
TargetProcess->ProgramBreak->InitBrk(ProgramBreak);
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
@ -169,39 +226,8 @@ namespace Execute
|
||||
|
||||
debug("Entry Point: %#lx", EntryPoint);
|
||||
|
||||
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd);
|
||||
void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true);
|
||||
strcpy((char *)execfn_str, execfn.c_str());
|
||||
|
||||
// prep. for AT_PHDR
|
||||
void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true);
|
||||
lseek(fd, ELFHeader.e_phoff, SEEK_SET);
|
||||
fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr));
|
||||
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}});
|
||||
// AT_HWCAP2 26
|
||||
// AT_RANDOM 25
|
||||
// AT_SECURE 23
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||
// AT_FLAGS 8
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}});
|
||||
// AT_CLKTCK 17
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||
// AT_HWCAP 16
|
||||
// AT_MINSIGSTKSZ 51
|
||||
// AT_SYSINFO_EHDR 33
|
||||
this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader,
|
||||
EntryPoint, 0);
|
||||
|
||||
this->ip = EntryPoint;
|
||||
this->IsElfValid = true;
|
||||
@ -282,6 +308,7 @@ namespace Execute
|
||||
|
||||
/* Copy segments into memory */
|
||||
{
|
||||
Elf64_Phdr ProgramBreakHeader{};
|
||||
Elf64_Phdr ProgramHeader;
|
||||
std::size_t SegmentsSize = 0;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
@ -336,6 +363,7 @@ namespace Execute
|
||||
void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz);
|
||||
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
|
||||
}
|
||||
ProgramBreakHeader = ProgramHeader;
|
||||
break;
|
||||
}
|
||||
case PT_DYNAMIC:
|
||||
@ -373,6 +401,14 @@ namespace Execute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set program break */
|
||||
uintptr_t ProgramBreak = ROUND_UP(BaseAddress +
|
||||
ProgramBreakHeader.p_vaddr +
|
||||
ProgramBreakHeader.p_memsz,
|
||||
PAGE_SIZE);
|
||||
|
||||
TargetProcess->ProgramBreak->InitBrk(ProgramBreak);
|
||||
}
|
||||
|
||||
EntryPoint += BaseAddress;
|
||||
@ -578,39 +614,8 @@ namespace Execute
|
||||
|
||||
debug("Entry Point: %#lx", EntryPoint);
|
||||
|
||||
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd);
|
||||
void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true);
|
||||
strcpy((char *)execfn_str, execfn.c_str());
|
||||
|
||||
// prep. for AT_PHDR
|
||||
void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true);
|
||||
lseek(fd, ELFHeader.e_phoff, SEEK_SET);
|
||||
fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr));
|
||||
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}});
|
||||
// AT_HWCAP2 26
|
||||
// AT_RANDOM 25
|
||||
// AT_SECURE 23
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
||||
// AT_FLAGS 8
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}});
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}});
|
||||
// AT_CLKTCK 17
|
||||
Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||
// AT_HWCAP 16
|
||||
// AT_MINSIGSTKSZ 51
|
||||
// AT_SYSINFO_EHDR 33
|
||||
this->GenerateAuxiliaryVector_x86_64(mm, fd, ELFHeader,
|
||||
EntryPoint, BaseAddress);
|
||||
|
||||
this->ip = EntryPoint;
|
||||
this->IsElfValid = true;
|
||||
|
@ -33,7 +33,8 @@ namespace Execute
|
||||
{
|
||||
int Spawn(char *Path, const char **argv, const char **envp,
|
||||
Tasking::PCB *Parent,
|
||||
Tasking::TaskCompatibility Compatibility)
|
||||
Tasking::TaskCompatibility Compatibility,
|
||||
bool Critical)
|
||||
{
|
||||
int fd = fopen(Path, "r");
|
||||
if (fd < 0)
|
||||
@ -141,11 +142,16 @@ namespace Execute
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
TCB *Thread = TaskManager->CreateThread(Process,
|
||||
obj->InstructionPointer,
|
||||
obj->argv, obj->envp, obj->auxv,
|
||||
Arch,
|
||||
Compatibility);
|
||||
TCB *Thread = nullptr;
|
||||
{
|
||||
CriticalSection cs;
|
||||
Thread = TaskManager->CreateThread(Process,
|
||||
obj->InstructionPointer,
|
||||
obj->argv, obj->envp, obj->auxv,
|
||||
Arch,
|
||||
Compatibility);
|
||||
Thread->SetCritical(true);
|
||||
}
|
||||
fclose(fd);
|
||||
return Thread->ID;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace VirtualFileSystem
|
||||
{
|
||||
ReadFSFunction(USTAR_Read)
|
||||
{
|
||||
if (!Size)
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <smart_ptr.hpp>
|
||||
#include <convert.h>
|
||||
#include <stropts.h>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
@ -30,7 +31,7 @@ namespace VirtualFileSystem
|
||||
{
|
||||
ReadFSFunction(fd_Read)
|
||||
{
|
||||
if (!Size)
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
@ -45,7 +46,7 @@ namespace VirtualFileSystem
|
||||
|
||||
WriteFSFunction(fd_Write)
|
||||
{
|
||||
if (!Size)
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
@ -64,15 +65,32 @@ namespace VirtualFileSystem
|
||||
// .Write = fd_Write,
|
||||
};
|
||||
|
||||
FileDescriptorTable::FileDescriptor
|
||||
FileDescriptorTable::Fildes
|
||||
FileDescriptorTable::GetFileDescriptor(int FileDescriptor)
|
||||
{
|
||||
foreach (auto fd in FileDescriptors)
|
||||
{
|
||||
if (fd.Descriptor == FileDescriptor)
|
||||
{
|
||||
debug("Found file descriptor %d", FileDescriptor);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return {.Descriptor = -1};
|
||||
return {};
|
||||
}
|
||||
|
||||
FileDescriptorTable::DupFildes
|
||||
FileDescriptorTable::GetDupFildes(int FileDescriptor)
|
||||
{
|
||||
foreach (auto fd in FildesDuplicates)
|
||||
{
|
||||
if (fd.Descriptor == FileDescriptor)
|
||||
{
|
||||
debug("Found duplicated file descriptor %d", FileDescriptor);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int FileDescriptorTable::ProbeMode(mode_t Mode, int Flags)
|
||||
@ -118,9 +136,8 @@ namespace VirtualFileSystem
|
||||
|
||||
if (!n)
|
||||
{
|
||||
error("Failed to create file %s: %d",
|
||||
AbsolutePath, errno);
|
||||
return -1;
|
||||
debug("%s: File already exists, continuing...",
|
||||
AbsolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,23 +149,25 @@ namespace VirtualFileSystem
|
||||
if (!File)
|
||||
{
|
||||
errno = EEXIST;
|
||||
error("Failed to open file %s: %d",
|
||||
AbsolutePath, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Flags & O_TRUNC)
|
||||
{
|
||||
fixme("Implement O_TRUNC");
|
||||
fixme("O_TRUNC");
|
||||
}
|
||||
|
||||
if (Flags & O_APPEND)
|
||||
{
|
||||
fixme("Implement O_APPEND");
|
||||
fixme("O_APPEND");
|
||||
}
|
||||
|
||||
if (Flags & O_CLOEXEC)
|
||||
{
|
||||
fixme("Implement O_CLOEXEC");
|
||||
fixme("O_CLOEXEC");
|
||||
}
|
||||
|
||||
RefNode *File = vfs->Open(AbsolutePath,
|
||||
@ -161,8 +180,7 @@ namespace VirtualFileSystem
|
||||
return -1;
|
||||
}
|
||||
|
||||
FileDescriptorTable::FileDescriptor fd;
|
||||
fd.Descriptor = GetFreeFileDescriptor();
|
||||
Fildes fd = {.Descriptor = GetFreeFileDescriptor()};
|
||||
|
||||
if (fd.Descriptor < 0)
|
||||
{
|
||||
@ -205,6 +223,19 @@ namespace VirtualFileSystem
|
||||
}
|
||||
}
|
||||
|
||||
forItr(itr, FildesDuplicates)
|
||||
{
|
||||
if (itr->Descriptor == FileDescriptor)
|
||||
{
|
||||
FildesDuplicates.erase(itr);
|
||||
|
||||
char FileName[64];
|
||||
sprintf(FileName, "%d", FileDescriptor);
|
||||
vfs->Delete(FileName, false, this->fdDir);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
@ -223,6 +254,19 @@ namespace VirtualFileSystem
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
{
|
||||
foreach (auto fd in FildesDuplicates)
|
||||
{
|
||||
if (fd.Descriptor == i)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
return i;
|
||||
i++;
|
||||
@ -234,12 +278,20 @@ namespace VirtualFileSystem
|
||||
|
||||
std::string FileDescriptorTable::GetAbsolutePath(int FileDescriptor)
|
||||
{
|
||||
FileDescriptorTable::FileDescriptor fd =
|
||||
this->GetFileDescriptor(FileDescriptor);
|
||||
if (fd.Descriptor == -1)
|
||||
Fildes fd = this->GetFileDescriptor(FileDescriptor);
|
||||
DupFildes dfd = this->GetDupFildes(FileDescriptor);
|
||||
|
||||
if (fd.Descriptor == -1 &&
|
||||
dfd.Descriptor == -1)
|
||||
return "";
|
||||
|
||||
Node *node = fd.Handle->node;
|
||||
RefNode *hnd = nullptr;
|
||||
if (fd.Descriptor != -1)
|
||||
hnd = fd.Handle;
|
||||
else
|
||||
hnd = dfd.Handle;
|
||||
|
||||
Node *node = hnd->node;
|
||||
std::string absolutePath = vfs->GetPathFromNode(node);
|
||||
std::string path = absolutePath.c_str();
|
||||
return path;
|
||||
@ -264,36 +316,52 @@ namespace VirtualFileSystem
|
||||
|
||||
ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
FileDescriptor fdesc;
|
||||
fdesc = this->GetFileDescriptor(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0)
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fdesc.Handle->Read((uint8_t *)buf, count);
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->Read((uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
ssize_t FileDescriptorTable::_write(int fd, const void *buf,
|
||||
size_t count)
|
||||
{
|
||||
FileDescriptor fdesc;
|
||||
fdesc = this->GetFileDescriptor(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0)
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fdesc.Handle->Write((uint8_t *)buf, count);
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->Write((uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_close(int fd)
|
||||
{
|
||||
FileDescriptor fdesc;
|
||||
fdesc = this->GetFileDescriptor(fd);
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0)
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
@ -305,22 +373,61 @@ namespace VirtualFileSystem
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete fdesc.Handle;
|
||||
/* If the file descriptor is a duplicate,
|
||||
we don't need to close the handle,
|
||||
because it's a duplicate of another
|
||||
file descriptor. */
|
||||
|
||||
bool Found = false;
|
||||
RefNode *hnd = nullptr;
|
||||
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
foreach (auto dfd in FileDescriptors)
|
||||
{
|
||||
if (dfd.Handle == hnd)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (auto dfd in FildesDuplicates)
|
||||
{
|
||||
if (dfd.Handle == hnd)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
delete hnd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
FileDescriptor fdesc;
|
||||
fdesc = this->GetFileDescriptor(fd);
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0)
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fdesc.Handle->Seek(offset, whence);
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->Seek(offset, whence);
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_stat(const char *pathname,
|
||||
@ -353,22 +460,29 @@ namespace VirtualFileSystem
|
||||
statbuf->st_size = node->Length;
|
||||
statbuf->st_blksize = 0; /* FIXME: stub */
|
||||
statbuf->st_blocks = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_fstat(int fd, struct stat *statbuf)
|
||||
{
|
||||
FileDescriptor fdesc;
|
||||
fdesc = this->GetFileDescriptor(fd);
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0)
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Node *node = fdesc.Handle->node;
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
Node *node = hnd->node;
|
||||
statbuf->st_dev = 0; /* FIXME: stub */
|
||||
statbuf->st_ino = node->IndexNode;
|
||||
statbuf->st_mode = node->Flags | node->Mode;
|
||||
@ -379,7 +493,7 @@ namespace VirtualFileSystem
|
||||
statbuf->st_size = node->Length;
|
||||
statbuf->st_blksize = 0; /* FIXME: stub */
|
||||
statbuf->st_blocks = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -413,7 +527,112 @@ namespace VirtualFileSystem
|
||||
statbuf->st_size = node->Length;
|
||||
statbuf->st_blksize = 0; /* FIXME: stub */
|
||||
statbuf->st_blocks = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
statbuf->st_attr = 0; /* FIXME: stub */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_dup(int oldfd)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(oldfd);
|
||||
DupFildes dfdesc = this->GetDupFildes(oldfd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int newfd = this->GetFreeFileDescriptor();
|
||||
if (newfd < 0)
|
||||
{
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DupFildes new_dfd{};
|
||||
if (fdesc.Descriptor != -1)
|
||||
{
|
||||
new_dfd.Handle = fdesc.Handle;
|
||||
new_dfd.Mode = fdesc.Mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_dfd.Handle = dfdesc.Handle;
|
||||
new_dfd.Mode = dfdesc.Mode;
|
||||
}
|
||||
|
||||
new_dfd.Descriptor = newfd;
|
||||
this->FildesDuplicates.push_back(new_dfd);
|
||||
debug("Duplicated file descriptor %d to %d",
|
||||
oldfd, newfd);
|
||||
return newfd;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_dup2(int oldfd, int newfd)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(oldfd);
|
||||
DupFildes dfdesc = this->GetDupFildes(oldfd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (newfd < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (newfd == oldfd)
|
||||
return newfd;
|
||||
|
||||
/* Even if it's not valid
|
||||
we ignore it. */
|
||||
this->_close(newfd);
|
||||
|
||||
DupFildes new_dfd{};
|
||||
if (fdesc.Descriptor != -1)
|
||||
{
|
||||
new_dfd.Handle = fdesc.Handle;
|
||||
new_dfd.Mode = fdesc.Mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_dfd.Handle = dfdesc.Handle;
|
||||
new_dfd.Mode = dfdesc.Mode;
|
||||
}
|
||||
|
||||
new_dfd.Descriptor = newfd;
|
||||
this->FildesDuplicates.push_back(new_dfd);
|
||||
debug("Duplicated file descriptor %d to %d",
|
||||
oldfd, newfd);
|
||||
return newfd;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_ioctl(int fd, unsigned long request, void *argp)
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)argp;
|
||||
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
||||
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case TIOCGWINSZ:
|
||||
fixme("TIOCGWINSZ: stub");
|
||||
ws->ws_xpixel = uint16_t(sb->Width);
|
||||
ws->ws_ypixel = uint16_t(sb->Height);
|
||||
ws->ws_col = uint16_t(sb->Width / fi.Width);
|
||||
ws->ws_row = uint16_t(sb->Height / fi.Height);
|
||||
break;
|
||||
default:
|
||||
fixme("Unknown request %#lx", request);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,13 @@
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *SeekStrings[] =
|
||||
{"SEEK_SET",
|
||||
"SEEK_CUR",
|
||||
"SEEK_END"};
|
||||
#endif
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
ReferenceNode *Node::CreateReference()
|
||||
@ -83,10 +90,10 @@ namespace VirtualFileSystem
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t ReferenceNode::Seek(off_t Offset, int Whence)
|
||||
off_t ReferenceNode::Seek(off_t _Offset, int Whence)
|
||||
{
|
||||
if (this->SymlinkTo)
|
||||
return this->SymlinkTo->Seek(Offset, Whence);
|
||||
return this->SymlinkTo->Seek(_Offset, Whence);
|
||||
|
||||
if (!this->node->Operator)
|
||||
{
|
||||
@ -99,25 +106,40 @@ namespace VirtualFileSystem
|
||||
if (this->node->Operator->Seek)
|
||||
{
|
||||
off_t RefOffset = off_t(this->Offset.load());
|
||||
return this->node->Operator->Seek(this->node, Offset, Whence, RefOffset);
|
||||
debug("The node has a seek function");
|
||||
return this->node->Operator->Seek(this->node, _Offset, Whence, RefOffset);
|
||||
}
|
||||
|
||||
debug("Current offset is %d", this->Offset.load());
|
||||
switch (Whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
{
|
||||
if (Offset > this->node->Length)
|
||||
if (_Offset > this->node->Length)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->Offset.store(Offset);
|
||||
if (_Offset < 0)
|
||||
{
|
||||
fixme("Negative offset %d is not implemented", _Offset);
|
||||
_Offset = 0;
|
||||
}
|
||||
|
||||
if (_Offset > this->node->Length)
|
||||
{
|
||||
fixme("Offset %d is bigger than file size %d",
|
||||
_Offset, this->node->Length);
|
||||
_Offset = this->node->Length;
|
||||
}
|
||||
|
||||
this->Offset.store(_Offset);
|
||||
break;
|
||||
}
|
||||
case SEEK_CUR:
|
||||
{
|
||||
off_t NewOffset = off_t(this->Offset.load()) + Offset;
|
||||
off_t NewOffset = off_t(this->Offset.load()) + _Offset;
|
||||
if (NewOffset > this->node->Length ||
|
||||
NewOffset < 0)
|
||||
{
|
||||
@ -130,7 +152,7 @@ namespace VirtualFileSystem
|
||||
}
|
||||
case SEEK_END:
|
||||
{
|
||||
off_t NewOffset = this->node->Length + Offset;
|
||||
off_t NewOffset = this->node->Length + _Offset;
|
||||
if (NewOffset > this->node->Length ||
|
||||
NewOffset < 0)
|
||||
{
|
||||
@ -149,7 +171,12 @@ namespace VirtualFileSystem
|
||||
}
|
||||
}
|
||||
|
||||
return (off_t)this->Offset.load();
|
||||
off_t RetOffset = off_t(this->Offset.load());
|
||||
debug("( %d %ld %s[%d] ) -> %d",
|
||||
_Offset, this->Offset.load(),
|
||||
SeekStrings[Whence], Whence,
|
||||
RetOffset);
|
||||
return RetOffset;
|
||||
}
|
||||
|
||||
ReferenceNode::ReferenceNode(Node *node)
|
||||
|
49
FileSystem/Mounts/Null.cpp
Normal file
49
FileSystem/Mounts/Null.cpp
Normal 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;
|
||||
}
|
52
FileSystem/Mounts/Random.cpp
Normal file
52
FileSystem/Mounts/Random.cpp
Normal 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;
|
||||
}
|
43
FileSystem/Mounts/Teletype.cpp
Normal file
43
FileSystem/Mounts/Teletype.cpp
Normal 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;
|
||||
}
|
49
FileSystem/Mounts/Zero.cpp
Normal file
49
FileSystem/Mounts/Zero.cpp
Normal 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;
|
||||
}
|
18
Kernel.cpp
18
Kernel.cpp
@ -17,10 +17,11 @@
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ustar.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <convert.h>
|
||||
#include <ints.hpp>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <uart.hpp>
|
||||
@ -34,12 +35,6 @@
|
||||
|
||||
bool DebuggerIsAttached = false;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool EnableExternalMemoryTracer = false; /* This can be modified while we are debugging with GDB. */
|
||||
char mExtTrkLog[MEM_TRK_MAX_SIZE];
|
||||
LockClass mExtTrkLock;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Fennix Kernel
|
||||
* -------------
|
||||
@ -223,7 +218,7 @@ Time::time *TimeManager = nullptr;
|
||||
VirtualFileSystem::Virtual *vfs = nullptr;
|
||||
|
||||
KernelConfig Config = {
|
||||
.AllocatorType = Memory::MemoryAllocatorType::XallocV1,
|
||||
.AllocatorType = Memory::MemoryAllocatorType::liballoc11,
|
||||
.SchedulerType = Multi,
|
||||
.DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'},
|
||||
.InitPath = {'/', 'b', 'i', 'n', '/', 'i', 'n', 'i', 't', '\0'},
|
||||
@ -521,6 +516,11 @@ EXTERNC NIF void Main()
|
||||
}
|
||||
}
|
||||
|
||||
Init_Null(vfs);
|
||||
Init_Random(vfs);
|
||||
Init_Teletype(vfs);
|
||||
Init_Zero(vfs);
|
||||
|
||||
KPrint("\e058C19################################");
|
||||
TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread));
|
||||
CPU::Halt(true);
|
||||
@ -574,9 +574,9 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
|
||||
* is a global constructor but we need
|
||||
* memory management to be initialized first.
|
||||
*/
|
||||
TestMemoryAllocation();
|
||||
TestString();
|
||||
Test_std();
|
||||
TestMemoryAllocation();
|
||||
#endif
|
||||
EnableProfiler = true;
|
||||
Main();
|
||||
|
@ -162,6 +162,11 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
KPrint("\eAAFFAAUsing XallocV1 as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV1;
|
||||
}
|
||||
else if (strcmp(value, "xallocv2") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing XallocV2 as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV2;
|
||||
}
|
||||
else if (strcmp(value, "liballoc11") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing Liballoc11 as memory allocator");
|
||||
|
@ -27,7 +27,8 @@ void cmd_lsof(const char *)
|
||||
if (!Proc)
|
||||
continue;
|
||||
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::FileDescriptor> fds_array = Proc->FileDescriptors->GetFileDescriptors();
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> fds_array =
|
||||
Proc->FileDescriptors->GetFileDescriptors();
|
||||
foreach (auto fd in fds_array)
|
||||
printf("%s %d: %s\n", Proc->Name, fd.Descriptor,
|
||||
fd.Handle->AbsolutePath.c_str());
|
||||
|
@ -254,7 +254,8 @@ void lsof()
|
||||
|
||||
printf("%s:\n", Proc->Name);
|
||||
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::FileDescriptor> fds_array = Proc->FileDescriptors->GetFileDescriptors();
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> fds_array =
|
||||
Proc->FileDescriptors->GetFileDescriptors();
|
||||
foreach (auto fd in fds_array)
|
||||
printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str());
|
||||
}
|
||||
@ -307,7 +308,10 @@ int SpawnInit()
|
||||
"--critical",
|
||||
nullptr};
|
||||
|
||||
return Execute::Spawn(Config.InitPath, argv, envp);
|
||||
return Execute::Spawn(Config.InitPath, argv, envp,
|
||||
nullptr,
|
||||
Tasking::TaskCompatibility::Native,
|
||||
true);
|
||||
}
|
||||
|
||||
/* Files: 0.tga 1.tga ... 26.tga */
|
||||
@ -451,7 +455,10 @@ void ExitLogoAnimationThread()
|
||||
}
|
||||
}
|
||||
|
||||
void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); }
|
||||
void CleanupProcessesThreadWrapper()
|
||||
{
|
||||
TaskManager->CleanupProcessesThread();
|
||||
}
|
||||
|
||||
void KernelMainThread()
|
||||
{
|
||||
@ -530,11 +537,10 @@ void KernelMainThread()
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
initThread = TaskManager->GetThreadByID(tid);
|
||||
initThread->SetCritical(true);
|
||||
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
initThread = TaskManager->GetThreadByID(tid);
|
||||
TaskManager->WaitForThread(initThread);
|
||||
ExitCode = initThread->GetExitCode();
|
||||
Exit:
|
||||
|
1583
Library/Convert.cpp
1583
Library/Convert.cpp
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
@ -40,6 +40,27 @@ using Tasking::TaskStatus::Terminated;
|
||||
#define ARCH_GET_FS 0x1003
|
||||
#define ARCH_GET_GS 0x1004
|
||||
|
||||
#define ARCH_GET_CPUID 0x1011
|
||||
#define ARCH_SET_CPUID 0x1012
|
||||
|
||||
#define ARCH_GET_XCOMP_SUPP 0x1021
|
||||
#define ARCH_GET_XCOMP_PERM 0x1022
|
||||
#define ARCH_REQ_XCOMP_PERM 0x1023
|
||||
#define ARCH_GET_XCOMP_GUEST_PERM 0x1024
|
||||
#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025
|
||||
|
||||
#define ARCH_XCOMP_TILECFG 17
|
||||
#define ARCH_XCOMP_TILEDATA 18
|
||||
|
||||
#define ARCH_MAP_VDSO_X32 0x2001
|
||||
#define ARCH_MAP_VDSO_32 0x2002
|
||||
#define ARCH_MAP_VDSO_64 0x2003
|
||||
|
||||
#define ARCH_GET_UNTAG_MASK 0x4001
|
||||
#define ARCH_ENABLE_TAGGED_ADDR 0x4002
|
||||
#define ARCH_GET_MAX_TAG_BITS 0x4003
|
||||
#define ARCH_FORCE_TAGGED_SVA 0x4004
|
||||
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
@ -47,16 +68,14 @@ using Tasking::TaskStatus::Terminated;
|
||||
#define PROT_GROWSDOWN 0x01000000
|
||||
#define PROT_GROWSUP 0x02000000
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
#define MAP_TYPE 0x0f
|
||||
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_SHARED_VALIDATE 0x03
|
||||
#define MAP_TYPE 0x0f
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANON 0x20
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_NORESERVE 0x4000
|
||||
#define MAP_GROWSDOWN 0x0100
|
||||
#define MAP_DENYWRITE 0x0800
|
||||
@ -96,17 +115,41 @@ static int ConvertErrno(int r)
|
||||
/* https://man7.org/linux/man-pages/man2/read.2.html */
|
||||
static ssize_t sys_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
debug("Reading %d bytes from fd %d", count, fd);
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_read(fd, buf, count));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check(buf, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pBuf = pcb->PageTable->Get(buf);
|
||||
|
||||
ssize_t ret = ConvertErrno(fdt->_read(fd, pBuf, count));
|
||||
debug("Read %d bytes from fd %d, got %d", count, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/write.2.html */
|
||||
static ssize_t sys_write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
debug("Writing %d bytes to fd %d", count, fd);
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_write(fd, buf, count));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)buf, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pBuf = pcb->PageTable->Get(buf);
|
||||
|
||||
ssize_t ret = ConvertErrno(fdt->_write(fd, pBuf, count));
|
||||
debug("Wrote %d bytes to fd %d, got %d", count, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/open.2.html */
|
||||
@ -114,7 +157,19 @@ static int sys_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_open(pathname, flags, mode));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)pathname, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", pathname);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pPathname = pcb->PageTable->Get(pathname);
|
||||
|
||||
int ret = ConvertErrno(fdt->_open(pPathname, flags, mode));
|
||||
debug("Opened %s with flags %d and mode %d, got fd %d",
|
||||
pPathname, flags, mode, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/close.2.html */
|
||||
@ -122,7 +177,9 @@ static int sys_close(int fd)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_close(fd));
|
||||
int ret = ConvertErrno(fdt->_close(fd));
|
||||
debug("Closed fd %d, got %d", fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/stat.3p.html */
|
||||
@ -130,7 +187,16 @@ static int sys_stat(const char *pathname, struct stat *statbuf)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_stat(pathname, statbuf));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)pathname, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", pathname);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pPathname = pcb->PageTable->Get(pathname);
|
||||
|
||||
return ConvertErrno(fdt->_stat(pPathname, statbuf));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/fstat.3p.html */
|
||||
@ -139,7 +205,16 @@ static int sys_fstat(int fd, struct stat *statbuf)
|
||||
#undef fstat
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_fstat(fd, statbuf));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)statbuf, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", statbuf);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pStatbuf = pcb->PageTable->Get(statbuf);
|
||||
|
||||
return ConvertErrno(fdt->_fstat(fd, pStatbuf));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/lstat.2.html */
|
||||
@ -148,7 +223,24 @@ static int sys_lstat(const char *pathname, struct stat *statbuf)
|
||||
#undef lstat
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_lstat(pathname, statbuf));
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)pathname, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", pathname);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!vmm.Check((void *)statbuf, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", statbuf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
auto pPathname = pcb->PageTable->Get(pathname);
|
||||
auto pStatbuf = pcb->PageTable->Get(statbuf);
|
||||
|
||||
return ConvertErrno(fdt->_lstat(pPathname, pStatbuf));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/lseek.2.html */
|
||||
@ -156,7 +248,10 @@ static off_t sys_lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_lseek(fd, offset, whence));
|
||||
|
||||
off_t ret = ConvertErrno(fdt->_lseek(fd, offset, whence));
|
||||
debug("(%d, %d, %d) = %d", fd, offset, whence, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/mmap.3p.html */
|
||||
@ -165,49 +260,66 @@ static void *sys_mmap(void *addr, size_t length, int prot,
|
||||
{
|
||||
UNUSED(offset); /* FIXME */
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
Memory::MemMgr *mgr = pcb->Memory;
|
||||
Memory::MemMgr *mm = pcb->Memory;
|
||||
|
||||
if (!addr)
|
||||
void *newPages = mm->RequestPages(TO_PAGES(length));
|
||||
if (newPages == nullptr)
|
||||
return (void *)-ENOMEM;
|
||||
|
||||
bool MustUseAddr = (flags & MAP_FIXED) != 0;
|
||||
if (addr == NULL && !MustUseAddr)
|
||||
addr = newPages;
|
||||
|
||||
if (MustUseAddr)
|
||||
{
|
||||
void *newPages = mgr->RequestPages(TO_PAGES(length));
|
||||
if (newPages == nullptr)
|
||||
return MAP_FAILED;
|
||||
|
||||
Memory::Virtual vma = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (prot & PROT_READ)
|
||||
vma.Map(newPages, newPages, length, Memory::P | Memory::US, Memory::Virtual::FourKiB);
|
||||
if (prot & PROT_WRITE)
|
||||
vma.Map(newPages, newPages, length, Memory::RW, Memory::Virtual::FourKiB);
|
||||
if (prot & PROT_EXEC)
|
||||
fixme("PROT_EXEC not implemented");
|
||||
|
||||
if (flags & MAP_FILE)
|
||||
fixme("MAP_FILE not implemented");
|
||||
if (flags & MAP_SHARED)
|
||||
fixme("MAP_SHARED not implemented");
|
||||
if (flags & MAP_PRIVATE)
|
||||
fixme("MAP_PRIVATE not implemented");
|
||||
if (flags & MAP_SHARED_VALIDATE)
|
||||
fixme("MAP_SHARED_VALIDATE not implemented");
|
||||
if (flags & MAP_TYPE)
|
||||
fixme("MAP_TYPE not implemented");
|
||||
if (flags & MAP_FIXED)
|
||||
fixme("MAP_FIXED not implemented");
|
||||
if (flags & MAP_ANONYMOUS)
|
||||
fixme("MAP_ANONYMOUS not implemented");
|
||||
|
||||
if (fildes != -1)
|
||||
{
|
||||
fixme("File mapping not implemented");
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
return newPages;
|
||||
debug("Using fixed address %#lx", addr);
|
||||
}
|
||||
|
||||
stub;
|
||||
return MAP_FAILED;
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
uint64_t MapFlags = Memory::P;
|
||||
if (prot & PROT_READ)
|
||||
MapFlags |= Memory::US;
|
||||
if (prot & PROT_WRITE)
|
||||
MapFlags |= Memory::RW;
|
||||
if (prot & PROT_EXEC)
|
||||
debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */
|
||||
|
||||
switch (flags & MAP_TYPE)
|
||||
{
|
||||
case MAP_FILE:
|
||||
debug("MAP_FILE ignored");
|
||||
[[fallthrough]];
|
||||
case MAP_SHARED:
|
||||
fixme("MAP_SHARED not implemented");
|
||||
[[fallthrough]];
|
||||
case MAP_SHARED_VALIDATE:
|
||||
fixme("MAP_SHARED_VALIDATE not implemented");
|
||||
[[fallthrough]];
|
||||
case MAP_PRIVATE:
|
||||
debug("MAP_PRIVATE ignored");
|
||||
[[fallthrough]];
|
||||
case MAP_ANONYMOUS:
|
||||
fixme("MAP_ANONYMOUS not implemented");
|
||||
[[fallthrough]];
|
||||
default:
|
||||
{
|
||||
debug("mmap flags %#x", flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vmm.Map(addr, newPages, length, MapFlags, Memory::Virtual::FourKiB);
|
||||
debug("Mapped %#lx to %#lx (%d pages)", addr, newPages, TO_PAGES(length));
|
||||
|
||||
if (fildes != -1)
|
||||
{
|
||||
fixme("File mapping not implemented");
|
||||
mm->FreePages(newPages, TO_PAGES(length));
|
||||
return (void *)-ENOSYS;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/mprotect.3p.html */
|
||||
@ -215,37 +327,58 @@ static int sys_mprotect(void *addr, size_t len, int prot)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
|
||||
Memory::Virtual vma = Memory::Virtual(pcb->PageTable);
|
||||
vma.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB);
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
vmm.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB);
|
||||
|
||||
if (prot & PROT_READ)
|
||||
vma.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB);
|
||||
vmm.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB);
|
||||
if (prot & PROT_WRITE)
|
||||
vma.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB);
|
||||
vmm.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB);
|
||||
if (prot & PROT_EXEC)
|
||||
fixme("PROT_EXEC not implemented");
|
||||
debug("PROT_EXEC ignored"); /* MapFlags |= Memory::XD; */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/munmap.3p.html */
|
||||
static int sys_munmap(void *addr, size_t length)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
Memory::MemMgr *mm = pcb->Memory;
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
mm->FreePages(addr, TO_PAGES(length));
|
||||
vmm.Unmap(addr, length, Memory::Virtual::FourKiB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/brk.2.html */
|
||||
static void *sys_brk(intptr_t increment)
|
||||
static void *sys_brk(void *addr)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
Memory::MemMgr *mgr = pcb->Memory;
|
||||
|
||||
stub;
|
||||
size_t PagesToAllocate = increment ? TO_PAGES(increment) : 1;
|
||||
return (void *)mgr->RequestPages(PagesToAllocate, true);
|
||||
trace("Ignoring brk syscall...");
|
||||
return (void *)-ENOSYS;
|
||||
// Tasking::PCB *pcb = thisProcess;
|
||||
// void *ret = pcb->ProgramBreak->brk(addr);
|
||||
// debug("brk(%#lx) = %#lx", addr, ret);
|
||||
// return ret;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/ioctl.2.html */
|
||||
static int sys_ioctl(int fd, unsigned long request, void *argp)
|
||||
{
|
||||
UNUSED(fd);
|
||||
UNUSED(request);
|
||||
UNUSED(argp);
|
||||
return -ENOSYS;
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)argp, Memory::US))
|
||||
{
|
||||
warn("Invalid address %#lx", argp);
|
||||
return -EFAULT;
|
||||
}
|
||||
auto pArgp = pcb->PageTable->Get(argp);
|
||||
|
||||
return ConvertErrno(fdt->_ioctl(fd, request, pArgp));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/readv.3p.html */
|
||||
@ -254,14 +387,20 @@ static ssize_t sys_readv(int fildes, const struct iovec *iov, int iovcnt)
|
||||
ssize_t Total = 0;
|
||||
for (int i = 0; i < iovcnt; i++)
|
||||
{
|
||||
debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len);
|
||||
ssize_t n = sys_read(fildes, iov[i].iov_base, iov[i].iov_len);
|
||||
if (n < 0)
|
||||
return n;
|
||||
debug("n: %d", n);
|
||||
|
||||
Total += n;
|
||||
if (n < (ssize_t)iov[i].iov_len)
|
||||
{
|
||||
debug("break");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("readv: %d", Total);
|
||||
return Total;
|
||||
}
|
||||
|
||||
@ -271,17 +410,39 @@ static ssize_t sys_writev(int fildes, const struct iovec *iov, int iovcnt)
|
||||
ssize_t Total = 0;
|
||||
for (int i = 0; i < iovcnt; i++)
|
||||
{
|
||||
debug("%d: iov[%d]: %p %d", fildes, i, iov[i].iov_base, iov[i].iov_len);
|
||||
ssize_t n = sys_write(fildes, iov[i].iov_base, iov[i].iov_len);
|
||||
if (n < 0)
|
||||
return n;
|
||||
debug("n: %d", n);
|
||||
|
||||
Total += n;
|
||||
if (n < (ssize_t)iov[i].iov_len)
|
||||
{
|
||||
debug("break");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("writev: %d", Total);
|
||||
return Total;
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/dup.2.html */
|
||||
static int sys_dup(int oldfd)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_dup(oldfd));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/dup.2.html */
|
||||
static int sys_dup2(int oldfd, int newfd)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_dup2(oldfd, newfd));
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/exit.3.html */
|
||||
static __noreturn void sys_exit(int status)
|
||||
{
|
||||
@ -307,9 +468,24 @@ static int sys_creat(const char *pathname, mode_t mode)
|
||||
/* https://man7.org/linux/man-pages/man2/arch_prctl.2.html */
|
||||
static int sys_arch_prctl(int code, unsigned long addr)
|
||||
{
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
Memory::Virtual vmm = Memory::Virtual(pcb->PageTable);
|
||||
|
||||
if (!vmm.Check((void *)addr))
|
||||
{
|
||||
warn("Invalid address %#lx", addr);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!vmm.Check((void *)addr, Memory::US))
|
||||
{
|
||||
warn("Address %#lx is not user accessible", addr);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0x1001: // ARCH_SET_GS
|
||||
case ARCH_SET_GS:
|
||||
{
|
||||
#if defined(a64)
|
||||
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr);
|
||||
@ -318,7 +494,7 @@ static int sys_arch_prctl(int code, unsigned long addr)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
case 0x1002: // ARCH_SET_FS
|
||||
case ARCH_SET_FS:
|
||||
{
|
||||
#if defined(a64)
|
||||
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr);
|
||||
@ -327,7 +503,7 @@ static int sys_arch_prctl(int code, unsigned long addr)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
case 0x1003: // ARCH_GET_FS
|
||||
case ARCH_GET_FS:
|
||||
{
|
||||
#if defined(a64)
|
||||
*r_cst(uint64_t *, addr) =
|
||||
@ -338,7 +514,7 @@ static int sys_arch_prctl(int code, unsigned long addr)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
case 0x1004: // ARCH_GET_GS
|
||||
case ARCH_GET_GS:
|
||||
{
|
||||
#if defined(a64)
|
||||
*r_cst(uint64_t *, addr) =
|
||||
@ -349,17 +525,43 @@ static int sys_arch_prctl(int code, unsigned long addr)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
fixme("code=%d", code);
|
||||
case ARCH_GET_CPUID:
|
||||
case ARCH_SET_CPUID:
|
||||
case ARCH_GET_XCOMP_SUPP:
|
||||
case ARCH_GET_XCOMP_PERM:
|
||||
case ARCH_REQ_XCOMP_PERM:
|
||||
case ARCH_GET_XCOMP_GUEST_PERM:
|
||||
case ARCH_REQ_XCOMP_GUEST_PERM:
|
||||
case ARCH_XCOMP_TILECFG:
|
||||
case ARCH_XCOMP_TILEDATA:
|
||||
case ARCH_MAP_VDSO_X32:
|
||||
case ARCH_MAP_VDSO_32:
|
||||
case ARCH_MAP_VDSO_64:
|
||||
case ARCH_GET_UNTAG_MASK:
|
||||
case ARCH_ENABLE_TAGGED_ADDR:
|
||||
case ARCH_GET_MAX_TAG_BITS:
|
||||
case ARCH_FORCE_TAGGED_SVA:
|
||||
{
|
||||
fixme("Code %#lx not implemented", code);
|
||||
return -ENOSYS;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Invalid code %#lx", code);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */
|
||||
static pid_t sys_set_tid_address(int *tidptr)
|
||||
{
|
||||
if (tidptr == nullptr)
|
||||
return -EINVAL;
|
||||
|
||||
Tasking::TCB *tcb = thisThread;
|
||||
*tidptr = tcb->ID;
|
||||
|
||||
tcb->Linux.clear_child_tid = tidptr;
|
||||
return tcb->ID;
|
||||
}
|
||||
|
||||
@ -382,7 +584,7 @@ static SyscallData LinuxSyscallsTable[] = {
|
||||
[__NR_lseek] = {"lseek", (void *)sys_lseek},
|
||||
[__NR_mmap] = {"mmap", (void *)sys_mmap},
|
||||
[__NR_mprotect] = {"mprotect", (void *)sys_mprotect},
|
||||
[__NR_munmap] = {"munmap", (void *)nullptr},
|
||||
[__NR_munmap] = {"munmap", (void *)sys_munmap},
|
||||
[__NR_brk] = {"brk", (void *)sys_brk},
|
||||
[__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr},
|
||||
[__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr},
|
||||
@ -403,8 +605,8 @@ static SyscallData LinuxSyscallsTable[] = {
|
||||
[__NR_shmget] = {"shmget", (void *)nullptr},
|
||||
[__NR_shmat] = {"shmat", (void *)nullptr},
|
||||
[__NR_shmctl] = {"shmctl", (void *)nullptr},
|
||||
[__NR_dup] = {"dup", (void *)nullptr},
|
||||
[__NR_dup2] = {"dup2", (void *)nullptr},
|
||||
[__NR_dup] = {"dup", (void *)sys_dup},
|
||||
[__NR_dup2] = {"dup2", (void *)sys_dup2},
|
||||
[__NR_pause] = {"pause", (void *)nullptr},
|
||||
[__NR_nanosleep] = {"nanosleep", (void *)nullptr},
|
||||
[__NR_getitimer] = {"getitimer", (void *)nullptr},
|
||||
@ -837,7 +1039,7 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame)
|
||||
|
||||
if (unlikely(!call))
|
||||
{
|
||||
error("Syscall %s(%d) not implemented.",
|
||||
fixme("Syscall %s(%d) not implemented.",
|
||||
Syscall.Name, Frame->rax);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@ -224,6 +224,9 @@ static int sys_ipc(SysFrm *, enum IPCCommand Command,
|
||||
static long sys_local_thread_state(SysFrm *, int Code,
|
||||
unsigned long Address)
|
||||
{
|
||||
/* TODO: return EFAULT if Address is not mapped */
|
||||
/* TODO: return EINVAL if Code is invalid */
|
||||
/* TODO: return EPERM if Address is outside of process address space */
|
||||
#if defined(a64) || defined(aa64)
|
||||
switch (Code)
|
||||
{
|
||||
|
@ -21,44 +21,76 @@
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
class AutoSwitchPageTable
|
||||
{
|
||||
private:
|
||||
uintptr_t Original;
|
||||
|
||||
public:
|
||||
AutoSwitchPageTable()
|
||||
{
|
||||
#if defined(a86)
|
||||
asmv("mov %%cr3, %0"
|
||||
: "=r"(Original));
|
||||
|
||||
asmv("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(KernelPageTable));
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoSwitchPageTable()
|
||||
{
|
||||
#if defined(a86)
|
||||
asmv("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(Original));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
|
||||
{
|
||||
Tasking::TaskInfo *Ptinfo = &thisProcess->Info;
|
||||
Tasking::TaskInfo *Ttinfo = &thisThread->Info;
|
||||
uint64_t TempTimeCalc = TimeManager->GetCounter();
|
||||
/* Automatically switch to kernel page table
|
||||
and switch back when this function returns. */
|
||||
AutoSwitchPageTable PageSwitcher;
|
||||
|
||||
switch (Ttinfo->Compatibility)
|
||||
{
|
||||
case Tasking::TaskCompatibility::Native:
|
||||
{
|
||||
uintptr_t ret = 0;
|
||||
if (Config.UseLinuxSyscalls)
|
||||
ret = HandleLinuxSyscalls(Frame);
|
||||
else
|
||||
ret = HandleNativeSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Linux:
|
||||
{
|
||||
uintptr_t ret = HandleLinuxSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Windows:
|
||||
{
|
||||
error("Windows compatibility not implemented yet.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown compatibility mode! Killing thread...");
|
||||
TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(false); /* Should never reach here. */
|
||||
return 0;
|
||||
uint64_t TempTimeCalc = TimeManager->GetCounter();
|
||||
Tasking::TaskInfo *Ptinfo = &thisProcess->Info;
|
||||
Tasking::TaskInfo *Ttinfo = &thisThread->Info;
|
||||
|
||||
switch (Ttinfo->Compatibility)
|
||||
{
|
||||
case Tasking::TaskCompatibility::Native:
|
||||
{
|
||||
uintptr_t ret = 0;
|
||||
if (Config.UseLinuxSyscalls)
|
||||
ret = HandleLinuxSyscalls(Frame);
|
||||
else
|
||||
ret = HandleNativeSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Linux:
|
||||
{
|
||||
uintptr_t ret = HandleLinuxSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Windows:
|
||||
{
|
||||
error("Windows compatibility not implemented yet.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown compatibility mode! Killing thread...");
|
||||
TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(false); /* Should never reach here. */
|
||||
return 0;
|
||||
}
|
||||
|
@ -55,16 +55,19 @@ namespace Tasking
|
||||
assert(name != nullptr);
|
||||
assert(strlen(name) > 0);
|
||||
|
||||
trace("Renaming thread %s to %s", this->Name, name);
|
||||
trace("Renaming thread %s to %s",
|
||||
this->Name, name);
|
||||
|
||||
if (this->Name)
|
||||
delete[] this->Name;
|
||||
|
||||
this->Name = new char[strlen(name) + 1];
|
||||
strcpy((char *)this->Name, name);
|
||||
}
|
||||
|
||||
void PCB::SetWorkingDirectory(VirtualFileSystem::Node *node)
|
||||
{
|
||||
debug("Setting working directory of process %s to %#lx (%s)",
|
||||
trace("Setting working directory of process %s to %#lx (%s)",
|
||||
this->Name, node, node->Name);
|
||||
CurrentWorkingDirectory = node;
|
||||
}
|
||||
@ -75,94 +78,89 @@ namespace Tasking
|
||||
uint16_t UserID, uint16_t GroupID)
|
||||
{
|
||||
assert(ctx != nullptr);
|
||||
assert(Name != nullptr);
|
||||
assert(strlen(Name) > 0);
|
||||
assert(ExecutionMode >= _ExecuteModeMin);
|
||||
assert(ExecutionMode <= _ExecuteModeMax);
|
||||
|
||||
this->ctx = ctx;
|
||||
this->ID = ctx->NextPID++;
|
||||
if (this->Name)
|
||||
|
||||
if (this->Name) /* Prevent memory leak */
|
||||
delete[] this->Name;
|
||||
|
||||
this->Name = new char[strlen(Name) + 1];
|
||||
strcpy((char *)this->Name, Name);
|
||||
this->ExitCode = KILL_CRASH;
|
||||
this->Security.ExecutionMode = ExecutionMode;
|
||||
|
||||
/* Check parent */
|
||||
if (Parent == nullptr)
|
||||
this->Parent = ctx->GetCurrentProcess();
|
||||
else
|
||||
this->Parent = Parent;
|
||||
|
||||
/* Set uid & gid */
|
||||
if (this->Parent &&
|
||||
UserID == UINT16_MAX &&
|
||||
GroupID == UINT16_MAX)
|
||||
{
|
||||
UserID = this->Parent->Security.Real.UserID;
|
||||
GroupID = this->Parent->Security.Real.GroupID;
|
||||
debug("Inherited uid & gid from parent process %s(%d) with uid %d and gid %d",
|
||||
this->Parent->Name, this->Parent->ID, UserID, GroupID);
|
||||
}
|
||||
|
||||
this->Security.Real.UserID = UserID;
|
||||
this->Security.Real.GroupID = GroupID;
|
||||
this->Security.Effective.UserID = UserID;
|
||||
this->Security.Effective.GroupID = GroupID;
|
||||
this->Security.ExecutionMode = ExecutionMode;
|
||||
|
||||
char ProcFSName[16];
|
||||
switch (ExecutionMode)
|
||||
{
|
||||
case TaskExecutionMode::System:
|
||||
fixme("Mode not supported.");
|
||||
[[fallthrough]];
|
||||
case TaskExecutionMode::Kernel:
|
||||
{
|
||||
this->Security.IsCritical = true;
|
||||
break;
|
||||
}
|
||||
case TaskExecutionMode::User:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
char ProcFSName[12];
|
||||
sprintf(ProcFSName, "%d", this->ID);
|
||||
this->ProcessDirectory = vfs->Create(ProcFSName, DIRECTORY, ProcFS);
|
||||
this->memDirectory = vfs->Create("mem", DIRECTORY, this->ProcessDirectory);
|
||||
this->FileDescriptors = new FileDescriptorTable(this);
|
||||
this->IPC = new class IPC((void *)this);
|
||||
|
||||
if (!DoNotCreatePageTable)
|
||||
this->FileDescriptors = new FileDescriptorTable(this);
|
||||
|
||||
/* If create page table */
|
||||
if (DoNotCreatePageTable == false)
|
||||
{
|
||||
OwnPageTable = true;
|
||||
switch (ExecutionMode)
|
||||
{
|
||||
case TaskExecutionMode::System:
|
||||
fixme("Mode not supported.");
|
||||
[[fallthrough]];
|
||||
case TaskExecutionMode::Kernel:
|
||||
{
|
||||
this->Security.IsCritical = true;
|
||||
#if defined(a64)
|
||||
this->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw;
|
||||
#elif defined(a32)
|
||||
this->PageTable = (Memory::PageTable *)CPU::x32::readcr3().raw;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
debug("Process %s(%d) has page table at %#lx",
|
||||
this->Name, this->ID, this->PageTable);
|
||||
break;
|
||||
}
|
||||
case TaskExecutionMode::User:
|
||||
{
|
||||
#if defined(a64)
|
||||
this->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(Memory::PageTable) + 1));
|
||||
memcpy(this->PageTable,
|
||||
KernelPageTable,
|
||||
sizeof(Memory::PageTable));
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
debug("Process %s(%d) has page table at %#lx",
|
||||
this->Name, this->ID, this->PageTable);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1);
|
||||
this->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(PTPgs);
|
||||
memcpy(this->PageTable, KernelPageTable, sizeof(Memory::PageTable));
|
||||
|
||||
debug("Process %s(%d) has page table at %#lx",
|
||||
this->Name, this->ID, this->PageTable);
|
||||
}
|
||||
|
||||
this->Memory = new Memory::MemMgr(this->PageTable, this->memDirectory);
|
||||
this->ProgramBreak = new Memory::ProgramBreak(this->PageTable, this->Memory);
|
||||
|
||||
this->IPC = new class IPC((void *)this);
|
||||
|
||||
if (Image)
|
||||
{
|
||||
this->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("No image provided for process \"%s\"(%d)",
|
||||
this->Name, this->ID);
|
||||
}
|
||||
|
||||
if (Parent)
|
||||
Parent->Children.push_back(this);
|
||||
@ -182,32 +180,51 @@ namespace Tasking
|
||||
debug("Destroying process \"%s\"(%d)",
|
||||
this->Name, this->ID);
|
||||
|
||||
/* Remove us from the process list so we
|
||||
don't get scheduled anymore */
|
||||
ctx->ProcessList.erase(std::find(ctx->ProcessList.begin(),
|
||||
ctx->ProcessList.end(),
|
||||
this));
|
||||
|
||||
/* If we have a symbol table allocated,
|
||||
we need to free it */
|
||||
if (this->ELFSymbolTable)
|
||||
delete this->ELFSymbolTable;
|
||||
|
||||
/* Free IPC */
|
||||
delete this->IPC;
|
||||
delete this->FileDescriptors;
|
||||
|
||||
/* Free all allocated memory */
|
||||
delete this->ProgramBreak;
|
||||
delete this->Memory;
|
||||
|
||||
/* Closing all open files */
|
||||
delete this->FileDescriptors;
|
||||
|
||||
/* Free Name */
|
||||
delete[] this->Name;
|
||||
|
||||
/* If we own the pointer to the
|
||||
PageTable, we need to free it */
|
||||
if (this->PageTable && OwnPageTable)
|
||||
{
|
||||
size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1);
|
||||
KernelAllocator.FreePages(this->PageTable, PTPgs);
|
||||
}
|
||||
|
||||
/* Exit all children processes */
|
||||
foreach (auto pcb in this->Children)
|
||||
delete pcb;
|
||||
|
||||
/* Exit all threads */
|
||||
foreach (auto tcb in this->Threads)
|
||||
delete tcb;
|
||||
|
||||
/* Delete /proc/{pid} directory */
|
||||
vfs->Delete(this->ProcessDirectory, true);
|
||||
|
||||
/* If we have a Parent, remove us from
|
||||
their children list */
|
||||
if (this->Parent)
|
||||
{
|
||||
std::vector<Tasking::PCB *> &pChild = this->Parent->Children;
|
||||
|
@ -49,15 +49,15 @@ namespace Tasking
|
||||
#if defined(a86)
|
||||
__naked __used __no_stack_protector void IdleProcessLoop()
|
||||
{
|
||||
asmv("IdleLoop:\n"
|
||||
"hlt\n"
|
||||
"jmp IdleLoop\n");
|
||||
asmv("IdleLoop:");
|
||||
asmv("hlt");
|
||||
asmv("jmp IdleLoop");
|
||||
#elif defined(aa64)
|
||||
__used __no_stack_protector void IdleProcessLoop()
|
||||
{
|
||||
asmv("IdleLoop:\n"
|
||||
"wfe\n"
|
||||
"b IdleLoop\n");
|
||||
asmv("IdleLoop:");
|
||||
asmv("wfe");
|
||||
asmv("b IdleLoop");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#define tskdbg(m, ...)
|
||||
#endif
|
||||
|
||||
/* For kernel threads only */
|
||||
void ThreadDoExit()
|
||||
{
|
||||
CPUData *CPUData = GetCurrentCPU();
|
||||
@ -64,9 +65,12 @@ namespace Tasking
|
||||
assert(name != nullptr);
|
||||
assert(strlen(name) > 0);
|
||||
|
||||
trace("Renaming thread %s to %s", this->Name, name);
|
||||
trace("Renaming thread %s to %s",
|
||||
this->Name, name);
|
||||
|
||||
if (this->Name)
|
||||
delete[] this->Name;
|
||||
|
||||
this->Name = new char[strlen(name) + 1];
|
||||
strcpy((char *)this->Name, name);
|
||||
}
|
||||
@ -120,18 +124,182 @@ namespace Tasking
|
||||
this->Registers.r9 = Arg6;
|
||||
if (Function != nullptr)
|
||||
this->Registers.rip = (uint64_t)Function;
|
||||
#elif defined(a32)
|
||||
this->Registers.eax = Arg1;
|
||||
this->Registers.ebx = Arg2;
|
||||
this->Registers.ecx = Arg3;
|
||||
this->Registers.edx = Arg4;
|
||||
this->Registers.esi = Arg5;
|
||||
this->Registers.edi = Arg6;
|
||||
if (Function != nullptr)
|
||||
this->Registers.eip = (uint32_t)Function;
|
||||
#else
|
||||
#warning "SYSV ABI not implemented for this architecture"
|
||||
#endif
|
||||
}
|
||||
|
||||
__no_sanitize("undefined")
|
||||
TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint,
|
||||
const char **argv, const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv,
|
||||
TaskArchitecture Architecture,
|
||||
TaskCompatibility Compatibility,
|
||||
bool ThreadNotReady)
|
||||
__no_sanitize("undefined") void TCB::SetupUserStack_x86_64(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv)
|
||||
{
|
||||
size_t ArgvSize = 0;
|
||||
if (argv)
|
||||
while (argv[ArgvSize] != nullptr)
|
||||
ArgvSize++;
|
||||
|
||||
size_t EnvpSize = 0;
|
||||
if (envp)
|
||||
while (envp[EnvpSize] != nullptr)
|
||||
EnvpSize++;
|
||||
|
||||
debug("ArgvSize: %d", ArgvSize);
|
||||
debug("EnvpSize: %d", EnvpSize);
|
||||
|
||||
/* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */
|
||||
/* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */
|
||||
// rsp is the top of the stack
|
||||
char *Stack = (char *)this->Stack->GetStackPhysicalTop();
|
||||
// Temporary stack pointer for strings
|
||||
char *StackStrings = (char *)Stack;
|
||||
char *StackStringsVirtual = (char *)this->Stack->GetStackTop();
|
||||
|
||||
// Store string pointers for later
|
||||
uintptr_t *ArgvStrings = nullptr;
|
||||
uintptr_t *EnvpStrings = nullptr;
|
||||
if (ArgvSize > 0)
|
||||
ArgvStrings = new uintptr_t[ArgvSize];
|
||||
if (EnvpSize > 0)
|
||||
EnvpStrings = new uintptr_t[EnvpSize];
|
||||
|
||||
for (size_t i = 0; i < ArgvSize; i++)
|
||||
{
|
||||
// Subtract the length of the string and the null terminator
|
||||
StackStrings -= strlen(argv[i]) + 1;
|
||||
StackStringsVirtual -= strlen(argv[i]) + 1;
|
||||
// Store the pointer to the string
|
||||
ArgvStrings[i] = (uintptr_t)StackStringsVirtual;
|
||||
// Copy the string to the stack
|
||||
strcpy(StackStrings, argv[i]);
|
||||
debug("argv[%d]: %s", i, argv[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < EnvpSize; i++)
|
||||
{
|
||||
// Subtract the length of the string and the null terminator
|
||||
StackStrings -= strlen(envp[i]) + 1;
|
||||
StackStringsVirtual -= strlen(envp[i]) + 1;
|
||||
// Store the pointer to the string
|
||||
EnvpStrings[i] = (uintptr_t)StackStringsVirtual;
|
||||
// Copy the string to the stack
|
||||
strcpy(StackStrings, envp[i]);
|
||||
debug("envp[%d]: %s", i, envp[i]);
|
||||
}
|
||||
|
||||
// Align the stack to 16 bytes
|
||||
StackStrings -= (uintptr_t)StackStrings & 0xF;
|
||||
// Set "Stack" to the new stack pointer
|
||||
Stack = (char *)StackStrings;
|
||||
// If argv and envp sizes are odd then we need to align the stack
|
||||
Stack -= (ArgvSize + EnvpSize) % 2;
|
||||
|
||||
// We need 8 bit pointers for the stack from here
|
||||
uintptr_t *Stack64 = (uintptr_t *)Stack;
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator
|
||||
std::vector<AuxiliaryVector> auxv_array = auxv;
|
||||
if (auxv_array.size() == 0)
|
||||
auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
|
||||
// Store auxillary vector
|
||||
foreach (AuxiliaryVector var in auxv_array)
|
||||
{
|
||||
// Subtract the size of the auxillary vector
|
||||
Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t);
|
||||
// Store the auxillary vector
|
||||
POKE(Elf64_auxv_t, Stack64) = var.archaux;
|
||||
// TODO: Store strings to the stack
|
||||
}
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// Store EnvpStrings[] to the stack
|
||||
Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize)
|
||||
for (size_t i = 0; i < EnvpSize; i++)
|
||||
{
|
||||
*(Stack64 + i) = (uintptr_t)EnvpStrings[i];
|
||||
debug("EnvpStrings[%d]: %#lx",
|
||||
i, EnvpStrings[i]);
|
||||
}
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// Store ArgvStrings[] to the stack
|
||||
Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize)
|
||||
for (size_t i = 0; i < ArgvSize; i++)
|
||||
{
|
||||
*(Stack64 + i) = (uintptr_t)ArgvStrings[i];
|
||||
debug("ArgvStrings[%d]: %#lx",
|
||||
i, ArgvStrings[i]);
|
||||
}
|
||||
|
||||
// Store the argc
|
||||
Stack64--;
|
||||
*Stack64 = ArgvSize;
|
||||
|
||||
// Set "Stack" to the new stack pointer
|
||||
Stack = (char *)Stack64;
|
||||
|
||||
/* We need the virtual address but because we are in the kernel we can't use the process page table.
|
||||
So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */
|
||||
uintptr_t SubtractStack = (uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)Stack;
|
||||
debug("SubtractStack: %#lx", SubtractStack);
|
||||
|
||||
// Set the stack pointer to the new stack
|
||||
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack);
|
||||
|
||||
if (ArgvSize > 0)
|
||||
delete[] ArgvStrings;
|
||||
if (EnvpSize > 0)
|
||||
delete[] EnvpStrings;
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack);
|
||||
#endif
|
||||
|
||||
this->Registers.rdi = (uintptr_t)ArgvSize; // argc
|
||||
this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv
|
||||
this->Registers.rcx = (uintptr_t)EnvpSize; // envc
|
||||
this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp
|
||||
}
|
||||
|
||||
void TCB::SetupUserStack_x86_32(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv)
|
||||
{
|
||||
fixme("Not implemented");
|
||||
}
|
||||
|
||||
void TCB::SetupUserStack_aarch64(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv)
|
||||
{
|
||||
fixme("Not implemented");
|
||||
}
|
||||
|
||||
TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint,
|
||||
const char **argv, const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv,
|
||||
TaskArchitecture Architecture,
|
||||
TaskCompatibility Compatibility,
|
||||
bool ThreadNotReady)
|
||||
{
|
||||
assert(ctx != nullptr);
|
||||
assert(Architecture >= _ArchitectureMin);
|
||||
@ -152,42 +320,20 @@ namespace Tasking
|
||||
|
||||
if (this->Name)
|
||||
delete[] this->Name;
|
||||
|
||||
this->Name = new char[strlen(this->Parent->Name) + 1];
|
||||
strcpy((char *)this->Name, this->Parent->Name);
|
||||
|
||||
this->EntryPoint = EntryPoint;
|
||||
this->ExitCode = KILL_CRASH;
|
||||
this->Info.Architecture = Architecture;
|
||||
this->Info.Compatibility = Compatibility;
|
||||
this->Security.ExecutionMode =
|
||||
this->Parent->Security.ExecutionMode;
|
||||
|
||||
if (ThreadNotReady)
|
||||
this->Status = TaskStatus::Zombie;
|
||||
else
|
||||
this->Status = TaskStatus::Ready;
|
||||
|
||||
this->Memory = new Memory::MemMgr(this->Parent->PageTable,
|
||||
this->Parent->memDirectory);
|
||||
std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1);
|
||||
this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs);
|
||||
memset(this->FPU, 0, sizeof(CPU::x64::FXState));
|
||||
|
||||
// TODO: Is really a good idea to use the FPU in kernel mode?
|
||||
this->FPU->mxcsr = 0b0001111110000000;
|
||||
this->FPU->mxcsrmask = 0b1111111110111111;
|
||||
this->FPU->fcw = 0b0000001100111111;
|
||||
|
||||
// CPU::x64::fxrstor(this->FPU);
|
||||
// uint16_t FCW = 0b1100111111;
|
||||
// asmv("fldcw %0"
|
||||
// :
|
||||
// : "m"(FCW)
|
||||
// : "memory");
|
||||
// uint32_t MXCSR = 0b1111110000000;
|
||||
// asmv("ldmxcsr %0"
|
||||
// :
|
||||
// : "m"(MXCSR)
|
||||
// : "memory");
|
||||
// CPU::x64::fxsave(this->FPU);
|
||||
|
||||
#if defined(a64)
|
||||
this->Registers.rip = EntryPoint;
|
||||
@ -221,7 +367,17 @@ namespace Tasking
|
||||
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop());
|
||||
POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit;
|
||||
#elif defined(a32)
|
||||
this->Registers.cs = GDT_KERNEL_CODE;
|
||||
this->Registers.ss = GDT_KERNEL_DATA;
|
||||
this->Registers.eflags.AlwaysOne = 1;
|
||||
this->Registers.eflags.IF = 1;
|
||||
this->Registers.eflags.ID = 1;
|
||||
this->Registers.esp = ((uintptr_t)this->Stack->GetStackTop());
|
||||
POKE(uintptr_t, this->Registers.esp) = (uintptr_t)ThreadDoExit;
|
||||
#elif defined(aa64)
|
||||
this->Registers.pc = EntryPoint;
|
||||
this->Registers.sp = ((uintptr_t)this->Stack->GetStackTop());
|
||||
POKE(uintptr_t, this->Registers.sp) = (uintptr_t)ThreadDoExit;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -250,150 +406,23 @@ namespace Tasking
|
||||
/* We need to leave the libc's crt
|
||||
to make a syscall when the Thread
|
||||
is exited or we are going to get
|
||||
GPF or PF exception. */
|
||||
|
||||
#pragma region
|
||||
size_t ArgvSize = 0;
|
||||
if (argv)
|
||||
while (argv[ArgvSize] != nullptr)
|
||||
ArgvSize++;
|
||||
|
||||
size_t EnvpSize = 0;
|
||||
if (envp)
|
||||
while (envp[EnvpSize] != nullptr)
|
||||
EnvpSize++;
|
||||
|
||||
debug("ArgvSize: %d", ArgvSize);
|
||||
debug("EnvpSize: %d", EnvpSize);
|
||||
|
||||
/* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */
|
||||
/* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */
|
||||
// rsp is the top of the stack
|
||||
char *Stack = (char *)this->Stack->GetStackPhysicalTop();
|
||||
// Temporary stack pointer for strings
|
||||
char *StackStrings = (char *)Stack;
|
||||
char *StackStringsVirtual = (char *)this->Stack->GetStackTop();
|
||||
|
||||
// Store string pointers for later
|
||||
uintptr_t *ArgvStrings = nullptr;
|
||||
uintptr_t *EnvpStrings = nullptr;
|
||||
if (ArgvSize > 0)
|
||||
ArgvStrings = new uintptr_t[ArgvSize];
|
||||
if (EnvpSize > 0)
|
||||
EnvpStrings = new uintptr_t[EnvpSize];
|
||||
|
||||
for (size_t i = 0; i < ArgvSize; i++)
|
||||
{
|
||||
// Subtract the length of the string and the null terminator
|
||||
StackStrings -= strlen(argv[i]) + 1;
|
||||
StackStringsVirtual -= strlen(argv[i]) + 1;
|
||||
// Store the pointer to the string
|
||||
ArgvStrings[i] = (uintptr_t)StackStringsVirtual;
|
||||
// Copy the string to the stack
|
||||
strcpy(StackStrings, argv[i]);
|
||||
debug("argv[%d]: %s", i, argv[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < EnvpSize; i++)
|
||||
{
|
||||
// Subtract the length of the string and the null terminator
|
||||
StackStrings -= strlen(envp[i]) + 1;
|
||||
StackStringsVirtual -= strlen(envp[i]) + 1;
|
||||
// Store the pointer to the string
|
||||
EnvpStrings[i] = (uintptr_t)StackStringsVirtual;
|
||||
// Copy the string to the stack
|
||||
strcpy(StackStrings, envp[i]);
|
||||
debug("envp[%d]: %s", i, envp[i]);
|
||||
}
|
||||
|
||||
// Align the stack to 16 bytes
|
||||
StackStrings -= (uintptr_t)StackStrings & 0xF;
|
||||
// Set "Stack" to the new stack pointer
|
||||
Stack = (char *)StackStrings;
|
||||
// If argv and envp sizes are odd then we need to align the stack
|
||||
Stack -= (ArgvSize + EnvpSize) % 2;
|
||||
|
||||
// We need 8 bit pointers for the stack from here
|
||||
uintptr_t *Stack64 = (uintptr_t *)Stack;
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator
|
||||
std::vector<AuxiliaryVector> auxv_array = auxv;
|
||||
if (auxv_array.size() == 0)
|
||||
auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
||||
|
||||
// Store auxillary vector
|
||||
foreach (AuxiliaryVector var in auxv_array)
|
||||
{
|
||||
// Subtract the size of the auxillary vector
|
||||
Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t);
|
||||
// Store the auxillary vector
|
||||
POKE(Elf64_auxv_t, Stack64) = var.archaux;
|
||||
// TODO: Store strings to the stack
|
||||
}
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// Store EnvpStrings[] to the stack
|
||||
Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize)
|
||||
for (size_t i = 0; i < EnvpSize; i++)
|
||||
{
|
||||
*(Stack64 + i) = (uintptr_t)EnvpStrings[i];
|
||||
debug("EnvpStrings[%d]: %#lx",
|
||||
i, EnvpStrings[i]);
|
||||
}
|
||||
|
||||
// Store the null terminator
|
||||
Stack64--;
|
||||
*Stack64 = AT_NULL;
|
||||
|
||||
// Store ArgvStrings[] to the stack
|
||||
Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize)
|
||||
for (size_t i = 0; i < ArgvSize; i++)
|
||||
{
|
||||
*(Stack64 + i) = (uintptr_t)ArgvStrings[i];
|
||||
debug("ArgvStrings[%d]: %#lx",
|
||||
i, ArgvStrings[i]);
|
||||
}
|
||||
|
||||
// Store the argc
|
||||
Stack64--;
|
||||
*Stack64 = ArgvSize;
|
||||
|
||||
// Set "Stack" to the new stack pointer
|
||||
Stack = (char *)Stack64;
|
||||
|
||||
/* We need the virtual address but because we are in the kernel we can't use the process page table.
|
||||
So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */
|
||||
uintptr_t SubtractStack = (uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)Stack;
|
||||
debug("SubtractStack: %#lx", SubtractStack);
|
||||
|
||||
// Set the stack pointer to the new stack
|
||||
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack);
|
||||
|
||||
if (ArgvSize > 0)
|
||||
delete[] ArgvStrings;
|
||||
if (EnvpSize > 0)
|
||||
delete[] EnvpStrings;
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack);
|
||||
#endif
|
||||
|
||||
this->Registers.rdi = (uintptr_t)ArgvSize; // argc
|
||||
this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv
|
||||
this->Registers.rcx = (uintptr_t)EnvpSize; // envc
|
||||
this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp
|
||||
|
||||
#pragma endregion
|
||||
an exception. */
|
||||
|
||||
this->SetupUserStack_x86_64(argv, envp, auxv);
|
||||
#elif defined(a32)
|
||||
this->Registers.cs = GDT_USER_CODE;
|
||||
this->Registers.ss = GDT_USER_DATA;
|
||||
this->Registers.eflags.AlwaysOne = 1;
|
||||
this->Registers.eflags.IF = 1;
|
||||
this->Registers.eflags.ID = 1;
|
||||
/* We need to leave the libc's crt
|
||||
to make a syscall when the Thread
|
||||
is exited or we are going to get
|
||||
an exception. */
|
||||
|
||||
this->SetupUserStack_x86_32(argv, envp, auxv);
|
||||
#elif defined(aa64)
|
||||
this->SetupUserStack_aarch64(argv, envp, auxv);
|
||||
#endif
|
||||
#ifdef DEBUG_TASKING
|
||||
DumpData(this->Name, this->Stack, STACK_SIZE);
|
||||
@ -404,7 +433,32 @@ namespace Tasking
|
||||
assert(false);
|
||||
}
|
||||
|
||||
this->Info.SpawnTime = TimeManager->GetCounter();
|
||||
this->Info.Architecture = Architecture;
|
||||
this->Info.Compatibility = Compatibility;
|
||||
this->Security.ExecutionMode =
|
||||
this->Parent->Security.ExecutionMode;
|
||||
|
||||
std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1);
|
||||
this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs);
|
||||
memset(this->FPU, 0, sizeof(CPU::x64::FXState));
|
||||
|
||||
// TODO: Is really a good idea to use the FPU in kernel mode?
|
||||
this->FPU->mxcsr = 0b0001111110000000;
|
||||
this->FPU->mxcsrmask = 0b1111111110111111;
|
||||
this->FPU->fcw = 0b0000001100111111;
|
||||
|
||||
// CPU::x64::fxrstor(this->FPU);
|
||||
// uint16_t FCW = 0b1100111111;
|
||||
// asmv("fldcw %0"
|
||||
// :
|
||||
// : "m"(FCW)
|
||||
// : "memory");
|
||||
// uint32_t MXCSR = 0b1111110000000;
|
||||
// asmv("ldmxcsr %0"
|
||||
// :
|
||||
// : "m"(MXCSR)
|
||||
// : "memory");
|
||||
// CPU::x64::fxsave(this->FPU);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef a64
|
||||
@ -436,6 +490,8 @@ namespace Tasking
|
||||
this->Parent->ID);
|
||||
#endif
|
||||
|
||||
this->Info.SpawnTime = TimeManager->GetCounter();
|
||||
|
||||
this->Parent->Threads.push_back(this);
|
||||
|
||||
if (this->Parent->Threads.size() == 1 &&
|
||||
@ -448,13 +504,20 @@ namespace Tasking
|
||||
|
||||
TCB::~TCB()
|
||||
{
|
||||
/* Remove us from the process list so we
|
||||
don't get scheduled anymore */
|
||||
std::vector<Tasking::TCB *> &Threads = this->Parent->Threads;
|
||||
Threads.erase(std::find(Threads.begin(),
|
||||
Threads.end(),
|
||||
this));
|
||||
|
||||
/* Free Name */
|
||||
delete[] this->Name;
|
||||
|
||||
/* Free CPU Stack */
|
||||
delete this->Stack;
|
||||
|
||||
/* Free all allocated memory */
|
||||
delete this->Memory;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ test_mem_new_delete::~test_mem_new_delete()
|
||||
;
|
||||
}
|
||||
|
||||
extern bool EnableExternalMemoryTracer;
|
||||
extern bool DebuggerIsAttached;
|
||||
|
||||
void TestMemoryAllocation()
|
||||
@ -52,9 +51,9 @@ void TestMemoryAllocation()
|
||||
#ifdef a32
|
||||
return; /* Not ready for now. */
|
||||
#endif
|
||||
if (EnableExternalMemoryTracer || DebuggerIsAttached)
|
||||
if (DebuggerIsAttached)
|
||||
{
|
||||
debug("The test is disabled when the external memory tracer or a debugger is enabled.");
|
||||
debug("The test is disabled when the debugger is enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -68,13 +67,13 @@ void TestMemoryAllocation()
|
||||
|
||||
debug("Single Page Request Test");
|
||||
{
|
||||
uint64_t prq1 = (uint64_t)KernelAllocator.RequestPage();
|
||||
uintptr_t prq1 = (uintptr_t)KernelAllocator.RequestPage();
|
||||
KernelAllocator.FreePage((void *)prq1);
|
||||
|
||||
for (size_t i = 0; i < MEMTEST_ITERATIONS; i++)
|
||||
KernelAllocator.FreePage(KernelAllocator.RequestPage());
|
||||
|
||||
uint64_t prq2 = (uint64_t)KernelAllocator.RequestPage();
|
||||
uintptr_t prq2 = (uintptr_t)KernelAllocator.RequestPage();
|
||||
KernelAllocator.FreePage((void *)prq2);
|
||||
|
||||
debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
|
||||
@ -83,13 +82,13 @@ void TestMemoryAllocation()
|
||||
|
||||
debug("Multiple Page Request Test");
|
||||
{
|
||||
uint64_t prq1 = (uint64_t)KernelAllocator.RequestPages(10);
|
||||
uintptr_t prq1 = (uintptr_t)KernelAllocator.RequestPages(10);
|
||||
KernelAllocator.FreePages((void *)prq1, 10);
|
||||
|
||||
for (size_t i = 0; i < MEMTEST_ITERATIONS; i++)
|
||||
KernelAllocator.FreePages(KernelAllocator.RequestPages(20), 20);
|
||||
|
||||
uint64_t prq2 = (uint64_t)KernelAllocator.RequestPages(10);
|
||||
uintptr_t prq2 = (uintptr_t)KernelAllocator.RequestPages(10);
|
||||
KernelAllocator.FreePages((void *)prq2, 10);
|
||||
|
||||
debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2);
|
||||
|
@ -21,15 +21,15 @@
|
||||
#include <memory.hpp>
|
||||
#include <convert.h>
|
||||
|
||||
extern bool EnableExternalMemoryTracer;
|
||||
|
||||
extern bool DebuggerIsAttached;
|
||||
extern Memory::MemoryAllocatorType AllocatorType;
|
||||
|
||||
__constructor void TestMemoryOperations()
|
||||
{
|
||||
if (EnableExternalMemoryTracer || DebuggerIsAttached)
|
||||
if (DebuggerIsAttached)
|
||||
{
|
||||
debug("The test is disabled when the external memory tracer or a debugger is enabled.");
|
||||
debug("The test is disabled when the debugger is enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,18 @@ namespace Execute
|
||||
std::vector<AuxiliaryVector> Elfauxv;
|
||||
Tasking::IP ip;
|
||||
|
||||
void GenerateAuxiliaryVector_x86_32(Memory::MemMgr *mm,
|
||||
int fd,
|
||||
Elf32_Ehdr ELFHeader,
|
||||
uint32_t EntryPoint,
|
||||
uint32_t BaseAddress);
|
||||
|
||||
void GenerateAuxiliaryVector_x86_64(Memory::MemMgr *mm,
|
||||
int fd,
|
||||
Elf64_Ehdr ELFHeader,
|
||||
uint64_t EntryPoint,
|
||||
uint64_t BaseAddress);
|
||||
|
||||
void LoadExec_x86_32(int fd,
|
||||
Tasking::PCB *TargetProcess);
|
||||
|
||||
@ -99,7 +111,8 @@ namespace Execute
|
||||
|
||||
int Spawn(char *Path, const char **argv, const char **envp,
|
||||
Tasking::PCB *Parent = nullptr,
|
||||
Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native);
|
||||
Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native,
|
||||
bool Critical = false);
|
||||
|
||||
bool ELFIs64(void *Header);
|
||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
|
||||
|
@ -357,7 +357,23 @@ namespace VirtualFileSystem
|
||||
class FileDescriptorTable
|
||||
{
|
||||
public:
|
||||
struct FileDescriptor
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
};
|
||||
|
||||
struct Fildes
|
||||
{
|
||||
RefNode *Handle{};
|
||||
mode_t Mode = 0;
|
||||
int Flags = 0;
|
||||
int Descriptor = -1;
|
||||
};
|
||||
|
||||
struct DupFildes
|
||||
{
|
||||
RefNode *Handle{};
|
||||
mode_t Mode = 0;
|
||||
@ -366,10 +382,13 @@ namespace VirtualFileSystem
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<FileDescriptor> FileDescriptors;
|
||||
std::vector<Fildes> FileDescriptors;
|
||||
std::vector<DupFildes> FildesDuplicates;
|
||||
VirtualFileSystem::Node *fdDir = nullptr;
|
||||
|
||||
FileDescriptor GetFileDescriptor(int FileDescriptor);
|
||||
Fildes GetFileDescriptor(int FileDescriptor);
|
||||
FileDescriptorTable::DupFildes GetDupFildes(int FileDescriptor);
|
||||
|
||||
int ProbeMode(mode_t Mode, int Flags);
|
||||
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
|
||||
int RemoveFileDescriptor(int FileDescriptor);
|
||||
@ -377,7 +396,7 @@ namespace VirtualFileSystem
|
||||
|
||||
public:
|
||||
std::string GetAbsolutePath(int FileDescriptor);
|
||||
std::vector<FileDescriptor> &GetFileDescriptors() { return FileDescriptors; }
|
||||
std::vector<Fildes> &GetFileDescriptors() { return FileDescriptors; }
|
||||
|
||||
int _open(const char *pathname, int flags, mode_t mode);
|
||||
int _creat(const char *pathname, mode_t mode);
|
||||
@ -388,6 +407,9 @@ namespace VirtualFileSystem
|
||||
int _stat(const char *pathname, struct stat *statbuf);
|
||||
int _fstat(int fd, struct stat *statbuf);
|
||||
int _lstat(const char *pathname, struct stat *statbuf);
|
||||
int _dup(int oldfd);
|
||||
int _dup2(int oldfd, int newfd);
|
||||
int _ioctl(int fd, unsigned long request, void *argp);
|
||||
|
||||
FileDescriptorTable(void *Owner);
|
||||
~FileDescriptorTable();
|
||||
|
@ -22,93 +22,9 @@
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
/* Manage /dev */
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Node *AddFileSystem(FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags);
|
||||
Device();
|
||||
~Device();
|
||||
};
|
||||
|
||||
/* Manage /mnt */
|
||||
class Mount
|
||||
{
|
||||
public:
|
||||
Node *MountFileSystem(FileSystemOperations *Operator, uint64_t Mode, const char *Name);
|
||||
void DetectAndMountFS(void *drive);
|
||||
Mount();
|
||||
~Mount();
|
||||
};
|
||||
|
||||
/* Manage /prc */
|
||||
class Process
|
||||
{
|
||||
public:
|
||||
Process();
|
||||
~Process();
|
||||
};
|
||||
|
||||
/* Manage /drv */
|
||||
class Driver
|
||||
{
|
||||
public:
|
||||
Node *AddDriver(struct FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags);
|
||||
Driver();
|
||||
~Driver();
|
||||
};
|
||||
|
||||
/* Manage /net */
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
Node *AddNetworkCard(struct FileSystemOperations *Operator, uint64_t Mode, const char *Name, int Flags);
|
||||
Network();
|
||||
~Network();
|
||||
};
|
||||
|
||||
/* Manage /dev/serialX */
|
||||
class Serial
|
||||
{
|
||||
public:
|
||||
Serial();
|
||||
~Serial();
|
||||
};
|
||||
|
||||
/* Manage /dev/random */
|
||||
class Random
|
||||
{
|
||||
public:
|
||||
Random();
|
||||
~Random();
|
||||
};
|
||||
|
||||
/* Manage /dev/null */
|
||||
class Null
|
||||
{
|
||||
public:
|
||||
Null();
|
||||
~Null();
|
||||
};
|
||||
|
||||
/* Manage /dev/zero */
|
||||
class Zero
|
||||
{
|
||||
public:
|
||||
Zero();
|
||||
~Zero();
|
||||
};
|
||||
|
||||
/* Manage /dev/fbX */
|
||||
class FB
|
||||
{
|
||||
public:
|
||||
void SetFrameBufferData(uintptr_t Address, size_t Size, uint32_t Width, uint32_t Height, uint32_t PixelsPerScanLine);
|
||||
FB();
|
||||
~FB();
|
||||
};
|
||||
}
|
||||
void Init_Null(VirtualFileSystem::Virtual *vfs_ctx);
|
||||
void Init_Random(VirtualFileSystem::Virtual *vfs_ctx);
|
||||
void Init_Teletype(VirtualFileSystem::Virtual *vfs_ctx);
|
||||
void Init_Zero(VirtualFileSystem::Virtual *vfs_ctx);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_FILESYSTEM_DEV_H__
|
||||
|
@ -66,16 +66,12 @@ extern uintptr_t _kernel_bss_start, _kernel_bss_end;
|
||||
#define FROM_PAGES(d) ((d)*PAGE_SIZE)
|
||||
|
||||
#if defined(a64) || defined(aa64)
|
||||
#define NORMAL_VMA_OFFSET 0xFFFF800000000000
|
||||
#define KERNEL_VMA_OFFSET 0xFFFFFFFF80000000
|
||||
#define KERNEL_HEAP_BASE 0xFFFFA00000000000
|
||||
#define USER_HEAP_BASE 0xFFFFB00000000000
|
||||
#define KERNEL_HEAP_BASE 0xFFFFFF0000000000
|
||||
#define USER_STACK_BASE 0xFFFFEFFFFFFF0000
|
||||
#elif defined(a32)
|
||||
#define NORMAL_VMA_OFFSET 0x80000000
|
||||
#define KERNEL_VMA_OFFSET 0xC0000000
|
||||
#define KERNEL_HEAP_BASE 0xA0000000
|
||||
#define USER_HEAP_BASE 0xB0000000
|
||||
#define USER_STACK_BASE 0xEFFFFFFF
|
||||
#endif
|
||||
|
||||
@ -86,6 +82,7 @@ namespace Memory
|
||||
None,
|
||||
Pages,
|
||||
XallocV1,
|
||||
XallocV2,
|
||||
liballoc11
|
||||
};
|
||||
|
||||
@ -584,8 +581,35 @@ namespace Memory
|
||||
* @return A new PageTable with the same content
|
||||
*/
|
||||
PageTable Fork();
|
||||
|
||||
template <typename T>
|
||||
T Get(T Address);
|
||||
} __aligned(0x1000);
|
||||
|
||||
class TempSwitchPT
|
||||
{
|
||||
private:
|
||||
PageTable *Replace = nullptr;
|
||||
PageTable *Restore = nullptr;
|
||||
|
||||
public:
|
||||
TempSwitchPT(PageTable *ReplaceWith,
|
||||
PageTable *RestoreWith = nullptr)
|
||||
: Replace(ReplaceWith)
|
||||
{
|
||||
extern PageTable *KernelPageTable;
|
||||
|
||||
if (RestoreWith)
|
||||
Restore = RestoreWith;
|
||||
else
|
||||
Restore = KernelPageTable;
|
||||
|
||||
Replace->Update();
|
||||
}
|
||||
|
||||
~TempSwitchPT() { Restore->Update(); }
|
||||
};
|
||||
|
||||
class Physical
|
||||
{
|
||||
private:
|
||||
@ -1077,6 +1101,30 @@ namespace Memory
|
||||
std::vector<AllocatedPages> AllocatedPagesList;
|
||||
};
|
||||
|
||||
class ProgramBreak
|
||||
{
|
||||
private:
|
||||
PageTable *Table = nullptr;
|
||||
MemMgr *mm = nullptr;
|
||||
|
||||
uintptr_t HeapStart = 0x0;
|
||||
uintptr_t Break = 0x0;
|
||||
|
||||
public:
|
||||
/* Directly to syscall */
|
||||
void *brk(void *Address);
|
||||
|
||||
void InitBrk(uintptr_t Address)
|
||||
{
|
||||
function("%#lx", Address);
|
||||
HeapStart = Address;
|
||||
Break = Address;
|
||||
}
|
||||
|
||||
ProgramBreak(PageTable *Table, MemMgr *mm);
|
||||
~ProgramBreak();
|
||||
};
|
||||
|
||||
class SmartHeap
|
||||
{
|
||||
private:
|
||||
|
@ -159,17 +159,35 @@ namespace Tasking
|
||||
private:
|
||||
class Task *ctx = nullptr;
|
||||
|
||||
void SetupUserStack_x86_64(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv);
|
||||
|
||||
void SetupUserStack_x86_32(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv);
|
||||
|
||||
void SetupUserStack_aarch64(const char **argv,
|
||||
const char **envp,
|
||||
const std::vector<AuxiliaryVector> &auxv);
|
||||
|
||||
public:
|
||||
/* Basic info */
|
||||
TID ID = -1;
|
||||
const char * Name = nullptr;
|
||||
const char *Name = nullptr;
|
||||
class PCB *Parent = nullptr;
|
||||
IP EntryPoint = 0;
|
||||
|
||||
/* Statuses */
|
||||
std::atomic_int ExitCode;
|
||||
std::atomic<TaskStatus> Status = TaskStatus::UnknownStatus;
|
||||
Memory::StackGuard *Stack;
|
||||
Memory::MemMgr *Memory;
|
||||
std::atomic<TaskStatus> Status = TaskStatus::Zombie;
|
||||
int ErrorNumber;
|
||||
|
||||
/* Memory */
|
||||
Memory::MemMgr *Memory;
|
||||
Memory::StackGuard *Stack;
|
||||
|
||||
/* CPU state */
|
||||
#if defined(a64)
|
||||
CPU::x64::TrapFrame Registers{};
|
||||
uintptr_t ShadowGSBase, GSBase, FSBase;
|
||||
@ -180,6 +198,9 @@ namespace Tasking
|
||||
uintptr_t Registers; // TODO
|
||||
#endif
|
||||
uintptr_t IPHistory[128];
|
||||
CPU::x64::FXState *FPU;
|
||||
|
||||
/* Info & Security info */
|
||||
struct
|
||||
{
|
||||
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
|
||||
@ -188,7 +209,13 @@ namespace Tasking
|
||||
bool IsKernelDebugEnabled = false;
|
||||
} Security{};
|
||||
TaskInfo Info{};
|
||||
CPU::x64::FXState *FPU;
|
||||
|
||||
/* Compatibility structures */
|
||||
struct
|
||||
{
|
||||
int *set_child_tid{};
|
||||
int *clear_child_tid{};
|
||||
} Linux{};
|
||||
|
||||
void Rename(const char *name);
|
||||
void SetPriority(TaskPriority priority);
|
||||
@ -228,11 +255,16 @@ namespace Tasking
|
||||
bool OwnPageTable = false;
|
||||
|
||||
public:
|
||||
/* Basic info */
|
||||
PID ID = -1;
|
||||
const char * Name = nullptr;
|
||||
const char *Name = nullptr;
|
||||
PCB *Parent = nullptr;
|
||||
|
||||
/* Statuses */
|
||||
std::atomic_int ExitCode;
|
||||
std::atomic<TaskStatus> Status = Zombie;
|
||||
|
||||
/* Info & Security info */
|
||||
struct
|
||||
{
|
||||
TaskExecutionMode ExecutionMode = UnknownExecutionMode;
|
||||
@ -246,17 +278,26 @@ namespace Tasking
|
||||
} Real, Effective;
|
||||
} Security{};
|
||||
TaskInfo Info{};
|
||||
std::vector<TCB *> Threads;
|
||||
std::vector<PCB *> Children;
|
||||
InterProcessCommunication::IPC *IPC;
|
||||
Memory::PageTable *PageTable;
|
||||
SymbolResolver::Symbols *ELFSymbolTable;
|
||||
|
||||
/* Filesystem */
|
||||
Node *CurrentWorkingDirectory;
|
||||
Node *ProcessDirectory;
|
||||
Node *memDirectory;
|
||||
Memory::MemMgr *Memory;
|
||||
FileDescriptorTable *FileDescriptors;
|
||||
|
||||
/* Memory */
|
||||
Memory::PageTable *PageTable;
|
||||
Memory::MemMgr *Memory;
|
||||
Memory::ProgramBreak *ProgramBreak;
|
||||
|
||||
/* Other */
|
||||
InterProcessCommunication::IPC *IPC;
|
||||
SymbolResolver::Symbols *ELFSymbolTable;
|
||||
|
||||
/* Threads & Children */
|
||||
std::vector<TCB *> Threads;
|
||||
std::vector<PCB *> Children;
|
||||
|
||||
public:
|
||||
void Rename(const char *name);
|
||||
void SetWorkingDirectory(Node *node);
|
||||
|
@ -21,10 +21,10 @@
|
||||
#ifdef __cplusplus
|
||||
#define EXTERNC extern "C"
|
||||
#define START_EXTERNC \
|
||||
EXTERNC \
|
||||
{
|
||||
EXTERNC \
|
||||
{
|
||||
#define END_EXTERNC \
|
||||
}
|
||||
}
|
||||
#else // __cplusplus
|
||||
#define EXTERNC
|
||||
#define START_EXTERNC
|
||||
@ -52,8 +52,8 @@
|
||||
#define in :
|
||||
|
||||
#define forItr(itr, container) \
|
||||
for (auto itr = container.begin(); \
|
||||
itr != container.end(); ++itr)
|
||||
for (auto itr = container.begin(); \
|
||||
itr != container.end(); ++itr)
|
||||
|
||||
#define r_cst(t, v) reinterpret_cast<t>(v)
|
||||
#define c_cst(t, v) const_cast<t>(v)
|
||||
@ -83,18 +83,18 @@ typedef __builtin_va_list va_list;
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define MIN(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
|
||||
#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
|
||||
@ -291,19 +291,19 @@ typedef unsigned gid_t;
|
||||
|
||||
#if defined(a64)
|
||||
#define BREAK __asm__ __volatile__("int $0x3" \
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
#elif defined(a32)
|
||||
#define BREAK __asm__ __volatile__("int $0x3" \
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
#elif defined(aa64)
|
||||
#define BREAK __asm__ __volatile__("brk #0" \
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
#ifdef __INT48_TYPE__
|
||||
@ -327,11 +327,11 @@ typedef uint48_t uint_fast48_t;
|
||||
#define b16(x) __builtin_bswap16(x)
|
||||
#define b32(x) __builtin_bswap32(x)
|
||||
#define b48(x) (((((x)&0x0000000000ff) << 40) | \
|
||||
(((x)&0x00000000ff00) << 24) | \
|
||||
(((x)&0x000000ff0000) << 8) | \
|
||||
(((x)&0x0000ff000000) >> 8) | \
|
||||
(((x)&0x00ff00000000) >> 24) | \
|
||||
(((x)&0xff0000000000) >> 40)))
|
||||
(((x)&0x00000000ff00) << 24) | \
|
||||
(((x)&0x000000ff0000) << 8) | \
|
||||
(((x)&0x0000ff000000) >> 8) | \
|
||||
(((x)&0x00ff00000000) >> 24) | \
|
||||
(((x)&0xff0000000000) >> 40)))
|
||||
#define b64(x) __builtin_bswap64(x)
|
||||
|
||||
/* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */
|
||||
@ -411,16 +411,10 @@ typedef uint48_t uint_fast48_t;
|
||||
|
||||
#define NIF __no_instrument_function
|
||||
|
||||
#define int1 \
|
||||
__asm__ __volatile__("int $0x1" \
|
||||
: \
|
||||
: \
|
||||
: "memory")
|
||||
|
||||
#define int3 \
|
||||
__asm__ __volatile__("int3" \
|
||||
: \
|
||||
: \
|
||||
: "memory")
|
||||
__asm__ __volatile__("int3" \
|
||||
: \
|
||||
: \
|
||||
: "memory")
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TYPES_H__
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <convert.h>
|
||||
#include <debug.h>
|
||||
|
||||
// show debug messages
|
||||
// Show debug messages
|
||||
// #define DEBUG_CPP_STRING 1
|
||||
// #define DEBUG_CPP_STRING_VERBOSE 1
|
||||
|
||||
@ -62,48 +62,49 @@ namespace std
|
||||
this->Capacity = this->Length + 1;
|
||||
this->Data = new char[this->Capacity];
|
||||
strcpy(this->Data, Str);
|
||||
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
~string()
|
||||
{
|
||||
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
delete[] this->Data, this->Data = nullptr;
|
||||
}
|
||||
|
||||
size_t length() const
|
||||
{
|
||||
v_strdbg("String length: %d",
|
||||
this->Length);
|
||||
v_strdbg("%#lx: String length: %d",
|
||||
this, this->Length);
|
||||
return this->Length;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
v_strdbg("String capacity: %d",
|
||||
this->Capacity);
|
||||
v_strdbg("%#lx: String capacity: %d",
|
||||
this, this->Capacity);
|
||||
return this->Capacity;
|
||||
}
|
||||
|
||||
const char *c_str() const
|
||||
{
|
||||
v_strdbg("String data: \"%s\"",
|
||||
this->Data);
|
||||
v_strdbg("%#lx: String data: \"%s\"",
|
||||
this, this->Data);
|
||||
return this->Data;
|
||||
}
|
||||
|
||||
void resize(size_t NewLength)
|
||||
{
|
||||
strdbg("String resize: %d", NewLength);
|
||||
strdbg("%#lx: String resize: %d",
|
||||
this, NewLength);
|
||||
if (NewLength < this->Capacity)
|
||||
{
|
||||
this->Length = NewLength;
|
||||
this->Data[this->Length] = '\0';
|
||||
|
||||
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -111,16 +112,16 @@ namespace std
|
||||
char *newData = new char[newCapacity];
|
||||
strcpy(newData, this->Data);
|
||||
|
||||
strdbg("old: %#lx, new: %#lx",
|
||||
this->Data, newData);
|
||||
strdbg("%#lx: old: %#lx, new: %#lx",
|
||||
this, this->Data, newData);
|
||||
|
||||
delete[] this->Data;
|
||||
this->Data = newData;
|
||||
this->Length = NewLength;
|
||||
this->Capacity = newCapacity;
|
||||
|
||||
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
void concat(const string &Other)
|
||||
@ -129,31 +130,34 @@ namespace std
|
||||
this->resize(NewLength);
|
||||
|
||||
strcat(this->Data, Other.Data);
|
||||
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
strdbg("String empty: %d", this->Length == 0);
|
||||
strdbg("%#lx: String empty: %d",
|
||||
this, this->Length == 0);
|
||||
return this->Length == 0;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
strdbg("String size: %d", this->Length);
|
||||
strdbg("%#lx: String size: %d",
|
||||
this, this->Length);
|
||||
return this->Length;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
strdbg("String clear");
|
||||
strdbg("%#lx: String clear", this);
|
||||
this->resize(0);
|
||||
}
|
||||
|
||||
size_t find(const char *Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String find: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String find: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos >= this->Length)
|
||||
return npos;
|
||||
|
||||
@ -176,13 +180,15 @@ namespace std
|
||||
|
||||
size_t find(const string &Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String find: \"%s\", %d", Str.c_str(), Pos);
|
||||
strdbg("%#lx: String find: \"%s\", %d",
|
||||
this, Str.c_str(), Pos);
|
||||
return this->find(Str.c_str(), Pos);
|
||||
}
|
||||
|
||||
void erase(int Index, int Count = 1)
|
||||
{
|
||||
strdbg("String erase: %d, %d", Index, Count);
|
||||
strdbg("%#lx: String erase: %d, %d",
|
||||
this, Index, Count);
|
||||
if (Index < 0 || (size_t)Index >= this->Length)
|
||||
return;
|
||||
|
||||
@ -197,12 +203,14 @@ namespace std
|
||||
|
||||
this->Length -= Count;
|
||||
this->Data[this->Length] = '\0';
|
||||
strdbg("String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
size_t find_last_not_of(const char *Str, size_t Pos = npos) const
|
||||
{
|
||||
strdbg("String find_last_not_of: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String find_last_not_of: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos == npos)
|
||||
Pos = this->Length - 1;
|
||||
|
||||
@ -225,7 +233,8 @@ namespace std
|
||||
|
||||
size_t find_first_not_of(const char *Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String find_first_not_of: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String find_first_not_of: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos >= this->Length)
|
||||
return npos;
|
||||
|
||||
@ -248,7 +257,8 @@ namespace std
|
||||
|
||||
size_t find_first_of(const char *Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String find_first_of: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String find_first_of: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos >= this->Length)
|
||||
return npos;
|
||||
|
||||
@ -271,7 +281,8 @@ namespace std
|
||||
|
||||
size_t find_last_of(const char *Str, size_t Pos = npos) const
|
||||
{
|
||||
strdbg("String find_last_of: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String find_last_of: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos == npos)
|
||||
Pos = this->Length - 1;
|
||||
|
||||
@ -294,7 +305,8 @@ namespace std
|
||||
|
||||
size_t find_first_of(char C, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String find_first_of: '%c', %d", C, Pos);
|
||||
strdbg("%#lx: String find_first_of: '%c', %d",
|
||||
this, C, Pos);
|
||||
if (Pos >= this->Length)
|
||||
return npos;
|
||||
|
||||
@ -308,7 +320,8 @@ namespace std
|
||||
|
||||
size_t find_last_of(char C, size_t Pos = npos) const
|
||||
{
|
||||
strdbg("String find_last_of: '%c', %d", C, Pos);
|
||||
strdbg("%#lx: String find_last_of: '%c', %d",
|
||||
this, C, Pos);
|
||||
if (Pos == npos)
|
||||
Pos = this->Length - 1;
|
||||
|
||||
@ -322,7 +335,8 @@ namespace std
|
||||
|
||||
size_t substr(const char *Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String substr: \"%s\", %d", Str, Pos);
|
||||
strdbg("%#lx: String substr: \"%s\", %d",
|
||||
this, Str, Pos);
|
||||
if (Pos >= this->Length)
|
||||
return npos;
|
||||
|
||||
@ -345,13 +359,15 @@ namespace std
|
||||
|
||||
size_t substr(const string &Str, size_t Pos = 0) const
|
||||
{
|
||||
strdbg("String substr: \"%s\", %d", Str.c_str(), Pos);
|
||||
strdbg("%#lx: String substr: \"%s\", %d",
|
||||
this, Str.c_str(), Pos);
|
||||
return this->substr(Str.c_str(), Pos);
|
||||
}
|
||||
|
||||
string substr(size_t Pos = 0, size_t Count = npos) const
|
||||
{
|
||||
strdbg("String substr: %d, %d", Pos, Count);
|
||||
strdbg("%#lx: String substr: %d, %d",
|
||||
this, Pos, Count);
|
||||
if (Pos >= this->Length)
|
||||
return string();
|
||||
|
||||
@ -371,7 +387,8 @@ namespace std
|
||||
|
||||
void replace(size_t Pos, size_t Count, const char *Str)
|
||||
{
|
||||
strdbg("String replace: %d, %d, \"%s\"", Pos, Count, Str);
|
||||
strdbg("%#lx: String replace: %d, %d, \"%s\"",
|
||||
this, Pos, Count, Str);
|
||||
if (Pos >= this->Length)
|
||||
return;
|
||||
|
||||
@ -390,12 +407,14 @@ namespace std
|
||||
for (unsigned long i = 0; i < strlen(Str); i++)
|
||||
this->Data[Pos + i] = Str[i];
|
||||
|
||||
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
void replace(size_t Pos, size_t Count, const string &Str)
|
||||
{
|
||||
strdbg("String replace: %d, %d, \"%s\"", Pos, Count, Str.Data);
|
||||
strdbg("%#lx: String replace: %d, %d, \"%s\"",
|
||||
this, Pos, Count, Str.Data);
|
||||
if (Pos >= this->Length)
|
||||
return;
|
||||
|
||||
@ -414,13 +433,13 @@ namespace std
|
||||
for (size_t i = 0; i < Str.Length; i++)
|
||||
this->Data[Pos + i] = Str.Data[i];
|
||||
|
||||
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
strdbg("String pop_back");
|
||||
strdbg("%#lx: String pop_back", this);
|
||||
if (this->Length > 0)
|
||||
{
|
||||
this->Data[this->Length - 1] = '\0';
|
||||
@ -432,8 +451,8 @@ namespace std
|
||||
{
|
||||
string result = *this;
|
||||
result.concat(Other);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
result.Data, result.Data, result.Length, result.Capacity);
|
||||
strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, result.Data, result.Data, result.Length, result.Capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -441,24 +460,24 @@ namespace std
|
||||
{
|
||||
string result = *this;
|
||||
result.concat(Other);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
result.Data, result.Data, result.Length, result.Capacity);
|
||||
strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, result.Data, result.Data, result.Length, result.Capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
string &operator+=(const string &Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator+=(const char *Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -466,8 +485,8 @@ namespace std
|
||||
{
|
||||
const char str[2] = {Other, '\0'};
|
||||
this->concat(str);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -482,8 +501,8 @@ namespace std
|
||||
// this->Data = Other.Data;
|
||||
// this->Length = Other.Length;
|
||||
// this->Capacity = Other.Capacity;
|
||||
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
// this->Data, this->Data, this->Length, this->Capacity);
|
||||
// strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
// this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
// }
|
||||
// return *this;
|
||||
// }
|
||||
@ -495,72 +514,76 @@ namespace std
|
||||
delete[] this->Data;
|
||||
this->Data = new char[this->Capacity];
|
||||
strcpy(this->Data, Other);
|
||||
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator<<(const string &Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator<<(const char *Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this, this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
char &operator[](int Index)
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
strdbg("%#lx: String index: %d", this, Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
const char &operator[](int Index) const
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
strdbg("%#lx: String index: %d", this, Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
char &operator[](size_t Index)
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
strdbg("%#lx: String index: %d", this, Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
const char &operator[](size_t Index) const
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
strdbg("%#lx: String index: %d", this, Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
bool operator==(const string &Other) const
|
||||
{
|
||||
strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other.Data);
|
||||
strdbg("%#lx: String compared: \"%s\" == \"%s\"",
|
||||
this, this->Data, Other.Data);
|
||||
return strcmp(this->Data, Other.Data) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const char *Other) const
|
||||
{
|
||||
strdbg("String compared: \"%s\" != \"%s\"", this->Data, Other);
|
||||
strdbg("%#lx: String compared: \"%s\" != \"%s\"",
|
||||
this, this->Data, Other);
|
||||
return strcmp(this->Data, Other) != 0;
|
||||
}
|
||||
|
||||
bool operator!=(const string &Other) const
|
||||
{
|
||||
strdbg("String compared: \"%s\" != \"%s\"", this->Data, Other.Data);
|
||||
strdbg("%#lx: String compared: \"%s\" != \"%s\"",
|
||||
this, this->Data, Other.Data);
|
||||
return strcmp(this->Data, Other.Data) != 0;
|
||||
}
|
||||
|
||||
bool operator==(const char *Other) const
|
||||
{
|
||||
strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other);
|
||||
strdbg("%#lx: String compared: \"%s\" == \"%s\"",
|
||||
this, this->Data, Other);
|
||||
return strcmp(this->Data, Other) == 0;
|
||||
}
|
||||
|
||||
@ -575,42 +598,44 @@ namespace std
|
||||
iterator &operator++()
|
||||
{
|
||||
++this->Pointer;
|
||||
strdbg("String iterator incremented: %#lx",
|
||||
this->Pointer);
|
||||
strdbg("%#lx: String iterator incremented: %#lx",
|
||||
this, this->Pointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
char &operator*()
|
||||
{
|
||||
strdbg("String iterator dereferenced: %#lx",
|
||||
this->Pointer);
|
||||
strdbg("%#lx: String iterator dereferenced: %#lx",
|
||||
this, this->Pointer);
|
||||
return *this->Pointer;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator &Other) const
|
||||
{
|
||||
strdbg("String iterator compared: %#lx != %#lx",
|
||||
this->Pointer, Other.Pointer);
|
||||
strdbg("%#lx: String iterator compared: %#lx != %#lx",
|
||||
this, this->Pointer, Other.Pointer);
|
||||
return this->Pointer != Other.Pointer;
|
||||
}
|
||||
|
||||
bool operator==(const iterator &Other) const
|
||||
{
|
||||
strdbg("String iterator compared: %#lx == %#lx",
|
||||
this->Pointer, Other.Pointer);
|
||||
strdbg("%#lx: String iterator compared: %#lx == %#lx",
|
||||
this, this->Pointer, Other.Pointer);
|
||||
return this->Pointer == Other.Pointer;
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
strdbg("String iterator begin: %#lx", this->Data);
|
||||
strdbg("%#lx: String iterator begin: %#lx",
|
||||
this, this->Data);
|
||||
return iterator(this->Data);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
strdbg("String iterator end: %#lx", this->Data + this->Length);
|
||||
strdbg("%#lx: String iterator end: %#lx",
|
||||
this, this->Data + this->Length);
|
||||
return iterator(this->Data + this->Length);
|
||||
}
|
||||
};
|
||||
|
78
include_std/stropts.h
Normal file
78
include_std/stropts.h
Normal 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
|
7
kernel.h
7
kernel.h
@ -39,13 +39,6 @@ extern struct BootInfo bInfo;
|
||||
extern bool DebuggerIsAttached;
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MEM_TRK_MAX_SIZE 0x100
|
||||
extern bool EnableExternalMemoryTracer;
|
||||
extern char mExtTrkLog[];
|
||||
extern LockClass mExtTrkLock;
|
||||
#endif
|
||||
|
||||
extern Video::Display *Display;
|
||||
extern SymbolResolver::Symbols *KernelSymbolTable;
|
||||
extern Power::Power *PowerManager;
|
||||
|
Loading…
x
Reference in New Issue
Block a user