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)
> 

_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to