/* * Utilities implemented by using the Spike HTIF. * * codes are borrowed from riscv-pk (https://github.com/riscv/riscv-pk) */ #include "atomic.h" #include "spike_htif.h" #include "util/functions.h" #include "util/snprintf.h" #include "spike_utils.h" #include "spike_file.h" //============= encapsulating htif syscalls, invoking Spike functions ============= long frontend_syscall(long n, uint64 a0, uint64 a1, uint64 a2, uint64 a3, uint64 a4, uint64 a5, uint64 a6) { static volatile uint64 magic_mem[8]; static spinlock_t lock = SPINLOCK_INIT; spinlock_lock(&lock); magic_mem[0] = n; magic_mem[1] = a0; magic_mem[2] = a1; magic_mem[3] = a2; magic_mem[4] = a3; magic_mem[5] = a4; magic_mem[6] = a5; magic_mem[7] = a6; htif_syscall((uintptr_t)magic_mem); long ret = magic_mem[0]; spinlock_unlock(&lock); return ret; } //=============== Spike-assisted printf, output string to terminal =============== static uintptr_t mcall_console_putchar(uint8 ch) { if (htif) { htif_console_putchar(ch); } return 0; } void vprintk(const char* s, va_list vl) { char out[256]; int res = vsnprintf(out, sizeof(out), s, vl); //you need spike_file_init before this call spike_file_write(stderr, out, res < sizeof(out) ? res : sizeof(out)); } void printk(const char* s, ...) { va_list vl; va_start(vl, s); vprintk(s, vl); va_end(vl); } void putstring(const char* s) { while (*s) mcall_console_putchar(*s++); } void vprintm(const char* s, va_list vl) { char buf[256]; vsnprintf(buf, sizeof buf, s, vl); putstring(buf); } void sprint(const char* s, ...) { va_list vl; va_start(vl, s); vprintk(s, vl); va_end(vl); } //=============== Spike-assisted termination, panic and assert =============== void poweroff(uint16_t code) { assert(htif); sprint("Power off\r\n"); if (htif) { htif_poweroff(); } else { // we consider only one HART case in PKE experiments. May extend this later. // send_ipi_many(0, IPI_HALT); while (1) { asm volatile("wfi\n"); } } } void shutdown(int code) { sprint("System is shutting down with exit code %d.\n", code); frontend_syscall(HTIFSYS_exit, code, 0, 0, 0, 0, 0, 0); while (1) ; } void do_panic(const char* s, ...) { va_list vl; va_start(vl, s); sprint(s, vl); shutdown(-1); va_end(vl); } void kassert_fail(const char* s) { register uintptr_t ra asm("ra"); do_panic("assertion failed @ %p: %s\n", ra, s); // sprint("assertion failed @ %p: %s\n", ra, s); shutdown(-1); }