Message ID | 20230803204803.639733-3-deller@gmx.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | linux-user: /proc/cpuinfo fix and content emulation for arm | expand |
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 >
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; + + 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)
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(-) -- 2.41.0