# HG changeset patch # User tobaru # Date 1579845249 -32400 # Node ID 291d4e9304a10dedf45f3f285901a75f407ac17d # Parent 2ecf1e09e9815bf13e979c778fdc1345fca9af5c allocuvm_loopvm_imp diff -r 2ecf1e09e981 -r 291d4e9304a1 src/impl/vm_impl.h --- a/src/impl/vm_impl.h Fri Jan 24 14:45:38 2020 +0900 +++ b/src/impl/vm_impl.h Fri Jan 24 14:54:09 2020 +0900 @@ -13,6 +13,7 @@ uint newsz; uint a; int ret; + char* mem; __code kpt_alloc_check_impl(Type* vm_impl, __code next(...)); __code loaduvm_ptesize_check(Type* vm_impl, __code next(...)); diff -r 2ecf1e09e981 -r 291d4e9304a1 src/impl/vm_impl_private.cbc --- a/src/impl/vm_impl_private.cbc Fri Jan 24 14:45:38 2020 +0900 +++ b/src/impl/vm_impl_private.cbc Fri Jan 24 14:54:09 2020 +0900 @@ -116,6 +116,37 @@ struct run* freelist; } kpt_mem; + +static int mappages (pde_t *pgdir, void *va, uint size, uint pa, int ap) +{ + char *a, *last; + pte_t *pte; + + a = (char*) align_dn(va, PTE_SZ); + last = (char*) align_dn((uint)va + size - 1, PTE_SZ); + + for (;;) { + if ((pte = walkpgdir(pgdir, a, 1)) == 0) { + return -1; + } + + if (*pte & PE_TYPES) { + panic("remap"); + } + + *pte = pa | ((ap & 0x3) << 4) | PE_CACHE | PE_BUF | PTE_TYPE; + + if (a == last) { + break; + } + + a += PTE_SZ; + pa += PTE_SZ; + } + + return 0; +} + __code kpt_alloc_check_impl(struct vm_impl* vm_impl, __code next(...)) { struct run* r; if ((r = kpt_mem.freelist) != NULL ) { @@ -139,19 +170,31 @@ if (newsz < oldsz) { ret = newsz; - goto next(ret); + goto next(ret, ...); } + char* mem; uint a = align_up(oldsz, PTE_SZ); - goto allocuvm_loopvm_impl(vm_impl, pgdir, oldsz, newsz, a, next(...)); + goto allocuvm_loopvm_impl(vm_impl, pgdir, oldsz, newsz, mem, a, next(ret, ...)); } -__code allocuvm_loopvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, uint a, __code next(...)) { +__code allocuvm_loopvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, char* mem, uint a, __code next(int ret, ...)){ if (a < newsz) { - goto allocuvm_loopvm_impl(vm_impl, pgdir, oldsz, newsz, a + PTE_SZ, next(...)); + mem = alloc_page(); + + if (mem == 0) { + cprintf("allocuvm out of memory\n"); + deallocuvm(pgdir, newsz, oldsz); + goto next(ret, ...); + } + + memset(mem, 0, PTE_SZ); + mappages(pgdir, (char*) a, PTE_SZ, v2p(mem), AP_KU); + + goto allocuvm_loopvm_impl(vm_impl, pgdir, oldsz, newsz, a + PTE_SZ, next(ret, ...)); } - - goto next(newsz); + ret = newsz; + goto next(ret, ...); }