Xiang Wang has uploaded this change for review. ( https://review.coreboot.org/28096
Change subject: riscv: add support for supervisor binary interface (SBI) ......................................................................
riscv: add support for supervisor binary interface (SBI)
SBI is runtime service for OS. For an introduction, please refer to https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.md
Change-Id: Ib6c1f21d2f085f02208305dc4e3a0f970d400c27 Signed-off-by: Xiang Wang wxjstz@126.com --- M src/arch/riscv/Makefile.inc A src/arch/riscv/include/sbi.h A src/arch/riscv/sbi.c M src/arch/riscv/trap_handler.c 4 files changed, 175 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/96/28096/1
diff --git a/src/arch/riscv/Makefile.inc b/src/arch/riscv/Makefile.inc index 89feb1b..eae0f0a 100644 --- a/src/arch/riscv/Makefile.inc +++ b/src/arch/riscv/Makefile.inc @@ -45,6 +45,7 @@ bootblock-y += trap_handler.c bootblock-y += fp_asm.S bootblock-y += misaligend.c +bootblock-y += sbi.c bootblock-y += mcall.c bootblock-y += virtual_memory.c bootblock-y += boot.c diff --git a/src/arch/riscv/include/sbi.h b/src/arch/riscv/include/sbi.h new file mode 100644 index 0000000..2c6106d --- /dev/null +++ b/src/arch/riscv/include/sbi.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 HardenedLinux + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 + +#define IPI_SOFT 1 +#define IPI_FENCE_I 2 +#define IPI_SFENCE_VMA 4 +#define IPI_SFENCE_VMA_ASID 8 +#define IPI_SHUTDOWN 16 + +void handle_sbi(trapframe *tf); + diff --git a/src/arch/riscv/sbi.c b/src/arch/riscv/sbi.c new file mode 100644 index 0000000..e76e152 --- /dev/null +++ b/src/arch/riscv/sbi.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 HardenedLinux + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <mcall.h> +#include <stdint.h> +#include <compiler.h> +#include <arch/exception.h> +#include <sbi.h> +#include <vm.h> +#include <console/uart.h> + +void set_msip(int hartid, int val); + +/* FIXME: removed when implemented by a specific platform */ +__weak void set_msip(int hartid, int val) { } + +static uintptr_t send_ipi(uintptr_t *pmask, intptr_t type) +{ + uintptr_t mask = mprv_read_ulong((unsigned long *)pmask); + for (int i = 0; mask; i++) { + if (mask & 1) { + OTHER_HLS(i)->ipi_pending |= type; + /* send soft interrupt to target hart */ + set_msip(i, 1); + } + mask = mask >> 1; + } + return 0; +} + +static uintptr_t sbi_set_timer(uint64_t when) +{ + *(HLS()->timecmp) = when; + clear_csr(mip, MIP_STIP); + set_csr(mie, MIP_MTIP); + return 0; +} + +static uintptr_t sbi_console_putchar(uint8_t ch) +{ +#if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) + uart_tx_byte(CONFIG_UART_FOR_CONSOLE, ch); + return 0; +#else + return -1; +#endif +} + +static uintptr_t sbi_console_getchar(void) +{ +#if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) + return uart_rx_byte(CONFIG_UART_FOR_CONSOLE); +#else + return -1; +#endif +} + +static uintptr_t sbi_clear_ipi(void) +{ + return clear_csr(mip, MIP_SSIP) & MIP_SSIP; +} + +void handle_sbi(trapframe *tf) +{ +#define arg0 (tf->gpr[10]) +#define arg1 (tf->gpr[11]) +#define arg2 (tf->gpr[12]) +#define which (tf->gpr[17]) +#define ret (tf->gpr[10]) + switch (which) { + case SBI_SET_TIMER: +#if __riscv_xlen == 32 + ret = sbi_set_timer(arg0 + ((uint64_t)arg1 << 32)); +#else + ret = sbi_set_timer(arg0); +#endif + break; + case SBI_CONSOLE_PUTCHAR: + ret = sbi_console_putchar(arg0); + break; + case SBI_CONSOLE_GETCHAR: + ret = sbi_console_getchar(); + break; + case SBI_CLEAR_IPI: + ret = sbi_clear_ipi(); + break; + case SBI_SEND_IPI: + ret = send_ipi((uintptr_t *)arg0, IPI_SOFT); + break; + case SBI_REMOTE_FENCE_I: + ret = send_ipi((uintptr_t *)arg0, IPI_FENCE_I); + break; + case SBI_REMOTE_SFENCE_VMA: + ret = send_ipi((uintptr_t *)arg0, IPI_SFENCE_VMA); + break; + case SBI_REMOTE_SFENCE_VMA_ASID: + ret = send_ipi((uintptr_t *)arg0, IPI_SFENCE_VMA_ASID); + break; + case SBI_SHUTDOWN: + ret = send_ipi((uintptr_t *)arg0, IPI_SHUTDOWN); + break; + } +} + + + + + + + diff --git a/src/arch/riscv/trap_handler.c b/src/arch/riscv/trap_handler.c index e9771af..d4c3932 100644 --- a/src/arch/riscv/trap_handler.c +++ b/src/arch/riscv/trap_handler.c @@ -19,6 +19,8 @@ #include <console/console.h> #include <string.h> #include <vm.h> +#include <mcall.h> +#include <sbi.h>
static uint64_t *time; static uint64_t *timecmp; @@ -135,6 +137,20 @@ msip |= SIP_STIP; write_csr(mip, msip); break; + case IRQ_M_SOFT: + if (HLS()->ipi_pending & IPI_SOFT) { + set_csr(mip, MIP_SSIP); + } else if (HLS()->ipi_pending & IPI_FENCE_I) { + asm("fence.i"); + } else if (HLS()->ipi_pending & IPI_SFENCE_VMA) { + asm("sfence.vma"); + } else if (HLS()->ipi_pending & IPI_SFENCE_VMA_ASID) { + asm("sfence.vma"); + } else if (HLS()->ipi_pending & IPI_SHUTDOWN) { + while (HLS()->ipi_pending & IPI_SHUTDOWN) + asm("wfi"); + } + break; default: printk(BIOS_EMERG, "======================================\n"); printk(BIOS_EMERG, "coreboot: Unknown machine interrupt: 0x%llx\n", @@ -161,6 +177,9 @@ case CAUSE_STORE_ACCESS: case CAUSE_USER_ECALL: case CAUSE_SUPERVISOR_ECALL: + print_trap_information(tf); + handle_sbi(tf); + return; case CAUSE_HYPERVISOR_ECALL: case CAUSE_MACHINE_ECALL: print_trap_information(tf);