From 0d77d97561ef3a1d755366b53b90d8f1dd627e81 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 8 Jan 2023 12:13:59 +0000 Subject: [PATCH] memblock can now self re-allocate its internal buffers memory allocated by memblock_alloc() can now be limited to a certain region. --- sandbox/base/include/socks/status.h | 9 ++++ sandbox/base/main.c | 10 +++++ sandbox/memblock/include/socks/memblock.h | 10 +++++ sandbox/memblock/memblock.c | 53 ++++++++++++++++++++++- sandbox/vm/{ => include/socks}/vm.h | 21 ++++----- sandbox/vm/vm_bootstrap.c | 34 +++++++++++++++ 6 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 sandbox/base/include/socks/status.h rename sandbox/vm/{ => include/socks}/vm.h (67%) create mode 100644 sandbox/vm/vm_bootstrap.c diff --git a/sandbox/base/include/socks/status.h b/sandbox/base/include/socks/status.h new file mode 100644 index 0000000..6783f49 --- /dev/null +++ b/sandbox/base/include/socks/status.h @@ -0,0 +1,9 @@ +#ifndef SOCKS_STATUS_H_ +#define SOCKS_STATUS_H_ + +typedef unsigned int kern_status_t; + +#define KERN_OK (0) +#define KERN_ERR_UNIMPLEMENTED (1) + +#endif diff --git a/sandbox/base/main.c b/sandbox/base/main.c index 973a6e2..955c6f9 100644 --- a/sandbox/base/main.c +++ b/sandbox/base/main.c @@ -2,11 +2,15 @@ #include #include #include +#include #include /* we're working with 4MiB of simulated system RAM */ #define MEMORY_SIZE_MB 128 +#define ALLOC_START_MB 16 +#define ALLOC_END_MB 18 + /* virtual address of where system memory is mapped */ static void *system_memory = NULL; @@ -33,6 +37,12 @@ int main(int argc, const char **argv) printf("allocated %u MiB (0x%zx bytes) of memory to act as system RAM at %p\n", MEMORY_SIZE_MB, MB_TO_BYTES(MEMORY_SIZE_MB), system_memory); + uintptr_t voffset = (uintptr_t)system_memory; + + memblock_init(MB_TO_BYTES(ALLOC_START_MB) + voffset, MB_TO_BYTES(ALLOC_END_MB) + voffset, voffset); + + printf("memblock heap initialised in 0x%zx-0x%zx\n", MB_TO_BYTES(ALLOC_START_MB), MB_TO_BYTES(ALLOC_END_MB)); + memblock_add(0, MB_TO_BYTES(MEMORY_SIZE_MB)); memblock_reserve(0x00000, 0x40000); diff --git a/sandbox/memblock/include/socks/memblock.h b/sandbox/memblock/include/socks/memblock.h index fe99107..dd18129 100644 --- a/sandbox/memblock/include/socks/memblock.h +++ b/sandbox/memblock/include/socks/memblock.h @@ -52,6 +52,14 @@ typedef struct memblock_type { } memblock_type_t; typedef struct memblock { + /* bounds of the memory region that can be used by memblock_alloc() + both of these are virtual addresses */ + uintptr_t m_alloc_start, m_alloc_end; + /* memblock assumes that all memory in the alloc zone is contiguously mapped + (if paging is enabled). m_voffset is the offset that needs to be added to + a given physical address to get the corresponding virtual address */ + uintptr_t m_voffset; + struct memblock_type memory; struct memblock_type reserved; } memblock_t; @@ -67,6 +75,8 @@ extern memblock_t memblock; extern int __next_mem_range(memblock_iter_t *it); +extern int memblock_init(uintptr_t alloc_start, uintptr_t alloc_end, uintptr_t voffset); + extern int memblock_add(phys_addr_t base, size_t size); extern int memblock_reserve(phys_addr_t base, size_t size); diff --git a/sandbox/memblock/memblock.c b/sandbox/memblock/memblock.c index 9d6c36b..d832333 100644 --- a/sandbox/memblock/memblock.c +++ b/sandbox/memblock/memblock.c @@ -1,3 +1,4 @@ +#include "socks/types.h" #include #include #include @@ -20,6 +21,8 @@ static memblock_region_t init_memory_regions[MEMBLOCK_INIT_MEMORY_REGION_COUNT]; static memblock_region_t init_reserved_regions[MEMBLOCK_INIT_RESERVED_REGION_COUNT]; +static phys_addr_t do_alloc(size_t size); + memblock_t memblock = { .memory.regions = init_memory_regions, .memory.count = 0, @@ -32,6 +35,19 @@ memblock_t memblock = { .reserved.name = "reserved", }; +static void memblock_double_capacity(memblock_type_t *type) +{ + size_t new_max = type->max * 2; + + phys_addr_t new_regions_p = do_alloc(new_max * sizeof(memblock_region_t)); + + void *new_regions = (void *)(new_regions_p + memblock.m_voffset); + memcpy(new_regions, type->regions, type->count * sizeof(memblock_region_t)); + + type->regions = new_regions; + type->max = new_max; +} + static int memblock_insert_region(memblock_type_t *type, memblock_region_t *to_add) { unsigned int i = 0; @@ -71,6 +87,15 @@ static int memblock_remove_region(memblock_type_t *type, unsigned int i) return 0; } +int memblock_init(uintptr_t alloc_start, uintptr_t alloc_end, uintptr_t voffset) +{ + memblock.m_alloc_start = alloc_start; + memblock.m_alloc_end =alloc_end; + memblock.m_voffset = voffset; + + return 0; +} + int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size, memblock_region_status_t status) { if (size == 0) { @@ -163,20 +188,35 @@ int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size, membl int memblock_add(uintptr_t base, size_t size) { + if (memblock.memory.count >= memblock.memory.max - 2) { + if (memblock.reserved.count >= memblock.reserved.max - 2) { + memblock_double_capacity(&memblock.reserved); + } + + memblock_double_capacity(&memblock.memory); + } + return memblock_add_range(&memblock.memory, base, size, MEMBLOCK_MEMORY); } int memblock_reserve(uintptr_t base, size_t size) { + if (memblock.reserved.count >= memblock.reserved.max - 2) { + memblock_double_capacity(&memblock.reserved); + } + return memblock_add_range(&memblock.reserved, base, size, MEMBLOCK_RESERVED); } -phys_addr_t memblock_alloc(size_t size) +static phys_addr_t do_alloc(size_t size) { phys_addr_t allocated_base = ADDR_MAX; + phys_addr_t region_start = memblock.m_alloc_start - memblock.m_voffset; + phys_addr_t region_end = memblock.m_alloc_end - memblock.m_voffset; + memblock_iter_t it; - for_each_free_mem_range (&it, 0x0, ADDR_MAX) { + for_each_free_mem_range (&it, region_start, region_end) { size_t region_size = it.it_limit - it.it_base + 1; if (region_size >= size) { allocated_base = it.it_base; @@ -196,6 +236,15 @@ phys_addr_t memblock_alloc(size_t size) return allocated_base; } +phys_addr_t memblock_alloc(size_t size) +{ + if (memblock.reserved.count >= memblock.reserved.max - 2) { + memblock_double_capacity(&memblock.reserved); + } + + return do_alloc(size); +} + int memblock_free(phys_addr_t addr, size_t size) { return 0; diff --git a/sandbox/vm/vm.h b/sandbox/vm/include/socks/vm.h similarity index 67% rename from sandbox/vm/vm.h rename to sandbox/vm/include/socks/vm.h index cfe9f6b..646e649 100644 --- a/sandbox/vm/vm.h +++ b/sandbox/vm/include/socks/vm.h @@ -1,19 +1,16 @@ #ifndef SOCKS_VM_H_ #define SOCKS_VM_H_ +#include #include +#include -/******************************************* - * Beginning of machine-specific definitions - *******************************************/ typedef enum vm_zone_id { - VM_ZONE_DMA = 0x01u, - VM_ZONE_NORMAL = 0x02u, - VM_ZONE_HIGHMEM = 0x03u, + VM_ZONE_DMA = 1u, + VM_ZONE_NORMAL = 2u, + VM_ZONE_HIGHMEM = 3u, + VM_ZONE_COUNT } vm_zone_id_t; -/******************************************* - * End of machine-specific definitions. - *******************************************/ typedef enum vm_memory_region_status { VM_REGION_FREE = 0x01u, @@ -30,6 +27,10 @@ typedef struct vm_zone { unsigned z_reserved[32]; } vm_zone_t; +typedef struct vm_pg_data { + vm_zone_t pg_zones[VM_ZONE_COUNT]; +} vm_pg_data_t; + typedef struct vm_region { vm_memory_region_status_t r_status; phys_addr_t r_base; @@ -44,7 +45,7 @@ typedef struct vm_page { uint32_t p_flags; /* vm_page_flags_t bitfield */ } __attribute__((packed)) vm_page_t; -extern void vm_bootstrap(void); +extern kern_status_t vm_bootstrap(const vm_region_t *mem_map, size_t nr_mem_map_entries); extern void vm_page_init(vm_page_t *pg); diff --git a/sandbox/vm/vm_bootstrap.c b/sandbox/vm/vm_bootstrap.c new file mode 100644 index 0000000..037ec9e --- /dev/null +++ b/sandbox/vm/vm_bootstrap.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +/* One vm_pg_data_t per NUMA node. Right now we're only worrying about a single node */ +static vm_pg_data_t node_data = {}; + +kern_status_t vm_bootstrap(const vm_region_t *mem_map, size_t nr_mem_map_entries) +{ + uintptr_t pmap_min = UINTPTR_MAX, pmap_max = 0x0; + + for (size_t i = 0; i < nr_mem_map_entries; i++) { + if (mem_map[i].r_base < pmap_min) { + pmap_min = mem_map[i].r_base; + } + + if (mem_map[i].r_limit > pmap_max) { + pmap_max = mem_map[i].r_limit; + } + } + + memblock_add(pmap_min, pmap_max); + + + for (size_t i = 0; i < nr_mem_map_entries; i++) { + if (mem_map[i].r_status == VM_REGION_RESERVED) { + memblock_reserve(mem_map[i].r_base, mem_map[i].r_limit); + } + } + + return KERN_OK; +}