From: Richard Henderson <richard.henderson@linaro.org>
To: Helge Deller <deller@gmx.de>, qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Daniel P . Berrangé" <berrange@redhat.com>,
qemu-arm@nongnu.org, "Laurent Vivier" <laurent@vivier.eu>
Subject: Re: [PATCH v3 2/3] linux-user: Emulate /proc/cpuinfo on aarch64 and arm
Date: Thu, 3 Aug 2023 14:10:13 -0700 [thread overview]
Message-ID: <679e6fca-f921-5eb8-f59d-8d11703e96c6@linaro.org> (raw)
In-Reply-To: <20230803204803.639733-3-deller@gmx.de>
On 8/3/23 13:48, Helge Deller wrote:
> Add emulation for /proc/cpuinfo for arm architecture.
> The output below mimics output as seen on debian porterboxes.
>
> aarch64 output example:
>
> processor : 0
> model name : ARMv8 Processor rev 0 (v8l)
> BogoMIPS : 100.00
> Features : swp half thumb fast_mult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae aes pmull sha1 sha2 crc32
> CPU implementer : 0x41
> CPU architecture: 8
> CPU variant : 0x1
> CPU part : 0xd07
> CPU revision : 0
> Hardware : QEMU v8.0.92 arm,cortex-a57
>
> arm 32-bit output example:
>
> processor : 0
> model name : ARMv5 Processor rev 6 (armv5l)
> BogoMIPS : 50.00
> Features : swp half thumb fast_mult edsp
> CPU implementer : 0x69
> CPU architecture: 5
> CPU variant : 0
> CPU part : 0x2d0
> CPU revision : 6
> Hardware : QEMU v8.0.92 marvell,xscale
> Revision : 0000
> Serial : 0000000000000000
>
> Signed-off-by: Helge Deller <deller@gmx.de>
>
> v4:
> - more refinements based on Richards feedback
> v3:
> - show variant, part, revision and implementor based on midr
> value (suggested by Richard Henderson)
> v2:
> - show features of CPU which is actually being emulated by qemu
> (suggested by Peter Maydell)
> ---
> linux-user/elfload.c | 130 +++++++++++++++++++++++++++++++++++++++++--
> linux-user/loader.h | 6 +-
> linux-user/syscall.c | 76 ++++++++++++++++++++++++-
> 3 files changed, 205 insertions(+), 7 deletions(-)
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 861ec07abc..99804e477d 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -466,7 +466,7 @@ static bool init_guest_commpage(void)
> #define ELF_HWCAP get_elf_hwcap()
> #define ELF_HWCAP2 get_elf_hwcap2()
>
> -static uint32_t get_elf_hwcap(void)
> +uint32_t get_elf_hwcap(void)
> {
> ARMCPU *cpu = ARM_CPU(thread_cpu);
> uint32_t hwcaps = 0;
> @@ -508,7 +508,7 @@ static uint32_t get_elf_hwcap(void)
> return hwcaps;
> }
>
> -static uint32_t get_elf_hwcap2(void)
> +uint32_t get_elf_hwcap2(void)
> {
> ARMCPU *cpu = ARM_CPU(thread_cpu);
> uint32_t hwcaps = 0;
> @@ -521,6 +521,49 @@ static uint32_t get_elf_hwcap2(void)
> return hwcaps;
> }
>
> +const char *elf_hwcap_str(uint32_t bit)
> +{
> + static const char *hwcap_str[] = {
> + [__builtin_ctz(ARM_HWCAP_ARM_SWP )] = "swp",
> + [__builtin_ctz(ARM_HWCAP_ARM_HALF )] = "half",
> + [__builtin_ctz(ARM_HWCAP_ARM_THUMB )] = "thumb",
> + [__builtin_ctz(ARM_HWCAP_ARM_26BIT )] = "26bit",
> + [__builtin_ctz(ARM_HWCAP_ARM_FAST_MULT)] = "fast_mult",
> + [__builtin_ctz(ARM_HWCAP_ARM_FPA )] = "fpa",
> + [__builtin_ctz(ARM_HWCAP_ARM_VFP )] = "vfp",
> + [__builtin_ctz(ARM_HWCAP_ARM_EDSP )] = "edsp",
> + [__builtin_ctz(ARM_HWCAP_ARM_JAVA )] = "java",
> + [__builtin_ctz(ARM_HWCAP_ARM_IWMMXT )] = "iwmmxt",
> + [__builtin_ctz(ARM_HWCAP_ARM_CRUNCH )] = "crunch",
> + [__builtin_ctz(ARM_HWCAP_ARM_THUMBEE )] = "thumbee",
> + [__builtin_ctz(ARM_HWCAP_ARM_NEON )] = "neon",
> + [__builtin_ctz(ARM_HWCAP_ARM_VFPv3 )] = "vfpv3",
> + [__builtin_ctz(ARM_HWCAP_ARM_VFPv3D16 )] = "vfpv3d16",
> + [__builtin_ctz(ARM_HWCAP_ARM_TLS )] = "tls",
> + [__builtin_ctz(ARM_HWCAP_ARM_VFPv4 )] = "vfpv4",
> + [__builtin_ctz(ARM_HWCAP_ARM_IDIVA )] = "idiva",
> + [__builtin_ctz(ARM_HWCAP_ARM_IDIVT )] = "idivt",
> + [__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32",
> + [__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae",
> + [__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm",
> + };
> +
> + return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
> +}
> +
> +const char *elf_hwcap2_str(uint32_t bit)
> +{
> + static const char *hwcap_str[] = {
> + [__builtin_ctz(ARM_HWCAP2_ARM_AES )] = "aes",
> + [__builtin_ctz(ARM_HWCAP2_ARM_PMULL)] = "pmull",
> + [__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1",
> + [__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2",
> + [__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32",
> + };
> +
> + return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
> +}
> +
> #undef GET_FEATURE
> #undef GET_FEATURE_ID
>
> @@ -668,7 +711,7 @@ enum {
> #define GET_FEATURE_ID(feat, hwcap) \
> do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
>
> -static uint32_t get_elf_hwcap(void)
> +uint32_t get_elf_hwcap(void)
> {
> ARMCPU *cpu = ARM_CPU(thread_cpu);
> uint32_t hwcaps = 0;
> @@ -706,7 +749,7 @@ static uint32_t get_elf_hwcap(void)
> return hwcaps;
> }
>
> -static uint32_t get_elf_hwcap2(void)
> +uint32_t get_elf_hwcap2(void)
> {
> ARMCPU *cpu = ARM_CPU(thread_cpu);
> uint32_t hwcaps = 0;
> @@ -741,6 +784,85 @@ static uint32_t get_elf_hwcap2(void)
> return hwcaps;
> }
>
> +const char *elf_hwcap_str(uint32_t bit)
> +{
> + static const char *hwcap_str[] = {
> + [__builtin_ctz(ARM_HWCAP_A64_FP )] = "fp",
> + [__builtin_ctz(ARM_HWCAP_A64_ASIMD )] = "asimd",
> + [__builtin_ctz(ARM_HWCAP_A64_EVTSTRM )] = "evtstrm",
> + [__builtin_ctz(ARM_HWCAP_A64_AES )] = "aes",
> + [__builtin_ctz(ARM_HWCAP_A64_PMULL )] = "pmull",
> + [__builtin_ctz(ARM_HWCAP_A64_SHA1 )] = "sha1",
> + [__builtin_ctz(ARM_HWCAP_A64_SHA2 )] = "sha2",
> + [__builtin_ctz(ARM_HWCAP_A64_CRC32 )] = "crc32",
> + [__builtin_ctz(ARM_HWCAP_A64_ATOMICS )] = "atomics",
> + [__builtin_ctz(ARM_HWCAP_A64_FPHP )] = "fphp",
> + [__builtin_ctz(ARM_HWCAP_A64_ASIMDHP )] = "asimdhp",
> + [__builtin_ctz(ARM_HWCAP_A64_CPUID )] = "cpuid",
> + [__builtin_ctz(ARM_HWCAP_A64_ASIMDRDM)] = "asimdrdm",
> + [__builtin_ctz(ARM_HWCAP_A64_JSCVT )] = "jscvt",
> + [__builtin_ctz(ARM_HWCAP_A64_FCMA )] = "fcma",
> + [__builtin_ctz(ARM_HWCAP_A64_LRCPC )] = "lrcpc",
> + [__builtin_ctz(ARM_HWCAP_A64_DCPOP )] = "dcpop",
> + [__builtin_ctz(ARM_HWCAP_A64_SHA3 )] = "sha3",
> + [__builtin_ctz(ARM_HWCAP_A64_SM3 )] = "sm3",
> + [__builtin_ctz(ARM_HWCAP_A64_SM4 )] = "sm4",
> + [__builtin_ctz(ARM_HWCAP_A64_ASIMDDP )] = "asimddp",
> + [__builtin_ctz(ARM_HWCAP_A64_SHA512 )] = "sha512",
> + [__builtin_ctz(ARM_HWCAP_A64_SVE )] = "sve",
> + [__builtin_ctz(ARM_HWCAP_A64_ASIMDFHM)] = "asimdfhm",
> + [__builtin_ctz(ARM_HWCAP_A64_DIT )] = "dit",
> + [__builtin_ctz(ARM_HWCAP_A64_USCAT )] = "uscat",
> + [__builtin_ctz(ARM_HWCAP_A64_ILRCPC )] = "ilrcpc",
> + [__builtin_ctz(ARM_HWCAP_A64_FLAGM )] = "flagm",
> + [__builtin_ctz(ARM_HWCAP_A64_SSBS )] = "ssbs",
> + [__builtin_ctz(ARM_HWCAP_A64_SB )] = "sb",
> + [__builtin_ctz(ARM_HWCAP_A64_PACA )] = "paca",
> + [__builtin_ctz(ARM_HWCAP_A64_PACG )] = "pacg",
> + };
> +
> + return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
> +}
> +
> +const char *elf_hwcap2_str(uint32_t bit)
> +{
> + static const char *hwcap_str[] = {
> + [__builtin_ctz(ARM_HWCAP2_A64_DCPODP )] = "dcpodp",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVE2 )] = "sve2",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEAES )] = "sveaes",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEPMULL )] = "svepmull",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEBITPERM )] = "svebitperm",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVESHA3 )] = "svesha3",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVESM4 )] = "svesm4",
> + [__builtin_ctz(ARM_HWCAP2_A64_FLAGM2 )] = "flagm2",
> + [__builtin_ctz(ARM_HWCAP2_A64_FRINT )] = "frint",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEI8MM )] = "svei8mm",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEF32MM )] = "svef32mm",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEF64MM )] = "svef64mm",
> + [__builtin_ctz(ARM_HWCAP2_A64_SVEBF16 )] = "svebf16",
> + [__builtin_ctz(ARM_HWCAP2_A64_I8MM )] = "i8mm",
> + [__builtin_ctz(ARM_HWCAP2_A64_BF16 )] = "bf16",
> + [__builtin_ctz(ARM_HWCAP2_A64_DGH )] = "dgh",
> + [__builtin_ctz(ARM_HWCAP2_A64_RNG )] = "rng",
> + [__builtin_ctz(ARM_HWCAP2_A64_BTI )] = "bti",
> + [__builtin_ctz(ARM_HWCAP2_A64_MTE )] = "mte",
> + [__builtin_ctz(ARM_HWCAP2_A64_ECV )] = "ecv",
> + [__builtin_ctz(ARM_HWCAP2_A64_AFP )] = "afp",
> + [__builtin_ctz(ARM_HWCAP2_A64_RPRES )] = "rpres",
> + [__builtin_ctz(ARM_HWCAP2_A64_MTE3 )] = "mte3",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME )] = "sme",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "sme_i16i64",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "sme_f64f64",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "sme_i8i32",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "sme_f16f32",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "sme_b16f32",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "sme_f32f32",
> + [__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "sme_fa64",
> + };
> +
> + return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
> +}
> +
> #undef GET_FEATURE_ID
>
> #endif /* not TARGET_AARCH64 */
> diff --git a/linux-user/loader.h b/linux-user/loader.h
> index 59cbeacf24..324e5c872a 100644
> --- a/linux-user/loader.h
> +++ b/linux-user/loader.h
> @@ -56,9 +56,13 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
>
> extern unsigned long guest_stack_size;
>
> -#ifdef TARGET_S390X
> +#if defined(TARGET_S390X) || defined(TARGET_AARCH64) || defined(TARGET_ARM)
> uint32_t get_elf_hwcap(void);
> const char *elf_hwcap_str(uint32_t bit);
> #endif
> +#if defined(TARGET_AARCH64) || defined(TARGET_ARM)
> +uint32_t get_elf_hwcap2(void);
> +const char *elf_hwcap2_str(uint32_t bit);
> +#endif
>
> #endif /* LINUX_USER_LOADER_H */
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 1ec7d27e37..bac764f502 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -8323,7 +8323,8 @@ void target_exception_dump(CPUArchState *env, const char *fmt, int code)
>
> #if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
> defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA) || \
> - defined(TARGET_RISCV) || defined(TARGET_S390X)
> + defined(TARGET_RISCV) || defined(TARGET_S390X) || defined(TARGET_ARM) || \
> + defined(TARGET_AARCH64)
> static int is_proc(const char *filename, const char *entry)
> {
> return strcmp(filename, entry) == 0;
> @@ -8539,6 +8540,76 @@ static int open_hardware(CPUArchState *cpu_env, int fd)
> }
> #endif
>
> +#if defined(TARGET_AARCH64) || defined(TARGET_ARM)
> +static int open_cpuinfo(CPUArchState *cpu_env, int fd)
> +{
> + ARMCPU *cpu = ARM_CPU(thread_cpu);
> + const int rev = FIELD_EX64(cpu->midr, MIDR_EL1, REVISION);
> + int arch, is64;
> + uint32_t elf_hwcap = get_elf_hwcap();
> + uint32_t elf_hwcap2 = get_elf_hwcap2();
> + const char *hwcap_str;
> + int i, j, num_cpus;
> +
> + if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
> + arch = 8;
> + } else if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
> + arch = 7;
> + } else if (arm_feature(&cpu->env, ARM_FEATURE_V6)) {
> + arch = 6;
> + } else if (arm_feature(&cpu->env, ARM_FEATURE_V5)) {
> + arch = 5;
> + } else {
> + arch = 4;
> + }
> + is64 = (arch >= 8) ? 1 : 0;
No, there's 32-bit armv8 as well. Either
is64 = is_a64(&cpu->env);
or
#ifdef TARGET_AARCH64
is64 = true;
#endif
r~
> +
> + num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
> + for (i = 0; i < num_cpus; i++) {
> + dprintf(fd, "processor\t: %d\n", i);
> + dprintf(fd, "model name\t: ARMv%d Processor rev %d (%sv%d%c)\n",
> + arch, rev, is64 ? "" : "arm", arch, TARGET_BIG_ENDIAN ? 'b' : 'l');
> + dprintf(fd, "BogoMIPS\t: %d.00\n", is64 ? 100 : 50);
> + dprintf(fd, "Features\t:");
> + for (j = 0; j < sizeof(elf_hwcap) * 8; j++) {
> + if (!(elf_hwcap & (1 << j))) {
> + continue;
> + }
> + hwcap_str = elf_hwcap_str(j);
> + if (hwcap_str) {
> + dprintf(fd, " %s", hwcap_str);
> + }
> + }
> + for (j = 0; j < sizeof(elf_hwcap2) * 8; j++) {
> + if (!(elf_hwcap2 & (1 << j))) {
> + continue;
> + }
> + hwcap_str = elf_hwcap2_str(j);
> + if (hwcap_str) {
> + dprintf(fd, " %s", hwcap_str);
> + }
> + }
> + dprintf(fd, "\n");
> + dprintf(fd, "CPU implementer\t: %#02x\n",
> + (unsigned int) FIELD_EX64(cpu->midr, MIDR_EL1, IMPLEMENTER));
> + dprintf(fd, "CPU architecture: %d\n", arch);
> + dprintf(fd, "CPU variant\t: %#x\n",
> + (unsigned int) FIELD_EX64(cpu->midr, MIDR_EL1, VARIANT));
> + dprintf(fd, "CPU part\t: %#03x\n",
> + (unsigned int) FIELD_EX64(cpu->midr, MIDR_EL1, PARTNUM));
> + dprintf(fd, "CPU revision\t: %d\n\n", rev);
> + }
> +
> + dprintf(fd, "Hardware\t: QEMU v%s %s\n", QEMU_VERSION,
> + cpu->dtb_compatible ? : "");
> + if (!is64) {
> + dprintf(fd, "Revision\t: 0000\n");
> + dprintf(fd, "Serial\t\t: 0000000000000000\n");
> + }
> +
> + return 0;
> +}
> +#endif
>
> int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
> int flags, mode_t mode, bool safe)
> @@ -8561,7 +8632,8 @@ int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *fname,
> { "/proc/net/route", open_net_route, is_proc },
> #endif
> #if defined(TARGET_SPARC) || defined(TARGET_HPPA) || \
> - defined(TARGET_RISCV) || defined(TARGET_S390X)
> + defined(TARGET_RISCV) || defined(TARGET_S390X) || \
> + defined(TARGET_ARM) || defined(TARGET_AARCH64)
> { "/proc/cpuinfo", open_cpuinfo, is_proc },
> #endif
> #if defined(TARGET_M68K)
> --
> 2.41.0
>
next prev parent reply other threads:[~2023-08-03 21:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-03 20:48 [PATCH v3 0/3] linux-user: /proc/cpuinfo fix and content emulation for arm Helge Deller
2023-08-03 20:48 ` [PATCH v3 1/3] linux-user: Fix openat() emulation to correctly detect accesses to /proc Helge Deller
2023-08-03 20:48 ` [PATCH v3 2/3] linux-user: Emulate /proc/cpuinfo on aarch64 and arm Helge Deller
2023-08-03 21:10 ` Richard Henderson [this message]
2023-08-03 20:48 ` [PATCH v3 3/3] linux-user: Emulate /proc/cpuinfo for Alpha Helge Deller
2023-08-03 21:12 ` Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=679e6fca-f921-5eb8-f59d-8d11703e96c6@linaro.org \
--to=richard.henderson@linaro.org \
--cc=berrange@redhat.com \
--cc=deller@gmx.de \
--cc=laurent@vivier.eu \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).