Module Name: src Committed By: ryo Date: Wed Sep 30 08:43:47 UTC 2020
Modified Files: src/sys/arch/aarch64/aarch64: procfs_machdep.c Log Message: add linux compatible /proc/cpuinfo To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/aarch64/aarch64/procfs_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/aarch64/aarch64/procfs_machdep.c diff -u src/sys/arch/aarch64/aarch64/procfs_machdep.c:1.1 src/sys/arch/aarch64/aarch64/procfs_machdep.c:1.2 --- src/sys/arch/aarch64/aarch64/procfs_machdep.c:1.1 Sun Aug 10 05:47:37 2014 +++ src/sys/arch/aarch64/aarch64/procfs_machdep.c Wed Sep 30 08:43:47 2020 @@ -1,12 +1,9 @@ -/* $NetBSD: procfs_machdep.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */ +/* $NetBSD: procfs_machdep.c,v 1.2 2020/09/30 08:43:47 ryo Exp $ */ /*- - * Copyright (c) 2014 The NetBSD Foundation, Inc. + * Copyright (c) 2020 Ryo Shimizu <r...@nerv.org> * All rights reserved. * - * This code is derived from software contributed to The NetBSD Foundation - * by Matt Thomas of 3am Software Foundry. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -16,39 +13,202 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_machdep.c,v 1.1 2014/08/10 05:47:37 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_machdep.c,v 1.2 2020/09/30 08:43:47 ryo Exp $"); #include <sys/param.h> -#include <sys/systm.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/proc.h> - #include <miscfs/procfs/procfs.h> +#include <aarch64/armreg.h> + + +/* use variables named 'buf', 'left', 'total' */ +#define FORWARD_BUF(_len) \ + do { \ + total += _len; \ + if (_len < left) { \ + buf += _len; \ + left -= _len; \ + } else { \ + buf += left; \ + left = 0; \ + } \ + } while (0 /*CONSTCOND*/) + +#define OUTPUT_BUF(fmt, args...) \ + do { \ + size_t l = snprintf(buf, left, fmt, ## args); \ + FORWARD_BUF(l); \ + } while (0/*CONSTCOND*/) + +static int +procfs_cpuinfo_features(struct cpu_info *ci, char *buf, int buflen) +{ + uint64_t isar0, isar1, mmfr2, pfr0, pfr1; + size_t left, total; + + isar0 = ci->ci_id.ac_aa64isar0; + isar1 = ci->ci_id.ac_aa64isar1; + mmfr2 = ci->ci_id.ac_aa64mmfr2; + pfr0 = ci->ci_id.ac_aa64pfr0; + pfr1 = ci->ci_id.ac_aa64pfr1; + + left = buflen; + total = 0; + + /* + * I don't know if we need to mimic the order of HWCAP in linux + */ + OUTPUT_BUF("Features\t:"); +#define SO_EQ(reg, mask, val) (__SHIFTOUT((reg), (mask)) == (val)) + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_FP, ID_AA64PFR0_EL1_FP_IMPL)) + OUTPUT_BUF(" fp"); + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_ADVSIMD, ID_AA64PFR0_EL1_ADV_SIMD_IMPL)) + OUTPUT_BUF(" asimd"); + /* notyet: " evtstrm" */ + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_AES, ID_AA64ISAR0_EL1_AES_AES)) + OUTPUT_BUF(" aes"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_AES, ID_AA64ISAR0_EL1_AES_PMUL)) + OUTPUT_BUF(" pmull"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SHA1, + ID_AA64ISAR0_EL1_SHA1_SHA1CPMHSU)) + OUTPUT_BUF(" sha1"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SHA2, + ID_AA64ISAR0_EL1_SHA2_SHA256HSU)) + OUTPUT_BUF(" sha2"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_CRC32, ID_AA64ISAR0_EL1_CRC32_CRC32X)) + OUTPUT_BUF(" crc32"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_ATOMIC, ID_AA64ISAR0_EL1_ATOMIC_SWP)) + OUTPUT_BUF(" atomics"); + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_FP, ID_AA64PFR0_EL1_FP_HP)) + OUTPUT_BUF(" fphp"); + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_ADVSIMD, ID_AA64PFR0_EL1_ADV_SIMD_HP)) + OUTPUT_BUF(" asimdhp"); + /* notyet: " cpuid" */ + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_RDM, ID_AA64ISAR0_EL1_RDM_SQRDML)) + OUTPUT_BUF(" asimdrdm"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_JSCVT, + ID_AA64ISAR1_EL1_JSCVT_SUPPORTED)) + OUTPUT_BUF(" jscvt"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_FCMA, + ID_AA64ISAR1_EL1_FCMA_SUPPORTED)) + OUTPUT_BUF(" fcma"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_LRCPC, ID_AA64ISAR1_EL1_LRCPC_PR)) + OUTPUT_BUF(" lrcpc"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_DPB, ID_AA64ISAR1_EL1_DPB_CVAP)) + OUTPUT_BUF(" dcpop"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SHA3, ID_AA64ISAR0_EL1_SHA3_EOR3)) + OUTPUT_BUF(" sha3"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SM3, ID_AA64ISAR0_EL1_SM3_SM3)) + OUTPUT_BUF(" sm3"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SM4, ID_AA64ISAR0_EL1_SM4_SM4)) + OUTPUT_BUF(" sm4"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_DP, ID_AA64ISAR0_EL1_DP_UDOT)) + OUTPUT_BUF(" asimddp"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_SHA2, + ID_AA64ISAR0_EL1_SHA2_SHA512HSU)) + OUTPUT_BUF(" sha512"); + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_SVE, ID_AA64PFR0_EL1_SVE_IMPL)) + OUTPUT_BUF(" sve"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_FHM, ID_AA64ISAR0_EL1_FHM_FMLAL)) + OUTPUT_BUF(" asimdfhm"); + if (SO_EQ(pfr0, ID_AA64PFR0_EL1_DIT, ID_AA64PFR0_EL1_DIT_IMPL)) + OUTPUT_BUF(" dit"); + if (SO_EQ(mmfr2, ID_AA64MMFR2_EL1_AT, ID_AA64MMFR2_EL1_AT_16BIT)) + OUTPUT_BUF(" uscat"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_LRCPC, ID_AA64ISAR1_EL1_LRCPC_PR_UR)) + OUTPUT_BUF(" ilrcpc"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_TS, ID_AA64ISAR0_EL1_TS_CFINV)) + OUTPUT_BUF(" flagm"); + if (SO_EQ(pfr1, ID_AA64PFR1_EL1_SSBS, ID_AA64PFR1_EL1_SSBS_MSR_MRS)) + OUTPUT_BUF(" ssbs"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_SB, ID_AA64ISAR1_EL1_SB_SUPPORTED)) + OUTPUT_BUF(" sb"); +#ifdef ARMV83_PAC + if (aarch64_pac_enabled) + OUTPUT_BUF(" paca pacg"); +#endif + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_DPB, ID_AA64ISAR1_EL1_DPB_CVAP_CVADP)) + OUTPUT_BUF(" dcpodp"); + /* notyet: " sve2" */ + /* notyet: " sveaes" */ + /* notyet: " svepmull" */ + /* notyet: " svebitperm" */ + /* notyet: " svesha3" */ + /* notyet: " svesm4" */ + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_TS, ID_AA64ISAR0_EL1_TS_AXFLAG)) + OUTPUT_BUF(" flagm2"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_FRINTTS, + ID_AA64ISAR1_EL1_FRINTTS_SUPPORTED)) + OUTPUT_BUF(" frint"); + /* notyet: " svei8mm" */ + /* notyet: " svef32mm" */ + /* notyet: " svef64mm" */ + /* notyet: " svebf16" */ + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_I8MM, + ID_AA64ISAR1_EL1_I8MM_SUPPORTED)) + OUTPUT_BUF(" i8mm"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_BF16, ID_AA64ISAR1_EL1_BF16_BFDOT)) + OUTPUT_BUF(" bf16"); + if (SO_EQ(isar1, ID_AA64ISAR1_EL1_DGH, ID_AA64ISAR1_EL1_DGH_SUPPORTED)) + OUTPUT_BUF(" dgh"); + if (SO_EQ(isar0, ID_AA64ISAR0_EL1_RNDR, ID_AA64ISAR0_EL1_RNDR_RNDRRS)) + OUTPUT_BUF(" rng"); +#ifdef ARMV85_BTI + if (aarch64_bti_enabled) + OUTPUT_BUF(" bti"); +#endif + OUTPUT_BUF("\n"); +#undef SO_EQ + + return total; +} -/* - * Linux-style /proc/cpuinfo. - * Only used when procfs is mounted with -o linux. - */ int -procfs_getcpuinfstr(char *buf, size_t *len) +procfs_getcpuinfstr(char *buf, size_t *lenp) { - *len = 0; + struct cpu_info *ci; + CPU_INFO_ITERATOR cii; + size_t left, len, total; + int ret = 0; + + left = *lenp; + total = 0; + + for (CPU_INFO_FOREACH(cii, ci)) { + OUTPUT_BUF("processor\t: %lu\n", cii); + + len = procfs_cpuinfo_features(ci, buf, left); + FORWARD_BUF(len); + + OUTPUT_BUF("CPU implementer\t: 0x%02lx\n", + __SHIFTOUT(ci->ci_id.ac_midr, CPU_ID_IMPLEMENTOR_MASK)); + OUTPUT_BUF("CPU architecture: 8\n"); /* ARMv8 */ + OUTPUT_BUF("CPU variant\t: 0x%lx\n", + __SHIFTOUT(ci->ci_id.ac_midr, CPU_ID_VARIANT_MASK)); + OUTPUT_BUF("CPU part\t: 0x%03lx\n", + __SHIFTOUT(ci->ci_id.ac_midr, CPU_ID_PARTNO_MASK)); + OUTPUT_BUF("CPU revision\t: %lu\n", + __SHIFTOUT(ci->ci_id.ac_midr, CPU_ID_REVISION_MASK)); + OUTPUT_BUF("\n"); + } + + /* not enough buffer? */ + if (total >= *lenp) + ret = -1; - return 0; + *lenp = total + 1; /* total output + '\0' */ + return ret; }