aboutsummaryrefslogtreecommitdiff
path: root/env
diff options
context:
space:
mode:
authorYunsup Lee <yunsup@cs.berkeley.edu>2013-04-22 14:56:59 -0700
committerYunsup Lee <yunsup@cs.berkeley.edu>2013-04-22 14:56:59 -0700
commit81ad66f25ce4c15180e558696961bd8eaf967fea (patch)
treed70676fb1d11a4a66a268f7860d3ef7d469987fe /env
downloadriscv-tests-81ad66f25ce4c15180e558696961bd8eaf967fea.zip
riscv-tests-81ad66f25ce4c15180e558696961bd8eaf967fea.tar.gz
riscv-tests-81ad66f25ce4c15180e558696961bd8eaf967fea.tar.bz2
initial commit
Diffstat (limited to 'env')
-rw-r--r--env/p/link.ld44
-rw-r--r--env/p/riscv_test.h76
-rw-r--r--env/pm/link.ld44
-rw-r--r--env/pm/riscv_test.h75
-rw-r--r--env/pt/link.ld44
-rw-r--r--env/pt/pcr.h93
-rw-r--r--env/pt/riscv_test.h236
-rw-r--r--env/v/entry.S171
-rw-r--r--env/v/link.ld50
-rw-r--r--env/v/pcr.h93
-rw-r--r--env/v/riscv_test.h129
-rw-r--r--env/v/vm.c263
12 files changed, 1318 insertions, 0 deletions
diff --git a/env/p/link.ld b/env/p/link.ld
new file mode 100644
index 0000000..6b19389
--- /dev/null
+++ b/env/p/link.ld
@@ -0,0 +1,44 @@
+/*======================================================================*/
+/* Proxy kernel linker script */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+ argument is one of the names used in the BFD library. More
+ specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+ to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+ /* text: test code section */
+ . = 0x00002000;
+ .text :
+ {
+ *(.text)
+ }
+
+ /* data: Initialized data segment */
+ .data :
+ {
+ *(.data)
+ }
+
+ /* End of uninitalized data segement */
+ _end = .;
+}
+
diff --git a/env/p/riscv_test.h b/env/p/riscv_test.h
new file mode 100644
index 0000000..a4f9668
--- /dev/null
+++ b/env/p/riscv_test.h
@@ -0,0 +1,76 @@
+#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
+#define _ENV_PHYSICAL_SINGLE_CORE_H
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U \
+
+#define RVTEST_RV64S \
+
+#define RVTEST_FP_ENABLE \
+ setpcr cr0, 2; \
+ mfpcr a0, cr0; \
+ and a0, a0, 2; \
+ beqz a0, 1f; \
+ mtfsr x0; \
+1:
+
+#define RVTEST_PASS_NOFP \
+ RVTEST_FP_ENABLE \
+ bnez a0, 2f; \
+ RVTEST_PASS \
+2: \
+
+#define RVTEST_VEC_ENABLE \
+ mfpcr a0, cr0; \
+ ori a0, a0, 4; \
+ mtpcr a0, cr0; \
+ li a0, 0xff; \
+ mtpcr a0, cr18; \
+
+#define RVTEST_CODE_BEGIN \
+ .text; \
+ .align 4; \
+ .global _start; \
+_start: \
+ RVTEST_FP_ENABLE \
+ RVTEST_VEC_ENABLE \
+ mfpcr a0, cr10; 1: bnez a0, 1b; \
+
+//-----------------------------------------------------------------------
+// End Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_END \
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_PASS \
+ fence; \
+ li x1, 1; \
+ mtpcr x1, cr30; \
+1: b 1b; \
+
+#define RVTEST_FAIL \
+ fence; \
+ beqz x28, 1f; \
+ sll x28, x28, 1; \
+ or x28, x28, 1; \
+ mtpcr x28, cr30; \
+1: b 1b; \
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_DATA_BEGIN
+#define RVTEST_DATA_END
+
+//#define RVTEST_DATA_BEGIN .align 4; .global begin_signature; begin_signature:
+//#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+#endif
diff --git a/env/pm/link.ld b/env/pm/link.ld
new file mode 100644
index 0000000..6b19389
--- /dev/null
+++ b/env/pm/link.ld
@@ -0,0 +1,44 @@
+/*======================================================================*/
+/* Proxy kernel linker script */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+ argument is one of the names used in the BFD library. More
+ specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+ to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+ /* text: test code section */
+ . = 0x00002000;
+ .text :
+ {
+ *(.text)
+ }
+
+ /* data: Initialized data segment */
+ .data :
+ {
+ *(.data)
+ }
+
+ /* End of uninitalized data segement */
+ _end = .;
+}
+
diff --git a/env/pm/riscv_test.h b/env/pm/riscv_test.h
new file mode 100644
index 0000000..102e6e0
--- /dev/null
+++ b/env/pm/riscv_test.h
@@ -0,0 +1,75 @@
+#ifndef _ENV_PHYSICAL_MULTI_CORE_H
+#define _ENV_PHYSICAL_MULTI_CORE_H
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U \
+
+#define RVTEST_RV64S \
+
+#define RVTEST_FP_ENABLE \
+ setpcr cr0, 2; \
+ mfpcr a0, cr0; \
+ and a0, a0, 2; \
+ beqz a0, 1f; \
+ mtfsr x0; \
+1:
+
+#define RVTEST_PASS_NOFP \
+ RVTEST_FP_ENABLE \
+ bnez a0, 2f; \
+ RVTEST_PASS \
+2: \
+
+#define RVTEST_VEC_ENABLE \
+ mfpcr a0, cr0; \
+ ori a0, a0, 4; \
+ mtpcr a0, cr0; \
+ li a0, 0xff; \
+ mtpcr a0, cr18; \
+
+#define RVTEST_CODE_BEGIN \
+ .text; \
+ .align 4; \
+ .global _start; \
+_start: \
+ RVTEST_FP_ENABLE \
+ RVTEST_VEC_ENABLE \
+
+//-----------------------------------------------------------------------
+// End Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_END \
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_FAIL \
+ fence; \
+ beqz x28, 1f; \
+ sll x28, x28, 1; \
+ or x28, x28, 1; \
+ mtpcr x28, cr30; \
+1: b 1b; \
+
+#define RVTEST_PASS \
+ fence; \
+ li x1, 1; \
+ mtpcr x1, cr30; \
+1: b 1b; \
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_DATA_BEGIN
+#define RVTEST_DATA_END
+
+//#define RVTEST_DATA_BEGIN .align 4; .global begin_signature; begin_signature:
+//#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+#endif
diff --git a/env/pt/link.ld b/env/pt/link.ld
new file mode 100644
index 0000000..6b19389
--- /dev/null
+++ b/env/pt/link.ld
@@ -0,0 +1,44 @@
+/*======================================================================*/
+/* Proxy kernel linker script */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+ argument is one of the names used in the BFD library. More
+ specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+ to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+ /* text: test code section */
+ . = 0x00002000;
+ .text :
+ {
+ *(.text)
+ }
+
+ /* data: Initialized data segment */
+ .data :
+ {
+ *(.data)
+ }
+
+ /* End of uninitalized data segement */
+ _end = .;
+}
+
diff --git a/env/pt/pcr.h b/env/pt/pcr.h
new file mode 100644
index 0000000..72043b7
--- /dev/null
+++ b/env/pt/pcr.h
@@ -0,0 +1,93 @@
+#ifndef _RISCV_PCR_H
+#define _RISCV_PCR_H
+
+#define SR_ET 0x00000001
+#define SR_EF 0x00000002
+#define SR_EV 0x00000004
+#define SR_EC 0x00000008
+#define SR_PS 0x00000010
+#define SR_S 0x00000020
+#define SR_U64 0x00000040
+#define SR_S64 0x00000080
+#define SR_VM 0x00000100
+#define SR_IM 0x00FF0000
+#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IM_SHIFT 16
+
+#define PCR_SR 0
+#define PCR_EPC 1
+#define PCR_BADVADDR 2
+#define PCR_EVEC 3
+#define PCR_COUNT 4
+#define PCR_COMPARE 5
+#define PCR_CAUSE 6
+#define PCR_PTBR 7
+#define PCR_SEND_IPI 8
+#define PCR_CLR_IPI 9
+#define PCR_COREID 10
+#define PCR_IMPL 11
+#define PCR_K0 12
+#define PCR_K1 13
+#define PCR_VECBANK 18
+#define PCR_VECCFG 19
+#define PCR_RESET 29
+#define PCR_TOHOST 30
+#define PCR_FROMHOST 31
+
+#define IMPL_ISASIM 1
+#define IMPL_ROCKET 2
+
+#define IRQ_IPI 5
+#define IRQ_TIMER 7
+
+#define CAUSE_MISALIGNED_FETCH 0
+#define CAUSE_FAULT_FETCH 1
+#define CAUSE_ILLEGAL_INSTRUCTION 2
+#define CAUSE_PRIVILEGED_INSTRUCTION 3
+#define CAUSE_FP_DISABLED 4
+#define CAUSE_SYSCALL 6
+#define CAUSE_BREAKPOINT 7
+#define CAUSE_MISALIGNED_LOAD 8
+#define CAUSE_MISALIGNED_STORE 9
+#define CAUSE_FAULT_LOAD 10
+#define CAUSE_FAULT_STORE 11
+#define CAUSE_VECTOR_DISABLED 12
+#define CAUSE_VECTOR_BANK 13
+
+#define CAUSE_VECTOR_MISALIGNED_FETCH 24
+#define CAUSE_VECTOR_FAULT_FETCH 25
+#define CAUSE_VECTOR_ILLEGAL_INSTRUCTION 26
+#define CAUSE_VECTOR_ILLEGAL_COMMAND 27
+#define CAUSE_VECTOR_MISALIGNED_LOAD 28
+#define CAUSE_VECTOR_MISALIGNED_STORE 29
+#define CAUSE_VECTOR_FAULT_LOAD 30
+#define CAUSE_VECTOR_FAULT_STORE 31
+
+#ifdef __riscv
+
+#define ASM_CR(r) _ASM_CR(r)
+#define _ASM_CR(r) cr##r
+
+#ifndef __ASSEMBLER__
+
+#define mtpcr(reg,val) ({ long __tmp = (long)(val), __tmp2; \
+ asm volatile ("mtpcr %0,%1,cr%2" : "=r"(__tmp2) : "r"(__tmp),"i"(reg)); \
+ __tmp2; })
+
+#define mfpcr(reg) ({ long __tmp; \
+ asm volatile ("mfpcr %0,cr%1" : "=r"(__tmp) : "i"(reg)); \
+ __tmp; })
+
+#define setpcr(reg,val) ({ long __tmp; \
+ asm volatile ("setpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+ __tmp; })
+
+#define clearpcr(reg,val) ({ long __tmp; \
+ asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+ __tmp; })
+
+#endif
+
+#endif
+
+#endif
diff --git a/env/pt/riscv_test.h b/env/pt/riscv_test.h
new file mode 100644
index 0000000..4c42803
--- /dev/null
+++ b/env/pt/riscv_test.h
@@ -0,0 +1,236 @@
+#ifndef _ENV_PHYSICAL_SINGLE_CORE_TIMER_H
+#define _ENV_PHYSICAL_SINGLE_CORE_TIMER_H
+
+#include "pcr.h"
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U \
+
+#define RVTEST_FP_ENABLE \
+ setpcr cr0, 2; \
+ mfpcr a0, cr0; \
+ and a0, a0, 2; \
+ beqz a0, 1f; \
+ mtfsr x0; \
+1:
+
+#define RVTEST_PASS_NOFP \
+ RVTEST_FP_ENABLE \
+ bnez a0, 2f; \
+ RVTEST_PASS \
+2: \
+
+#define RVTEST_VEC_ENABLE \
+ mfpcr a0, cr0; \
+ ori a0, a0, 4; \
+ mtpcr a0, cr0; \
+ li a0, 0xff; \
+ mtpcr a0, cr18; \
+
+#define RVTEST_CODE_BEGIN \
+ .text; \
+ .align 4; \
+ .global _start; \
+_start: \
+ RVTEST_FP_ENABLE \
+ RVTEST_VEC_ENABLE \
+ mfpcr a0, cr10; 1: bnez a0, 1b; \
+ ENABLE_TIMER_INTERRUPT \
+
+//-----------------------------------------------------------------------
+// End Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_END \
+ XCPT_HANDLER \
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_PASS \
+ fence; \
+ li x1, 1; \
+ mtpcr x1, cr30; \
+1: b 1b; \
+
+#define RVTEST_FAIL \
+ fence; \
+ beqz x28, 1f; \
+ sll x28, x28, 1; \
+ or x28, x28, 1; \
+ mtpcr x28, cr30; \
+1: b 1b; \
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_DATA_BEGIN \
+ .align 3; \
+regspill: \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+evac: \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+ .dword 0xdeadbeefcafebabe; \
+
+#define RVTEST_DATA_END
+
+//#define RVTEST_DATA_BEGIN .align 4; .global begin_signature; begin_signature:
+//#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+//-----------------------------------------------------------------------
+// Misc
+//-----------------------------------------------------------------------
+
+#define ENABLE_TIMER_INTERRUPT \
+ mtpcr x0,ASM_CR(PCR_CLR_IPI);\
+ mfpcr a0,ASM_CR(PCR_SR); \
+ li a1, SR_ET|SR_IM; \
+ or a0,a0,a1; \
+ mtpcr a0,ASM_CR(PCR_SR); \
+ la a0,handler; \
+ mtpcr a0,ASM_CR(PCR_EVEC); \
+ mtpcr x0,ASM_CR(PCR_COUNT); \
+ addi a0,x0,60; \
+ mtpcr a0,ASM_CR(PCR_COMPARE);\
+
+#define XCPT_HANDLER \
+handler: \
+ mtpcr a0,ASM_CR(PCR_K0); \
+ mtpcr a1,ASM_CR(PCR_K1); \
+ la a0,regspill; \
+ sd a2,0(a0); \
+ sd a3,8(a0); \
+ sd a4,16(a0); \
+ sd a5,24(a0); \
+ sd s0,32(a0); \
+ sd s1,40(a0); \
+ mfpcr s1,ASM_CR(PCR_VECBANK);\
+ mfpcr s0,ASM_CR(PCR_VECCFG); \
+ la a0,evac; \
+ vxcptevac a0; \
+ mtpcr s1,ASM_CR(PCR_VECBANK);\
+ srli a1,s0,12; \
+ andi a1,a1,0x3f; \
+ srli a2,s0,18; \
+ andi a2,a2,0x3f; \
+ vvcfg a1,a2; \
+ li a2,0xfff; \
+ and a1,s0,a2; \
+ vsetvl a1,a1; \
+ vxcpthold; \
+ li a5,0; \
+handler_loop: \
+ ld a1,0(a0); \
+ addi a0,a0,8; \
+ blt a1,x0,done; \
+ srli a2,a1,32; \
+ andi a2,a2,0x1; \
+ beq a2,x0,vcnt; \
+vcmd: \
+ beq a5,x0,vcmd_skip; \
+ venqcmd a4,a3; \
+vcmd_skip: \
+ li a5,1; \
+ move a4,a1; \
+ srli a3,a4,36; \
+ andi a3,a3,0x1; \
+vimm1: \
+ srli a2,a4,35; \
+ andi a2,a2,0x1; \
+ beq a2,x0,vimm2; \
+ ld a1,0(a0); \
+ addi a0,a0,8; \
+ venqimm1 a1,a3; \
+vimm2: \
+ srli a2,a4,34; \
+ andi a2,a2,0x1; \
+ beq a2,x0,end; \
+ ld a1,0(a0); \
+ addi a0,a0,8; \
+ venqimm2 a1,a3; \
+ j end; \
+vcnt: \
+ ld a2,0(a0); \
+ srli a2,a2,31; \
+ andi a2,a2,0x2; \
+ or a3,a3,a2; \
+ venqcnt a1,a3; \
+end: \
+ j handler_loop; \
+done: \
+ beq a5,x0,done_skip; \
+ venqcmd a4,a3; \
+done_skip: \
+ la a0,regspill; \
+ ld a2,0(a0); \
+ ld a3,8(a0); \
+ ld a4,16(a0); \
+ ld a5,24(a0); \
+ ld s0,32(a0); \
+ ld s1,40(a0); \
+ mfpcr a0,ASM_CR(PCR_COUNT); \
+ addi a0,a0,60; \
+ mtpcr a0,ASM_CR(PCR_COMPARE);\
+ mfpcr a0,ASM_CR(PCR_K0); \
+ mfpcr a1,ASM_CR(PCR_K1); \
+ eret; \
+
+#endif
diff --git a/env/v/entry.S b/env/v/entry.S
new file mode 100644
index 0000000..35eaae3
--- /dev/null
+++ b/env/v/entry.S
@@ -0,0 +1,171 @@
+#include "riscv_test.h"
+
+#ifdef __riscv64
+# define STORE sd
+# define LOAD ld
+# define REGBYTES 8
+#else
+# define STORE sw
+# define LOAD lw
+# define REGBYTES 4
+#endif
+
+ .text
+ .global _start
+_start:
+ la sp, stack_top
+ li a1, 1337
+ la a0, userstart
+ j vm_boot
+
+save_tf: # write the trap frame onto the stack
+
+ # save gprs
+ STORE x3,3*REGBYTES(x2)
+ STORE x4,4*REGBYTES(x2)
+ STORE x5,5*REGBYTES(x2)
+ STORE x6,6*REGBYTES(x2)
+ STORE x7,7*REGBYTES(x2)
+ STORE x8,8*REGBYTES(x2)
+ STORE x9,9*REGBYTES(x2)
+ STORE x10,10*REGBYTES(x2)
+ STORE x11,11*REGBYTES(x2)
+ STORE x12,12*REGBYTES(x2)
+ STORE x13,13*REGBYTES(x2)
+ STORE x14,14*REGBYTES(x2)
+ STORE x15,15*REGBYTES(x2)
+ STORE x16,16*REGBYTES(x2)
+ STORE x17,17*REGBYTES(x2)
+ STORE x18,18*REGBYTES(x2)
+ STORE x19,19*REGBYTES(x2)
+ STORE x20,20*REGBYTES(x2)
+ STORE x21,21*REGBYTES(x2)
+ STORE x22,22*REGBYTES(x2)
+ STORE x23,23*REGBYTES(x2)
+ STORE x24,24*REGBYTES(x2)
+ STORE x25,25*REGBYTES(x2)
+ STORE x26,26*REGBYTES(x2)
+ STORE x27,27*REGBYTES(x2)
+ STORE x28,28*REGBYTES(x2)
+ STORE x29,29*REGBYTES(x2)
+ STORE x30,30*REGBYTES(x2)
+ STORE x31,31*REGBYTES(x2)
+
+ mfpcr x3,ASM_CR(PCR_K0)
+ STORE x3,1*REGBYTES(x2) # x1 is in PCR_K0
+ mfpcr x3,ASM_CR(PCR_K1)
+ STORE x3,2*REGBYTES(x2) # x2 is in PCR_K1
+
+ # get sr, epc, badvaddr, cause
+ mfpcr x3,ASM_CR(PCR_SR) # sr
+ STORE x3,32*REGBYTES(x2)
+ mfpcr x4,ASM_CR(PCR_EPC) # epc
+ STORE x4,33*REGBYTES(x2)
+ mfpcr x3,ASM_CR(PCR_BADVADDR) # badvaddr
+ STORE x3,34*REGBYTES(x2)
+ mfpcr x3,ASM_CR(PCR_CAUSE) # cause
+ STORE x3,35*REGBYTES(x2)
+
+ # get faulting insn, if it wasn't a fetch-related trap
+ li x5, CAUSE_MISALIGNED_FETCH
+ li x6, CAUSE_FAULT_FETCH
+ beq x3, x5, 1f
+ beq x3, x6, 1f
+ lh x3,0(x4)
+ lh x4,2(x4)
+ sh x3, 36*REGBYTES(x2)
+ sh x4,2+36*REGBYTES(x2)
+1:
+
+ mfpcr x3,ASM_CR(PCR_VECBANK) # vecbank
+ STORE x3,37*REGBYTES(x2)
+ mfpcr x3,ASM_CR(PCR_VECCFG) # veccfg
+ STORE x3,38*REGBYTES(x2)
+
+ ret
+
+ .globl pop_tf
+pop_tf: # write the trap frame onto the stack
+ # restore gprs
+ LOAD a1,32*REGBYTES(a0) # restore sr (should disable interrupts)
+ mtpcr a1,ASM_CR(PCR_SR)
+
+ LOAD x1,1*REGBYTES(a0)
+ mtpcr x1,ASM_CR(PCR_K0)
+ LOAD x1,2*REGBYTES(a0)
+ mtpcr x1,ASM_CR(PCR_K1)
+ move x1,a0
+ LOAD x3,3*REGBYTES(x1)
+ LOAD x4,4*REGBYTES(x1)
+ LOAD x5,5*REGBYTES(x1)
+ LOAD x6,6*REGBYTES(x1)
+ LOAD x7,7*REGBYTES(x1)
+ LOAD x8,8*REGBYTES(x1)
+ LOAD x9,9*REGBYTES(x1)
+ LOAD x10,10*REGBYTES(x1)
+ LOAD x11,11*REGBYTES(x1)
+ LOAD x12,12*REGBYTES(x1)
+ LOAD x13,13*REGBYTES(x1)
+ LOAD x14,14*REGBYTES(x1)
+ LOAD x15,15*REGBYTES(x1)
+ LOAD x16,16*REGBYTES(x1)
+ LOAD x17,17*REGBYTES(x1)
+ LOAD x18,18*REGBYTES(x1)
+ LOAD x19,19*REGBYTES(x1)
+ LOAD x20,20*REGBYTES(x1)
+ LOAD x21,21*REGBYTES(x1)
+ LOAD x22,22*REGBYTES(x1)
+ LOAD x23,23*REGBYTES(x1)
+ LOAD x24,24*REGBYTES(x1)
+ LOAD x25,25*REGBYTES(x1)
+ LOAD x26,26*REGBYTES(x1)
+ LOAD x27,27*REGBYTES(x1)
+ LOAD x28,28*REGBYTES(x1)
+ LOAD x29,29*REGBYTES(x1)
+ LOAD x30,30*REGBYTES(x1)
+ LOAD x31,31*REGBYTES(x1)
+
+ # gtfo!
+ LOAD x2,33*REGBYTES(x1)
+ mtpcr x2,ASM_CR(PCR_EPC)
+ mfpcr x1,ASM_CR(PCR_K0)
+ mfpcr x2,ASM_CR(PCR_K1)
+ eret
+
+ .global trap_entry
+trap_entry:
+ mtpcr ra,ASM_CR(PCR_K0)
+ mtpcr x2,ASM_CR(PCR_K1)
+
+ # coming from kernel?
+ mfpcr ra,ASM_CR(PCR_SR)
+ and ra,ra,SR_PS
+ bnez ra, 1f
+
+ # no, so start at the top of the stack
+ la x2,stack_top+MAX_TEST_PAGES*PGSIZE-SIZEOF_TRAPFRAME_T
+ jal save_tf
+ move sp,x2
+ setpcr ASM_CR(PCR_SR), SR_ET
+ move a0,x2
+ mfpcr ra,ASM_CR(PCR_SR)
+ and ra,ra,SR_EV
+ beqz ra, 2f
+ addi x2,x2,39*REGBYTES
+ vxcptsave x2
+2:jal handle_trap
+
+ # when coming from kernel, continue below its stack
+1:add x2, sp, -SIZEOF_TRAPFRAME_T
+ jal save_tf
+ move sp,x2
+ setpcr ASM_CR(PCR_SR), SR_ET
+ move a0,x2
+ jal handle_trap
+
+ .bss
+ .global stack_bot
+ .global stack_top
+stack_bot:
+ .skip 32768
+stack_top:
diff --git a/env/v/link.ld b/env/v/link.ld
new file mode 100644
index 0000000..4efeaaa
--- /dev/null
+++ b/env/v/link.ld
@@ -0,0 +1,50 @@
+/*======================================================================*/
+/* Proxy kernel linker script */
+/*======================================================================*/
+/* This is the linker script used when building the proxy kernel. */
+
+/*----------------------------------------------------------------------*/
+/* Setup */
+/*----------------------------------------------------------------------*/
+
+/* The OUTPUT_ARCH command specifies the machine architecture where the
+ argument is one of the names used in the BFD library. More
+ specifically one of the entires in bfd/cpu-mips.c */
+
+OUTPUT_ARCH( "riscv" )
+
+/* The ENTRY command specifies the entry point (ie. first instruction
+ to execute). The symbol _start should be defined in each test. */
+
+ENTRY( _start )
+
+/*----------------------------------------------------------------------*/
+/* Sections */
+/*----------------------------------------------------------------------*/
+
+SECTIONS
+{
+
+ /* text: test code section */
+ . = 0x00002000;
+ .text :
+ {
+ *(.text)
+ }
+
+ /* data: Initialized data segment */
+ .data ALIGN(0x2000):
+ {
+ *(.data)
+ }
+
+ /* bss: Initialized bss segment */
+ .bss ALIGN(0x2000):
+ {
+ *(.bss)
+ }
+
+ /* End of uninitalized bss segement */
+ _end = .;
+}
+
diff --git a/env/v/pcr.h b/env/v/pcr.h
new file mode 100644
index 0000000..72043b7
--- /dev/null
+++ b/env/v/pcr.h
@@ -0,0 +1,93 @@
+#ifndef _RISCV_PCR_H
+#define _RISCV_PCR_H
+
+#define SR_ET 0x00000001
+#define SR_EF 0x00000002
+#define SR_EV 0x00000004
+#define SR_EC 0x00000008
+#define SR_PS 0x00000010
+#define SR_S 0x00000020
+#define SR_U64 0x00000040
+#define SR_S64 0x00000080
+#define SR_VM 0x00000100
+#define SR_IM 0x00FF0000
+#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IM_SHIFT 16
+
+#define PCR_SR 0
+#define PCR_EPC 1
+#define PCR_BADVADDR 2
+#define PCR_EVEC 3
+#define PCR_COUNT 4
+#define PCR_COMPARE 5
+#define PCR_CAUSE 6
+#define PCR_PTBR 7
+#define PCR_SEND_IPI 8
+#define PCR_CLR_IPI 9
+#define PCR_COREID 10
+#define PCR_IMPL 11
+#define PCR_K0 12
+#define PCR_K1 13
+#define PCR_VECBANK 18
+#define PCR_VECCFG 19
+#define PCR_RESET 29
+#define PCR_TOHOST 30
+#define PCR_FROMHOST 31
+
+#define IMPL_ISASIM 1
+#define IMPL_ROCKET 2
+
+#define IRQ_IPI 5
+#define IRQ_TIMER 7
+
+#define CAUSE_MISALIGNED_FETCH 0
+#define CAUSE_FAULT_FETCH 1
+#define CAUSE_ILLEGAL_INSTRUCTION 2
+#define CAUSE_PRIVILEGED_INSTRUCTION 3
+#define CAUSE_FP_DISABLED 4
+#define CAUSE_SYSCALL 6
+#define CAUSE_BREAKPOINT 7
+#define CAUSE_MISALIGNED_LOAD 8
+#define CAUSE_MISALIGNED_STORE 9
+#define CAUSE_FAULT_LOAD 10
+#define CAUSE_FAULT_STORE 11
+#define CAUSE_VECTOR_DISABLED 12
+#define CAUSE_VECTOR_BANK 13
+
+#define CAUSE_VECTOR_MISALIGNED_FETCH 24
+#define CAUSE_VECTOR_FAULT_FETCH 25
+#define CAUSE_VECTOR_ILLEGAL_INSTRUCTION 26
+#define CAUSE_VECTOR_ILLEGAL_COMMAND 27
+#define CAUSE_VECTOR_MISALIGNED_LOAD 28
+#define CAUSE_VECTOR_MISALIGNED_STORE 29
+#define CAUSE_VECTOR_FAULT_LOAD 30
+#define CAUSE_VECTOR_FAULT_STORE 31
+
+#ifdef __riscv
+
+#define ASM_CR(r) _ASM_CR(r)
+#define _ASM_CR(r) cr##r
+
+#ifndef __ASSEMBLER__
+
+#define mtpcr(reg,val) ({ long __tmp = (long)(val), __tmp2; \
+ asm volatile ("mtpcr %0,%1,cr%2" : "=r"(__tmp2) : "r"(__tmp),"i"(reg)); \
+ __tmp2; })
+
+#define mfpcr(reg) ({ long __tmp; \
+ asm volatile ("mfpcr %0,cr%1" : "=r"(__tmp) : "i"(reg)); \
+ __tmp; })
+
+#define setpcr(reg,val) ({ long __tmp; \
+ asm volatile ("setpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+ __tmp; })
+
+#define clearpcr(reg,val) ({ long __tmp; \
+ asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \
+ __tmp; })
+
+#endif
+
+#endif
+
+#endif
diff --git a/env/v/riscv_test.h b/env/v/riscv_test.h
new file mode 100644
index 0000000..4d9cceb
--- /dev/null
+++ b/env/v/riscv_test.h
@@ -0,0 +1,129 @@
+#ifndef _ENV_VIRTUAL_SINGLE_CORE_H
+#define _ENV_VIRTUAL_SINGLE_CORE_H
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U \
+
+#define RVTEST_RV64S \
+
+#define RVTEST_FP_ENABLE \
+ mfpcr t0, cr0; \
+ or t0, t0, 2; \
+ mtpcr t0, cr0; \
+ mtfsr x0; \
+
+#define RVTEST_VEC_ENABLE \
+ mfpcr t0, cr0; \
+ ori t0, t0, 4; \
+ mtpcr t0, cr0; \
+ li t0, 0xff; \
+ mtpcr t0, cr11; \
+
+#define RVTEST_CODE_BEGIN \
+ .text; \
+ .align 13; \
+ .global userstart; \
+userstart: \
+
+//-----------------------------------------------------------------------
+// End Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_END \
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_PASS li a0, 1; syscall;
+#define RVTEST_FAIL sll a0, x28, 1; 1:beqz a0, 1b; or a0, a0, 1; syscall;
+
+#define RVTEST_PASS_NOFP li a0, 1234; syscall;
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_DATA_BEGIN
+#define RVTEST_DATA_END
+
+//#define RVTEST_DATA_BEGIN .align 4; .global begin_signature; begin_signature:
+//#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+//-----------------------------------------------------------------------
+// Supervisor mode definitions and macros
+//-----------------------------------------------------------------------
+
+#include "pcr.h"
+
+#define vvcfg(nxregs, nfregs) ({ \
+ asm volatile ("vvcfg %0,%1" : : "r"(nxregs), "r"(nfregs)); })
+
+#define vsetvl(vl) ({ long __tmp; \
+ asm volatile ("vsetvl %0,%1" : "=r"(__tmp) : "r"(vl)); })
+
+#define vcfg(word) ({ vvcfg((word)>>12, (word)>>18); vsetvl((word)); })
+
+#define dword_bit_cmd(dw) ((dw >> 32) & 0x1)
+#define dword_bit_cnt(dw) (!dword_bit_cmd(dw))
+#define dword_bit_imm1(dw) ((dw >> 35) & 0x1)
+#define dword_bit_imm2(dw) ((dw >> 34) & 0x1)
+#define dword_bit_pf(dw) ((dw >> 36) & 0x1)
+
+#define fencevl() ({ \
+ asm volatile ("fence.v.l" ::: "memory"); })
+
+#define vxcptkill() ({ \
+ asm volatile ("vxcptkill"); })
+
+#define vxcpthold() ({ \
+ asm volatile ("vxcpthold"); })
+
+#define venqcmd(bits, pf) ({ \
+ asm volatile ("venqcmd %0,%1" : : "r"(bits), "r"(pf)); })
+
+#define venqimm1(bits, pf) ({ \
+ asm volatile ("venqimm1 %0,%1" : : "r"(bits), "r"(pf)); })
+
+#define venqimm2(bits, pf) ({ \
+ asm volatile ("venqimm2 %0,%1" : : "r"(bits), "r"(pf)); })
+
+#define venqcnt(bits, pf) ({ \
+ asm volatile ("venqcnt %0,%1" :: "r"(bits), "r"(pf)); })
+
+#define MAX_TEST_PAGES 63 // this must be the period of the LFSR below
+#define LFSR_NEXT(x) (((((x)^((x)>>1)) & 1) << 5) | ((x) >> 1))
+
+#define PGSHIFT 13
+#define PGSIZE (1 << PGSHIFT)
+
+#define SIZEOF_TRAPFRAME_T 1336
+
+#ifndef __ASSEMBLER__
+
+
+typedef unsigned long pte_t;
+#define LEVELS (sizeof(pte_t) == sizeof(uint64_t) ? 3 : 2)
+#define PTIDXBITS (PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2))
+#define VPN_BITS (PTIDXBITS * LEVELS)
+#define VA_BITS (VPN_BITS + PGSHIFT)
+#define PTES_PER_PT (PGSIZE/sizeof(pte_t))
+
+typedef struct
+{
+ long gpr[32];
+ long sr;
+ long epc;
+ long badvaddr;
+ long cause;
+ long insn;
+ long vecbank;
+ long veccfg;
+ long evac[128];
+} trapframe_t;
+#endif
+
+#endif
diff --git a/env/v/vm.c b/env/v/vm.c
new file mode 100644
index 0000000..37ef19e
--- /dev/null
+++ b/env/v/vm.c
@@ -0,0 +1,263 @@
+#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));
+}
+
+#define stringify1(x) #x
+#define stringify(x) stringify1(x)
+#define assert(x) do { \
+ if (x) break; \
+ cputstring("Assertion failed: " stringify(x)); \
+ terminate(3); \
+ while(1); \
+} 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 | 0x3F2;
+ mtpcr(PCR_PTBR, l1pt);
+
+ 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);
+}
+
+void emulate_vxcptsave(trapframe_t* tf)
+{
+ long where = tf->gpr[(tf->insn >> 22) & 0x1F];
+
+ asm volatile ("vxcptevac %0" : : "r"(where));
+ fencevl();
+}
+
+void do_vxcptrestore(long* where)
+{
+ vxcpthold();
+
+ int idx = 0;
+ 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);
+ }
+}
+
+void emulate_vxcptrestore(trapframe_t* tf)
+{
+ long* where = (long*)tf->gpr[(tf->insn >> 22) & 0x1F];
+ vxcptkill();
+ vcfg(tf->veccfg);
+ do_vxcptrestore(where);
+}
+
+void restore_vector(trapframe_t* tf)
+{
+ mtpcr(PCR_VECBANK, tf->vecbank);
+ vcfg(tf->veccfg);
+
+ if (mfpcr(PCR_IMPL) == IMPL_ROCKET)
+ do_vxcptrestore(tf->evac);
+ else
+ asm volatile("vxcptrestore %0" : : "r"(tf->evac) : "memory");
+}
+
+void handle_trap(trapframe_t* tf)
+{
+ if (tf->cause == CAUSE_SYSCALL)
+ {
+ int n = tf->gpr[18];
+ if (n == 1234) // TEST_PASS_NOFP
+ {
+ if (mfpcr(PCR_SR) & SR_EF)
+ {
+ tf->epc += 4;
+ goto out;
+ }
+ n = 1;
+ }
+
+ for (long i = 1; i < MAX_TEST_PAGES; i++)
+ evict(i*PGSIZE);
+
+ terminate(n);
+ while(1);
+ }
+ else if (tf->cause == CAUSE_FAULT_FETCH)
+ handle_fault(tf->epc);
+ else if (tf->cause == CAUSE_ILLEGAL_INSTRUCTION)
+ {
+ if ((tf->insn & 0xF83FFFFF) == 0x37B)
+ emulate_vxcptsave(tf);
+ else if ((tf->insn & 0xF83FFFFF) == 0x77B)
+ emulate_vxcptrestore(tf);
+ else
+ assert(0);
+ tf->epc += 4;
+ }
+ else if (tf->cause == CAUSE_FAULT_LOAD || tf->cause == CAUSE_FAULT_STORE ||
+ tf->cause == CAUSE_VECTOR_FAULT_LOAD || tf->cause == CAUSE_VECTOR_FAULT_STORE ||
+ tf->cause == CAUSE_VECTOR_FAULT_FETCH)
+ handle_fault(tf->badvaddr);
+ else
+ assert(0);
+
+out:
+ if (!(tf->sr & SR_PS) && (tf->sr & SR_EV))
+ restore_vector(tf);
+ pop_tf(tf);
+}
+
+void vm_boot(long test_addr, long seed)
+{
+ while (mfpcr(PCR_COREID) > 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 | 1;
+ l2pt[0] = (pte_t)l3pt | 1;
+ for (long i = 0; i < MAX_TEST_PAGES; i++)
+ l3pt[i] = l3pt[i+MAX_TEST_PAGES] = (i*PGSIZE) | 0x382;
+
+ mtpcr(PCR_PTBR, l1pt);
+ mtpcr(PCR_SR, mfpcr(PCR_SR) | SR_VM | SR_EF);
+
+ if (mfpcr(PCR_SR) & SR_EF)
+ asm volatile ("mtfsr x0");
+
+ // relocate
+ long adjustment = RELOC(0L), tmp;
+ mtpcr(PCR_EVEC, (char*)&trap_entry + adjustment);
+ asm volatile ("add sp, sp, %1; rdpc %0; addi %0, %0, 16; add %0, %0, %1; jr %0" : "=&r"(tmp) : "r"(adjustment));
+
+ memset(RELOC(&l3pt[0]), 0, MAX_TEST_PAGES*sizeof(pte_t));
+ mtpcr(PCR_PTBR, l1pt);
+
+ trapframe_t tf;
+ memset(&tf, 0, sizeof(tf));
+ tf.sr = SR_EF | SR_EV | SR_S | SR_U64 | SR_S64 | SR_VM;
+ tf.epc = test_addr;
+
+ pop_tf(&tf);
+}