From 4991166b0c9a676ead9eb92980db646c680c097b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 23 Feb 2016 12:46:56 -0800 Subject: Use simpler, less-general IPI interface No need for active messages in this context. --- pk/mtrap.c | 84 ++++++++++++++++++++++++++++---------------------------------- pk/mtrap.h | 14 +++++------ 2 files changed, 44 insertions(+), 54 deletions(-) diff --git a/pk/mtrap.c b/pk/mtrap.c index ca0f890..c7cad95 100644 --- a/pk/mtrap.c +++ b/pk/mtrap.c @@ -198,23 +198,27 @@ static uintptr_t mcall_dev_resp() // only clear SSIP if no other events are pending clear_csr(mip, MIP_SSIP); mb(); - if (HLS()->ipi_pending) + if (HLS()->ipi_pending & IPI_SOFT) set_csr(mip, MIP_SSIP); } } return (uintptr_t)m; } -static uintptr_t mcall_send_ipi(uintptr_t recipient) +static void send_ipi(uintptr_t recipient, int event) { - if (recipient >= num_harts) - return -1; - - if (atomic_swap(&OTHER_HLS(recipient)->ipi_pending, 1) == 0) { + if ((atomic_or(&OTHER_HLS(recipient)->ipi_pending, event) & event) == 0) { mb(); OTHER_HLS(recipient)->csrs[CSR_MIPI] = 1; } +} +static uintptr_t mcall_send_ipi(uintptr_t recipient) +{ + if (recipient >= num_harts) + return -1; + + send_ipi(recipient, IPI_SOFT); return 0; } @@ -251,64 +255,52 @@ static uintptr_t mcall_set_timer(unsigned long long when) void software_interrupt() { clear_csr(mip, MIP_MSIP); - __sync_synchronize(); + mb(); + int ipi_pending = atomic_swap(&HLS()->ipi_pending, 0); - if (HLS()->ipi_pending) + if (ipi_pending & IPI_SOFT) set_csr(mip, MIP_SSIP); - if (HLS()->rpc_func) { - __sync_synchronize(); - rpc_func_t f = *HLS()->rpc_func; - (f.func)(f.arg); - __sync_synchronize(); - HLS()->rpc_func = (void*)1; - } + if (ipi_pending & IPI_FENCE_I) + asm volatile ("fence.i"); + + if (ipi_pending & IPI_SFENCE_VM) + asm volatile ("sfence.vm"); } -static void call_func_all(uintptr_t* mask, void (*func)(uintptr_t), uintptr_t arg) +static void send_ipi_many(uintptr_t* pmask, int event) { - kassert(MAX_HARTS <= 8*sizeof(*mask)); - kassert(supervisor_paddr_valid((uintptr_t)mask, sizeof(uintptr_t))); - - rpc_func_t f = {func, arg}; - - uintptr_t harts = *mask; - for (ssize_t i = num_harts-1; i >= 0; i--) { - if (((harts >> i) & 1) == 0) - continue; + kassert(MAX_HARTS <= 8 * sizeof(*pmask)); + uintptr_t mask = -1; + if (pmask) { + kassert(supervisor_paddr_valid((uintptr_t)pmask, sizeof(uintptr_t))); + mask = *pmask; + } - if (HLS()->hart_id == i) { - func(arg); - } else { - rpc_func_t** p = &OTHER_HLS(i)->rpc_func; - uintptr_t* mipi = &OTHER_HLS(i)->csrs[CSR_MIPI]; + // send IPIs to everyone + for (ssize_t i = num_harts-1; i >= 0; i--) + if ((mask >> i) & 1) + send_ipi(i, event); - while (atomic_cas(p, 0, &f) != &f) + // wait until all events have been handled. + // 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) software_interrupt(); - - __sync_synchronize(); - *mipi = 1; - __sync_synchronize(); - - while (atomic_cas(p, (void*)1, 0) != (void*)1) - ; - } - } } static uintptr_t mcall_remote_sfence_vm(uintptr_t* hart_mask, uintptr_t asid) { - void sfence_vm(uintptr_t arg) { - asm volatile ("csrrw %0, sasid, %0; sfence.vm; csrw sasid, %0" : "+r"(arg)); - } - call_func_all(hart_mask, &sfence_vm, asid); + // ignore the ASID and do a global flush. + // this allows us to avoid queueing a message. + send_ipi_many(hart_mask, IPI_SFENCE_VM); return 0; } static uintptr_t mcall_remote_fence_i(uintptr_t* hart_mask) { - void fence_i(uintptr_t arg) { asm volatile ("fence.i"); } - call_func_all(hart_mask, &fence_i, 0); + send_ipi_many(hart_mask, IPI_FENCE_I); return 0; } diff --git a/pk/mtrap.h b/pk/mtrap.h index 64caaab..99308a2 100644 --- a/pk/mtrap.h +++ b/pk/mtrap.h @@ -163,22 +163,20 @@ static inline int xlen() } typedef struct { - void (*func)(uintptr_t); - uintptr_t arg; -} rpc_func_t; - -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; - rpc_func_t* rpc_func; - uintptr_t* csrs; + volatile uintptr_t* csrs; int hart_id; - int ipi_pending; + volatile int ipi_pending; } hls_t; +#define IPI_SOFT 0x1 +#define IPI_FENCE_I 0x2 +#define IPI_SFENCE_VM 0x4 + void hls_init(uint32_t hart_id, uintptr_t* csrs); #define MACHINE_STACK_TOP() ({ \ -- cgit v1.1