From d2d2e0a55c08b15a08892d5b89ee939a5986e69e Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 28 Feb 2016 20:42:42 -0800 Subject: Remove SBI HTIF support; add console_getchar --- pk/frontend.c | 16 +----- pk/frontend.h | 1 - pk/mcall.h | 4 +- pk/minit.c | 2 + pk/mtrap.c | 176 +++++++++++++++++++++------------------------------------ pk/mtrap.h | 11 ++-- pk/sbi.S | 3 +- pk/sbi.h | 14 +---- pk/sbi_entry.S | 12 ++-- 9 files changed, 84 insertions(+), 155 deletions(-) diff --git a/pk/frontend.c b/pk/frontend.c index b2d26ce..5055a28 100644 --- a/pk/frontend.c +++ b/pk/frontend.c @@ -8,20 +8,6 @@ #include "syscall.h" #include -uint64_t tohost_sync(unsigned dev, unsigned cmd, uint64_t payload) -{ - uint64_t fromhost; - __sync_synchronize(); - - sbi_device_message m = {dev, cmd, payload}, *p; - do_mcall(MCALL_SEND_DEVICE_REQUEST, &m); - while ((p = (void*)do_mcall(MCALL_RECEIVE_DEVICE_RESPONSE)) == 0); - kassert(p == &m); - - __sync_synchronize(); - return m.data; -} - long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long a5, long a6) { static volatile uint64_t magic_mem[8]; @@ -38,7 +24,7 @@ long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long magic_mem[6] = a5; magic_mem[7] = a6; - tohost_sync(0, 0, (uintptr_t)magic_mem); + do_mcall(MCALL_HTIF_SYSCALL, magic_mem); long ret = magic_mem[0]; diff --git a/pk/frontend.h b/pk/frontend.h index 65f3c47..ea5d244 100644 --- a/pk/frontend.h +++ b/pk/frontend.h @@ -20,7 +20,6 @@ void die(int) __attribute__((noreturn)); long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long a5, long a6); -uint64_t tohost_sync(unsigned dev, unsigned cmd, uint64_t payload); struct frontend_stat { uint64_t dev; diff --git a/pk/mcall.h b/pk/mcall.h index c829f21..e612628 100644 --- a/pk/mcall.h +++ b/pk/mcall.h @@ -3,8 +3,8 @@ #define MCALL_HART_ID 0 #define MCALL_CONSOLE_PUTCHAR 1 -#define MCALL_SEND_DEVICE_REQUEST 2 -#define MCALL_RECEIVE_DEVICE_RESPONSE 3 +#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/pk/minit.c b/pk/minit.c index 2c662b4..4784e75 100644 --- a/pk/minit.c +++ b/pk/minit.c @@ -76,6 +76,7 @@ void hls_init(uint32_t id, uintptr_t* csrs) memset(hls, 0, sizeof(*hls)); hls->hart_id = id; hls->csrs = csrs; + hls->console_ibuf = -1; if (id != 0) { while (((booted_harts_mask >> id) & 1) == 0) @@ -106,6 +107,7 @@ void init_first_hart() memory_init(); vm_init(); + request_htif_keyboard_interrupt(); boot_loader(args); } diff --git a/pk/mtrap.c b/pk/mtrap.c index c7cad95..e55aaa6 100644 --- a/pk/mtrap.c +++ b/pk/mtrap.c @@ -80,72 +80,54 @@ void __attribute__((noreturn)) bad_trap() panic("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); } -void htif_interrupt() +static uintptr_t mcall_hart_id() { - uintptr_t fromhost = swap_csr(mfromhost, 0); - if (!fromhost) - return; - - uintptr_t dev = FROMHOST_DEV(fromhost); - uintptr_t cmd = FROMHOST_CMD(fromhost); - uintptr_t data = FROMHOST_DATA(fromhost); - - sbi_device_message* m = HLS()->device_request_queue_head; - sbi_device_message* prev = NULL; - for (size_t i = 0, n = HLS()->device_request_queue_size; i < n; i++) { - if (!supervisor_paddr_valid(m, sizeof(*m)) - && EXTRACT_FIELD(read_csr(mstatus), MSTATUS_MPP) != PRV_M) - panic("htif: page fault"); - - sbi_device_message* next = (void*)m->sbi_private_data; - if (m->dev == dev && m->cmd == cmd) { - m->data = data; - - // dequeue from request queue - if (prev) - prev->sbi_private_data = (uintptr_t)next; - else - HLS()->device_request_queue_head = next; - HLS()->device_request_queue_size = n-1; - m->sbi_private_data = 0; - - // enqueue to response queue - if (HLS()->device_response_queue_tail) - HLS()->device_response_queue_tail->sbi_private_data = (uintptr_t)m; - else - HLS()->device_response_queue_head = m; - HLS()->device_response_queue_tail = m; - - // signal software interrupt - set_csr(mip, MIP_SSIP); - return; - } - - prev = m; - m = (void*)atomic_read(&m->sbi_private_data); - } + return HLS()->hart_id; +} - panic("htif: no record"); +void request_htif_keyboard_interrupt() +{ + uintptr_t old_tohost = swap_csr(mtohost, TOHOST_CMD(1, 0, 0)); + kassert(old_tohost == 0); } -static uintptr_t mcall_hart_id() +void htif_interrupt() { - return HLS()->hart_id; + // we should only be interrupted by keypresses + uintptr_t fromhost = swap_csr(mfromhost, 0); + kassert(FROMHOST_DEV(fromhost) == 1 && FROMHOST_CMD(fromhost) == 0); + HLS()->console_ibuf = (uint8_t)FROMHOST_DATA(fromhost); + set_csr(mip, MIP_SSIP); + request_htif_keyboard_interrupt(); } -static uintptr_t mcall_console_putchar(uint8_t ch) +static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) { - while (swap_csr(mtohost, TOHOST_CMD(1, 1, ch)) != 0); + while (swap_csr(mtohost, TOHOST_CMD(dev, cmd, data)) != 0) + if (read_csr(mfromhost)) + htif_interrupt(); + while (1) { uintptr_t fromhost = read_csr(mfromhost); - if (FROMHOST_DEV(fromhost) != 1 || FROMHOST_CMD(fromhost) != 1) { - if (fromhost) - htif_interrupt(); - continue; + if (fromhost) { + if (FROMHOST_DEV(fromhost) == dev && FROMHOST_CMD(fromhost) == cmd) { + write_csr(mfromhost, 0); + break; + } + htif_interrupt(); } - write_csr(mfromhost, 0); - break; } +} + +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); return 0; } @@ -163,51 +145,9 @@ void printm(const char* s, ...) mcall_console_putchar(*p++); } -static uintptr_t mcall_dev_req(sbi_device_message *m) -{ - //printm("req %d %p\n", HLS()->device_request_queue_size, m); - if (!supervisor_paddr_valid(m, sizeof(*m)) - && EXTRACT_FIELD(read_csr(mstatus), MSTATUS_MPP) != PRV_M) - return -EFAULT; - - if ((m->dev > 0xFFU) | (m->cmd > 0xFFU) | (m->data > 0x0000FFFFFFFFFFFFU)) - return -EINVAL; - - while (swap_csr(mtohost, TOHOST_CMD(m->dev, m->cmd, m->data)) != 0) - ; - - m->sbi_private_data = (uintptr_t)HLS()->device_request_queue_head; - HLS()->device_request_queue_head = m; - HLS()->device_request_queue_size++; - - return 0; -} - -static uintptr_t mcall_dev_resp() -{ - htif_interrupt(); - - sbi_device_message* m = HLS()->device_response_queue_head; - if (m) { - //printm("resp %p\n", m); - sbi_device_message* next = (void*)atomic_read(&m->sbi_private_data); - HLS()->device_response_queue_head = next; - if (!next) { - HLS()->device_response_queue_tail = 0; - - // only clear SSIP if no other events are pending - clear_csr(mip, MIP_SSIP); - mb(); - if (HLS()->ipi_pending & IPI_SOFT) - set_csr(mip, MIP_SSIP); - } - } - return (uintptr_t)m; -} - static void send_ipi(uintptr_t recipient, int event) { - if ((atomic_or(&OTHER_HLS(recipient)->ipi_pending, event) & event) == 0) { + if ((atomic_or(&OTHER_HLS(recipient)->mipi_pending, event) & event) == 0) { mb(); OTHER_HLS(recipient)->csrs[CSR_MIPI] = 1; } @@ -222,15 +162,27 @@ static uintptr_t mcall_send_ipi(uintptr_t recipient) return 0; } -static uintptr_t mcall_clear_ipi() +static void reset_ssip() { - // only clear SSIP if no other events are pending - if (HLS()->device_response_queue_head == NULL) { - clear_csr(mip, MIP_SSIP); - mb(); - } + clear_csr(mip, MIP_SSIP); + mb(); + + if (HLS()->sipi_pending || HLS()->console_ibuf >= 0) + set_csr(mip, MIP_SSIP); +} - return atomic_swap(&HLS()->ipi_pending, 0); +static uintptr_t mcall_console_getchar() +{ + int ch = atomic_swap(&HLS()->console_ibuf, -1); + reset_ssip(); + return ch; +} + +static uintptr_t mcall_clear_ipi() +{ + int ipi = atomic_swap(&HLS()->sipi_pending, 0); + reset_ssip(); + return ipi; } static uintptr_t mcall_shutdown() @@ -256,10 +208,12 @@ void software_interrupt() { clear_csr(mip, MIP_MSIP); mb(); - int ipi_pending = atomic_swap(&HLS()->ipi_pending, 0); + int ipi_pending = atomic_swap(&HLS()->mipi_pending, 0); - if (ipi_pending & IPI_SOFT) + if (ipi_pending & IPI_SOFT) { + HLS()->sipi_pending = 1; set_csr(mip, MIP_SSIP); + } if (ipi_pending & IPI_FENCE_I) asm volatile ("fence.i"); @@ -286,7 +240,7 @@ static void send_ipi_many(uintptr_t* pmask, int event) // prevent deadlock while spinning by handling any IPIs from other harts. for (ssize_t i = num_harts-1; i >= 0; i--) if ((mask >> i) & 1) - while (OTHER_HLS(i)->ipi_pending & event) + while (OTHER_HLS(i)->mipi_pending & event) software_interrupt(); } @@ -315,11 +269,11 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) case MCALL_CONSOLE_PUTCHAR: retval = mcall_console_putchar(arg0); break; - case MCALL_SEND_DEVICE_REQUEST: - retval = mcall_dev_req((sbi_device_message*)arg0); + case MCALL_CONSOLE_GETCHAR: + retval = mcall_console_getchar(); break; - case MCALL_RECEIVE_DEVICE_RESPONSE: - retval = mcall_dev_resp(); + case MCALL_HTIF_SYSCALL: + retval = mcall_htif_syscall(arg0); break; case MCALL_SEND_IPI: retval = mcall_send_ipi(arg0); diff --git a/pk/mtrap.h b/pk/mtrap.h index b0369ca..7ab1f6c 100644 --- a/pk/mtrap.h +++ b/pk/mtrap.h @@ -163,20 +163,19 @@ static inline int xlen() } typedef struct { - sbi_device_message* device_request_queue_head; - size_t device_request_queue_size; - sbi_device_message* device_response_queue_head; - sbi_device_message* device_response_queue_tail; - volatile uintptr_t* csrs; int hart_id; - volatile int ipi_pending; + volatile int mipi_pending; + volatile int sipi_pending; + int console_ibuf; } hls_t; #define IPI_SOFT 0x1 #define IPI_FENCE_I 0x2 #define IPI_SFENCE_VM 0x4 +void request_htif_keyboard_interrupt(); + void hls_init(uint32_t hart_id, uintptr_t* csrs); #define MACHINE_STACK_TOP() ({ \ diff --git a/pk/sbi.S b/pk/sbi.S index 0c32d06..cbea78a 100644 --- a/pk/sbi.S +++ b/pk/sbi.S @@ -2,8 +2,7 @@ .globl sbi_num_harts; sbi_num_harts = -2032 .globl sbi_query_memory; sbi_query_memory = -2016 .globl sbi_console_putchar; sbi_console_putchar = -2000 -.globl sbi_send_device_request; sbi_send_device_request = -1984 -.globl sbi_receive_device_response; sbi_receive_device_response = -1968 +.globl sbi_console_getchar; sbi_console_getchar = -1984 .globl sbi_send_ipi; sbi_send_ipi = -1952 .globl sbi_clear_ipi; sbi_clear_ipi = -1936 .globl sbi_timebase; sbi_timebase = -1920 diff --git a/pk/sbi.h b/pk/sbi.h index cc112d9..4e2fbd8 100644 --- a/pk/sbi.h +++ b/pk/sbi.h @@ -15,23 +15,15 @@ unsigned long sbi_timebase(void); void sbi_set_timer(unsigned long long stime_value); void sbi_send_ipi(unsigned long hart_id); unsigned long sbi_clear_ipi(void); -void sbi_console_putchar(unsigned long ch); void sbi_shutdown(void); +void sbi_console_putchar(unsigned char ch); +int sbi_console_getchar(void); + void sbi_remote_sfence_vm(unsigned long hart_mask_ptr, unsigned long asid); void sbi_remote_sfence_vm_range(unsigned long hart_mask_ptr, unsigned long asid, unsigned long start, unsigned long size); void sbi_remote_fence_i(unsigned long hart_mask_ptr); -typedef struct { - unsigned long dev; - unsigned long cmd; - unsigned long data; - unsigned long sbi_private_data; -} sbi_device_message; - -unsigned long sbi_send_device_request(unsigned long req); -unsigned long sbi_receive_device_response(void); - unsigned long sbi_mask_interrupt(unsigned long which); unsigned long sbi_unmask_interrupt(unsigned long which); diff --git a/pk/sbi_entry.S b/pk/sbi_entry.S index eef456b..bfb0703 100644 --- a/pk/sbi_entry.S +++ b/pk/sbi_entry.S @@ -32,17 +32,15 @@ sbi_base: ecall ret - # send_device_request + # console_getchar .align 4 - li a7, MCALL_SEND_DEVICE_REQUEST + li a7, MCALL_CONSOLE_GETCHAR ecall ret - # receive_device_response + # empty .align 4 - li a7, MCALL_RECEIVE_DEVICE_RESPONSE - ecall - ret + unimp # send ipi .align 4 @@ -50,7 +48,7 @@ sbi_base: ecall ret - # send ipi + # clear ipi .align 4 li a7, MCALL_CLEAR_IPI ecall -- cgit v1.1