diff options
author | Andrew Waterman <andrew@sifive.com> | 2017-03-09 12:42:07 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2017-03-09 12:42:07 -0800 |
commit | 00d8922398c202c13d6eb5da07e92be6364309a1 (patch) | |
tree | 72d518fd759b9b3184bb5aba5b6c5d91619c5f17 /v | |
parent | b3e14827904c2b1247171f4f1522be397349e7ea (diff) | |
download | env-00d8922398c202c13d6eb5da07e92be6364309a1.zip env-00d8922398c202c13d6eb5da07e92be6364309a1.tar.gz env-00d8922398c202c13d6eb5da07e92be6364309a1.tar.bz2 |
WIP on priv-1.10
Diffstat (limited to 'v')
-rw-r--r-- | v/vm.c | 65 |
1 files changed, 40 insertions, 25 deletions
@@ -9,20 +9,21 @@ void trap_entry(); void pop_tf(trapframe_t*); -volatile uint64_t tohost __attribute__((aligned(64))); -volatile uint64_t fromhost __attribute__((aligned(64))); +volatile uint64_t tohost; +volatile uint64_t fromhost; static void do_tohost(uint64_t tohost_value) { + while (tohost) + fromhost = 0; tohost = tohost_value; - while (fromhost == 0) - ; - fromhost = 0; } #define pa2kva(pa) ((void*)(pa) - DRAM_BASE - MEGAPAGE_SIZE) #define uva2kva(pa) ((void*)(pa) - MEGAPAGE_SIZE) +#define flush_page(addr) asm volatile ("sfence.vma %0" : : "r" (addr)) + static uint64_t lfsr63(uint64_t x) { uint64_t bit = (x ^ (x >> 1)) & 1; @@ -61,15 +62,13 @@ void wtf() #define l1pt pt[0] #define user_l2pt pt[1] -#define kernel_l2pt pt[2] #if __riscv_xlen == 64 -# define NPT 5 +# define NPT 4 +#define kernel_l2pt pt[2] # define user_l3pt pt[3] -# define kernel_l3pt pt[4] #else -# define NPT 3 +# define NPT 2 # define user_l3pt user_l2pt -# define kernel_l3pt kernel_l2pt #endif pte_t pt[NPT][PTES_PER_PT] __attribute__((aligned(PGSIZE))); @@ -119,24 +118,39 @@ static void evict(unsigned long addr) } } -void handle_fault(unsigned long addr) +void handle_fault(uintptr_t addr, uintptr_t cause) { assert(addr >= PGSIZE && addr < MAX_TEST_PAGES * PGSIZE); addr = addr/PGSIZE*PGSIZE; + if (user_l3pt[addr/PGSIZE]) { + if (!(user_l3pt[addr/PGSIZE] & PTE_A)) { + user_l3pt[addr/PGSIZE] |= PTE_A; + } else { + assert(!(user_l3pt[addr/PGSIZE] & PTE_D) && cause == CAUSE_FAULT_STORE); + user_l3pt[addr/PGSIZE] |= PTE_D; + } + flush_page(addr); + return; + } + freelist_t* node = freelist_head; assert(node); freelist_head = node->next; if (freelist_head == freelist_tail) freelist_tail = 0; - user_l3pt[addr/PGSIZE] = (node->addr >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X; - asm volatile ("sfence.vm"); + uintptr_t new_pte = (node->addr >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X; + user_l3pt[addr/PGSIZE] = new_pte | PTE_A | PTE_D; + flush_page(addr); assert(user_mapping[addr/PGSIZE].addr == 0); user_mapping[addr/PGSIZE] = *node; memcpy((void*)addr, uva2kva(addr), PGSIZE); + user_l3pt[addr/PGSIZE] = new_pte; + flush_page(addr); + __builtin___clear_cache(0,0); } @@ -165,7 +179,7 @@ void handle_trap(trapframe_t* tf) tf->epc += 4; } else if (tf->cause == CAUSE_FAULT_FETCH || tf->cause == CAUSE_FAULT_LOAD || tf->cause == CAUSE_FAULT_STORE) - handle_fault(tf->badvaddr); + handle_fault(tf->badvaddr, tf->cause); else assert(!"unexpected exception"); @@ -196,18 +210,23 @@ void vm_boot(uintptr_t test_addr) _Static_assert(SIZEOF_TRAPFRAME_T == sizeof(trapframe_t), "???"); -#if MAX_TEST_PAGES > PTES_PER_PT +#if (MAX_TEST_PAGES > PTES_PER_PT) || (DRAM_BASE % MEGAPAGE_SIZE) != 0 # error #endif - write_csr(sptbr, (uintptr_t)l1pt >> PGSHIFT); - // map kernel to uppermost megapage - l1pt[PTES_PER_PT-1] = ((pte_t)kernel_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V; // map user to lowermost megapage l1pt[0] = ((pte_t)user_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V; + // map kernel to uppermost megapage #if __riscv_xlen == 64 - kernel_l2pt[PTES_PER_PT-1] = ((pte_t)kernel_l3pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V; + l1pt[PTES_PER_PT-1] = ((pte_t)kernel_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V; + kernel_l2pt[PTES_PER_PT-1] = (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D; user_l2pt[0] = ((pte_t)user_l3pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V; + uintptr_t vm_choice = SPTBR_MODE_SV39; +#else + l1pt[PTES_PER_PT-1] = (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D; + uintptr_t vm_choice = SPTBR_MODE_SV32; #endif + write_csr(sptbr, ((uintptr_t)l1pt >> PGSHIFT) | + (vm_choice * (SPTBR_MODE & ~(SPTBR_MODE<<1)))); // set up supervisor trap handling write_csr(stvec, pa2kva(trap_entry)); @@ -217,10 +236,8 @@ void vm_boot(uintptr_t test_addr) (1 << CAUSE_FAULT_FETCH) | (1 << CAUSE_FAULT_LOAD) | (1 << CAUSE_FAULT_STORE)); - // on ERET, user mode; FPU on; accelerator on; VM on - int vm_choice = sizeof(long) == 8 ? VM_SV39 : VM_SV32; - write_csr(mstatus, MSTATUS_FS | MSTATUS_XS | - (vm_choice * (MSTATUS_VM & ~(MSTATUS_VM<<1)))); + // FPU on; accelerator on + write_csr(mstatus, MSTATUS_FS | MSTATUS_XS); write_csr(mie, 0); random = 1 + (random % MAX_TEST_PAGES); @@ -231,8 +248,6 @@ void vm_boot(uintptr_t test_addr) freelist_nodes[i].addr = DRAM_BASE + (MAX_TEST_PAGES + random)*PGSIZE; freelist_nodes[i].next = pa2kva(&freelist_nodes[i+1]); random = LFSR_NEXT(random); - - kernel_l3pt[i] = ((i + DRAM_BASE/RISCV_PGSIZE) << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X; } freelist_nodes[MAX_TEST_PAGES-1].next = 0; |