aboutsummaryrefslogtreecommitdiff
path: root/machine/mtrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'machine/mtrap.c')
-rw-r--r--machine/mtrap.c78
1 files changed, 35 insertions, 43 deletions
diff --git a/machine/mtrap.c b/machine/mtrap.c
index fb6c3f9..b9adebf 100644
--- a/machine/mtrap.c
+++ b/machine/mtrap.c
@@ -9,9 +9,9 @@
#include <stdarg.h>
#include <stdio.h>
-void __attribute__((noreturn)) bad_trap()
+void __attribute__((noreturn)) bad_trap(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc)
{
- die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc));
+ die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), mepc);
}
static uintptr_t mcall_console_putchar(uint8_t ch)
@@ -45,10 +45,9 @@ void printm(const char* s, ...)
static void send_ipi(uintptr_t recipient, int event)
{
- if ((atomic_or(&OTHER_HLS(recipient)->mipi_pending, event) & event) == 0) {
- mb();
- *OTHER_HLS(recipient)->ipi = 1;
- }
+ atomic_or(&OTHER_HLS(recipient)->mipi_pending, event);
+ mb();
+ *OTHER_HLS(recipient)->ipi = 1;
}
static uintptr_t mcall_console_getchar()
@@ -77,21 +76,24 @@ static uintptr_t mcall_set_timer(uint64_t when)
static void send_ipi_many(uintptr_t* pmask, int event)
{
_Static_assert(MAX_HARTS <= 8 * sizeof(*pmask), "# harts > uintptr_t bits");
- uintptr_t mask = -1;
+ uintptr_t mask = ((uintptr_t)1 << num_harts) - 1;
if (pmask)
- mask = load_uintptr_t(pmask, read_csr(mepc));
+ mask &= load_uintptr_t(pmask, read_csr(mepc));
// send IPIs to everyone
- for (ssize_t i = num_harts-1; i >= 0; i--)
- if ((mask >> i) & 1)
+ for (uintptr_t i = 0, m = mask; m; i++, m >>= 1)
+ if (m & 1)
send_ipi(i, event);
+ if (event == IPI_SOFT)
+ return;
+
// wait until all events have been handled.
// prevent deadlock by consuming incoming IPIs.
uint32_t incoming_ipi = 0;
- for (ssize_t i = num_harts-1; i >= 0; i--)
- if ((mask >> i) & 1)
- while (OTHER_HLS(i)->ipi)
+ for (uintptr_t i = 0, m = mask; m; i++, m >>= 1)
+ if (m & 1)
+ while (*OTHER_HLS(i)->ipi)
incoming_ipi |= atomic_swap(HLS()->ipi, 0);
// if we got an IPI, restore it; it will be taken after returning
@@ -101,49 +103,40 @@ static void send_ipi_many(uintptr_t* pmask, int event)
}
}
-static uintptr_t mcall_remote_sfence_vm(uintptr_t* hart_mask)
-{
- // 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)
-{
- send_ipi_many(hart_mask, IPI_FENCE_I);
- return 0;
-}
-
void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
{
- uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval;
- uintptr_t ipi_type = 0;
+ write_csr(mepc, mepc + 4);
+
+ uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval, ipi_type;
switch (n)
{
- case MCALL_CONSOLE_PUTCHAR:
+ case SBI_CONSOLE_PUTCHAR:
retval = mcall_console_putchar(arg0);
break;
- case MCALL_CONSOLE_GETCHAR:
+ case SBI_CONSOLE_GETCHAR:
retval = mcall_console_getchar();
break;
- case MCALL_SEND_IPI:
+ case SBI_SEND_IPI:
ipi_type = IPI_SOFT;
- case MCALL_REMOTE_SFENCE_VM:
- ipi_type = IPI_SFENCE_VM;
- case MCALL_REMOTE_FENCE_I:
+ goto send_ipi;
+ case SBI_REMOTE_SFENCE_VMA:
+ case SBI_REMOTE_SFENCE_VMA_ASID:
+ ipi_type = IPI_SFENCE_VMA;
+ goto send_ipi;
+ case SBI_REMOTE_FENCE_I:
ipi_type = IPI_FENCE_I;
+send_ipi:
send_ipi_many((uintptr_t*)arg0, ipi_type);
retval = 0;
break;
- case MCALL_CLEAR_IPI:
+ case SBI_CLEAR_IPI:
retval = mcall_clear_ipi();
break;
- case MCALL_SHUTDOWN:
+ case SBI_SHUTDOWN:
retval = mcall_shutdown();
break;
- case MCALL_SET_TIMER:
+ case SBI_SET_TIMER:
#if __riscv_xlen == 32
retval = mcall_set_timer(arg0 + ((uint64_t)arg1 << 32));
#else
@@ -155,7 +148,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
break;
}
regs[10] = retval;
- write_csr(mepc, mepc + 4);
}
void redirect_trap(uintptr_t epc, uintptr_t mstatus)
@@ -175,7 +167,7 @@ void redirect_trap(uintptr_t epc, uintptr_t mstatus)
return __redirect_trap();
}
-static void machine_page_fault(uintptr_t* regs, uintptr_t mepc)
+static void machine_page_fault(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc)
{
// MPRV=1 iff this trap occurred while emulating an instruction on behalf
// of a lower privilege level. In that case, a2=epc and a3=mstatus.
@@ -183,7 +175,7 @@ static void machine_page_fault(uintptr_t* regs, uintptr_t mepc)
write_csr(sbadaddr, read_csr(mbadaddr));
return redirect_trap(regs[12], regs[13]);
}
- bad_trap();
+ bad_trap(regs, dummy, mepc);
}
void trap_from_machine_mode(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc)
@@ -194,8 +186,8 @@ void trap_from_machine_mode(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc)
{
case CAUSE_FAULT_LOAD:
case CAUSE_FAULT_STORE:
- return machine_page_fault(regs, mepc);
+ return machine_page_fault(regs, dummy, mepc);
default:
- bad_trap();
+ bad_trap(regs, dummy, mepc);
}
}