Skip to content

Commit

Permalink
target-arm: Use the kernel's idea of MPIDR if we're using KVM
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Shlomo Pongratz <shlomo.pongratz@huawei.com>
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Message-id: 02f601d0a1e6$90c7d630$b2578290$@samsung.com
[PMM: Use a local #define rather than a global variable for
 the TCG ARM_CPUS_PER_CLUSTER setting. Tweak a comment. Update the
 commit message.]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pfedin authored and pm215 committed Jun 15, 2015
1 parent 8f4d260 commit eb5e1d3
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 9 deletions.
2 changes: 1 addition & 1 deletion hw/arm/virt.c
Expand Up @@ -311,7 +311,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
"enable-method", "psci");
}

qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", cpu);
qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", armcpu->mp_affinity);
g_free(nodename);
}
}
Expand Down
1 change: 1 addition & 0 deletions target-arm/cpu-qom.h
Expand Up @@ -160,6 +160,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.
*/
Expand Down
12 changes: 12 additions & 0 deletions target-arm/cpu.c
Expand Up @@ -383,17 +383,29 @@ static inline void unset_feature(CPUARMState *env, int feature)
env->features &= ~(1ULL << feature);
}

#define ARM_CPUS_PER_CLUSTER 8

static void arm_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
ARMCPU *cpu = ARM_CPU(obj);
static bool inited;
uint32_t Aff1, Aff0;

cs->env_ptr = &cpu->env;
cpu_exec_init(&cpu->env);
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;

#ifndef CONFIG_USER_ONLY
/* Our inbound IRQ and FIQ lines */
if (kvm_enabled()) {
Expand Down
9 changes: 3 additions & 6 deletions target-arm/helper.c
Expand Up @@ -2063,12 +2063,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(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)
Expand Down
15 changes: 15 additions & 0 deletions target-arm/kvm32.c
Expand Up @@ -153,10 +153,14 @@ bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
}
}

#define ARM_MPIDR_HWID_BITMASK 0xFFFFFF
#define ARM_CPU_ID_MPIDR 0, 0, 0, 5

int kvm_arch_init_vcpu(CPUState *cs)
{
int ret;
uint64_t v;
uint32_t mpidr;
struct kvm_one_reg r;
ARMCPU *cpu = ARM_CPU(cs);

Expand Down Expand Up @@ -193,6 +197,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
return -EINVAL;
}

/*
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
* Currently KVM has its own idea about MPIDR assignment, so we
* override our defaults with what we get from KVM.
*/
ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
if (ret) {
return ret;
}
cpu->mp_affinity = mpidr & ARM_MPIDR_HWID_BITMASK;

return kvm_arm_init_cpreg_list(cpu);
}

Expand Down
15 changes: 15 additions & 0 deletions target-arm/kvm64.c
Expand Up @@ -77,9 +77,13 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
return true;
}

#define ARM_MPIDR_HWID_BITMASK 0xFF00FFFFFFULL
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5

int kvm_arch_init_vcpu(CPUState *cs)
{
int ret;
uint64_t mpidr;
ARMCPU *cpu = ARM_CPU(cs);

if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
Expand Down Expand Up @@ -107,6 +111,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}

/*
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
* Currently KVM has its own idea about MPIDR assignment, so we
* override our defaults with what we get from KVM.
*/
ret = kvm_get_one_reg(cs, ARM64_SYS_REG(ARM_CPU_ID_MPIDR), &mpidr);
if (ret) {
return ret;
}
cpu->mp_affinity = mpidr & ARM_MPIDR_HWID_BITMASK;

return kvm_arm_init_cpreg_list(cpu);
}

Expand Down
19 changes: 17 additions & 2 deletions target-arm/psci.c
Expand Up @@ -72,6 +72,21 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
}
}

static CPUState *get_cpu_by_id(uint64_t id)
{
CPUState *cpu;

CPU_FOREACH(cpu) {
ARMCPU *armcpu = ARM_CPU(cpu);

if (armcpu->mp_affinity == id) {
return cpu;
}
}

return NULL;
}

void arm_handle_psci_call(ARMCPU *cpu)
{
/*
Expand Down Expand Up @@ -121,7 +136,7 @@ void arm_handle_psci_call(ARMCPU *cpu)

switch (param[2]) {
case 0:
target_cpu_state = qemu_get_cpu(mpidr & 0xff);
target_cpu_state = get_cpu_by_id(mpidr);
if (!target_cpu_state) {
ret = QEMU_PSCI_RET_INVALID_PARAMS;
break;
Expand Down Expand Up @@ -153,7 +168,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
context_id = param[3];

/* change to the cpu we are powering up */
target_cpu_state = qemu_get_cpu(mpidr & 0xff);
target_cpu_state = get_cpu_by_id(mpidr);
if (!target_cpu_state) {
ret = QEMU_PSCI_RET_INVALID_PARAMS;
break;
Expand Down

0 comments on commit eb5e1d3

Please sign in to comment.