Index: sys/conf/files.riscv =================================================================== --- sys/conf/files.riscv +++ sys/conf/files.riscv @@ -55,6 +55,7 @@ riscv/riscv/plic.c standard riscv/riscv/pmap.c standard riscv/riscv/riscv_console.c optional rcons +riscv/riscv/sbi.c standard riscv/riscv/soc.c standard riscv/riscv/stack_machdep.c optional ddb | stack riscv/riscv/support.S standard Index: sys/riscv/include/md_var.h =================================================================== --- sys/riscv/include/md_var.h +++ sys/riscv/include/md_var.h @@ -39,6 +39,9 @@ extern uint64_t *vm_page_dump; extern int vm_page_dump_size; extern u_long elf_hwcap; +extern register_t mvendorid; +extern register_t marchid; +extern register_t mimpid; struct dumperinfo; Index: sys/riscv/include/sbi.h =================================================================== --- sys/riscv/include/sbi.h +++ sys/riscv/include/sbi.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2016-2017 Ruslan Bukin * All rights reserved. + * Copyright (c) 2019 Mitchell Horne * * Portions of this software were developed by SRI International and the * University of Cambridge Computer Laboratory under DARPA/AFRL contract @@ -37,6 +38,35 @@ #ifndef _MACHINE_SBI_H_ #define _MACHINE_SBI_H_ +/* SBI Specification Version */ +#define SBI_SPEC_VERS_MAJOR_OFFSET 24 +#define SBI_SPEC_VERS_MAJOR_MASK (0x7F << SBI_SPEC_VERS_MAJOR_OFFSET) +#define SBI_SPEC_VERS_MINOR_OFFSET 0 +#define SBI_SPEC_VERS_MINOR_MASK (0xFFFFFF << SBI_SPEC_VERS_MINOR_OFFSET) + +/* SBI Implementation IDs */ +#define SBI_IMPL_ID_BBL 0 +#define SBI_IMPL_ID_OPENSBI 1 + +/* SBI Error Codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 + +/* SBI Base Extension */ +#define SBI_EXT_ID_BASE 0x10 +#define SBI_BASE_GET_SPEC_VERSION 0 +#define SBI_BASE_GET_IMPL_ID 1 +#define SBI_BASE_GET_IMPL_VERSION 2 +#define SBI_BASE_PROBE_EXTENSION 3 +#define SBI_BASE_GET_MVENDORID 4 +#define SBI_BASE_GET_MARCHID 5 +#define SBI_BASE_GET_MIMPID 6 + +/* Legacy Extensions */ #define SBI_SET_TIMER 0 #define SBI_CONSOLE_PUTCHAR 1 #define SBI_CONSOLE_GETCHAR 2 @@ -55,13 +85,20 @@ /* * Documentation available at - * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.md + * https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc */ -static __inline uint64_t +struct sbi_ret { + long error; + long value; +}; + +static __inline struct sbi_ret sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) { + struct sbi_ret ret; + register uintptr_t a0 __asm ("a0") = (uintptr_t)(arg0); register uintptr_t a1 __asm ("a1") = (uintptr_t)(arg1); register uintptr_t a2 __asm ("a2") = (uintptr_t)(arg2); @@ -71,13 +108,27 @@ __asm __volatile( \ "ecall" \ - :"+r"(a0) \ - :"r"(a1), "r"(a2), "r"(a3), "r"(a6), "r"(a7) \ + :"+r"(a0), "+r"(a1) \ + :"r"(a2), "r"(a3), "r"(a6), "r"(a7) \ :"memory"); - return (a0); + ret.error = a0; + ret.value = a1; + return (ret); } +/* Base extension functions and variables. */ +extern u_int sbi_spec_version; +extern u_int sbi_impl_id; +extern u_int sbi_impl_version; + +static __inline long +sbi_probe_extension(long id) +{ + return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); +} + +/* Legacy extension functions. */ static __inline void sbi_console_putchar(int ch) { @@ -89,7 +140,7 @@ sbi_console_getchar(void) { - return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0)); + return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).value); } static __inline void @@ -146,4 +197,6 @@ start, size, asid); } +void sbi_init(void); + #endif /* !_MACHINE_SBI_H_ */ Index: sys/riscv/riscv/identcpu.c =================================================================== --- sys/riscv/riscv/identcpu.c +++ sys/riscv/riscv/identcpu.c @@ -60,6 +60,11 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class"); +/* Hardware implementation info. These values may be empty. */ +register_t mvendorid; /* The CPU's JEDEC vendor ID */ +register_t marchid; /* The architecture ID */ +register_t mimpid; /* The implementation ID */ + struct cpu_desc { u_int cpu_impl; u_int cpu_part_num; Index: sys/riscv/riscv/machdep.c =================================================================== --- sys/riscv/riscv/machdep.c +++ sys/riscv/riscv/machdep.c @@ -850,6 +850,9 @@ PCPU_SET(curthread, &thread0); + /* Initialize SBI interface. */ + sbi_init(); + /* Set the module data location */ lastaddr = fake_preload_metadata(rvbp); Index: sys/riscv/riscv/sbi.c =================================================================== --- /dev/null +++ sys/riscv/riscv/sbi.c @@ -0,0 +1,124 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Mitchell Horne + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +u_int sbi_spec_version; +u_int sbi_impl_id; +u_int sbi_impl_version; + +static struct sbi_ret +sbi_get_spec_version(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION)); +} + +static struct sbi_ret +sbi_get_impl_id(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID)); +} + +static struct sbi_ret +sbi_get_impl_version(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION)); +} + +static struct sbi_ret +sbi_get_mvendorid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MVENDORID)); +} + + +static struct sbi_ret +sbi_get_marchid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MARCHID)); +} + +static struct sbi_ret +sbi_get_mimpid(void) +{ + return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MIMPID)); +} + +void +sbi_init(void) +{ + struct sbi_ret sret; + + /* + * Get the spec version. For legacy SBI implementations this will + * return an error, otherwise it is guaranteed to succeed. + */ + sret = sbi_get_spec_version(); + if (sret.error != 0) { + /* We are running a legacy SBI implementation. */ + sbi_spec_version = 0; + return; + } + + /* Set the SBI implementation info. */ + sbi_spec_version = sret.value; + sbi_impl_id = sbi_get_impl_id().value; + sbi_impl_version = sbi_get_impl_version().value; + + /* Set the hardware implementation info. */ + mvendorid = sbi_get_mvendorid().value; + marchid = sbi_get_marchid().value; + mimpid = sbi_get_mimpid().value; + + /* + * Probe for legacy extensions. Currently we rely on all of them + * to be implemented, but this is not guaranteed by the spec. + */ + KASSERT(sbi_probe_extension(SBI_SET_TIMER) != 0, + ("SBI doesn't implement sbi_set_timer()")); + KASSERT(sbi_probe_extension(SBI_CONSOLE_PUTCHAR) != 0, + ("SBI doesn't implement sbi_console_putchar()")); + KASSERT(sbi_probe_extension(SBI_CONSOLE_GETCHAR) != 0, + ("SBI doesn't implement sbi_console_getchar()")); + KASSERT(sbi_probe_extension(SBI_CLEAR_IPI) != 0, + ("SBI doesn't implement sbi_clear_ipi()")); + KASSERT(sbi_probe_extension(SBI_SEND_IPI) != 0, + ("SBI doesn't implement sbi_send_ipi()")); + KASSERT(sbi_probe_extension(SBI_REMOTE_FENCE_I) != 0, + ("SBI doesn't implement sbi_remote_fence_i()")); + KASSERT(sbi_probe_extension(SBI_REMOTE_SFENCE_VMA) != 0, + ("SBI doesn't implement sbi_remote_sfence_vma()")); + KASSERT(sbi_probe_extension(SBI_REMOTE_SFENCE_VMA_ASID) != 0, + ("SBI doesn't implement sbi_remote_sfence_vma_asid()")); + KASSERT(sbi_probe_extension(SBI_SHUTDOWN) != 0, + ("SBI doesn't implement sbi_shutdown()")); +}