Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Jun 2019 19:12:24 -0600
From:      Ian Lepore <ian@freebsd.org>
To:        Mitchell Horne <mhorne@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r348886 - in head/sys/riscv: include riscv
Message-ID:  <b0cd8506da0817b55319cae5db9677a1f64ef382.camel@freebsd.org>
In-Reply-To: <201906110055.x5B0tsOM089231@repo.freebsd.org>
References:  <201906110055.x5B0tsOM089231@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 2019-06-11 at 00:55 +0000, Mitchell Horne wrote:
> Author: mhorne
> Date: Tue Jun 11 00:55:54 2019
> New Revision: 348886
> URL: https://svnweb.freebsd.org/changeset/base/348886
> 
> Log:
>   RISC-V: expose extension bits in AT_HWCAP
>   
>   AT_HWCAP is a field in the elf auxiliary vector meant to describe
>   cpu-specific hardware features. For RISC-V we want to use this to
>   indicate the presence of any standard extensions supported by the
> CPU.
>   This allows userland applications to query the system for supported
>   extensions using elf_aux_info(3).
>   
>   Support for an extension is indicated by the presence of its
>   corresponding bit in AT_HWCAP -- e.g. systems supporting the 'c'
>   extension (compressed instructions) will have the second bit set.
>   
>   Extensions advertised through AT_HWCAP are only those that are
> supported
>   by all harts in the system.
>   

A word of advice from the arm world (a don't make the mistakes we did
kind of thing):  If linux has already defined AT_HWCAP values for
riscv, life may be better in the long run if our values match theirs as
much as possible.  It will especially help with ports.

-- Ian

>   Reviewed by:	jhb, markj
>   Approved by:	markj (mentor)
>   MFC after:	2 weeks
>   Differential Revision:	https://reviews.freebsd.org/D20493
> 
> Modified:
>   head/sys/riscv/include/elf.h
>   head/sys/riscv/include/md_var.h
>   head/sys/riscv/riscv/elf_machdep.c
>   head/sys/riscv/riscv/identcpu.c
> 
> Modified: head/sys/riscv/include/elf.h
> =====================================================================
> =========
> --- head/sys/riscv/include/elf.h	Mon Jun 10 23:25:40 2019	(r348
> 885)
> +++ head/sys/riscv/include/elf.h	Tue Jun 11 00:55:54 2019	(r348
> 886)
> @@ -74,4 +74,15 @@ __ElfType(Auxinfo);
>  /* TODO: set correct value */
>  #define	ET_DYN_LOAD_ADDR 0x100000
>  
> +/* Flags passed in AT_HWCAP */
> +#define	HWCAP_ISA_BIT(c)	(1 << ((c) - 'A'))
> +#define	HWCAP_ISA_I		HWCAP_ISA_BIT('I')
> +#define	HWCAP_ISA_M		HWCAP_ISA_BIT('M')
> +#define	HWCAP_ISA_A		HWCAP_ISA_BIT('A')
> +#define	HWCAP_ISA_F		HWCAP_ISA_BIT('F')
> +#define	HWCAP_ISA_D		HWCAP_ISA_BIT('D')
> +#define	HWCAP_ISA_C		HWCAP_ISA_BIT('C')
> +#define	HWCAP_ISA_G		\
> +    (HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F |
> HWCAP_ISA_D)
> +
>  #endif /* !_MACHINE_ELF_H_ */
> 
> Modified: head/sys/riscv/include/md_var.h
> =====================================================================
> =========
> --- head/sys/riscv/include/md_var.h	Mon Jun 10 23:25:40 2019	(r348
> 885)
> +++ head/sys/riscv/include/md_var.h	Tue Jun 11 00:55:54 2019	(r348
> 886)
> @@ -38,6 +38,7 @@ extern char sigcode[];
>  extern int szsigcode;
>  extern uint64_t *vm_page_dump;
>  extern int vm_page_dump_size;
> +extern u_long elf_hwcap;
>  
>  struct dumperinfo;
>  
> 
> Modified: head/sys/riscv/riscv/elf_machdep.c
> =====================================================================
> =========
> --- head/sys/riscv/riscv/elf_machdep.c	Mon Jun 10 23:25:40
> 2019	(r348885)
> +++ head/sys/riscv/riscv/elf_machdep.c	Tue Jun 11 00:55:54
> 2019	(r348886)
> @@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$");
>  #include <machine/elf.h>
>  #include <machine/md_var.h>
>  
> +u_long elf_hwcap;
> +
>  struct sysentvec elf64_freebsd_sysvec = {
>  	.sv_size	= SYS_MAXSYSCALL,
>  	.sv_table	= sysent,
> @@ -90,6 +92,7 @@ struct sysentvec elf64_freebsd_sysvec = {
>  	.sv_schedtail	= NULL,
>  	.sv_thread_detach = NULL,
>  	.sv_trap	= NULL,
> +	.sv_hwcap	= &elf_hwcap,
>  };
>  INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
>  
> 
> Modified: head/sys/riscv/riscv/identcpu.c
> =====================================================================
> =========
> --- head/sys/riscv/riscv/identcpu.c	Mon Jun 10 23:25:40 2019	(r348
> 885)
> +++ head/sys/riscv/riscv/identcpu.c	Tue Jun 11 00:55:54 2019	(r348
> 886)
> @@ -32,18 +32,28 @@
>   * SUCH DAMAGE.
>   */
>  
> +#include "opt_platform.h"
> +
>  #include <sys/cdefs.h>
>  __FBSDID("$FreeBSD$");
>  
>  #include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/kernel.h>
>  #include <sys/pcpu.h>
>  #include <sys/sysctl.h>
> -#include <sys/systm.h>
>  
>  #include <machine/cpu.h>
>  #include <machine/cpufunc.h>
> +#include <machine/elf.h>
> +#include <machine/md_var.h>
>  #include <machine/trap.h>
>  
> +#ifdef FDT
> +#include <dev/fdt/fdt_common.h>
> +#include <dev/ofw/openfirm.h>
> +#endif
> +
>  char machine[] = "riscv";
>  
>  SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
> @@ -87,6 +97,84 @@ const struct cpu_implementers cpu_implementers[] =
> {
>  	{ CPU_IMPL_UCB_ROCKET,	"UC Berkeley Rocket" },
>  	CPU_IMPLEMENTER_NONE,
>  };
> +
> +#ifdef FDT
> +/*
> + * The ISA string is made up of a small prefix (e.g. rv64) and up to
> 26 letters
> + * indicating the presence of the 26 possible standard extensions.
> Therefore 32
> + * characters will be sufficient.
> + */
> +#define	ISA_NAME_MAXLEN		32
> +#define	ISA_PREFIX		("rv"
> __XSTRING(__riscv_xlen))
> +#define	ISA_PREFIX_LEN		(sizeof(ISA_PREFIX) - 1)
> +
> +static void
> +fill_elf_hwcap(void *dummy __unused)
> +{
> +	u_long caps[256] = {0};
> +	char isa[ISA_NAME_MAXLEN];
> +	u_long hwcap;
> +	phandle_t node;
> +	ssize_t len;
> +	int i;
> +
> +	caps['i'] = caps['I'] = HWCAP_ISA_I;
> +	caps['m'] = caps['M'] = HWCAP_ISA_M;
> +	caps['a'] = caps['A'] = HWCAP_ISA_A;
> +#ifdef FPE
> +	caps['f'] = caps['F'] = HWCAP_ISA_F;
> +	caps['d'] = caps['D'] = HWCAP_ISA_D;
> +#endif
> +	caps['c'] = caps['C'] = HWCAP_ISA_C;
> +
> +	node = OF_finddevice("/cpus");
> +	if (node == -1) {
> +		if (bootverbose)
> +			printf("fill_elf_hwcap: Can't find cpus
> node\n");
> +		return;
> +	}
> +
> +	/*
> +	 * Iterate through the CPUs and examine their ISA string. While
> we
> +	 * could assign elf_hwcap to be whatever the boot CPU supports,
> to
> +	 * handle the (unusual) case of running a system with
> hetergeneous
> +	 * ISAs, keep only the extension bits that are common to all
> harts.
> +	 */
> +	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
> +		if (!fdt_is_compatible_strict(node, "riscv")) {
> +			if (bootverbose)
> +				printf("fill_elf_hwcap: Can't find
> cpu\n");
> +			return;
> +		}
> +
> +		len = OF_getprop(node, "riscv,isa", isa, sizeof(isa));
> +		KASSERT(len <= ISA_NAME_MAXLEN, ("ISA string
> truncated"));
> +		if (len == -1) {
> +			if (bootverbose)
> +				printf("fill_elf_hwcap: "
> +				    "Can't find riscv,isa property\n");
> +			return;
> +		} else if (strncmp(isa, ISA_PREFIX, ISA_PREFIX_LEN) !=
> 0) {
> +			if (bootverbose)
> +				printf("fill_elf_hwcap: "
> +				    "Unsupported ISA string: %s\n",
> isa);
> +			return;
> +		}
> +
> +		hwcap = 0;
> +		for (i = ISA_PREFIX_LEN; i < len; i++)
> +			hwcap |= caps[(unsigned char)isa[i]];
> +
> +		if (elf_hwcap != 0)
> +			elf_hwcap &= hwcap;
> +		else
> +			elf_hwcap = hwcap;
> +
> +	}
> +}
> +
> +SYSINIT(identcpu, SI_SUB_CPU, SI_ORDER_ANY, fill_elf_hwcap, NULL);
> +#endif
>  
>  void
>  identify_cpu(void)
> 




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?b0cd8506da0817b55319cae5db9677a1f64ef382.camel>