target/arm/arm-powerctl: Add new arm_set_cpu_on_and_reset()
Currently the Arm arm-powerctl.h APIs allow: * arm_set_cpu_on(), which powers on a CPU and sets its initial PC and other startup state * arm_reset_cpu(), which resets a CPU which is already on (and fails if the CPU is powered off) but there is no way to say "power on a CPU as if it had just come out of reset and don't do anything else to it". Add a new function arm_set_cpu_on_and_reset(), which does this. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190219125808.25174-5-peter.maydell@linaro.org
This commit is contained in:
parent
f9f62e4c37
commit
ea824b9742
@ -228,6 +228,62 @@ int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id,
|
||||
return QEMU_ARM_POWERCTL_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static void arm_set_cpu_on_and_reset_async_work(CPUState *target_cpu_state,
|
||||
run_on_cpu_data data)
|
||||
{
|
||||
ARMCPU *target_cpu = ARM_CPU(target_cpu_state);
|
||||
|
||||
/* Initialize the cpu we are turning on */
|
||||
cpu_reset(target_cpu_state);
|
||||
target_cpu_state->halted = 0;
|
||||
|
||||
/* Finally set the power status */
|
||||
assert(qemu_mutex_iothread_locked());
|
||||
target_cpu->power_state = PSCI_ON;
|
||||
}
|
||||
|
||||
int arm_set_cpu_on_and_reset(uint64_t cpuid)
|
||||
{
|
||||
CPUState *target_cpu_state;
|
||||
ARMCPU *target_cpu;
|
||||
|
||||
assert(qemu_mutex_iothread_locked());
|
||||
|
||||
/* Retrieve the cpu we are powering up */
|
||||
target_cpu_state = arm_get_cpu_by_id(cpuid);
|
||||
if (!target_cpu_state) {
|
||||
/* The cpu was not found */
|
||||
return QEMU_ARM_POWERCTL_INVALID_PARAM;
|
||||
}
|
||||
|
||||
target_cpu = ARM_CPU(target_cpu_state);
|
||||
if (target_cpu->power_state == PSCI_ON) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"[ARM]%s: CPU %" PRId64 " is already on\n",
|
||||
__func__, cpuid);
|
||||
return QEMU_ARM_POWERCTL_ALREADY_ON;
|
||||
}
|
||||
|
||||
/*
|
||||
* If another CPU has powered the target on we are in the state
|
||||
* ON_PENDING and additional attempts to power on the CPU should
|
||||
* fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI
|
||||
* spec)
|
||||
*/
|
||||
if (target_cpu->power_state == PSCI_ON_PENDING) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"[ARM]%s: CPU %" PRId64 " is already powering on\n",
|
||||
__func__, cpuid);
|
||||
return QEMU_ARM_POWERCTL_ON_PENDING;
|
||||
}
|
||||
|
||||
async_run_on_cpu(target_cpu_state, arm_set_cpu_on_and_reset_async_work,
|
||||
RUN_ON_CPU_NULL);
|
||||
|
||||
/* We are good to go */
|
||||
return QEMU_ARM_POWERCTL_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static void arm_set_cpu_off_async_work(CPUState *target_cpu_state,
|
||||
run_on_cpu_data data)
|
||||
{
|
||||
|
@ -74,4 +74,20 @@ int arm_set_cpu_off(uint64_t cpuid);
|
||||
*/
|
||||
int arm_reset_cpu(uint64_t cpuid);
|
||||
|
||||
/*
|
||||
* arm_set_cpu_on_and_reset:
|
||||
* @cpuid: the id of the CPU we want to star
|
||||
*
|
||||
* Start the cpu designated by @cpuid and put it through its normal
|
||||
* CPU reset process. The CPU will start in the way it is architected
|
||||
* to start after a power-on reset.
|
||||
*
|
||||
* Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success.
|
||||
* QEMU_ARM_POWERCTL_INVALID_PARAM if there is no CPU with that ID.
|
||||
* QEMU_ARM_POWERCTL_ALREADY_ON if the CPU is already on.
|
||||
* QEMU_ARM_POWERCTL_ON_PENDING if the CPU is already partway through
|
||||
* powering on.
|
||||
*/
|
||||
int arm_set_cpu_on_and_reset(uint64_t cpuid);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user