diff options
Diffstat (limited to 'target-arm/arm-powerctl.c')
-rw-r--r-- | target-arm/arm-powerctl.c | 228 |
1 files changed, 0 insertions, 228 deletions
diff --git a/target-arm/arm-powerctl.c b/target-arm/arm-powerctl.c deleted file mode 100644 index fbb7a15daa..0000000000 --- a/target-arm/arm-powerctl.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * QEMU support -- ARM Power Control specific functions. - * - * Copyright (c) 2016 Jean-Christophe Dubois - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "cpu.h" -#include "cpu-qom.h" -#include "internals.h" -#include "arm-powerctl.h" -#include "qemu/log.h" -#include "exec/exec-all.h" - -#ifndef DEBUG_ARM_POWERCTL -#define DEBUG_ARM_POWERCTL 0 -#endif - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_ARM_POWERCTL) { \ - fprintf(stderr, "[ARM]%s: " fmt , __func__, ##args); \ - } \ - } while (0) - -CPUState *arm_get_cpu_by_id(uint64_t id) -{ - CPUState *cpu; - - DPRINTF("cpu %" PRId64 "\n", id); - - CPU_FOREACH(cpu) { - ARMCPU *armcpu = ARM_CPU(cpu); - - if (armcpu->mp_affinity == id) { - return cpu; - } - } - - qemu_log_mask(LOG_GUEST_ERROR, - "[ARM]%s: Requesting unknown CPU %" PRId64 "\n", - __func__, id); - - return NULL; -} - -int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, - uint32_t target_el, bool target_aa64) -{ - CPUState *target_cpu_state; - ARMCPU *target_cpu; - - DPRINTF("cpu %" PRId64 " (EL %d, %s) @ 0x%" PRIx64 " with R0 = 0x%" PRIx64 - "\n", cpuid, target_el, target_aa64 ? "aarch64" : "aarch32", entry, - context_id); - - /* requested EL level need to be in the 1 to 3 range */ - assert((target_el > 0) && (target_el < 4)); - - if (target_aa64 && (entry & 3)) { - /* - * if we are booting in AArch64 mode then "entry" needs to be 4 bytes - * aligned. - */ - return QEMU_ARM_POWERCTL_INVALID_PARAM; - } - - /* 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->powered_off) { - qemu_log_mask(LOG_GUEST_ERROR, - "[ARM]%s: CPU %" PRId64 " is already on\n", - __func__, cpuid); - return QEMU_ARM_POWERCTL_ALREADY_ON; - } - - /* - * The newly brought CPU is requested to enter the exception level - * "target_el" and be in the requested mode (AArch64 or AArch32). - */ - - if (((target_el == 3) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) || - ((target_el == 2) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL2))) { - /* - * The CPU does not support requested level - */ - return QEMU_ARM_POWERCTL_INVALID_PARAM; - } - - if (!target_aa64 && arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64)) { - /* - * For now we don't support booting an AArch64 CPU in AArch32 mode - * TODO: We should add this support later - */ - qemu_log_mask(LOG_UNIMP, - "[ARM]%s: Starting AArch64 CPU %" PRId64 - " in AArch32 mode is not supported yet\n", - __func__, cpuid); - return QEMU_ARM_POWERCTL_INVALID_PARAM; - } - - /* Initialize the cpu we are turning on */ - cpu_reset(target_cpu_state); - target_cpu->powered_off = false; - target_cpu_state->halted = 0; - - if (target_aa64) { - if ((target_el < 3) && arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) { - /* - * As target mode is AArch64, we need to set lower - * exception level (the requested level 2) to AArch64 - */ - target_cpu->env.cp15.scr_el3 |= SCR_RW; - } - - if ((target_el < 2) && arm_feature(&target_cpu->env, ARM_FEATURE_EL2)) { - /* - * As target mode is AArch64, we need to set lower - * exception level (the requested level 1) to AArch64 - */ - target_cpu->env.cp15.hcr_el2 |= HCR_RW; - } - - target_cpu->env.pstate = aarch64_pstate_mode(target_el, true); - } else { - /* We are requested to boot in AArch32 mode */ - static uint32_t mode_for_el[] = { 0, - ARM_CPU_MODE_SVC, - ARM_CPU_MODE_HYP, - ARM_CPU_MODE_SVC }; - - cpsr_write(&target_cpu->env, mode_for_el[target_el], CPSR_M, - CPSRWriteRaw); - } - - if (target_el == 3) { - /* Processor is in secure mode */ - target_cpu->env.cp15.scr_el3 &= ~SCR_NS; - } else { - /* Processor is not in secure mode */ - target_cpu->env.cp15.scr_el3 |= SCR_NS; - } - - /* We check if the started CPU is now at the correct level */ - assert(target_el == arm_current_el(&target_cpu->env)); - - if (target_aa64) { - target_cpu->env.xregs[0] = context_id; - target_cpu->env.thumb = false; - } else { - target_cpu->env.regs[0] = context_id; - target_cpu->env.thumb = entry & 1; - entry &= 0xfffffffe; - } - - /* Start the new CPU at the requested address */ - cpu_set_pc(target_cpu_state, entry); - - qemu_cpu_kick(target_cpu_state); - - /* We are good to go */ - return QEMU_ARM_POWERCTL_RET_SUCCESS; -} - -int arm_set_cpu_off(uint64_t cpuid) -{ - CPUState *target_cpu_state; - ARMCPU *target_cpu; - - DPRINTF("cpu %" PRId64 "\n", cpuid); - - /* change to the cpu we are powering up */ - target_cpu_state = arm_get_cpu_by_id(cpuid); - if (!target_cpu_state) { - return QEMU_ARM_POWERCTL_INVALID_PARAM; - } - target_cpu = ARM_CPU(target_cpu_state); - if (target_cpu->powered_off) { - qemu_log_mask(LOG_GUEST_ERROR, - "[ARM]%s: CPU %" PRId64 " is already off\n", - __func__, cpuid); - return QEMU_ARM_POWERCTL_IS_OFF; - } - - target_cpu->powered_off = true; - target_cpu_state->halted = 1; - target_cpu_state->exception_index = EXCP_HLT; - cpu_loop_exit(target_cpu_state); - /* notreached */ - - return QEMU_ARM_POWERCTL_RET_SUCCESS; -} - -int arm_reset_cpu(uint64_t cpuid) -{ - CPUState *target_cpu_state; - ARMCPU *target_cpu; - - DPRINTF("cpu %" PRId64 "\n", cpuid); - - /* change to the cpu we are resetting */ - target_cpu_state = arm_get_cpu_by_id(cpuid); - if (!target_cpu_state) { - return QEMU_ARM_POWERCTL_INVALID_PARAM; - } - target_cpu = ARM_CPU(target_cpu_state); - if (target_cpu->powered_off) { - qemu_log_mask(LOG_GUEST_ERROR, - "[ARM]%s: CPU %" PRId64 " is off\n", - __func__, cpuid); - return QEMU_ARM_POWERCTL_IS_OFF; - } - - /* Reset the cpu */ - cpu_reset(target_cpu_state); - - return QEMU_ARM_POWERCTL_RET_SUCCESS; -} |