Files
zinnia/core/mem/stack.c
T
2026-10-05 23:55:10 +02:00

61 lines
1.5 KiB
C

#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/pmap.h>
#include <zinnia/stack.h>
#include <zinnia/utils.h>
#include <zinnia/virt.h>
#include <zinnia/vma.h>
#include <arch/mem.h>
errno_t stack_init(struct stack* ks, size_t size) {
if (!ks || size == 0)
return EINVAL;
const size_t page_size = arch_mem_page_size();
size = ALIGN_UP(size, page_size);
uintptr_t va = vm_alloc(size + page_size);
if (!va)
return ENOMEM;
phys_t phys;
errno_t status = mem_phys_alloc(size / page_size, 0, &phys);
if (status)
goto err_vm;
const uintptr_t base = va + page_size;
size_t mapped = 0;
for (; mapped < size; mapped += page_size) {
status = pmap_map(&kernel_vma.pmap, base + mapped, phys + mapped, PTE_READ | PTE_WRITE, CACHE_WRITE_BACK);
if (status)
goto err_map;
}
ks->base = base;
ks->phys = phys;
ks->size = size;
return 0;
err_map:
for (size_t i = 0; i < mapped; i += page_size)
pmap_unmap(&kernel_vma.pmap, base + i);
mem_phys_free(phys, size / page_size);
err_vm:
vm_free(va, size + page_size);
return status;
}
void stack_destroy(struct stack* ks) {
if (!ks || !ks->base)
return;
const size_t page_size = arch_mem_page_size();
for (size_t i = 0; i < ks->size; i += page_size)
pmap_unmap(&kernel_vma.pmap, ks->base + i);
mem_phys_free(ks->phys, ks->size / page_size);
vm_free(ks->base - page_size, ks->size + page_size);
*ks = (struct stack){0};
}