5 #include "riscv_test.h"
8 void pop_tf(trapframe_t
*);
10 static void cputchar(int x
)
12 while (mtpcr(PCR_TOHOST
, 0x0101000000000000 | (unsigned char)x
));
15 static void cputstring(const char* s
)
22 static void terminate(int code
)
24 while (mtpcr(PCR_TOHOST
, code
));
28 #define stringify1(x) #x
29 #define stringify(x) stringify1(x)
30 #define assert(x) do { \
32 cputstring("Assertion failed: " stringify(x)); \
36 #define RELOC(x) ((typeof(x))((char*)(x) + (PGSIZE*MAX_TEST_PAGES)))
38 typedef struct { pte_t addr
; void* next
; } freelist_t
;
40 pte_t l1pt
[PTES_PER_PT
] __attribute__((aligned(PGSIZE
)));
41 pte_t l2pt
[PTES_PER_PT
] __attribute__((aligned(PGSIZE
)));
42 pte_t l3pt
[PTES_PER_PT
] __attribute__((aligned(PGSIZE
)));
43 freelist_t user_mapping
[MAX_TEST_PAGES
];
44 freelist_t freelist_nodes
[MAX_TEST_PAGES
];
45 freelist_t
*freelist_head
, *freelist_tail
;
47 void printhex(uint64_t x
)
50 for (int i
= 0; i
< 16; i
++)
52 str
[15-i
] = (x
& 0xF) + ((x
& 0xF) < 10 ? '0' : 'a'-10);
60 void evict(unsigned long addr
)
62 assert(addr
>= PGSIZE
&& addr
< RELOC(0L));
63 addr
= addr
/PGSIZE
*PGSIZE
;
65 freelist_t
* node
= RELOC(&user_mapping
[addr
/PGSIZE
]);
68 memcpy((void*)RELOC(addr
), (void*)addr
, PGSIZE
);
69 RELOC(&user_mapping
[addr
/PGSIZE
])->addr
= 0;
71 if (*RELOC(&freelist_tail
) == 0)
72 *RELOC(&freelist_head
) = *RELOC(&freelist_tail
) = node
;
75 (*RELOC(&freelist_tail
))->next
= node
;
76 *RELOC(&freelist_tail
) = node
;
81 void handle_fault(unsigned long addr
)
83 assert(addr
>= PGSIZE
&& addr
< RELOC(0L));
84 addr
= addr
/PGSIZE
*PGSIZE
;
86 freelist_t
* node
= *RELOC(&freelist_head
);
88 *RELOC(&freelist_head
) = node
->next
;
89 if (*RELOC(&freelist_head
) == *RELOC(&freelist_tail
))
90 *RELOC(&freelist_tail
) = 0;
92 *RELOC(&l3pt
[addr
/PGSIZE
]) = node
->addr
| PTE_UW
| PTE_UR
| PTE_UX
| PTE_SW
| PTE_SR
| PTE_SX
| PTE_V
;
95 assert(RELOC(&user_mapping
[addr
/PGSIZE
])->addr
== 0);
96 *RELOC(&user_mapping
[addr
/PGSIZE
]) = *node
;
97 memcpy((void*)addr
, (void*)RELOC(addr
), PGSIZE
);
99 __builtin___clear_cache(0,0);
102 static void emulate_vxcptsave(trapframe_t
* tf
)
104 long where
= tf
->gpr
[(tf
->insn
>> 22) & 0x1F];
106 asm volatile ("vxcptevac %0" : : "r"(where
));
110 static void do_vxcptrestore(long* where
)
120 dword
= where
[idx
++];
122 if (dword
< 0) break;
124 if (dword_bit_cnt(dword
))
126 venqcnt(dword
, pf
| (dword_bit_cmd(where
[idx
]) << 1));
137 pf
= dword_bit_pf(cmd
);
139 if (dword_bit_imm1(cmd
))
141 venqimm1(where
[idx
++], pf
);
143 if (dword_bit_imm2(cmd
))
145 venqimm2(where
[idx
++], pf
);
155 static void emulate_vxcptrestore(trapframe_t
* tf
)
157 long* where
= (long*)tf
->gpr
[(tf
->insn
>> 22) & 0x1F];
160 do_vxcptrestore(where
);
163 static void restore_vector(trapframe_t
* tf
)
165 mtpcr(PCR_VECBANK
, tf
->vecbank
);
168 if (mfpcr(PCR_IMPL
) == IMPL_ROCKET
)
169 do_vxcptrestore(tf
->evac
);
171 asm volatile("vxcptrestore %0" : : "r"(tf
->evac
) : "memory");
174 void handle_trap(trapframe_t
* tf
)
176 if (tf
->cause
== CAUSE_SYSCALL
)
180 for (long i
= 1; i
< MAX_TEST_PAGES
; i
++)
185 else if (tf
->cause
== CAUSE_FAULT_FETCH
)
186 handle_fault(tf
->epc
);
187 else if (tf
->cause
== CAUSE_ILLEGAL_INSTRUCTION
)
190 asm ("la %0, 1f; lw %0, 0(%0); b 2f; 1: fssr x0; 2:" : "=r"(fssr
));
192 if (tf
->insn
== fssr
)
193 terminate(1); // FP test on non-FP hardware. "succeed."
195 else if ((tf
->insn
& 0xF83FFFFF) == 0x37B)
196 emulate_vxcptsave(tf
);
197 else if ((tf
->insn
& 0xF83FFFFF) == 0x77B)
198 emulate_vxcptrestore(tf
);
204 else if (tf
->cause
== CAUSE_FAULT_LOAD
|| tf
->cause
== CAUSE_FAULT_STORE
||
205 tf
->cause
== CAUSE_VECTOR_FAULT_LOAD
|| tf
->cause
== CAUSE_VECTOR_FAULT_STORE
||
206 tf
->cause
== CAUSE_VECTOR_FAULT_FETCH
)
207 handle_fault(tf
->badvaddr
);
213 if (!(tf
->sr
& SR_PS
) && (tf
->sr
& SR_EV
))
219 void vm_boot(long test_addr
, long seed
)
221 while (mfpcr(PCR_HARTID
) > 0); // only core 0 proceeds
223 assert(SIZEOF_TRAPFRAME_T
== sizeof(trapframe_t
));
225 seed
= 1 + (seed
% MAX_TEST_PAGES
);
226 freelist_head
= RELOC(&freelist_nodes
[0]);
227 freelist_tail
= RELOC(&freelist_nodes
[MAX_TEST_PAGES
-1]);
228 for (long i
= 0; i
< MAX_TEST_PAGES
; i
++)
230 freelist_nodes
[i
].addr
= (MAX_TEST_PAGES
+i
)*PGSIZE
;
231 freelist_nodes
[i
].next
= RELOC(&freelist_nodes
[i
+1]);
232 seed
= LFSR_NEXT(seed
);
234 freelist_nodes
[MAX_TEST_PAGES
-1].next
= 0;
236 assert(MAX_TEST_PAGES
*2 < PTES_PER_PT
);
237 l1pt
[0] = (pte_t
)l2pt
| PTE_V
| PTE_T
;
238 l2pt
[0] = (pte_t
)l3pt
| PTE_V
| PTE_T
;
239 for (long i
= 0; i
< MAX_TEST_PAGES
; i
++)
240 l3pt
[i
] = l3pt
[i
+MAX_TEST_PAGES
] = (i
*PGSIZE
) | PTE_SW
| PTE_SR
| PTE_SX
| PTE_V
;
242 mtpcr(PCR_PTBR
, l1pt
);
243 mtpcr(PCR_SR
, mfpcr(PCR_SR
) | SR_VM
| SR_EF
);
246 long adjustment
= RELOC(0L), tmp
;
247 mtpcr(PCR_EVEC
, (char*)&trap_entry
+ adjustment
);
248 asm volatile ("add sp, sp, %1\n"
250 "1: add %0, %0, %1\n"
255 memset(RELOC(&l3pt
[0]), 0, MAX_TEST_PAGES
*sizeof(pte_t
));
259 memset(&tf
, 0, sizeof(tf
));
260 tf
.sr
= SR_EF
| SR_EV
| SR_S
| SR_U64
| SR_S64
| SR_VM
;