diff options
Diffstat (limited to 'env/v/vm.c')
-rw-r--r-- | env/v/vm.c | 275 |
1 files changed, 0 insertions, 275 deletions
diff --git a/env/v/vm.c b/env/v/vm.c deleted file mode 100644 index 6b61c02..0000000 --- a/env/v/vm.c +++ /dev/null @@ -1,275 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdio.h> - -#include "riscv_test.h" - -void trap_entry(); -void pop_tf(trapframe_t*); - -static void cputchar(int x) -{ - while (mtpcr(PCR_TOHOST, 0x0101000000000000 | (unsigned char)x)); -} - -static void cputstring(const char* s) -{ - while(*s) - cputchar(*s++); - cputchar('\n'); -} - -static void terminate(int code) -{ - while (mtpcr(PCR_TOHOST, code)); - while (1); -} - -#define stringify1(x) #x -#define stringify(x) stringify1(x) -#define assert(x) do { \ - if (x) break; \ - cputstring("Assertion failed: " stringify(x)); \ - terminate(3); \ -} while(0) - -#define RELOC(x) ((typeof(x))((char*)(x) + (PGSIZE*MAX_TEST_PAGES))) - -typedef struct { pte_t addr; void* next; } freelist_t; - -pte_t l1pt[PTES_PER_PT] __attribute__((aligned(PGSIZE))); -pte_t l2pt[PTES_PER_PT] __attribute__((aligned(PGSIZE))); -pte_t l3pt[PTES_PER_PT] __attribute__((aligned(PGSIZE))); -freelist_t user_mapping[MAX_TEST_PAGES]; -freelist_t freelist_nodes[MAX_TEST_PAGES]; -freelist_t *freelist_head, *freelist_tail; - -void printhex(uint64_t x) -{ - char str[17]; - for (int i = 0; i < 16; i++) - { - str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); - x >>= 4; - } - str[16] = 0; - - cputstring(str); -} - -void evict(unsigned long addr) -{ - assert(addr >= PGSIZE && addr < RELOC(0L)); - addr = addr/PGSIZE*PGSIZE; - - freelist_t* node = RELOC(&user_mapping[addr/PGSIZE]); - if (node->addr) - { - memcpy((void*)RELOC(addr), (void*)addr, PGSIZE); - RELOC(&user_mapping[addr/PGSIZE])->addr = 0; - - if (*RELOC(&freelist_tail) == 0) - *RELOC(&freelist_head) = *RELOC(&freelist_tail) = node; - else - { - (*RELOC(&freelist_tail))->next = node; - *RELOC(&freelist_tail) = node; - } - } -} - -void handle_fault(unsigned long addr) -{ - assert(addr >= PGSIZE && addr < RELOC(0L)); - addr = addr/PGSIZE*PGSIZE; - - freelist_t* node = *RELOC(&freelist_head); - assert(node); - *RELOC(&freelist_head) = node->next; - if (*RELOC(&freelist_head) == *RELOC(&freelist_tail)) - *RELOC(&freelist_tail) = 0; - - *RELOC(&l3pt[addr/PGSIZE]) = node->addr | PTE_UW | PTE_UR | PTE_UX | PTE_SW | PTE_SR | PTE_SX | PTE_V; - mtpcr(PCR_FATC, 0); - - assert(RELOC(&user_mapping[addr/PGSIZE])->addr == 0); - *RELOC(&user_mapping[addr/PGSIZE]) = *node; - memcpy((void*)addr, (void*)RELOC(addr), PGSIZE); - - __builtin___clear_cache(0,0); -} - -static void emulate_vxcptsave(trapframe_t* tf) -{ - long* where = (long*)tf->gpr[(tf->insn >> 15) & 0x1F]; - - where[0] = vgetcfg(); - where[1] = vgetvl(); - vxcptevac(&where[2]); - fence(); -} - -static void do_vxcptrestore(long* where) -{ - vsetcfg(where[0]); - vsetvl(where[1]); - - vxcpthold(); - - int idx = 2; - long dword, cmd, pf; - int first = 1; - - while (1) - { - dword = where[idx++]; - - if (dword < 0) break; - - if (dword_bit_cnt(dword)) - { - venqcnt(dword, pf | (dword_bit_cmd(where[idx]) << 1)); - } - else - { - if (!first) - { - venqcmd(cmd, pf); - } - - first = 0; - cmd = dword; - pf = dword_bit_pf(cmd); - - if (dword_bit_imm1(cmd)) - { - venqimm1(where[idx++], pf); - } - if (dword_bit_imm2(cmd)) - { - venqimm2(where[idx++], pf); - } - } - } - if (!first) - { - venqcmd(cmd, pf); - } -} - -static void emulate_vxcptrestore(trapframe_t* tf) -{ - long* where = (long*)tf->gpr[(tf->insn >> 15) & 0x1F]; - vxcptkill(); - do_vxcptrestore(where); -} - -static void restore_vector(trapframe_t* tf) -{ - if (mfpcr(PCR_IMPL) == IMPL_ROCKET) - do_vxcptrestore(tf->evac); - else - vxcptrestore(tf->evac); -} - -void handle_trap(trapframe_t* tf) -{ - if (tf->cause == CAUSE_SYSCALL) - { - int n = tf->gpr[18]; - - for (long i = 1; i < MAX_TEST_PAGES; i++) - evict(i*PGSIZE); - - terminate(n); - } - else if (tf->cause == CAUSE_FAULT_FETCH) - handle_fault(tf->epc); - else if (tf->cause == CAUSE_ILLEGAL_INSTRUCTION) - { - int fssr; - asm ("la %0, 1f; lw %0, 0(%0); b 2f; 1: fssr x0; 2:" : "=r"(fssr)); - - if (tf->insn == fssr) - terminate(1); // FP test on non-FP hardware. "succeed." -#if 0 - else if ((tf->insn & 0xF83FFFFF) == 0x37B) - emulate_vxcptsave(tf); - else if ((tf->insn & 0xF83FFFFF) == 0x77B) - emulate_vxcptrestore(tf); -#endif - else - assert(0); - tf->epc += 4; - } - else if (tf->cause == CAUSE_FAULT_LOAD || tf->cause == CAUSE_FAULT_STORE) - handle_fault(tf->badvaddr); - else if ((tf->cause << 1) == (IRQ_COP << 1)) - { - if (tf->hwacha_cause == HWACHA_CAUSE_VF_FAULT_FETCH || - tf->hwacha_cause == HWACHA_CAUSE_FAULT_LOAD || - tf->hwacha_cause == HWACHA_CAUSE_FAULT_STORE) - { - long badvaddr = vxcptaux(); - handle_fault(badvaddr); - } - else - assert(0); - } - else - assert(0); - -out: - if (!(tf->sr & SR_PS) && (tf->sr & SR_EA)) { - restore_vector(tf); - tf->sr |= SR_PEI; - } - pop_tf(tf); -} - -void vm_boot(long test_addr, long seed) -{ - while (mfpcr(PCR_HARTID) > 0); // only core 0 proceeds - - assert(SIZEOF_TRAPFRAME_T == sizeof(trapframe_t)); - - seed = 1 + (seed % MAX_TEST_PAGES); - freelist_head = RELOC(&freelist_nodes[0]); - freelist_tail = RELOC(&freelist_nodes[MAX_TEST_PAGES-1]); - for (long i = 0; i < MAX_TEST_PAGES; i++) - { - freelist_nodes[i].addr = (MAX_TEST_PAGES+i)*PGSIZE; - freelist_nodes[i].next = RELOC(&freelist_nodes[i+1]); - seed = LFSR_NEXT(seed); - } - freelist_nodes[MAX_TEST_PAGES-1].next = 0; - - assert(MAX_TEST_PAGES*2 < PTES_PER_PT); - l1pt[0] = (pte_t)l2pt | PTE_V | PTE_T; - l2pt[0] = (pte_t)l3pt | PTE_V | PTE_T; - for (long i = 0; i < MAX_TEST_PAGES; i++) - l3pt[i] = l3pt[i+MAX_TEST_PAGES] = (i*PGSIZE) | PTE_SW | PTE_SR | PTE_SX | PTE_V; - - mtpcr(PCR_PTBR, l1pt); - mtpcr(PCR_SR, mfpcr(PCR_SR) | SR_VM | SR_EF); - - // relocate - long adjustment = RELOC(0L), tmp; - mtpcr(PCR_EVEC, (char*)&trap_entry + adjustment); - asm volatile ("add sp, sp, %1\n" - "jal %0, 1f\n" - "1: add %0, %0, %1\n" - "jr %0, 8" - : "=&r"(tmp) - : "r"(adjustment)); - - memset(RELOC(&l3pt[0]), 0, MAX_TEST_PAGES*sizeof(pte_t)); - mtpcr(PCR_FATC, 0); - - trapframe_t tf; - memset(&tf, 0, sizeof(tf)); - tf.sr = SR_PEI | ((1 << IRQ_COP) << SR_IM_SHIFT) | SR_EF | SR_EA | SR_S | SR_U64 | SR_S64 | SR_VM; - tf.epc = test_addr; - - pop_tf(&tf); -} |