From 611290ccde8d76c1973a37d82a5d4b3e4b7b90c4 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 15 Feb 2017 18:59:21 -0800 Subject: Cleanly separate HTIF code; don't poll keyboard on timer interrupt --- machine/htif.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ machine/htif.h | 5 +++ machine/machine.mk.in | 1 + machine/mcall.h | 1 - machine/mtrap.c | 89 ++++----------------------------------------------- machine/mtrap.h | 1 - 6 files changed, 90 insertions(+), 85 deletions(-) create mode 100644 machine/htif.c (limited to 'machine') diff --git a/machine/htif.c b/machine/htif.c new file mode 100644 index 0000000..a513305 --- /dev/null +++ b/machine/htif.c @@ -0,0 +1,78 @@ +#include "htif.h" +#include "atomic.h" +#include "mtrap.h" + +volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif"))); +volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif"))); +volatile int htif_console_buf; +static spinlock_t htif_lock = SPINLOCK_INIT; + +static void request_htif_keyboard_interrupt() +{ + assert(tohost == 0); + tohost = TOHOST_CMD(1, 0, 0); +} + +static void __check_fromhost() +{ + // we should only be interrupted by keypresses + uint64_t fh = fromhost; + if (!fh) + return; + if (!(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0)) + die("unexpected htif interrupt"); + htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh); + fromhost = 0; +} + +int htif_console_getchar() +{ + if (spinlock_trylock(&htif_lock) == 0) { + __check_fromhost(); + spinlock_unlock(&htif_lock); + } + + int ch = atomic_swap(&htif_console_buf, -1); + if (ch >= 0) + request_htif_keyboard_interrupt(); + return ch - 1; +} + +static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) +{ + spinlock_lock(&htif_lock); + while (tohost) + __check_fromhost(); + tohost = TOHOST_CMD(dev, cmd, data); + + while (1) { + uint64_t fh = fromhost; + if (fh) { + if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) { + fromhost = 0; + break; + } + __check_fromhost(); + } + } + spinlock_unlock(&htif_lock); +} + +uintptr_t htif_syscall(uintptr_t arg) +{ + do_tohost_fromhost(0, 0, arg); + return 0; +} + +void htif_console_putchar(uint8_t ch) +{ + do_tohost_fromhost(1, 1, ch); +} + +void htif_poweroff() +{ + while (1) { + fromhost = 0; + tohost = 1; + } +} diff --git a/machine/htif.h b/machine/htif.h index 7107ddb..f47e965 100644 --- a/machine/htif.h +++ b/machine/htif.h @@ -15,4 +15,9 @@ #define FROMHOST_CMD(fromhost_value) ((uint64_t)(fromhost_value) << 8 >> 56) #define FROMHOST_DATA(fromhost_value) ((uint64_t)(fromhost_value) << 16 >> 16) +void htif_console_putchar(uint8_t); +int htif_console_getchar(); +void htif_poweroff() __attribute__((noreturn)); +uintptr_t htif_syscall(uintptr_t); + #endif diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 6568dc5..e224982 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -18,6 +18,7 @@ machine_hdrs = \ machine_c_srcs = \ mtrap.c \ minit.c \ + htif.c \ emulation.c \ muldiv_emulation.c \ fp_emulation.c \ diff --git a/machine/mcall.h b/machine/mcall.h index 2096d16..ed5a28c 100644 --- a/machine/mcall.h +++ b/machine/mcall.h @@ -4,7 +4,6 @@ #define MCALL_HART_ID 0 #define MCALL_CONSOLE_PUTCHAR 1 #define MCALL_CONSOLE_GETCHAR 2 -#define MCALL_HTIF_SYSCALL 3 #define MCALL_SEND_IPI 4 #define MCALL_CLEAR_IPI 5 #define MCALL_SHUTDOWN 6 diff --git a/machine/mtrap.c b/machine/mtrap.c index 34772b7..0ed27e9 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -8,10 +8,6 @@ #include #include -volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif"))); -volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif"))); -static spinlock_t htif_lock = SPINLOCK_INIT; - void __attribute__((noreturn)) bad_trap() { die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); @@ -22,81 +18,24 @@ static uintptr_t mcall_hart_id() return read_const_csr(mhartid); } -static void request_htif_keyboard_interrupt() -{ - assert(tohost == 0); - tohost = TOHOST_CMD(1, 0, 0); -} - -static void __htif_interrupt() -{ - // we should only be interrupted by keypresses - uint64_t fh = fromhost; - if (!fh) - return; - if (!(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0)) - die("unexpected htif interrupt"); - HLS()->console_ibuf = 1 + (uint8_t)FROMHOST_DATA(fh); - fromhost = 0; - set_csr(mip, MIP_SSIP); -} - -static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) -{ - spinlock_lock(&htif_lock); - while (tohost) - __htif_interrupt(); - tohost = TOHOST_CMD(dev, cmd, data); - - while (1) { - uint64_t fh = fromhost; - if (fh) { - if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) { - fromhost = 0; - break; - } - __htif_interrupt(); - } - } - spinlock_unlock(&htif_lock); -} - -static void htif_interrupt() -{ - if (spinlock_trylock(&htif_lock) == 0) { - __htif_interrupt(); - spinlock_unlock(&htif_lock); - } -} - uintptr_t timer_interrupt() { // just send the timer interrupt to the supervisor clear_csr(mie, MIP_MTIP); set_csr(mip, MIP_STIP); - // and poll the HTIF console - htif_interrupt(); - return 0; } static uintptr_t mcall_console_putchar(uint8_t ch) { - do_tohost_fromhost(1, 1, ch); - return 0; -} - -static uintptr_t mcall_htif_syscall(uintptr_t magic_mem) -{ - do_tohost_fromhost(0, 0, magic_mem); + htif_console_putchar(ch); return 0; } void poweroff() { - while (1) - tohost = 1; + htif_poweroff(); } void putstring(const char* s) @@ -134,29 +73,16 @@ static uintptr_t mcall_send_ipi(uintptr_t recipient) return 0; } -static void reset_ssip() -{ - clear_csr(mip, MIP_SSIP); - mb(); - - if (HLS()->sipi_pending || HLS()->console_ibuf > 0) - set_csr(mip, MIP_SSIP); -} - static uintptr_t mcall_console_getchar() { - int ch = atomic_swap(&HLS()->console_ibuf, -1); - if (ch >= 0) - request_htif_keyboard_interrupt(); - reset_ssip(); - return ch - 1; + return htif_console_getchar(); } static uintptr_t mcall_clear_ipi() { - int ipi = atomic_swap(&HLS()->sipi_pending, 0); - reset_ssip(); - return ipi; + clear_csr(mip, MIP_SSIP); + mb(); + return atomic_swap(&HLS()->sipi_pending, 0); } static uintptr_t mcall_shutdown() @@ -239,9 +165,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) case MCALL_CONSOLE_GETCHAR: retval = mcall_console_getchar(); break; - case MCALL_HTIF_SYSCALL: - retval = mcall_htif_syscall(arg0); - break; case MCALL_SEND_IPI: retval = mcall_send_ipi(arg0); break; diff --git a/machine/mtrap.h b/machine/mtrap.h index 9995203..68c93f2 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -41,7 +41,6 @@ typedef struct { uint32_t* ipi; volatile int mipi_pending; volatile int sipi_pending; - int console_ibuf; volatile uint32_t* plic_m_thresh; volatile uintptr_t* plic_m_ie; -- cgit v1.1