Curle
75f44b0514
This replaces the old way of appending the memory bitmap to the end of the kernel, which started causing problems with expansion.. I hardcoded the value to 0x1440, which is the start of the first FREE block of memory given to SeaBIOS in QEMU. This should be changed in the future..
260 lines
8.5 KiB
C
260 lines
8.5 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <kernel/system/interrupts.h>
|
|
#include <lainlib/lainlib.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 CONCAT(x, y) x ## y
|
|
#define CONCAT2(x, y) CONCAT(x, y)
|
|
#define ASSERT(exp, error) \
|
|
if(!(exp)) SomethingWentWrong(error);
|
|
// typedef char CONCAT2(static_assert, __LINE__) [(exp) ? 1 : -1]
|
|
|
|
#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 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
|
|
|
|
|
|
/*
|
|
* 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 0x00000000E0000000ull // Physical location of the Framebuffer
|
|
#define KERNEL_REGION 0xFFFFFFFFFFE00000ull // -2MiB, from bootloader
|
|
#define KERNEL_PHYSICAL 0x0000000000008000ull // Physical location of the kernel
|
|
#define KERNEL_PHYSICAL_2 0x000000000011C000ull // For some reason the kernel is split in half
|
|
|
|
#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 DIRECT_REGION 0xFFFF800000000000ull
|
|
|
|
#define LOWER_REGION 0x0000000100000000ull // Lower Memory cutoff - 4GB
|
|
|
|
#define PAGE_SHIFT 12
|
|
|
|
/*********************************************
|
|
* T Y P E D E F I N I T I O N S
|
|
**********************************************/
|
|
|
|
typedef void* directptr_t;
|
|
|
|
typedef struct {
|
|
ticketlock_t Lock;
|
|
|
|
directptr_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);
|
|
|
|
|
|
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);
|
|
|
|
|
|
/************************************************************
|
|
* 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;
|
|
|
|
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 FreePhysMem(directptr_t Phys);
|
|
|
|
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
|
|
**********************************************/
|
|
|
|
void SetAddressSpace(address_space_t* Space);
|
|
//TODO: Copy to/from Userspace
|
|
void MapVirtualMemory(address_space_t* Space, void* VirtualAddress, size_t PhysicalAddress, mapflags_t Flags);
|
|
void UnmapVirtualMemory(address_space_t* Space, void* VirtualAddress);
|
|
|
|
void CacheVirtualMemory(address_space_t* Space, void* VirtualAddress, pagecache_t CacheType);
|
|
|
|
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); |