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-head mailing list