linux-user: Emulate /proc/cpuinfo on s390x
Some s390x userspace programs are confused when seeing a foreign /proc/cpuinfo [1]. Add the emulation for s390x; follow the respective kernel code structure where possible. Output example: vendor_id : IBM/S390 # processors : 12 bogomips per cpu: 13370.00 max thread id : 0 features : esan3 zarch stfle msa facilities : 0 1 2 3 4 7 9 16 17 18 19 21 22 24 25 27 30 31 32 33 34 35 37 40 41 45 49 51 52 53 57 58 61 69 71 72 75 76 77 129 130 131 135 138 146 148 processor 0: version = 00, identification = 000000, machine = 8561 processor 1: version = 00, identification = 100000, machine = 8561 [...] cpu number : 0 version : 00 identification : 000000 machine : 8561 cpu number : 1 version : 00 identification : 100000 machine : 8561 [...] [1] https://bugzilla.redhat.com/show_bug.cgi?id=2211472 Reported-by: Tulio Magno Quites Machado Filho <tuliom@redhat.com> Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20230605113950.1169228-5-iii@linux.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
e19807bee3
commit
1fb9bdaf59
@ -8232,7 +8232,7 @@ 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_RISCV) || defined(TARGET_S390X)
|
||||
static int is_proc(const char *filename, const char *entry)
|
||||
{
|
||||
return strcmp(filename, entry) == 0;
|
||||
@ -8339,6 +8339,107 @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_S390X)
|
||||
/*
|
||||
* Emulate what a Linux kernel running in qemu-system-s390x -M accel=tcg would
|
||||
* show in /proc/cpuinfo.
|
||||
*
|
||||
* Skip the following in order to match the missing support in op_ecag():
|
||||
* - show_cacheinfo().
|
||||
* - show_cpu_topology().
|
||||
* - show_cpu_mhz().
|
||||
*
|
||||
* Use fixed values for certain fields:
|
||||
* - bogomips per cpu - from a qemu-system-s390x run.
|
||||
* - max thread id = 0, since SMT / SIGP_SET_MULTI_THREADING is not supported.
|
||||
*
|
||||
* Keep the code structure close to arch/s390/kernel/processor.c.
|
||||
*/
|
||||
|
||||
static void show_facilities(int fd)
|
||||
{
|
||||
size_t sizeof_stfl_bytes = 2048;
|
||||
g_autofree uint8_t *stfl_bytes = g_new0(uint8_t, sizeof_stfl_bytes);
|
||||
unsigned int bit;
|
||||
|
||||
dprintf(fd, "facilities :");
|
||||
s390_get_feat_block(S390_FEAT_TYPE_STFL, stfl_bytes);
|
||||
for (bit = 0; bit < sizeof_stfl_bytes * 8; bit++) {
|
||||
if (test_be_bit(bit, stfl_bytes)) {
|
||||
dprintf(fd, " %d", bit);
|
||||
}
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
|
||||
static int cpu_ident(unsigned long n)
|
||||
{
|
||||
return deposit32(0, CPU_ID_BITS - CPU_PHYS_ADDR_BITS, CPU_PHYS_ADDR_BITS,
|
||||
n);
|
||||
}
|
||||
|
||||
static void show_cpu_summary(CPUArchState *cpu_env, int fd)
|
||||
{
|
||||
S390CPUModel *model = env_archcpu(cpu_env)->model;
|
||||
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
uint32_t elf_hwcap = get_elf_hwcap();
|
||||
const char *hwcap_str;
|
||||
int i;
|
||||
|
||||
dprintf(fd, "vendor_id : IBM/S390\n"
|
||||
"# processors : %i\n"
|
||||
"bogomips per cpu: 13370.00\n",
|
||||
num_cpus);
|
||||
dprintf(fd, "max thread id : 0\n");
|
||||
dprintf(fd, "features\t: ");
|
||||
for (i = 0; i < sizeof(elf_hwcap) * 8; i++) {
|
||||
if (!(elf_hwcap & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
hwcap_str = elf_hwcap_str(i);
|
||||
if (hwcap_str) {
|
||||
dprintf(fd, "%s ", hwcap_str);
|
||||
}
|
||||
}
|
||||
dprintf(fd, "\n");
|
||||
show_facilities(fd);
|
||||
for (i = 0; i < num_cpus; i++) {
|
||||
dprintf(fd, "processor %d: "
|
||||
"version = %02X, "
|
||||
"identification = %06X, "
|
||||
"machine = %04X\n",
|
||||
i, model->cpu_ver, cpu_ident(i), model->def->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_cpu_ids(CPUArchState *cpu_env, int fd, unsigned long n)
|
||||
{
|
||||
S390CPUModel *model = env_archcpu(cpu_env)->model;
|
||||
|
||||
dprintf(fd, "version : %02X\n", model->cpu_ver);
|
||||
dprintf(fd, "identification : %06X\n", cpu_ident(n));
|
||||
dprintf(fd, "machine : %04X\n", model->def->type);
|
||||
}
|
||||
|
||||
static void show_cpuinfo(CPUArchState *cpu_env, int fd, unsigned long n)
|
||||
{
|
||||
dprintf(fd, "\ncpu number : %ld\n", n);
|
||||
show_cpu_ids(cpu_env, fd, n);
|
||||
}
|
||||
|
||||
static int open_cpuinfo(CPUArchState *cpu_env, int fd)
|
||||
{
|
||||
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
int i;
|
||||
|
||||
show_cpu_summary(cpu_env, fd);
|
||||
for (i = 0; i < num_cpus; i++) {
|
||||
show_cpuinfo(cpu_env, fd, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_M68K)
|
||||
static int open_hardware(CPUArchState *cpu_env, int fd)
|
||||
{
|
||||
@ -8363,7 +8464,8 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int
|
||||
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
|
||||
{ "/proc/net/route", open_net_route, is_proc },
|
||||
#endif
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined(TARGET_RISCV)
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_HPPA) || \
|
||||
defined(TARGET_RISCV) || defined(TARGET_S390X)
|
||||
{ "/proc/cpuinfo", open_cpuinfo, is_proc },
|
||||
#endif
|
||||
#if defined(TARGET_M68K)
|
||||
|
Loading…
Reference in New Issue
Block a user