320 lines
10 KiB
C
320 lines
10 KiB
C
#pragma once
|
|
|
|
#include <lainlib/lainlib.h>
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <kernel/system/interrupts.h>
|
|
|
|
/************************
|
|
*** Team Kitty, 2020 ***
|
|
*** Chroma ***
|
|
***********************/
|
|
|
|
|
|
/************************************************
|
|
* C O N S T A N T S A N D M A C R O S
|
|
*************************************************/
|
|
|
|
#define PAGE_SIZE 4096
|
|
#define PAGES_PER_BUCKET 8
|
|
|
|
#define OFFSET_BIT(i) Memory[i / PAGES_PER_BUCKET]
|
|
#define SET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) | (1 << (i % PAGES_PER_BUCKET))
|
|
#define UNSET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) & (~(1 << (i % PAGES_PER_BUCKET)))
|
|
#define READ_BIT(i) ((OFFSET_BIT(i) >> (i % PAGES_PER_BUCKET)) & 0x1)
|
|
#define GET_BUCKET32(i) (*((uint32_t*) (&Memory[i / 32])))
|
|
|
|
#define CAST(a, b) ((a) (b))
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
#define REINTERPRET_CAST(target, intermediate, value) ((target*)((intermediate*)value))
|
|
|
|
#define FIXENDIAN64(x) __builtin_bswap64(x)
|
|
#define FIXENDIAN32(x) __builtin_bswap32(x)
|
|
#define FIXENDIAN16(x) __builtin_bswap16(x)
|
|
|
|
|
|
#define CONCAT(x, y) x ## y
|
|
#define CONCAT2(x, y) CONCAT(x, y)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#define ASSERT(exp, error) \
|
|
if(!(exp)) SomethingWentWrong(error);
|
|
// typedef char CONCAT2(static_assert, __LINE__) [(exp) ? 1 : -1]
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#define CLZ(num) (num ? __builtin_clzll(num) : 64)
|
|
|
|
#define IS_ALIGNED(addr) (((size_t) addr | 0xFFFFFFFFFFFFF000) == 0)
|
|
#define PAGE_ALIGN(addr) ((((size_t) addr) & 0xFFFFFFFFFFFFF000) + 0x1000)
|
|
#define PAGE_ALIGN_DOWN(addr) ((((size_t) addr) & 0xFFFFFFFFFFFFF000) - 0x1000)
|
|
|
|
#define SET_PGBIT(cr0) (cr0 = cr0 | 1 << 31)
|
|
#define UNSET_PGBIT(cr0) (cr0 = cr0 ^ 1 << 31)
|
|
#define UNSET_PSEBIT(cr4) (cr4 = cr4 & 0xFFFFFFEF)
|
|
|
|
#define TOGGLE_PGEBIT(cr4) (cr4 = cr4 ^ (1 << 7))
|
|
#define SET_PAEBIT(cr4) (cr4 = cr4 | 1 << 5)
|
|
|
|
#define ERR_PRESENT 0x1
|
|
#define ERR_RW 0x2
|
|
#define ERR_USER 0x4
|
|
#define ERR_RESERVED 0x8
|
|
#define ERR_INST 0x10
|
|
|
|
#define ELF64MAGIC 0x7F454c46
|
|
#define ELF64MAGICBE 0x464c457F
|
|
|
|
|
|
/*
|
|
* The way we boot, using BOOTBOOT, and the static hard drive images, means
|
|
* we're limited to Protocol 1 - we cannot ask the bootloader to move anything
|
|
* around for us.
|
|
*
|
|
* That means we need to account for these unmovable sections in the paging system.
|
|
*
|
|
* MMIO_REGION
|
|
* Represents the MMIO symbol defined in the linkerscript and chroma.h.
|
|
* FB_REGION
|
|
* Represents the framebuffer used throughout the kernel.
|
|
* This is likely the most important thing to keep where it is. Without this, we
|
|
* have no video output.
|
|
* KERNEL_REGION
|
|
* This is where the kernel itself is loaded into memory. Protocol 1 means
|
|
* we're loaded into the -2MB area.
|
|
* We *CAN* mvoe the kernel about in memory. It's as simple as memcpying it around
|
|
* and calling a void pointer as a function to return to where we were.
|
|
* We *CANNOT* move the framebuffer in this manner, as it is set directly by BIOS,
|
|
* and the graphics device most likely will not allow this to happen.
|
|
* For this reason, the kernel, framebuffer and MMIO will remain where they are.
|
|
* Luckily, there are more components of Chroma than the kernel itself. That's what
|
|
* the kernel heap and kernel stack areas are for.
|
|
*
|
|
* USER_REGION
|
|
* This is the dedicated space 0...7FFFFFFFFFFF for userspace.
|
|
* No kernel objects or data will be put into this space.
|
|
* Protocol 1 puts the page tables at 0xA000 by default, so these will have to be moved
|
|
* up to kernel space.
|
|
*
|
|
* KERNEL_STACK_REGION
|
|
* KERNEL_STACK_END
|
|
* Encapsulate a 1GB large area of memory, to be used by the kernel for thread & interrupt stacks,
|
|
* call unwinding and other debug information.
|
|
*
|
|
* KERNEL_HEAP_REGION
|
|
* KERNEL_HEAP_END
|
|
* Encapsulate another 1GB large area for kernel objects. ie. resources (images, sounds), libraries,
|
|
* data structures, assorted information about the system.. etc.
|
|
*
|
|
* DIRECT_REGION
|
|
* As mentioned above, the lower half is reserved for user space.
|
|
* The higher half will be direct-mapped throughout.
|
|
* This is the cutoff for the higher half - FFFF800000000000.
|
|
*
|
|
*/
|
|
|
|
#define MMIO_REGION 0xFFFFFFFFF8000000ull // Cannot move!
|
|
#define FB_REGION 0xFFFFFFFFFC000000ull // Cannot move!
|
|
#define FB_PHYSICAL (size_t) bootldr.fb_ptr // 0x00000000FD000000ull - Physical location of the Framebuffer
|
|
#define KERNEL_REGION 0xFFFFFFFFFFE00000ull // -2MiB, from bootloader
|
|
#define KERNEL_TEXT 0x0000000000002000ull // Offset of symbols from the kernel text
|
|
|
|
#define KERNEL_PHYSICAL KernelLocation // The located kernel from the bootstrap process
|
|
#define KERNEL_END KernelLocation + (KernelEnd - KernelAddr)
|
|
#define KERNEL_OFFSET 0x0000000000039000ull // KERNEL_PHYSICAL -> KERNEL_PHYSICAL + KERNEL_OFFSET + KERNEL_REGION
|
|
|
|
#define CODE_STACK_PHYSICAL 0x0000000000006C00ull // The base of the stack running the C code we enter with
|
|
#define CODE_STACK_END 0x0000000000007C00ull
|
|
#define CORE_STACK_PHYSICAL 0x0000000000014000ull // The first CPU core's stack
|
|
#define CORE_STACK_END 0x0000000000015000ull
|
|
#define STACK_TOP 0xFFFFFFFFFFFFF000ull // The start of the highest stack
|
|
#define MEM_CEILING 0xFFFFFFFFFFFFFFFFull // The top of the stack in the map
|
|
|
|
#define CORE_BOOTSTRAP 0x0000000000001000ull // The physical location of the core bootstrapping function.
|
|
|
|
#define USER_REGION 0x00007FFFFFFFFFFFull // Not needed yet, but we're higher half so we might as well be thorough
|
|
|
|
#define KERNEL_STACK_REGION 0xFFFFE00000000000ull // Kernel Stack Space
|
|
#define KERNEL_STACK_END 0xFFFFE00040000000ull // End of Kernel Stack Space
|
|
|
|
#define KERNEL_HEAP_REGION 0xFFFFE00080000000ull // Kernel Object Space (kmalloc will allocate into this region)
|
|
#define KERNEL_HEAP_END 0xFFFFE000C0000000ull // End of Kernel Object Space
|
|
|
|
#define APIC_REGION 0x00000000FEE00000ull // Physical location of the APIC MMIO region.
|
|
|
|
#define DIRECT_REGION 0xFFFF800000000000ull
|
|
|
|
#define LOWER_REGION 0x0000000100000000ull // Lower Memory cutoff - 4GB
|
|
|
|
#define PAGE_SHIFT 12
|
|
|
|
#define TO_DIRECT(addr) ((size_t)(addr) + DIRECT_REGION)
|
|
#define FROM_DIRECT(addr) ((size_t)(addr) - DIRECT_REGION)
|
|
|
|
#define PREFIX(func) k ## func
|
|
|
|
/*********************************************
|
|
* T Y P E D E F I N I T I O N S
|
|
**********************************************/
|
|
|
|
typedef void* directptr_t;
|
|
|
|
typedef struct {
|
|
ticketlock_t Lock;
|
|
|
|
size_t* PML4;
|
|
} address_space_t;
|
|
|
|
typedef enum {
|
|
MAP_WRITE = 0x1,
|
|
MAP_EXEC = 0x2,
|
|
} mapflags_t;
|
|
|
|
typedef enum {
|
|
CACHE_NONE,
|
|
CACHE_WRITE_THROUGH,
|
|
CACHE_WRITE_BACK,
|
|
CACHE_WRITE_COMBINING
|
|
} pagecache_t;
|
|
|
|
typedef struct {
|
|
int MaxOrder;
|
|
|
|
directptr_t Base;
|
|
|
|
directptr_t* List;
|
|
|
|
ticketlock_t Lock;
|
|
} buddy_t;
|
|
|
|
/*********************************************
|
|
* A b s t r a c t A l l o c a t o r
|
|
**********************************************/
|
|
|
|
const char* IntToAscii(int In);
|
|
|
|
typedef void* allocator_t;
|
|
typedef void* mempool_t;
|
|
|
|
allocator_t CreateAllocator(void* Memory);
|
|
allocator_t CreateAllocatorWithPool(void* Memory, size_t Bytes);
|
|
|
|
void DestroyAllocator(allocator_t Allocator);
|
|
|
|
mempool_t GetPoolFromAllocator(allocator_t Allocator);
|
|
|
|
mempool_t AddPoolToAllocator(allocator_t Allocator, void* Memory, size_t Bytes);
|
|
void RemovePoolFromAllocator(allocator_t Allocator, mempool_t pool);
|
|
|
|
void* AllocatorMalloc (allocator_t Allocator, size_t Bytes);
|
|
void* AllocatorMalign (allocator_t Allocator, size_t Alignment, size_t Bytes);
|
|
void* AllocatorRealloc(allocator_t Allocator, void* VirtualAddress, size_t NewSize);
|
|
void AllocatorFree (allocator_t Allocator, void* VirtualAddress);
|
|
|
|
size_t AllocatorGetBlockSize(void* VirtualAddress);
|
|
|
|
size_t AllocatorSize(void);
|
|
size_t AllocatorAlignSize(void);
|
|
size_t AllocatorMinBlockSize(void);
|
|
size_t AllocatorMaxBlockSize(void);
|
|
|
|
size_t AllocatorPoolOverhead(void);
|
|
size_t AllocatorAllocateOverhead(void);
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
size_t AlignUpwards(size_t Pointer, size_t Alignment);
|
|
size_t AlignDownwards(size_t Pointer, size_t Alignment);
|
|
void* AlignPointer(const void* Pointer, size_t Alignment);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
/************************************************************
|
|
* C h r o m a M e m o r y M a n a g e m e n t
|
|
*************************************************************/
|
|
|
|
extern size_t memstart;
|
|
|
|
extern size_t end;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
void ListMemoryMap();
|
|
|
|
void InitMemoryManager();
|
|
|
|
void AddRangeToPhysMem(directptr_t Base, size_t Size);
|
|
|
|
directptr_t PhysAllocateLowMem(size_t Size);
|
|
|
|
directptr_t PhysAllocateMem(size_t Size);
|
|
|
|
directptr_t PhysAllocateZeroMem(size_t Size);
|
|
|
|
directptr_t PhysAllocateLowZeroMem(size_t Size);
|
|
|
|
directptr_t PhysAllocatePage();
|
|
|
|
void PhysRefPage(directptr_t Page);
|
|
|
|
void PhysFreePage(directptr_t Page);
|
|
|
|
void PhysFreeMem(directptr_t Phys, size_t count);
|
|
|
|
size_t SeekFrame();
|
|
|
|
void MemoryTest();
|
|
|
|
void InitPaging();
|
|
|
|
void TraversePageTables();
|
|
|
|
void* memcpy(void* dest, void const* src, size_t len);
|
|
|
|
|
|
|
|
/*********************************************
|
|
* C h r o m a A l l o c a t o r
|
|
**********************************************/
|
|
|
|
//TODO: Copy to/from Userspace
|
|
void MapVirtualPage(address_space_t* AddressSpace, size_t Physical, size_t Virtual, size_t PageFlags);
|
|
void MapVirtualPageNoDirect(address_space_t* AddressSpace, size_t Physical, size_t Virtual, size_t PageFlags);
|
|
|
|
size_t DecodeVirtualAddress(address_space_t* AddressSpace, size_t VirtualAddress);
|
|
size_t DecodeVirtualAddressNoDirect(address_space_t* AddressSpace, size_t VirtualAddress);
|
|
|
|
size_t* CreateNewPageTable(address_space_t* AddressSpace);
|
|
|
|
void* AllocateMemory(size_t Bits);
|
|
|
|
void* ReallocateMemory(void* VirtualAddress, size_t NewSize);
|
|
|
|
void FreeMemory(void* VirtualAddress);
|
|
|
|
void* AllocateKernelStack();
|
|
|
|
void FreeKernelStack(void* StackAddress);
|
|
|
|
void PageFaultHandler(INTERRUPT_FRAME Frame);
|
|
|
|
extern void *PREFIX(malloc)(size_t); ///< The standard function.
|
|
extern void *PREFIX(realloc)(void *, size_t); ///< The standard function.
|
|
extern void *PREFIX(calloc)(size_t, size_t); ///< The standard function.
|
|
extern void PREFIX(free)(void *); ///< The standard function.
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif |