summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/riscv/sbi.c75
1 files changed, 70 insertions, 5 deletions
diff --git a/src/arch/riscv/sbi.c b/src/arch/riscv/sbi.c
index 8bf21b72ba..2ef7625f57 100644
--- a/src/arch/riscv/sbi.c
+++ b/src/arch/riscv/sbi.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <console/console.h>
#include <mcall.h>
#include <stdint.h>
#include <arch/exception.h>
@@ -49,6 +50,54 @@ static uintptr_t sbi_clear_ipi(void)
return 0;
}
+static void print_sbi_trap(uintptr_t trap)
+{
+ switch (trap) {
+ case SBI_SHUTDOWN:
+ printk(BIOS_EMERG, "SBI_SHUTDOWN\n");
+ break;
+ case SBI_REMOTE_SFENCE_VMA_ASID:
+ printk(BIOS_EMERG, "SBI_REMOTE_SFENCE_VMA_ASID\n");
+ break;
+ case SBI_REMOTE_SFENCE_VMA:
+ printk(BIOS_EMERG, "SBI_REMOTE_SFENCE_VMA\n");
+ break;
+ case SBI_REMOTE_FENCE_I:
+ printk(BIOS_EMERG, "SBI_REMOTE_FENCE_I\n");
+ break;
+ case SBI_SEND_IPI:
+ printk(BIOS_EMERG, "SBI_SEND_IPI\n");
+ break;
+ case SBI_CLEAR_IPI:
+ printk(BIOS_EMERG, "SBI_CLEAR_IPI\n");
+ break;
+ case SBI_CONSOLE_GETCHAR:
+ printk(BIOS_EMERG, "SBI_CONSOLE_GETCHAR\n");
+ break;
+ case SBI_CONSOLE_PUTCHAR:
+ printk(BIOS_EMERG, "SBI_CONSOLE_PUTCHAR\n");
+ break;
+ case SBI_SET_TIMER:
+ printk(BIOS_EMERG, "SBI_SET_TIMER\n");
+ break;
+ case SBI_BASE_EXTENSION:
+ printk(BIOS_EMERG, "SBI_BASE_EXTENSION\n");
+ break;
+ default:
+ printk(BIOS_EMERG, "%lx is an unknown SBI trap\n", trap);
+ break;
+ }
+}
+
+/*
+ * These are the default SBI extension values.
+ * They can be overridden, by specialized code,
+ * but since this is a GPL SBI, it may be better
+ * that they evolve as we extend this SBI.
+ * over time, the will be updated.
+ */
+int sbi_features[] = {1, 0, 0, 0, 0, 0, 0};
+
/*
* sbi is triggered by the s-mode ecall
* parameter : register a0 a1 a2
@@ -58,11 +107,14 @@ static uintptr_t sbi_clear_ipi(void)
void handle_sbi(struct trapframe *tf)
{
uintptr_t ret = 0;
+ uintptr_t sbiret = 0;
uintptr_t arg0 = tf->gpr[10];
__maybe_unused uintptr_t arg1 = tf->gpr[11];
- uintptr_t which = tf->gpr[17];
+ uintptr_t fid = tf->gpr[16];
+ uintptr_t eid = tf->gpr[17];
+ uintptr_t retpc = read_csr(mepc) + 4;
- switch (which) {
+ switch (eid) {
case SBI_SET_TIMER:
#if __riscv_xlen == 32
ret = sbi_set_timer(arg0 + ((uint64_t)arg1 << 32));
@@ -96,10 +148,23 @@ void handle_sbi(struct trapframe *tf)
case SBI_SHUTDOWN:
ret = send_ipi((uintptr_t *)arg0, IPI_SHUTDOWN);
break;
+ case SBI_BASE_EXTENSION:
+ /* zero is an allowed return value for most features,
+ * and the only required one is feature 0.
+ * So this test will return legal values
+ * for all possible values of fid.
+ */
+ if (fid < ARRAY_SIZE(sbi_features))
+ ret = sbi_features[fid];
+ break;
default:
- ret = -SBI_ENOSYS;
+ print_sbi_trap(eid);
+ printk(BIOS_EMERG, "SBI: %lx: ENOSYS\n", fid);
+ sbiret = -SBI_ENOSYS;
break;
}
- tf->gpr[10] = ret;
- write_csr(mepc, read_csr(mepc) + 4);
+ tf->gpr[10] = sbiret;
+ tf->gpr[11] = ret;
+
+ write_csr(mepc, retpc);
}