From owner-svn-src-all@freebsd.org Tue Jun 11 00:55:56 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 3242415CCF56; Tue, 11 Jun 2019 00:55:56 +0000 (UTC) (envelope-from mhorne@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id CC49A6CEFD; Tue, 11 Jun 2019 00:55:55 +0000 (UTC) (envelope-from mhorne@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id B933E222E8; Tue, 11 Jun 2019 00:55:55 +0000 (UTC) (envelope-from mhorne@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x5B0ttxr089235; Tue, 11 Jun 2019 00:55:55 GMT (envelope-from mhorne@FreeBSD.org) Received: (from mhorne@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x5B0tsOM089231; Tue, 11 Jun 2019 00:55:54 GMT (envelope-from mhorne@FreeBSD.org) Message-Id: <201906110055.x5B0tsOM089231@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mhorne set sender to mhorne@FreeBSD.org using -f From: Mitchell Horne Date: Tue, 11 Jun 2019 00:55:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r348886 - in head/sys/riscv: include riscv X-SVN-Group: head X-SVN-Commit-Author: mhorne X-SVN-Commit-Paths: in head/sys/riscv: include riscv X-SVN-Commit-Revision: 348886 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: CC49A6CEFD X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.97 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.972,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Jun 2019 00:55:56 -0000 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. 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 (r348885) +++ head/sys/riscv/include/elf.h Tue Jun 11 00:55:54 2019 (r348886) @@ -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 (r348885) +++ head/sys/riscv/include/md_var.h Tue Jun 11 00:55:54 2019 (r348886) @@ -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 #include +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 (r348885) +++ head/sys/riscv/riscv/identcpu.c Tue Jun 11 00:55:54 2019 (r348886) @@ -32,18 +32,28 @@ * SUCH DAMAGE. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); #include +#include +#include #include #include -#include #include #include +#include +#include #include +#ifdef FDT +#include +#include +#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)