From 2147837e9e3f610cdf8c3bf887a58bb164569032 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 1 Feb 2023 12:26:49 +0000 Subject: [PATCH] sandbox: vm: encode vm_page zone id within p_flags --- sandbox/base/memory_test.c | 24 +++++++++++++--------- sandbox/vm/bootstrap.c | 2 +- sandbox/vm/include/socks/vm.h | 38 +++++++++++++++++++++++++---------- sandbox/vm/page.c | 14 +++++++++++++ sandbox/vm/zone.c | 7 +++++-- 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/sandbox/base/memory_test.c b/sandbox/base/memory_test.c index b5a3fa4..3b7c111 100644 --- a/sandbox/base/memory_test.c +++ b/sandbox/base/memory_test.c @@ -1,3 +1,4 @@ +#include "socks/queue.h" #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include @@ -42,16 +44,19 @@ static struct mem_map_region mem_map[] = { /* virtual address of where system memory is mapped */ static void *system_memory = NULL; -static void print_zone_pages(vm_zone_t *z) +static void print_free_pages(vm_zone_t *z) { + printf(" * %s:\n", z->z_info.zd_name); + for (int i = VM_PAGE_MIN_ORDER; i <= VM_PAGE_MAX_ORDER; i++) { - queue_foreach (vm_page_t, pg, &z->z_free_pages[i], p_free_list) { - printf(" * %08zx (%s, order %u, 0x%zx bytes)\n", - vm_page_get_paddr(pg), - z->z_info.zd_name, - pg->p_order, - vm_page_order_to_bytes(pg->p_order)); + if (queue_length(&z->z_free_pages[i]) == 0) { + continue; } + + char size_str[64]; + data_size_to_string(vm_page_order_to_bytes(i), size_str, sizeof size_str); + + printf(" - %u pages with size %s (order-%u)\n", queue_length(&z->z_free_pages[i]), size_str, i); } } @@ -63,9 +68,10 @@ static void print_all_pages(void) break; } + vm_zone_t *z = vm_page_get_zone(pg); printf(" * %08" PRIxPTR ": %s order-%u (%zu bytes) %s\n", i, - pg->p_zone ? pg->p_zone->z_info.zd_name : "[none]", + z ? z->z_info.zd_name : "[none]", pg->p_order, vm_page_order_to_bytes(pg->p_order), pg->p_flags & VM_PAGE_RESERVED ? "reserved" : "free"); @@ -162,7 +168,7 @@ int memory_test(void) vm_pg_data_t *pg_data = vm_pg_data_get(0); printf("free pages:\n"); for (int i = VM_ZONE_MIN; i <= VM_ZONE_MAX; i++) { - print_zone_pages(&pg_data->pg_zones[i]); + print_free_pages(&pg_data->pg_zones[i]); } printf("all pages:\n"); diff --git a/sandbox/vm/bootstrap.c b/sandbox/vm/bootstrap.c index c9c133d..4dcf9a8 100644 --- a/sandbox/vm/bootstrap.c +++ b/sandbox/vm/bootstrap.c @@ -26,7 +26,7 @@ kern_status_t vm_bootstrap(const vm_zone_descriptor_t *zones, size_t nr_zones) return KERN_OK; } -vm_pg_data_t *vm_pg_data_get(int node) +vm_pg_data_t *vm_pg_data_get(vm_node_id_t node) { if (node == 0) { return node_data; diff --git a/sandbox/vm/include/socks/vm.h b/sandbox/vm/include/socks/vm.h index bd694a0..a6c399a 100644 --- a/sandbox/vm/include/socks/vm.h +++ b/sandbox/vm/include/socks/vm.h @@ -6,17 +6,31 @@ #include #include +/* maximum number of NUMA nodes */ +#define VM_MAX_NODES 64 +/* maximum number of memory zones per node */ +#define VM_MAX_ZONES (VM_ZONE_MAX + 1) +/* maximum number of supported page orders */ +#define VM_MAX_PAGE_ORDERS (VM_PAGE_MAX_ORDER + 1) + #define VM_CHECK_ALIGN(p, mask) ((((p) & (mask)) == (p)) ? 1 : 0) #define VM_PAGE_SIZE 0x1000 #define VM_PAGE_SHIFT 12 typedef phys_addr_t vm_alignment_t; +typedef unsigned int vm_node_id_t; typedef struct vm_object { unsigned int reserved; } vm_object_t; +typedef enum vm_flags { + VM_GET_DMA = 0x01u, +} vm_flags_t; + typedef enum vm_zone_id { + /* NOTE that these are used as indices into the node_zones array in vm/zone.c + they need to be continuous, and must start at 0! */ VM_ZONE_DMA = 0u, VM_ZONE_NORMAL = 1u, VM_ZONE_HIGHMEM = 2u, @@ -55,7 +69,7 @@ typedef enum vm_memory_region_status { typedef struct vm_zone_descriptor { vm_zone_id_t zd_id; - unsigned int zd_node; + vm_node_id_t zd_node; const char zd_name[32]; phys_addr_t zd_base; phys_addr_t zd_limit; @@ -64,12 +78,12 @@ typedef struct vm_zone_descriptor { typedef struct vm_zone { vm_zone_descriptor_t z_info; - queue_t z_free_pages[VM_PAGE_MAX_ORDER + 1]; + queue_t z_free_pages[VM_MAX_PAGE_ORDERS]; unsigned long z_size; } vm_zone_t; typedef struct vm_pg_data { - vm_zone_t pg_zones[VM_ZONE_MAX + 1]; + vm_zone_t pg_zones[VM_MAX_ZONES]; } vm_pg_data_t; typedef struct vm_region { @@ -89,24 +103,23 @@ typedef enum vm_page_flags { } vm_page_flags_t; typedef struct vm_page { - /* vm_page_flags_t bitfields. - the 2 most significant bits of this field encode the ID of the vm_zone that - the page belongs to */ - uint32_t p_flags; + /* the id of the NUMA node that this page belongs to */ + uint32_t p_node : 6; + /* the id of the memory zone that this page belongs to */ + uint32_t p_zone : 2; + /* vm_page_flags_t bitfields. */ + uint32_t p_flags : 24; /* buddy allocator free page list head (vm_zone_t->z_free_pages[p_order]) */ queue_entry_t p_free_list; - /* temporary */ - vm_zone_t *p_zone; - /* order of the page block that this page belongs too */ unsigned char p_order; } __attribute__((aligned(2 * sizeof(unsigned long)))) vm_page_t; extern kern_status_t vm_bootstrap(const vm_zone_descriptor_t *zones, size_t nr_zones); -extern vm_pg_data_t *vm_pg_data_get(int node); +extern vm_pg_data_t *vm_pg_data_get(vm_node_id_t node); extern void vm_page_init_array(); extern vm_page_t *vm_page_get(phys_addr_t addr); @@ -117,9 +130,12 @@ extern size_t vm_page_get_pfn(vm_page_t *pg); extern size_t vm_page_order_to_bytes(vm_page_order_t order); extern size_t vm_page_order_to_pages(vm_page_order_t order); extern vm_alignment_t vm_page_order_to_alignment(vm_page_order_t order); +extern vm_page_t *vm_page_alloc(vm_page_order_t order, vm_flags_t flags); +extern void vm_page_free(vm_page_t *pg); extern size_t vm_bytes_to_pages(size_t bytes); extern void vm_zone_init(vm_zone_t *z, const vm_zone_descriptor_t *zone_info); +extern vm_page_t *vm_zone_alloc_page(vm_zone_t *z, vm_page_order_t order, vm_flags_t flags); #endif diff --git a/sandbox/vm/page.c b/sandbox/vm/page.c index 0ff38d9..46a798b 100644 --- a/sandbox/vm/page.c +++ b/sandbox/vm/page.c @@ -131,3 +131,17 @@ size_t vm_bytes_to_pages(size_t bytes) bytes >>= VM_PAGE_SHIFT; return bytes; } + +vm_zone_t *vm_page_get_zone(vm_page_t *pg) +{ + vm_pg_data_t *node = vm_pg_data_get(pg->p_node); + if (!node) { + return 0; + } + + if (pg->p_zone >= VM_MAX_ZONES) { + return NULL; + } + + return &node->pg_zones[pg->p_zone]; +} diff --git a/sandbox/vm/zone.c b/sandbox/vm/zone.c index 82c369b..f5fa3d0 100644 --- a/sandbox/vm/zone.c +++ b/sandbox/vm/zone.c @@ -23,13 +23,16 @@ static vm_page_t *group_pages_into_block(vm_zone_t *z, phys_addr_t base, phys_ad } pg->p_order = order; - pg->p_zone = z; + pg->p_node = z->z_info.zd_node; + pg->p_zone = z->z_info.zd_id; } return first_page; } -static void convert_region_to_blocks(vm_zone_t *zone, phys_addr_t base, phys_addr_t limit, int reserved) +static void convert_region_to_blocks(vm_zone_t *zone, + phys_addr_t base, phys_addr_t limit, + int reserved) { size_t block_frames = vm_bytes_to_pages(limit - base + 1); printf("adding region %08zx-%08zx (%zu frames) to zone %s\n",