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
));
27 #define stringify1(x) #x
28 #define stringify(x) stringify1(x)
29 #define assert(x) do { \
31 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
| 0x3F2;
93 mtpcr(PCR_PTBR
, l1pt
);
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 void emulate_vxcptsave(trapframe_t
* tf
)
104 long where
= tf
->gpr
[(tf
->insn
>> 22) & 0x1F];
106 asm volatile ("vxcptevac %0" : : "r"(where
));
110 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 void emulate_vxcptrestore(trapframe_t
* tf
)
157 long* where
= (long*)tf
->gpr
[(tf
->insn
>> 22) & 0x1F];
160 do_vxcptrestore(where
);
163 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
)
179 if (n
== 1234) // TEST_PASS_NOFP
181 if (mfpcr(PCR_SR
) & SR_EF
)
189 for (long i
= 1; i
< MAX_TEST_PAGES
; i
++)
195 else if (tf
->cause
== CAUSE_FAULT_FETCH
)
196 handle_fault(tf
->epc
);
197 else if (tf
->cause
== CAUSE_ILLEGAL_INSTRUCTION
)
199 if ((tf
->insn
& 0xF83FFFFF) == 0x37B)
200 emulate_vxcptsave(tf
);
201 else if ((tf
->insn
& 0xF83FFFFF) == 0x77B)
202 emulate_vxcptrestore(tf
);
207 else if (tf
->cause
== CAUSE_FAULT_LOAD
|| tf
->cause
== CAUSE_FAULT_STORE
||
208 tf
->cause
== CAUSE_VECTOR_FAULT_LOAD
|| tf
->cause
== CAUSE_VECTOR_FAULT_STORE
||
209 tf
->cause
== CAUSE_VECTOR_FAULT_FETCH
)
210 handle_fault(tf
->badvaddr
);
215 if (!(tf
->sr
& SR_PS
) && (tf
->sr
& SR_EV
))
220 void vm_boot(long test_addr
, long seed
)
222 while (mfpcr(PCR_COREID
) > 0); // only core 0 proceeds
224 assert(SIZEOF_TRAPFRAME_T
== sizeof(trapframe_t
));
226 seed
= 1 + (seed
% MAX_TEST_PAGES
);
227 freelist_head
= RELOC(&freelist_nodes
[0]);
228 freelist_tail
= RELOC(&freelist_nodes
[MAX_TEST_PAGES
-1]);
229 for (long i
= 0; i
< MAX_TEST_PAGES
; i
++)
231 freelist_nodes
[i
].addr
= (MAX_TEST_PAGES
+i
)*PGSIZE
;
232 freelist_nodes
[i
].next
= RELOC(&freelist_nodes
[i
+1]);
233 seed
= LFSR_NEXT(seed
);
235 freelist_nodes
[MAX_TEST_PAGES
-1].next
= 0;
237 assert(MAX_TEST_PAGES
*2 < PTES_PER_PT
);
238 l1pt
[0] = (pte_t
)l2pt
| 1;
239 l2pt
[0] = (pte_t
)l3pt
| 1;
240 for (long i
= 0; i
< MAX_TEST_PAGES
; i
++)
241 l3pt
[i
] = l3pt
[i
+MAX_TEST_PAGES
] = (i
*PGSIZE
) | 0x382;
243 mtpcr(PCR_PTBR
, l1pt
);
244 mtpcr(PCR_SR
, mfpcr(PCR_SR
) | SR_VM
| SR_EF
);
246 if (mfpcr(PCR_SR
) & SR_EF
)
247 asm volatile ("mtfsr x0");
250 long adjustment
= RELOC(0L), tmp
;
251 mtpcr(PCR_EVEC
, (char*)&trap_entry
+ adjustment
);
252 asm volatile ("add sp, sp, %1; rdpc %0; addi %0, %0, 16; add %0, %0, %1; jr %0" : "=&r"(tmp
) : "r"(adjustment
));
254 memset(RELOC(&l3pt
[0]), 0, MAX_TEST_PAGES
*sizeof(pte_t
));
255 mtpcr(PCR_PTBR
, l1pt
);
258 memset(&tf
, 0, sizeof(tf
));
259 tf
.sr
= SR_EF
| SR_EV
| SR_S
| SR_U64
| SR_S64
| SR_VM
;