From caed2f123dec80e7ee37b53338d2815f065e5e35 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Tue, 13 Feb 2018 14:31:09 -0500 Subject: [PATCH] target-arm: Use the kernel's idea of MPIDR if we're using KVM When we're using KVM, the kernel's internal idea of the MPIDR affinity fields must match the values we tell it for the guest vcpu cluster configuration in the device tree. Since at the moment the kernel doesn't support letting userspace tell it the correct affinity fields to use, we must read the kernel's view and reflect that back in the device tree. Backports commit eb5e1d3c85dffe677da2550d211f9304a7d5ba3b from qemu --- qemu/target-arm/cpu-qom.h | 1 + qemu/target-arm/cpu.c | 12 ++++++++++++ qemu/target-arm/helper.c | 9 +++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/qemu/target-arm/cpu-qom.h b/qemu/target-arm/cpu-qom.h index f9b360c2..5632fd56 100644 --- a/qemu/target-arm/cpu-qom.h +++ b/qemu/target-arm/cpu-qom.h @@ -159,6 +159,7 @@ typedef struct ARMCPU { uint64_t id_aa64mmfr1; uint32_t dbgdidr; uint32_t clidr; + uint64_t mp_affinity; /* MP ID without feature bits */ /* The elements of this array are the CCSIDR values for each cache, * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc. */ diff --git a/qemu/target-arm/cpu.c b/qemu/target-arm/cpu.c index 3361c076..01c160ad 100644 --- a/qemu/target-arm/cpu.c +++ b/qemu/target-arm/cpu.c @@ -325,16 +325,28 @@ static inline void unset_feature(CPUARMState *env, int feature) env->features &= ~(1ULL << feature); } +#define ARM_CPUS_PER_CLUSTER 8 + static void arm_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) { CPUState *cs = CPU(obj); ARMCPU *cpu = ARM_CPU(uc, obj); + uint32_t Aff1, Aff0; cs->env_ptr = &cpu->env; cpu_exec_init(&cpu->env, opaque); cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); + /* This cpu-id-to-MPIDR affinity is used only for TCG; KVM will override it. + * We don't support setting cluster ID ([16..23]) (known as Aff2 + * in later ARM ARM versions), or any of the higher affinity level fields, + * so these bits always RAZ. + */ + Aff1 = cs->cpu_index / ARM_CPUS_PER_CLUSTER; + Aff0 = cs->cpu_index % ARM_CPUS_PER_CLUSTER; + cpu->mp_affinity = (Aff1 << 8) | Aff0; + #if 0 #ifndef CONFIG_USER_ONLY /* Our inbound IRQ and FIQ lines */ diff --git a/qemu/target-arm/helper.c b/qemu/target-arm/helper.c index d0af7a25..81254eaf 100644 --- a/qemu/target-arm/helper.c +++ b/qemu/target-arm/helper.c @@ -1783,12 +1783,9 @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = { static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri) { - CPUState *cs = CPU(arm_env_get_cpu(env)); - uint32_t mpidr = cs->cpu_index; - /* We don't support setting cluster ID ([8..11]) (known as Aff1 - * in later ARM ARM versions), or any of the higher affinity level fields, - * so these bits always RAZ. - */ + ARMCPU *cpu = ARM_CPU(env->uc, arm_env_get_cpu(env)); + uint64_t mpidr = cpu->mp_affinity; + if (arm_feature(env, ARM_FEATURE_V7MP)) { mpidr |= (1U << 31); /* Cores which are uniprocessor (non-coherent)