aboutsummaryrefslogtreecommitdiff
path: root/env/v/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'env/v/vm.c')
-rw-r--r--env/v/vm.c275
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);
-}