svn commit: r348886 - in head/sys/riscv: include riscv
Mitchell Horne
mhorne at freebsd.org
Tue Jun 11 04:03:37 UTC 2019
On Mon, Jun 10, 2019 at 9:12 PM Ian Lepore <ian at freebsd.org> wrote:
>
> 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
That's good advice. Rest assured that in this case we are mimicking the
behaviour that's been implemented in Linux.
Mitchell
>
> > 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)
> >
>
More information about the svn-src-all
mailing list