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> Reviewed-on: https://review.coreboot.org/28096 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
committed by
Patrick Georgi
parent
26f725efc2
commit
22e0c560bb
@@ -50,6 +50,7 @@ bootblock-y += trap_util.S
|
|||||||
bootblock-y += trap_handler.c
|
bootblock-y += trap_handler.c
|
||||||
bootblock-y += fp_asm.S
|
bootblock-y += fp_asm.S
|
||||||
bootblock-y += misaligned.c
|
bootblock-y += misaligned.c
|
||||||
|
bootblock-y += sbi.c
|
||||||
bootblock-y += mcall.c
|
bootblock-y += mcall.c
|
||||||
bootblock-y += virtual_memory.c
|
bootblock-y += virtual_memory.c
|
||||||
bootblock-y += boot.c
|
bootblock-y += boot.c
|
||||||
@@ -118,6 +119,7 @@ ramstage-y += trap_util.S
|
|||||||
ramstage-y += trap_handler.c
|
ramstage-y += trap_handler.c
|
||||||
ramstage-y += fp_asm.S
|
ramstage-y += fp_asm.S
|
||||||
ramstage-y += misaligned.c
|
ramstage-y += misaligned.c
|
||||||
|
ramstage-y += sbi.c
|
||||||
ramstage-y += virtual_memory.c
|
ramstage-y += virtual_memory.c
|
||||||
ramstage-y += stages.c
|
ramstage-y += stages.c
|
||||||
ramstage-y += misc.c
|
ramstage-y += misc.c
|
||||||
|
37
src/arch/riscv/include/sbi.h
Normal file
37
src/arch/riscv/include/sbi.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RISCV_SBI_H
|
||||||
|
#define RISCV_SBI_H
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#endif /* RISCV_SBI_H */
|
@@ -102,6 +102,14 @@ DEFINE_MPRV_WRITE(mprv_write_u64, uint64_t, sd)
|
|||||||
DEFINE_MPRV_WRITE(mprv_write_long, long, sd)
|
DEFINE_MPRV_WRITE(mprv_write_long, long, sd)
|
||||||
DEFINE_MPRV_WRITE(mprv_write_ulong, unsigned long, sd)
|
DEFINE_MPRV_WRITE(mprv_write_ulong, unsigned long, sd)
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
DEFINE_MPRV_READ(mprv_read_uintptr_t, uintptr_t, lw)
|
||||||
|
DEFINE_MPRV_READ(mprv_write_uintptr_t, uintptr_t, sw)
|
||||||
|
#elif __riscv_xlen == 64
|
||||||
|
DEFINE_MPRV_READ(mprv_read_uintptr_t, uintptr_t, ld)
|
||||||
|
DEFINE_MPRV_READ(mprv_write_uintptr_t, uintptr_t, sd)
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef DEFINE_MPRV_READ_FLAGS
|
#undef DEFINE_MPRV_READ_FLAGS
|
||||||
#undef DEFINE_MPRV_READ
|
#undef DEFINE_MPRV_READ
|
||||||
#undef DEFINE_MPRV_READ_MXR
|
#undef DEFINE_MPRV_READ_MXR
|
||||||
|
121
src/arch/riscv/sbi.c
Normal file
121
src/arch/riscv/sbi.c
Normal file
@@ -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 <mcall.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <commonlib/compiler.h>
|
||||||
|
#include <arch/exception.h>
|
||||||
|
#include <sbi.h>
|
||||||
|
#include <vm.h>
|
||||||
|
#include <console/uart.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <commonlib/helpers.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
@@ -19,6 +19,8 @@
|
|||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
|
#include <mcall.h>
|
||||||
|
#include <sbi.h>
|
||||||
|
|
||||||
static const char *const exception_names[] = {
|
static const char *const exception_names[] = {
|
||||||
"Instruction address misaligned",
|
"Instruction address misaligned",
|
||||||
@@ -91,6 +93,20 @@ static void interrupt_handler(trapframe *tf)
|
|||||||
clear_csr(mie, MIP_MTIP);
|
clear_csr(mie, MIP_MTIP);
|
||||||
set_csr(mip, MIP_STIP);
|
set_csr(mip, MIP_STIP);
|
||||||
|
|
||||||
|
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 volatile("fence.i");
|
||||||
|
} else if (HLS()->ipi_pending & IPI_SFENCE_VMA) {
|
||||||
|
asm volatile("sfence.vma");
|
||||||
|
} else if (HLS()->ipi_pending & IPI_SFENCE_VMA_ASID) {
|
||||||
|
asm volatile("sfence.vma");
|
||||||
|
} else if (HLS()->ipi_pending & IPI_SHUTDOWN) {
|
||||||
|
while (HLS()->ipi_pending & IPI_SHUTDOWN)
|
||||||
|
asm volatile("wfi");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(BIOS_EMERG, "======================================\n");
|
printk(BIOS_EMERG, "======================================\n");
|
||||||
@@ -117,11 +133,13 @@ void trap_handler(trapframe *tf)
|
|||||||
case CAUSE_LOAD_ACCESS:
|
case CAUSE_LOAD_ACCESS:
|
||||||
case CAUSE_STORE_ACCESS:
|
case CAUSE_STORE_ACCESS:
|
||||||
case CAUSE_USER_ECALL:
|
case CAUSE_USER_ECALL:
|
||||||
case CAUSE_SUPERVISOR_ECALL:
|
|
||||||
case CAUSE_HYPERVISOR_ECALL:
|
case CAUSE_HYPERVISOR_ECALL:
|
||||||
case CAUSE_MACHINE_ECALL:
|
case CAUSE_MACHINE_ECALL:
|
||||||
print_trap_information(tf);
|
print_trap_information(tf);
|
||||||
break;
|
break;
|
||||||
|
case CAUSE_SUPERVISOR_ECALL:
|
||||||
|
handle_sbi(tf);
|
||||||
|
return;
|
||||||
case CAUSE_MISALIGNED_LOAD:
|
case CAUSE_MISALIGNED_LOAD:
|
||||||
case CAUSE_MISALIGNED_STORE:
|
case CAUSE_MISALIGNED_STORE:
|
||||||
print_trap_information(tf);
|
print_trap_information(tf);
|
||||||
|
Reference in New Issue
Block a user