RISC-V: add support for SBI spec v0.2

The Supervisor Binary Interface (SBI) specification v0.2 is a backwards
incompatible update to the SBI call interface for kernels running in
supervisor mode. The goal of this update was to make it easier for new
and optional functionality to be added to the SBI.

SBI functions are now called by passing an "extension ID" and a
"function ID" which are passed in a7 and a6 respectively. SBI calls
will also return an error and value in the following struct:

struct sbi_ret {
    long error;
    long value;
}

This version introduces several new functions under the "base"
extension. It is expected that all SBI implementations >= 0.2 will
support this base set of functions, as they implement some essential
services such as obtaining the SBI version, CPU implementation info, and
extension probing.

Existing SBI functions have been designated as "legacy". For the time
being they will remain implemented, but it is expected that in the
future their functionality will be duplicated or replaced by new SBI
extensions. Each legacy function has been assigned its own extension ID,
and for now we simply probe and assert for their existence.

Compatibility with legacy SBI implementations (such as BBL) is
maintained by checking the output of sbi_get_spec_version(). This
function is guaranteed to succeed by the new spec, but will return an
error in legacy implementations. We use this as an indicator of whether
or not we can rely on the new SBI base extensions.

For further info on the Supervisor Binary Interface, see:
https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc

Reviewed by:	kp, jhb
MFC after:	3 weeks
Differential Revision:	https://reviews.freebsd.org/D22326
This commit is contained in:
Mitchell Horne 2019-11-15 03:34:27 +00:00
parent 331baa6f1b
commit ff33210c04
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354720
4 changed files with 136 additions and 0 deletions

View File

@ -55,6 +55,7 @@ riscv/riscv/ofw_machdep.c optional fdt
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

View File

@ -60,6 +60,11 @@ char machine[] = "riscv";
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;

View File

@ -850,6 +850,9 @@ initriscv(struct riscv_bootparams *rvbp)
PCPU_SET(curthread, &thread0);
/* Initialize SBI interface. */
sbi_init();
/* Set the module data location */
lastaddr = fake_preload_metadata(rvbp);

127
sys/riscv/riscv/sbi.c Normal file
View File

@ -0,0 +1,127 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2019 Mitchell Horne <mhorne@FreeBSD.org>
*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <machine/md_var.h>
#include <machine/sbi.h>
u_long sbi_spec_version;
u_long sbi_impl_id;
u_long 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()"));
}