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:
9
sandbox/base/include/socks/status.h
Normal file
9
sandbox/base/include/socks/status.h
Normal 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
|
||||||
@@ -2,11 +2,15 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <socks/types.h>
|
||||||
#include <socks/memblock.h>
|
#include <socks/memblock.h>
|
||||||
|
|
||||||
/* we're working with 4MiB of simulated system RAM */
|
/* we're working with 4MiB of simulated system RAM */
|
||||||
#define MEMORY_SIZE_MB 128
|
#define MEMORY_SIZE_MB 128
|
||||||
|
|
||||||
|
#define ALLOC_START_MB 16
|
||||||
|
#define ALLOC_END_MB 18
|
||||||
|
|
||||||
/* virtual address of where system memory is mapped */
|
/* virtual address of where system memory is mapped */
|
||||||
static void *system_memory = NULL;
|
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);
|
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_add(0, MB_TO_BYTES(MEMORY_SIZE_MB));
|
||||||
|
|
||||||
memblock_reserve(0x00000, 0x40000);
|
memblock_reserve(0x00000, 0x40000);
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ typedef struct memblock_type {
|
|||||||
} memblock_type_t;
|
} memblock_type_t;
|
||||||
|
|
||||||
typedef struct memblock {
|
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 memory;
|
||||||
struct memblock_type reserved;
|
struct memblock_type reserved;
|
||||||
} memblock_t;
|
} memblock_t;
|
||||||
@@ -67,6 +75,8 @@ extern memblock_t memblock;
|
|||||||
|
|
||||||
extern int __next_mem_range(memblock_iter_t *it);
|
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_add(phys_addr_t base, size_t size);
|
||||||
extern int memblock_reserve(phys_addr_t base, size_t size);
|
extern int memblock_reserve(phys_addr_t base, size_t size);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "socks/types.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <limits.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_memory_regions[MEMBLOCK_INIT_MEMORY_REGION_COUNT];
|
||||||
static memblock_region_t init_reserved_regions[MEMBLOCK_INIT_RESERVED_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 = {
|
memblock_t memblock = {
|
||||||
.memory.regions = init_memory_regions,
|
.memory.regions = init_memory_regions,
|
||||||
.memory.count = 0,
|
.memory.count = 0,
|
||||||
@@ -32,6 +35,19 @@ memblock_t memblock = {
|
|||||||
.reserved.name = "reserved",
|
.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)
|
static int memblock_insert_region(memblock_type_t *type, memblock_region_t *to_add)
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
@@ -71,6 +87,15 @@ static int memblock_remove_region(memblock_type_t *type, unsigned int i)
|
|||||||
return 0;
|
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)
|
int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size, memblock_region_status_t status)
|
||||||
{
|
{
|
||||||
if (size == 0) {
|
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)
|
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);
|
return memblock_add_range(&memblock.memory, base, size, MEMBLOCK_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
int memblock_reserve(uintptr_t base, size_t size)
|
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);
|
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 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;
|
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;
|
size_t region_size = it.it_limit - it.it_base + 1;
|
||||||
if (region_size >= size) {
|
if (region_size >= size) {
|
||||||
allocated_base = it.it_base;
|
allocated_base = it.it_base;
|
||||||
@@ -196,6 +236,15 @@ phys_addr_t memblock_alloc(size_t size)
|
|||||||
return allocated_base;
|
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)
|
int memblock_free(phys_addr_t addr, size_t size)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
#ifndef SOCKS_VM_H_
|
#ifndef SOCKS_VM_H_
|
||||||
#define SOCKS_VM_H_
|
#define SOCKS_VM_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <socks/types.h>
|
#include <socks/types.h>
|
||||||
|
#include <socks/status.h>
|
||||||
|
|
||||||
/*******************************************
|
|
||||||
* Beginning of machine-specific definitions
|
|
||||||
*******************************************/
|
|
||||||
typedef enum vm_zone_id {
|
typedef enum vm_zone_id {
|
||||||
VM_ZONE_DMA = 0x01u,
|
VM_ZONE_DMA = 1u,
|
||||||
VM_ZONE_NORMAL = 0x02u,
|
VM_ZONE_NORMAL = 2u,
|
||||||
VM_ZONE_HIGHMEM = 0x03u,
|
VM_ZONE_HIGHMEM = 3u,
|
||||||
|
VM_ZONE_COUNT
|
||||||
} vm_zone_id_t;
|
} vm_zone_id_t;
|
||||||
/*******************************************
|
|
||||||
* End of machine-specific definitions.
|
|
||||||
*******************************************/
|
|
||||||
|
|
||||||
typedef enum vm_memory_region_status {
|
typedef enum vm_memory_region_status {
|
||||||
VM_REGION_FREE = 0x01u,
|
VM_REGION_FREE = 0x01u,
|
||||||
@@ -30,6 +27,10 @@ typedef struct vm_zone {
|
|||||||
unsigned z_reserved[32];
|
unsigned z_reserved[32];
|
||||||
} vm_zone_t;
|
} vm_zone_t;
|
||||||
|
|
||||||
|
typedef struct vm_pg_data {
|
||||||
|
vm_zone_t pg_zones[VM_ZONE_COUNT];
|
||||||
|
} vm_pg_data_t;
|
||||||
|
|
||||||
typedef struct vm_region {
|
typedef struct vm_region {
|
||||||
vm_memory_region_status_t r_status;
|
vm_memory_region_status_t r_status;
|
||||||
phys_addr_t r_base;
|
phys_addr_t r_base;
|
||||||
@@ -44,7 +45,7 @@ typedef struct vm_page {
|
|||||||
uint32_t p_flags; /* vm_page_flags_t bitfield */
|
uint32_t p_flags; /* vm_page_flags_t bitfield */
|
||||||
} __attribute__((packed)) vm_page_t;
|
} __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);
|
extern void vm_page_init(vm_page_t *pg);
|
||||||
|
|
||||||
34
sandbox/vm/vm_bootstrap.c
Normal file
34
sandbox/vm/vm_bootstrap.c
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user