From 22e0c560bb565642d52e4e0f8bab000c8d06f0b8 Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Wed, 15 Aug 2018 16:27:05 +0800 Subject: 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 Reviewed-on: https://review.coreboot.org/28096 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- src/arch/riscv/sbi.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/arch/riscv/sbi.c (limited to 'src/arch/riscv/sbi.c') diff --git a/src/arch/riscv/sbi.c b/src/arch/riscv/sbi.c new file mode 100644 index 0000000000..832d4d3d97 --- /dev/null +++ b/src/arch/riscv/sbi.c @@ -0,0 +1,121 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t send_ipi(uintptr_t *pmask, intptr_t type) +{ + uintptr_t mask = mprv_read_uintptr_t(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) +{ + clear_csr(mip, MIP_STIP); + set_csr(mie, MIP_MTIP); + *(HLS()->timecmp) = when; + return 0; +} + +#if IS_ENABLED(CONFIG_CONSOLE_SERIAL) +static uintptr_t sbi_console_putchar(uint8_t ch) +{ + uart_tx_byte(CONFIG_UART_FOR_CONSOLE, ch); + return 0; +} + +static uintptr_t sbi_console_getchar(void) +{ + return uart_rx_byte(CONFIG_UART_FOR_CONSOLE); +} +#endif + +static uintptr_t sbi_clear_ipi(void) +{ + clear_csr(mip, MIP_SSIP); + return 0; +} + + +/* + * sbi is triggered by the s-mode ecall + * parameter : register a0 a1 a2 + * function : register a7 + * return : register a0 + */ +void handle_sbi(trapframe *tf) +{ + uintptr_t ret = 0; + uintptr_t arg0 = tf->gpr[10]; + __unused uintptr_t arg1 = tf->gpr[11]; + uintptr_t which = tf->gpr[17]; + + 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; +#if IS_ENABLED(CONFIG_CONSOLE_SERIAL) + case SBI_CONSOLE_PUTCHAR: + ret = sbi_console_putchar(arg0); + break; + case SBI_CONSOLE_GETCHAR: + ret = sbi_console_getchar(); + break; +#endif + 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; + default: + ret = -38; + break; + } + tf->gpr[10] = ret; + write_csr(mepc, read_csr(mepc) + 4); +} -- cgit v1.2.3