Mercurial > hg > Members > menikon > CbC_xv6
changeset 215:291d4e9304a1
allocuvm_loopvm_imp
author | tobaru |
---|---|
date | Fri, 24 Jan 2020 14:54:09 +0900 |
parents | 2ecf1e09e981 |
children | 0f1700bd5cff |
files | src/impl/vm_impl.h src/impl/vm_impl_private.cbc |
diffstat | 2 files changed, 50 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- 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(...));
--- 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, ...); }