riscv-pke/spike_interface/spike_utils.c

120 lines
2.5 KiB
C

/*
* 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);
}