changeset 206: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, ...);
 }