For CPU_ON, check whether a CPU is disabled or if it actually does not exit. Return NOT_PRESENT rather than INVALID_PARAMS in the former case.
This requires an update to the PSCI spec. As of PSCI v1.1, NOT_PRESENT isn't a valid return value for CPU_ON.
Signed-off-by: Jean-Philippe Brucker jean-philippe@linaro.org --- target/arm/arm-powerctl.h | 1 + target/arm/arm-powerctl.c | 44 +++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/target/arm/arm-powerctl.h b/target/arm/arm-powerctl.h index 37c8a04f0a9..258f8570e8e 100644 --- a/target/arm/arm-powerctl.h +++ b/target/arm/arm-powerctl.h @@ -18,6 +18,7 @@ #define QEMU_ARM_POWERCTL_ALREADY_ON QEMU_PSCI_RET_ALREADY_ON #define QEMU_ARM_POWERCTL_IS_OFF QEMU_PSCI_RET_DENIED #define QEMU_ARM_POWERCTL_ON_PENDING QEMU_PSCI_RET_ON_PENDING +#define QEMU_ARM_POWERCTL_NOT_PRESENT QEMU_PSCI_RET_NOT_PRESENT
/* * arm_get_cpu_by_id: diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index b75f813b403..d80eec70b6a 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -13,6 +13,7 @@ #include "cpu-qom.h" #include "internals.h" #include "arm-powerctl.h" +#include "hw/boards.h" #include "qemu/log.h" #include "qemu/main-loop.h"
@@ -27,18 +28,37 @@ } \ } while (0)
+static CPUArchId *arm_get_archid_by_id(uint64_t id) +{ + int n; + CPUArchId *arch_id; + MachineState *ms = MACHINE(qdev_get_machine()); + + /* + * At this point disabled CPUs don't have a CPUState, but their CPUArchId + * exists. + * + * TODO: Is arch_id == mp_affinity? This needs work. + */ + for (n = 0; n < ms->possible_cpus->len; n++) { + arch_id = &ms->possible_cpus->cpus[n]; + + if (arch_id->arch_id == id) { + return arch_id; + } + } + return NULL; +} + CPUState *arm_get_cpu_by_id(uint64_t id) { - CPUState *cpu; + CPUArchId *arch_id;
DPRINTF("cpu %" PRId64 "\n", id);
- CPU_FOREACH(cpu) { - ARMCPU *armcpu = ARM_CPU(cpu); - - if (armcpu->mp_affinity == id) { - return cpu; - } + arch_id = arm_get_archid_by_id(id); + if (arch_id && arch_id->cpu) { + return CPU(arch_id->cpu); }
qemu_log_mask(LOG_GUEST_ERROR, @@ -145,6 +165,7 @@ int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, { CPUState *target_cpu_state; ARMCPU *target_cpu; + CPUArchId *arch_id; struct CpuOnInfo *info;
assert(qemu_mutex_iothread_locked()); @@ -165,11 +186,16 @@ int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, }
/* Retrieve the cpu we are powering up */ - target_cpu_state = arm_get_cpu_by_id(cpuid); - if (!target_cpu_state) { + arch_id = arm_get_archid_by_id(cpuid); + if (!arch_id) { /* The cpu was not found */ return QEMU_ARM_POWERCTL_INVALID_PARAM; } + if (!arch_id->cpu) { + /* The cpu is not plugged in */ + return QEMU_ARM_POWERCTL_NOT_PRESENT; + } + target_cpu_state = CPU(arch_id->cpu);
target_cpu = ARM_CPU(target_cpu_state); if (target_cpu->power_state == PSCI_ON) {