svn commit: r360808 - in stable/12/sys: conf riscv/include riscv/riscv

John Baldwin jhb at FreeBSD.org
Fri May 8 05:30:13 UTC 2020


Author: jhb
Date: Fri May  8 05:30:10 2020
New Revision: 360808
URL: https://svnweb.freebsd.org/changeset/base/360808

Log:
  MFC 354719,354720,354721,354722,357480: OpenSBI support.
  
  354719:
  RISC-V: pass arg6 in sbi_call
  
  Allow for an additional argument to sbi_call which will be passed in a6.
  This is required for SBI spec 0.2 support, as a6 will indicate the SBI
  function ID.
  
  While here, introduce some macros to clean up the calls.
  
  354720:
  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
  
  354721:
  Add missing files from r354720
  
  354722:
  RISC-V: Print SBI info at startup
  
  SBI version 0.2 introduces functions for obtaining the details of the
  SBI implementation, such as version and implemntation ID. Print this
  info at startup when it is available.
  
  357480:
  Set the LMA of the riscv kernel to the OpenSBI jump target by default
  
  This allows us to boot FreeBSD RISCV on QEMU using the -kernel command line
  options. When using that option, QEMU maps the kernel ELF file to the
  addresses specified in the LMAs in the program headers.
  
  Since version 4.2 QEMU ships with OpenSBI fw_jump by default so this allows
  booting FreeBSD using the following command line:
  qemu-system-riscv64 -bios default -kernel /.../boot/kernel/kernel -nographic -M virt
  
  Without this change the -kernel option cannot be used since the LMAs start
  at address zero and QEMU already maps a ROM to these low physical addresses.
  
  For targets that require a different kernel LMA the make variable
  KERNEL_LMA can be overwritten in the config file. For example, adding
  `makeoptions    KERNEL_LMA=0xc0200000` will create an ELF file that will be
  loaded at 0xc0200000.
  
  Before:
  There are 4 program headers, starting at offset 64
  
  Program Headers:
    Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
    LOAD           0x001000 0xffffffc000000000 0x0000000000000000 0x75e598 0x8be318 RWE 0x1000
    DYNAMIC        0x71fb20 0xffffffc00071eb20 0x000000000071eb20 0x000100 0x000100 RW  0x8
    GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x0
    NOTE           0x693400 0xffffffc000692400 0x0000000000692400 0x000024 0x000024 R   0x4
  
  After:
  
  There are 4 program headers, starting at offset 64
  
  Program Headers:
    Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
    LOAD           0x001000 0xffffffc000000000 0x0000000080200000 0x734198 0x893e18 RWE 0x1000
    DYNAMIC        0x6f7810 0xffffffc0006f6810 0x00000000808f6810 0x000100 0x000100 RW  0x8
    GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x0
    NOTE           0x66ca70 0xffffffc00066ba70 0x000000008086ba70 0x000024 0x000024 R   0x4

Added:
  stable/12/sys/riscv/riscv/sbi.c
     - copied, changed from r354720, head/sys/riscv/riscv/sbi.c
Modified:
  stable/12/sys/conf/Makefile.riscv
  stable/12/sys/conf/files.riscv
  stable/12/sys/conf/ldscript.riscv
  stable/12/sys/riscv/include/md_var.h
  stable/12/sys/riscv/include/sbi.h
  stable/12/sys/riscv/riscv/identcpu.c
  stable/12/sys/riscv/riscv/machdep.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/conf/Makefile.riscv
==============================================================================
--- stable/12/sys/conf/Makefile.riscv	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/conf/Makefile.riscv	Fri May  8 05:30:10 2020	(r360808)
@@ -28,8 +28,17 @@ S=	../../..
 
 INCLUDES+= -I$S/contrib/libfdt
 
+# Set the ELF LMA to the address that OpenSBI's fw_jump jumps to. This allows
+# us to load the kernel with the -kernel flag in QEMU without having to embed
+# it inside BBL or OpenSBI's fw_payload first.
+# Note: For rv32 the start address is different (0x80400000).
+# We set this value using --defsym rather than hardcoding it in ldscript.riscv
+# so that different kernel configs can override the load address.
+KERNEL_LMA?=	0x80200000
+
 SYSTEM_LD= @${LD} -N -m ${LD_EMULATION} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} \
 	--no-warn-mismatch --warn-common --export-dynamic \
+	--defsym='kernel_lma=${KERNEL_LMA}' \
 	--dynamic-linker /red/herring \
 	-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
 

Modified: stable/12/sys/conf/files.riscv
==============================================================================
--- stable/12/sys/conf/files.riscv	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/conf/files.riscv	Fri May  8 05:30:10 2020	(r360808)
@@ -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

Modified: stable/12/sys/conf/ldscript.riscv
==============================================================================
--- stable/12/sys/conf/ldscript.riscv	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/conf/ldscript.riscv	Fri May  8 05:30:10 2020	(r360808)
@@ -7,7 +7,8 @@ SECTIONS
 {
   /* Read-only sections, merged into text segment: */
   . = kernbase;
-  .text      : AT(ADDR(.text) - kernbase)
+  /* The load address kernel_lma is set using --defsym= on the command line. */
+  .text      : AT(kernel_lma)
   {
     *(.text)
     *(.stub)

Modified: stable/12/sys/riscv/include/md_var.h
==============================================================================
--- stable/12/sys/riscv/include/md_var.h	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/riscv/include/md_var.h	Fri May  8 05:30:10 2020	(r360808)
@@ -39,6 +39,9 @@ extern int szsigcode;
 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;
 

Modified: stable/12/sys/riscv/include/sbi.h
==============================================================================
--- stable/12/sys/riscv/include/sbi.h	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/riscv/include/sbi.h	Fri May  8 05:30:10 2020	(r360808)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2016-2017 Ruslan Bukin <br at bsdpad.com>
  * All rights reserved.
+ * Copyright (c) 2019 Mitchell Horne <mhorne at FreeBSD.org>
  *
  * 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
@@ -47,77 +77,109 @@
 #define	SBI_REMOTE_SFENCE_VMA_ASID	7
 #define	SBI_SHUTDOWN			8
 
+#define	SBI_CALL0(e, f)			SBI_CALL4(e, f, 0, 0, 0, 0)
+#define	SBI_CALL1(e, f, p1)		SBI_CALL4(e, f, p1, 0, 0, 0)
+#define	SBI_CALL2(e, f, p1, p2)		SBI_CALL4(e, f, p1, p2, 0, 0)
+#define	SBI_CALL3(e, f, p1, p2, p3)	SBI_CALL4(e, f, p1, p2, p3, 0)
+#define	SBI_CALL4(e, f, p1, p2, p3, p4)	sbi_call(e, f, p1, p2, p3, p4)
+
 /*
  * 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
-sbi_call(uint64_t arg7, uint64_t arg0, uint64_t arg1, uint64_t arg2,
-    uint64_t arg3)
+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);
 	register uintptr_t a3 __asm ("a3") = (uintptr_t)(arg3);
+	register uintptr_t a6 __asm ("a6") = (uintptr_t)(arg6);
 	register uintptr_t a7 __asm ("a7") = (uintptr_t)(arg7);
 
 	__asm __volatile(			\
 		"ecall"				\
-		:"+r"(a0)			\
-		:"r"(a1), "r"(a2), "r" (a3), "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_long sbi_spec_version;
+extern u_long sbi_impl_id;
+extern u_long 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)
 {
 
-	sbi_call(SBI_CONSOLE_PUTCHAR, ch, 0, 0, 0);
+	(void)SBI_CALL1(SBI_CONSOLE_PUTCHAR, 0, ch);
 }
 
 static __inline int
 sbi_console_getchar(void)
 {
 
-	return (sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0, 0));
+	/*
+	 * XXX: The "error" is returned here because legacy SBI functions
+	 * continue to return their value in a0.
+	 */
+	return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error);
 }
 
 static __inline void
 sbi_set_timer(uint64_t val)
 {
 
-	sbi_call(SBI_SET_TIMER, val, 0, 0, 0);
+	(void)SBI_CALL1(SBI_SET_TIMER, 0, val);
 }
 
 static __inline void
 sbi_shutdown(void)
 {
 
-	sbi_call(SBI_SHUTDOWN, 0, 0, 0, 0);
+	(void)SBI_CALL0(SBI_SHUTDOWN, 0);
 }
 
 static __inline void
 sbi_clear_ipi(void)
 {
 
-	sbi_call(SBI_CLEAR_IPI, 0, 0, 0, 0);
+	(void)SBI_CALL0(SBI_CLEAR_IPI, 0);
 }
 
 static __inline void
 sbi_send_ipi(const unsigned long *hart_mask)
 {
 
-	sbi_call(SBI_SEND_IPI, (uint64_t)hart_mask, 0, 0, 0);
+	(void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask);
 }
 
 static __inline void
 sbi_remote_fence_i(const unsigned long *hart_mask)
 {
 
-	sbi_call(SBI_REMOTE_FENCE_I, (uint64_t)hart_mask, 0, 0, 0);
+	(void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask);
 }
 
 static __inline void
@@ -125,7 +187,8 @@ sbi_remote_sfence_vma(const unsigned long *hart_mask,
     unsigned long start, unsigned long size)
 {
 
-	sbi_call(SBI_REMOTE_SFENCE_VMA, (uint64_t)hart_mask, start, size, 0);
+	(void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start,
+	    size);
 }
 
 static __inline void
@@ -134,8 +197,11 @@ sbi_remote_sfence_vma_asid(const unsigned long *hart_m
     unsigned long asid)
 {
 
-	sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, (uint64_t)hart_mask, start, size,
-	    asid);
+	(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask,
+	    start, size, asid);
 }
+
+void sbi_print_version(void);
+void sbi_init(void);
 
 #endif /* !_MACHINE_SBI_H_ */

Modified: stable/12/sys/riscv/riscv/identcpu.c
==============================================================================
--- stable/12/sys/riscv/riscv/identcpu.c	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/riscv/riscv/identcpu.c	Fri May  8 05:30:10 2020	(r360808)
@@ -59,6 +59,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;

Modified: stable/12/sys/riscv/riscv/machdep.c
==============================================================================
--- stable/12/sys/riscv/riscv/machdep.c	Fri May  8 02:42:15 2020	(r360807)
+++ stable/12/sys/riscv/riscv/machdep.c	Fri May  8 05:30:10 2020	(r360808)
@@ -128,6 +128,7 @@ static void
 cpu_startup(void *dummy)
 {
 
+	sbi_print_version();
 	identify_cpu();
 
 	printf("real memory  = %ju (%ju MB)\n", ptoa((uintmax_t)realmem),
@@ -847,6 +848,9 @@ initriscv(struct riscv_bootparams *rvbp)
 	__asm __volatile("mv tp, %0" :: "r"(pcpup));
 
 	PCPU_SET(curthread, &thread0);
+
+	/* Initialize SBI interface. */
+	sbi_init();
 
 	/* Set the module data location */
 	lastaddr = fake_preload_metadata(rvbp);

Copied and modified: stable/12/sys/riscv/riscv/sbi.c (from r354720, head/sys/riscv/riscv/sbi.c)
==============================================================================
--- head/sys/riscv/riscv/sbi.c	Fri Nov 15 03:34:27 2019	(r354720, copy source)
+++ stable/12/sys/riscv/riscv/sbi.c	Fri May  8 05:30:10 2020	(r360808)
@@ -35,6 +35,10 @@ __FBSDID("$FreeBSD$");
 #include <machine/md_var.h>
 #include <machine/sbi.h>
 
+/* SBI Implementation-Specific Definitions */
+#define	OPENSBI_VERSION_MAJOR_OFFSET	16
+#define	OPENSBI_VERSION_MINOR_MASK	0xFFFF
+
 u_long sbi_spec_version;
 u_long sbi_impl_id;
 u_long sbi_impl_version;
@@ -74,6 +78,39 @@ static struct sbi_ret
 sbi_get_mimpid(void)
 {
 	return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_MIMPID));
+}
+
+void
+sbi_print_version(void)
+{
+	u_int major;
+	u_int minor;
+
+	/* For legacy SBI implementations. */
+	if (sbi_spec_version == 0) {
+		printf("SBI: Unknown (Legacy) Implementation\n");
+		printf("SBI Specification Version: 0.1\n");
+		return;
+	}
+
+	switch (sbi_impl_id) {
+	case (SBI_IMPL_ID_BBL):
+		printf("SBI: Berkely Boot Loader %u\n", sbi_impl_version);
+		break;
+	case (SBI_IMPL_ID_OPENSBI):
+		major = sbi_impl_version >> OPENSBI_VERSION_MAJOR_OFFSET;
+		minor = sbi_impl_version & OPENSBI_VERSION_MINOR_MASK;
+		printf("SBI: OpenSBI v%u.%u\n", major, minor);
+		break;
+	default:
+		printf("SBI: Unrecognized Implementation: %u\n", sbi_impl_id);
+		break;
+	}
+
+	major = (sbi_spec_version & SBI_SPEC_VERS_MAJOR_MASK) >>
+	    SBI_SPEC_VERS_MAJOR_OFFSET;
+	minor = (sbi_spec_version & SBI_SPEC_VERS_MINOR_MASK);
+	printf("SBI Specification Version: %u.%u\n", major, minor);
 }
 
 void


More information about the svn-src-all mailing list