From 02211e6eba3e230f71bc92885c96007a7b69e786 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 29 Dec 2022 20:53:39 +0000 Subject: [PATCH] Implemented memblock_alloc() --- sandbox/base/main.c | 20 +++--- sandbox/memblock/include/socks/memblock.h | 12 ++-- sandbox/memblock/memblock.c | 85 ++++++++++++++++++----- 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/sandbox/base/main.c b/sandbox/base/main.c index d02e50f..973a6e2 100644 --- a/sandbox/base/main.c +++ b/sandbox/base/main.c @@ -35,32 +35,36 @@ int main(int argc, const char **argv) memblock_add(0, MB_TO_BYTES(MEMORY_SIZE_MB)); - memblock_reserve(0x10000, 0x40000); + memblock_reserve(0x00000, 0x40000); memblock_reserve(0x60000, 0x20000); memblock_reserve(0x30000, 0x40000); memblock_reserve(0x100000, 0x10000); + phys_addr_t alloc = memblock_alloc(512); + printf("allocated 512 bytes at 0x%" PRIxPTR "\n", alloc); + printf("memory regions:\n"); memblock_iter_t it; for_each_mem_range(&it, 0, 0x100000) { printf("\t%08" PRIxPTR "-%08" PRIxPTR "\n", - it.base, - it.limit); + it.it_base, + it.it_limit); } printf("reserved regions:\n"); for_each_reserved_mem_range(&it, 0, 0x100000) { - printf("\t%08" PRIxPTR "-%08" PRIxPTR "\n", - it.base, - it.limit); + printf("\t%08" PRIxPTR "-%08" PRIxPTR " (%s)\n", + it.it_base, + it.it_limit, + it.it_status == MEMBLOCK_ALLOC ? "allocated" : "reserved"); } printf("free regions:\n"); for_each_free_mem_range(&it, 0, ULLONG_MAX) { printf("\t%08" PRIxPTR "-%08" PRIxPTR "\n", - it.base, - it.limit); + it.it_base, + it.it_limit); } munmap(system_memory, MB_TO_BYTES(MEMORY_SIZE_MB)); diff --git a/sandbox/memblock/include/socks/memblock.h b/sandbox/memblock/include/socks/memblock.h index d4c721b..fe99107 100644 --- a/sandbox/memblock/include/socks/memblock.h +++ b/sandbox/memblock/include/socks/memblock.h @@ -9,8 +9,8 @@ #define MEMBLOCK_INIT_RESERVED_REGION_COUNT 128 #define __for_each_mem_range(i, type_a, type_b, p_start, p_end) \ - for ((i)->idx = 0, __next_memory_region(i, type_a, type_b, p_start, p_end); \ - (i)->idx != ULLONG_MAX; \ + for ((i)->__idx = 0, __next_memory_region(i, type_a, type_b, p_start, p_end); \ + (i)->__idx != ULLONG_MAX; \ __next_memory_region(i, type_a, type_b, p_start, p_end)) #define for_each_mem_range(i, p_start, p_end) \ @@ -57,9 +57,10 @@ typedef struct memblock { } memblock_t; typedef struct memblock_iter { - memblock_index_t idx; - phys_addr_t base; - phys_addr_t limit; + memblock_index_t __idx; + phys_addr_t it_base; + phys_addr_t it_limit; + memblock_region_status_t it_status; } memblock_iter_t; extern memblock_t memblock; @@ -70,6 +71,7 @@ extern int memblock_add(phys_addr_t base, size_t size); extern int memblock_reserve(phys_addr_t base, size_t size); extern phys_addr_t memblock_alloc(size_t size); +extern int memblock_free(phys_addr_t addr, size_t size); extern void __next_memory_region(memblock_iter_t *it, \ memblock_type_t *type_a, memblock_type_t *type_b, diff --git a/sandbox/memblock/memblock.c b/sandbox/memblock/memblock.c index abb6968..9d6c36b 100644 --- a/sandbox/memblock/memblock.c +++ b/sandbox/memblock/memblock.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -70,7 +71,7 @@ static int memblock_remove_region(memblock_type_t *type, unsigned int i) return 0; } -int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size) +int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size, memblock_region_status_t status) { if (size == 0) { return 0; @@ -85,7 +86,24 @@ int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size) return 0; } - memblock_region_t new_region = { .base = base, .limit = limit }; + memblock_region_t new_region = { .base = base, .limit = limit, .status = status }; + + /* two regions with different statuses CANNOT intersect. we first need to check + * to make sure the region being added doesn't violate this rule. */ + for (unsigned int i = 0; i < type->count; i++) { + memblock_region_t *cur_region = &type->regions[i]; + + if (new_region.base > cur_region->limit || new_region.limit < cur_region->base) { + continue; + } + + if (cur_region->status == new_region.status) { + continue; + } + + return -1; + } + bool add_new = true; for (unsigned int i = 0; i < type->count; i++) { @@ -119,11 +137,12 @@ int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size) /* there can be an overlap at the beginning and the end of the region being added, * anything else is either a full overlap (case 3) or not within the region being added at all. - * to handle this, remove the region that's already in the list and extend the region being added to cover it */ - if (new_region.base > cur_region->base || new_region.base == cur_region->limit - 1) { + * to handle this, remove the region that's already in the list and extend the region being added to cover it. + * the two regions may overlap and have incompatible statuses, but this case was handled earlier in this function. */ + if ((new_region.base > cur_region->base || new_region.base == cur_region->limit - 1) && new_region.status == cur_region->status) { /* the new region overlaps the END of the current region, change the base of the new region to match that of the current region. */ new_region.base = cur_region->base; - } else if (new_region.base < cur_region->base || new_region.limit + 1 == cur_region->base){ + } else if ((new_region.base < cur_region->base || new_region.limit + 1 == cur_region->base) && new_region.status == cur_region->status) { /* the new region overlaps the BEGINNING of the current region, change the limit of the new region to match that of the current region. */ new_region.limit = cur_region->limit; } else { @@ -144,31 +163,57 @@ int memblock_add_range(memblock_type_t *type, uintptr_t base, size_t size) int memblock_add(uintptr_t base, size_t size) { - return memblock_add_range(&memblock.memory, base, size); + return memblock_add_range(&memblock.memory, base, size, MEMBLOCK_MEMORY); } int memblock_reserve(uintptr_t base, size_t size) { - return memblock_add_range(&memblock.reserved, base, size); + return memblock_add_range(&memblock.reserved, base, size, MEMBLOCK_RESERVED); } -uintptr_t memblock_alloc(size_t size) +phys_addr_t memblock_alloc(size_t size) +{ + phys_addr_t allocated_base = ADDR_MAX; + + memblock_iter_t it; + for_each_free_mem_range (&it, 0x0, ADDR_MAX) { + size_t region_size = it.it_limit - it.it_base + 1; + if (region_size >= size) { + allocated_base = it.it_base; + break; + } + } + + if (allocated_base == ADDR_MAX) { + return 0; + } + + int status = memblock_add_range(&memblock.reserved, allocated_base, size, MEMBLOCK_ALLOC); + if (status != 0) { + return 0; + } + + return allocated_base; +} + +int memblock_free(phys_addr_t addr, size_t size) { return 0; } void __next_memory_region(memblock_iter_t *it, memblock_type_t *type_a, memblock_type_t *type_b, uintptr_t start, uintptr_t end) { - unsigned int idx_a = IDX_A(it->idx); - unsigned int idx_b = IDX_B(it->idx); + unsigned int idx_a = IDX_A(it->__idx); + unsigned int idx_b = IDX_B(it->__idx); for (; idx_a < type_a->count; idx_a++) { memblock_region_t *m = &type_a->regions[idx_a]; if (!type_b) { - it->base = m->base; - it->limit = m->limit; + it->it_base = m->base; + it->it_limit = m->limit; + it->it_status = m->status; - it->idx = ITER(idx_a + 1, idx_b); + it->__idx = ITER(idx_a + 1, idx_b); return; } @@ -213,13 +258,15 @@ void __next_memory_region(memblock_iter_t *it, memblock_type_t *type_a, memblock * region M (m_start - m_end) : The region defined as system memory. * region R (r_start - r_end) : The region defined as free / outside of any reserved regions. */ - it->base = MAX(m_start, r_start); - it->limit = MIN(m_end, r_end); + it->it_base = MAX(m_start, r_start); + it->it_limit = MIN(m_end, r_end); /* further limit the region to the intersection between the region itself and the * specified iteration bounds */ - it->base = MAX(it->base, start); - it->limit = MIN(it->limit, end); + it->it_base = MAX(it->it_base, start); + it->it_limit = MIN(it->it_limit, end); + + it->it_status = MEMBLOCK_MEMORY; /* whichever region is smaller, increment the pointer for that type, so we can * compare the larger region with the next region of the incremented type. */ @@ -230,11 +277,11 @@ void __next_memory_region(memblock_iter_t *it, memblock_type_t *type_a, memblock } /* store the position for the next iteration */ - it->idx = ITER(idx_a, idx_b); + it->__idx = ITER(idx_a, idx_b); return; } } /* ULLONG_MAX signals the end of the iteration */ - it->idx = ITER_END; + it->__idx = ITER_END; }