diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-02-23 12:46:56 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-02-23 12:46:56 -0800 |
commit | 4991166b0c9a676ead9eb92980db646c680c097b (patch) | |
tree | f67d78f678e93ddb4aee6072744ccb0d8595bc98 /pk | |
parent | bf9ee5ca114921718da280de46046dbc43722641 (diff) | |
download | pk-4991166b0c9a676ead9eb92980db646c680c097b.zip pk-4991166b0c9a676ead9eb92980db646c680c097b.tar.gz pk-4991166b0c9a676ead9eb92980db646c680c097b.tar.bz2 |
Use simpler, less-general IPI interface
No need for active messages in this context.
Diffstat (limited to 'pk')
-rw-r--r-- | pk/mtrap.c | 84 | ||||
-rw-r--r-- | pk/mtrap.h | 14 |
2 files changed, 44 insertions, 54 deletions
@@ -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; } @@ -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() ({ \ |