changeset 289:e2520f609094

merge
author menikon <e165723@ie.u-ryukyu.ac.jp>
date Fri, 24 Jan 2020 21:19:48 +0900
parents ab5a80021afe (current diff) 80398e02ae72 (diff)
children 696c6bdc1074
files
diffstat 5 files changed, 383 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/gearsTools/lib/Gears/Context/Template/XV6.pm	Thu Jan 23 20:33:39 2020 +0900
+++ b/src/gearsTools/lib/Gears/Context/Template/XV6.pm	Fri Jan 24 21:19:48 2020 +0900
@@ -161,6 +161,7 @@
 #ifndef USE_CUDAWorker
 typedef unsigned long long CUdeviceptr;
 #endif
+typedef struct proc proc_struct;
 typedef uint32  pte_t;
 typedef uint32  pde_t;
 EOFEOF
--- a/src/impl/vm_impl.cbc	Thu Jan 23 20:33:39 2020 +0900
+++ b/src/impl/vm_impl.cbc	Fri Jan 24 21:19:48 2020 +0900
@@ -26,6 +26,15 @@
     vm_impl->sz  = 0;
     vm_impl->loaduvm_ptesize_check = C_loaduvm_ptesize_checkvm_impl;
     vm_impl->loaduvm_loop = C_loaduvm_loopvm_impl;
+    vm_impl->allocuvm_check_newsz = C_allocuvm_check_newszvm_impl;
+    vm_impl->allocuvm_loop = C_allocuvm_loopvm_impl;
+    vm_impl->copyuvm_check_null = C_copyuvm_check_nullvm_impl;
+    vm_impl->copyuvm_loop = C_copyuvm_loopvm_impl;
+    vm_impl->uva2ka_check_pe_types = C_uva2ka_check_pe_types;
+    vm_impl->paging_intvm_impl = C_paging_intvmvm_impl;
+    vm_impl->copyout_loopvm_impl = C_copyout_loopvm_impl;
+    vm_impl->switchuvm_check_pgdirvm_impl = C_switchuvm_check_pgdirvm_impl;
+    vm_impl->init_inituvm_check_sz = C_init_inituvm_check_sz;
     vm->init_vmm = C_init_vmmvm_impl;
     vm->kpt_freerange = C_kpt_freerangevm_impl;
     vm->kpt_alloc = C_kpt_allocvm_impl;
@@ -37,7 +46,7 @@
     vm->copyuvm = C_copyuvmvm_impl;
     vm->uva2ka = C_uva2kavm_impl;
     vm->copyout = C_copyoutvm_impl;
-    vm->pagind_int = C_pagind_intvm_impl;
+    vm->paging_int = C_paging_intvm_impl;
     return vm;
 }
 
@@ -53,25 +62,43 @@
     goto next(...);
 }
 
-__code kpt_freerangevm_impl(struct vm_impl* vm, uint low, uint hi, __code next(...)) {
+extern struct run {
+    struct run *next;
+};
 
-    goto next(...);
+static void _kpt_free (char *v)
+{
+    struct run *r;
+
+    r = (struct run*) v;
+    r->next = kpt_mem.freelist;
+    kpt_mem.freelist = r;
 }
 
-__code kpt_allocvm_impl(struct vm_impl* vm ,__code next(...)) {
+__code kpt_freerangevm_impl(struct vm_impl* vm, uint low, uint hi, __code next(...)) { 
+ 
+   if (low < hi) { 
+     _kpt_free((char*)low);
+     goto kpt_freerangevm_impl(vm, low + PT_SZ, hi, next(...));  
+  
+   } 
+  goto next(...);
+}
+__code kpt_allocvm_impl(struct vm_impl* vm, __code next(...)) {
+  acquire(&kpt_mem.lock);
 
-    goto next(...);
+  goto kpt_alloc_check_impl(vm_impl, next(...));
 }
 
 typedef struct proc proc;
-__code switchuvmvm_impl(struct vm_impl* vm ,struct proc* p, __code next(...)) { //:skip
+__code switchuvmvm_impl(struct vm_impl* vm , struct proc* p, __code next(...)) { //:skip
 
-    goto next(...);
+    goto switchuvm_check_pgdirvm_impl(...);
 }
 
-__code init_inituvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)) { //:skip
+__code init_inituvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)) { 
 
-    goto next(...);
+    goto init_inituvm_check_sz(vm, pgdir, init, sz, next(...));
 }
 
 __code loaduvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz,  __code next(...)) {
@@ -81,36 +108,38 @@
     vm->offset = offset;
     vm->sz = sz;
     
-    goto loaduvm_ptesize_checkvm_impl(vm, next);
+    goto loaduvm_ptesize_checkvm_impl(vm, next(...));
 }
 
 __code allocuvmvm_impl(struct vm_impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...)) {
 
-    goto next(...);
+    goto allocuvm_check_newszvm_impl(vm, pgdir, oldsz, newsz, next(...));
 }
 
 __code clearpteuvm_impl(struct vm_impl* vm, pde_t* pgdir, char* uva,  __code next(...)) {
 
-    goto next(...);
+    goto clearpteu_check_ptevm_impl(vm, pgdir, uva, next(...));
 }
 
 __code copyuvmvm_impl(struct vm_impl* vm, pde_t* pgdir, uint sz, __code next(...)) {
 
-    goto next(...);
+    goto copyuvm_check_nullvm_impl(vm, pgdir, sz, __code next(...));
 }
 
 __code uva2kavm_impl(struct vm_impl* vm, pde_t* pgdir, char* uva, __code next(...)) {
 
-    goto next(...);
+    goto uva2ka_check_pe_types(vm, pgdir, uva, next(...));
 }
 
 __code copyoutvm_impl(struct vm_impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...)) {
 
-    goto next(...);
+    vm->buf = (char*) pp;    
+
+    goto copyout_loopvm_impl(vm, pgdir, va, pp, len, va0, pa0, next(...));
 }
 
-__code pagind_intvm_impl(struct vm_impl* vm, uint phy_low, uint phy_hi, __code next(...)) {
+__code paging_intvm_impl(struct vm_impl* vm, uint phy_low, uint phy_hi, __code next(...)) {
 
-    goto next(...);
+    goto paging_intvmvm_impl(vm, phy_low, phy_hi, next(...));
 }
 
--- a/src/impl/vm_impl.h	Thu Jan 23 20:33:39 2020 +0900
+++ b/src/impl/vm_impl.h	Fri Jan 24 21:19:48 2020 +0900
@@ -9,13 +9,39 @@
     uint offset;
     uint pa;
     uint n;
+    uint oldsz;
+    uint newsz;
+    uint a;
+    int ret;
+    char* mem;
+    char* uva;
+    pde_t* d;
+    uint ap;
+    uint phy_low;
+    uint phy_hi;
+    uint va;
+    void* pp;
+    uint len;
+    char* buf;
+    char* pa0;
+    uint va0;
+    proc_struct* p;
+    char* init;
 
-    __code init_vmm(Type* vm_impl, __code next(...));
-    __code loaduvm_ptesize_check(Type* vm_impl, __code next(...));
-    __code loaduvm_loop(Type* vm_impl, uint i, pte_t* pte, uint sz, __code next(...));
+    __code kpt_alloc_check_impl(Type* vm_impl, __code next(...));
+    __code loaduvm_ptesize_check(Type* vm_impl, __code next(int ret, ...));
+    __code loaduvm_loop(Type* vm_impl, uint i, pte_t* pte, uint sz, __code next(int ret, ...));
+    __code allocuvm_check_newsz(Type* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, __code next(...));
+    __code allocuvm_loop(Type* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, uint a, __code next(...));
+    __code copyuvm_check_null(Type* vm_impl, pde_t* pgdir, uint sz, __code next(...));
+    __code copyuvm_loop(Type* vm_impl,pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...));
+    __code clearpteu_check_ptevm_impl(Type* vm_impl, pde_t* pgdir, char* uva,  __code next(...));
+    __code uva2ka_check_pe_types(Type* vm_impl, pde_t* pgdir, char* uva, __code next(...));
+    __code paging_intvm_impl(Type* vm_impl, uint phy_low, uint phy_hi, __code next(...));
+    __code copyout_loopvm_impl(Type* vm_impl, pde_t* pgdir, uint va, void* pp, uint len, __code next(...));
+    __code switchuvm_check_pgdirvm_impl(struct vm_impl* vm_impl, struct proc* p, __code next(...));
+    __code init_inituvm_check_sz(struct vm_impl* vm_impl, pde_t* pgdir, char* init, uint sz, __code next(...));
     __code next(...);
- 
-
 } vm_impl;
 
 
--- a/src/impl/vm_impl_private.cbc	Thu Jan 23 20:33:39 2020 +0900
+++ b/src/impl/vm_impl_private.cbc	Fri Jan 24 21:19:48 2020 +0900
@@ -1,5 +1,7 @@
-#include "../../context.h"
+#include "param.h"
+#include "proc.h"
 #include "mmu.h"
+#include "defs.h"
 #include "memlayout.h"
 #interface "vm_impl.h"
 
@@ -7,25 +9,25 @@
 vm_impl* createvm_impl2();
 */
 
-__code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(...)) {
+__code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
     char* addr = vm_impl->addr;
 
     if ((uint) addr %PTE_SZ != 0) {
        // goto panic 
     }
 
-    goto loaduvm_loopvm_impl(vm_impl, next(...));
+    goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
 }
 
-__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(...)) {
+__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
     uint i = vm_impl->i;
     uint sz = vm_impl->sz;
 
     if (i < sz) {
-        goto loaduvm_check_pgdir(vm_impl, next(...));  
+        goto loaduvm_check_pgdir(vm_impl, next(ret, ...));  
     } 
 
-    goto loaduvm_exit(vm_impl, next(...));
+    goto loaduvm_exit(vm_impl, next(ret, ...));
 }
 
 
@@ -58,7 +60,7 @@
 }
 
 
-__code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(...)) {
+__code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(int ret, ...)) {
     pte_t* pte = vm_impl->pte;
     pde_t* pgdir = vm_impl->pgdir;
     uint i = vm_impl->i;
@@ -75,10 +77,10 @@
     vm_impl->addr = addr; 
     vm_impl->pa = pa; 
 
-    goto loaduvm_check_PTE_SZ(vm_impl, next(...));
+    goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...));
 }
 
-__code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(...)) {
+__code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(int ret, ...)) {
     uint sz = vm_impl->sz;
     uint i = vm_impl->i;
     uint n = vm_impl->n;
@@ -93,16 +95,305 @@
     }
 
     if (readi(ip, p2v(pa), offset + i, n) != n) {
-        // panic 
-        // return -1;
+        ret = -1;
+        goto next(ret, ...);
     }
 
     vm_impl->n = n;
  
-    goto loaduvm_exit(vm_impl, next(...));
+    goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
+}
+
+__code loaduvm_exit(struct vm_impl* vm_impl, __code next(int ret, ...)) {
+    ret = 0;
+    goto next(ret, ...);
+}
+
+struct run {
+    struct run *next;
+};
+
+struct {
+    struct spinlock lock;
+    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 ) {
+        kpt_mem.freelist = r->next;
+    }
+    release(&kpt_mem.lock);
+
+    if ((r == NULL) && ((r = kmalloc (PT_ORDER)) == NULL)) {
+        // panic("oom: kpt_alloc");
+        // goto panic
+    }
+
+    memset(r, 0, PT_SZ);
+    goto next((char*)r);
+}
+
+__code allocuvm_check_newszvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, __code next(int ret, ...)){
+    if (newsz >= UADDR_SZ) {
+       goto next(0, ...);
+    }
+
+    if (newsz < oldsz) {
+       ret = newsz;
+       goto next(ret, ...);
+    }
+
+    char* mem;
+    uint a = align_up(oldsz, PTE_SZ);
+
+    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, char* mem, uint a, __code next(int ret, ...)){
+
+    if (a < newsz) {
+        mem = alloc_page();
+
+        if (mem == 0) {
+            cprintf("allocuvm out of memory\n");
+            deallocuvm(pgdir, newsz, oldsz);
+            goto next(0, ...);
+        }
+
+        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, ...)); 
+    }
+    ret = newsz; 
+    goto next(ret, ...);
 }
 
-__code loaduvm_exit(struct vm_impl* vm_impl, __code next(...)) {
+__code clearpteu_check_ptevm_impl(struct vm_impl* vm_impl, pde_t* pgdir, char* uva, __code next(int ret, ...)) {
+    pte_t *pte;
+
+    pte = walkpgdir(pgdir, uva, 0);
+    if (pte == 0) {
+        // panic("clearpteu");
+        // goto panic;
+    }
+
+    // in ARM, we change the AP field (ap & 0x3) << 4)
+    *pte = (*pte & ~(0x03 << 4)) | AP_KO << 4;
+
+    goto next(ret, ...);
+}
+
+__code copyuvm_check_nullvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, __code next(int ret, ...)) {
+    pde_t *d;
+    pte_t *pte;
+    uint pa, i, ap;
+    char *mem;
+
+    // allocate a new first level page directory
+    d = kpt_alloc();
+    if (d == NULL ) {
+        ret = NULL;
+        goto next(ret, ...);
+    }
+    i = 0;
+
+    goto copyuvm_loopvm_impl(vm_impl, pgdir, sz, *d, *pte, pa, i, ap, *mem, next(ret, ...));
+}
+
+__code copyuvm_loopvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...)) {
+
+    if (i < sz) { 
+        goto copyuvm_loop_check_walkpgdir(vm_impl, pgdir, sz, d, pte, pa, i, ap, mem, __code next(int ret, ...));
+
+    }
+    ret = d;
+    goto next(ret, ...);
+}
+
+__code copyuvm_loop_check_walkpgdir(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...)) {
+        if ((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) {
+            // panic("copyuvm: pte should exist");
+            // goto panic();
+        }
+    goto copyuvm_loop_check_pte(vm_impl, pgdir, sz, d, pte, pa, i, ap, mem, __code next(int ret, ...));
+}
+
+__code copyuvm_loop_check_pte(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...)) {
+
+        if (!(*pte & PE_TYPES)) {
+            // panic("copyuvm: page not present");
+            // goto panic();
+        }
+
+    goto copyuvm_loop_check_mem(vm_impl, pgdir, sz, d, pte, pa, i, ap, mem, __code next(int ret, ...));
+}
+
+__code copyuvm_loop_check_mem(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...)) {
+    pa = PTE_ADDR (*pte);
+    ap = PTE_AP (*pte);
+
+    if ((mem = alloc_page()) == 0) {
+        goto copyuvm_loop_bad(vm_impl, d, next(...));
+    }
+    goto copyuvm_loop_check_mappages(vm_impl, pgdir, sz, d, pte, pa, i, ap, mem, __code next(int ret, ...));
+    
+}
+
+__code copyuvm_loop_check_mappages(struct vm_impl* vm_impl, pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...)) {
+
+    memmove(mem, (char*) p2v(pa), PTE_SZ);
+
+    if (mappages(d, (void*) i, PTE_SZ, v2p(mem), ap) < 0) {
+        goto copyuvm_loop_bad(vm_impl, d, next(...));
+    }
+    goto copyuvm_loopvm_impl(vm_impl, pgdir, sz, d, pte, pa, i, ap, mem, __code next(int ret, ...));
+ 
+}
+
+__code copyuvm_loop_bad(struct vm_impl* vm_impl, pde_t* d, __code next(int ret, ...)) {
+    freevm(d);
+    ret = 0;
+    goto next(ret, ...);
+}
+
+
+__code uva2ka_check_pe_types(struct vm_impl* vm, pde_t* pgdir, char* uva, __code next(int ret, ...)) {
+    pte_t* pte;
+
+    pte = walkpgdir(pgdir, uva, 0);
+
+    // make sure it exists
+    if ((*pte & PE_TYPES) == 0) {
+        ret = 0;
+        goto next(ret, ...);
+    }
+    goto uva2ka_check_pte_ap(vm, pgdir, uva, pte, next(...));
+}
+
+__code uva2ka_check_pte_ap(struct vm_impl* vm, pde_t* pgdir, char* uva, pte_t* pte, __code next(int ret, ...)) {
+    // make sure it is a user page
+    if (PTE_AP(*pte) != AP_KU) {
+        ret = 0;
+        goto next(ret, ...);
+    }
+    ret = (char*) p2v(PTE_ADDR(*pte));
+    goto next(ret, ...);
+}
+
+// flush all TLB
+static void flush_tlb (void)
+{
+    uint val = 0;
+    asm("MCR p15, 0, %[r], c8, c7, 0" : :[r]"r" (val):);
+
+    // invalid entire data and instruction cache
+    asm ("MCR p15,0,%[r],c7,c10,0": :[r]"r" (val):);
+    asm ("MCR p15,0,%[r],c7,c11,0": :[r]"r" (val):);
+}
+
+__code paging_intvmvm_impl(struct vm_impl* vm_impl, uint phy_low, uint phy_hi, __code next(...)) {
+    mappages (P2V(&_kernel_pgtbl), P2V(phy_low), phy_hi - phy_low, phy_low, AP_KU);
+    flush_tlb ();
 
     goto next(...);
 }
+
+__code copyout_loopvm_impl(struct vm_impl* vm_impl, pde_t* pgdir, uint va, void* pp, uint len, uint va0, char* pa0,  __code next(int ret, ...)) {
+    if (len > 0) {
+        va0 = align_dn(va, PTE_SZ);
+        pa0 = uva2ka(pgdir, (char*) va0);
+        goto copyout_loop_check_pa0(vm_impl, pgdir, va, pp, len, va0, pa0, n, next(...));
+    }
+    ret = 0;
+    goto next(ret, ...);
+
+}
+
+__code copyout_loop_check_pa0(struct vm_impl* vm_impl, pde_t* pgdir, uint va, void* pp, uint len, uint va0, char* pa0, uint n, __code next(int ret, ...)) {
+    if (pa0 == 0) {
+        ret = -1;
+        goto next(ret, ...);
+    }
+    goto copyout_loop_check_n(vm_impl, pgdir, va, pp, len, va0, pa0, n, buf, next(...));
+}
+__code copyout_loop_check_n(struct vm_impl* vm_impl, pde_t* pgdir, uint va, void* pp, uint len, uint va0, char* pa0, uint n, char* buf, __code next(...)) {
+    n = PTE_SZ - (va - va0);
+
+    if (n > len) {
+        n = len;
+    }
+
+    len -= n;
+    buf += n;
+    va = va0 + PTE_SZ;
+    goto copyout_loopvm_impl(vm_impl, pgdir, va, pp, len, va0, pa0, next(...));
+}
+
+typedef struct proc proc_struct;
+__code switchuvm_check_pgdirvm_impl(struct vm_impl* vm_impl, proc_struct* p, __code next(...)) { //:skip
+    uint val;
+
+    pushcli();
+
+    if (p->pgdir == 0) {
+        panic("switchuvm: no pgdir");
+    }
+
+    val = (uint) V2P(p->pgdir) | 0x00;
+
+    asm("MCR p15, 0, %[v], c2, c0, 0": :[v]"r" (val):);
+    flush_tlb();
+
+    popcli();
+
+    goto next(...);
+}
+
+__code init_inituvm_check_sz(struct vm_impl* vm_impl, pde_t* pgdir, char* init, uint sz, __code next(...)) {
+    char* mem;
+
+    if (sz >= PTE_SZ) {
+        // goto panic;
+        // panic("inituvm: more than a page");
+    }
+
+    mem = alloc_page();
+    memset(mem, 0, PTE_SZ);
+    mappages(pgdir, 0, PTE_SZ, v2p(mem), AP_KU);
+    memmove(mem, init, sz);
+
+    goto next(...);
+}
--- a/src/interface/vm.h	Thu Jan 23 20:33:39 2020 +0900
+++ b/src/interface/vm.h	Fri Jan 24 21:19:48 2020 +0900
@@ -28,6 +28,6 @@
     __code copyuvm(Impl* vm, pde_t* pgdir, uint sz, __code next(...));
     __code uva2ka(Impl* vm, pde_t* pgdir, char* uva, __code next(...));
     __code copyout(Impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...));
-    __code pagind_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...));
+    __code paging_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...));
     __code next(...);
 } vm;