memblock can now self re-allocate its internal buffers

memory allocated by memblock_alloc() can now be limited to a certain region.
This commit is contained in:
2023-01-08 12:13:59 +00:00
parent 02211e6eba
commit 0d77d97561
6 changed files with 125 additions and 12 deletions

View File

@@ -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

View File

@@ -2,11 +2,15 @@
#include <stddef.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <socks/types.h>
#include <socks/memblock.h>
/* 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);

View File

@@ -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);

View File

@@ -1,3 +1,4 @@
#include "socks/types.h"
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
@@ -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;

View File

@@ -1,19 +1,16 @@
#ifndef SOCKS_VM_H_
#define SOCKS_VM_H_
#include <stddef.h>
#include <socks/types.h>
#include <socks/status.h>
/*******************************************
* 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);

34
sandbox/vm/vm_bootstrap.c Normal file
View File

@@ -0,0 +1,34 @@
#include <limits.h>
#include <socks/vm.h>
#include <socks/memblock.h>
#include <stddef.h>
#include <limits.h>
/* 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;
}