198128601SRob Herring /* 298128601SRob Herring * Copyright (C) 2014 - Linaro 398128601SRob Herring * Author: Rob Herring <rob.herring@linaro.org> 498128601SRob Herring * 598128601SRob Herring * This program is free software; you can redistribute it and/or modify 698128601SRob Herring * it under the terms of the GNU General Public License as published by 798128601SRob Herring * the Free Software Foundation; either version 2 of the License, or 898128601SRob Herring * (at your option) any later version. 998128601SRob Herring * 1098128601SRob Herring * This program is distributed in the hope that it will be useful, 1198128601SRob Herring * but WITHOUT ANY WARRANTY; without even the implied warranty of 1298128601SRob Herring * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1398128601SRob Herring * GNU General Public License for more details. 1498128601SRob Herring * 1598128601SRob Herring * You should have received a copy of the GNU General Public License 1698128601SRob Herring * along with this program; if not, see <http://www.gnu.org/licenses/>. 1798128601SRob Herring */ 1874c21bd0SPeter Maydell #include "qemu/osdep.h" 1998128601SRob Herring #include <cpu.h> 2098128601SRob Herring #include <cpu-qom.h> 2198128601SRob Herring #include <exec/helper-proto.h> 2298128601SRob Herring #include <kvm-consts.h> 2398128601SRob Herring #include <sysemu/sysemu.h> 2498128601SRob Herring #include "internals.h" 2598128601SRob Herring 2698128601SRob Herring bool arm_is_psci_call(ARMCPU *cpu, int excp_type) 2798128601SRob Herring { 2898128601SRob Herring /* Return true if the r0/x0 value indicates a PSCI call and 2998128601SRob Herring * the exception type matches the configured PSCI conduit. This is 3098128601SRob Herring * called before the SMC/HVC instruction is executed, to decide whether 3198128601SRob Herring * we should treat it as a PSCI call or with the architecturally 3298128601SRob Herring * defined behaviour for an SMC or HVC (which might be UNDEF or trap 3398128601SRob Herring * to EL2 or to EL3). 3498128601SRob Herring */ 3598128601SRob Herring CPUARMState *env = &cpu->env; 3698128601SRob Herring uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0]; 3798128601SRob Herring 3898128601SRob Herring switch (excp_type) { 3998128601SRob Herring case EXCP_HVC: 4098128601SRob Herring if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_HVC) { 4198128601SRob Herring return false; 4298128601SRob Herring } 4398128601SRob Herring break; 4498128601SRob Herring case EXCP_SMC: 4598128601SRob Herring if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) { 4698128601SRob Herring return false; 4798128601SRob Herring } 4898128601SRob Herring break; 4998128601SRob Herring default: 5098128601SRob Herring return false; 5198128601SRob Herring } 5298128601SRob Herring 5398128601SRob Herring switch (param) { 5498128601SRob Herring case QEMU_PSCI_0_2_FN_PSCI_VERSION: 5598128601SRob Herring case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 5698128601SRob Herring case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 5798128601SRob Herring case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 5898128601SRob Herring case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 5998128601SRob Herring case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 6098128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_ON: 6198128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_ON: 6298128601SRob Herring case QEMU_PSCI_0_2_FN64_CPU_ON: 6398128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_OFF: 6498128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_OFF: 6598128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 6698128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 6798128601SRob Herring case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 6898128601SRob Herring case QEMU_PSCI_0_1_FN_MIGRATE: 6998128601SRob Herring case QEMU_PSCI_0_2_FN_MIGRATE: 7098128601SRob Herring return true; 7198128601SRob Herring default: 7298128601SRob Herring return false; 7398128601SRob Herring } 7498128601SRob Herring } 7598128601SRob Herring 76eb5e1d3cSPavel Fedin static CPUState *get_cpu_by_id(uint64_t id) 77eb5e1d3cSPavel Fedin { 78eb5e1d3cSPavel Fedin CPUState *cpu; 79eb5e1d3cSPavel Fedin 80eb5e1d3cSPavel Fedin CPU_FOREACH(cpu) { 81eb5e1d3cSPavel Fedin ARMCPU *armcpu = ARM_CPU(cpu); 82eb5e1d3cSPavel Fedin 83eb5e1d3cSPavel Fedin if (armcpu->mp_affinity == id) { 84eb5e1d3cSPavel Fedin return cpu; 85eb5e1d3cSPavel Fedin } 86eb5e1d3cSPavel Fedin } 87eb5e1d3cSPavel Fedin 88eb5e1d3cSPavel Fedin return NULL; 89eb5e1d3cSPavel Fedin } 90eb5e1d3cSPavel Fedin 9198128601SRob Herring void arm_handle_psci_call(ARMCPU *cpu) 9298128601SRob Herring { 9398128601SRob Herring /* 9498128601SRob Herring * This function partially implements the logic for dispatching Power State 9598128601SRob Herring * Coordination Interface (PSCI) calls (as described in ARM DEN 0022B.b), 9698128601SRob Herring * to the extent required for bringing up and taking down secondary cores, 9798128601SRob Herring * and for handling reset and poweroff requests. 9898128601SRob Herring * Additional information about the calling convention used is available in 9998128601SRob Herring * the document 'SMC Calling Convention' (ARM DEN 0028) 10098128601SRob Herring */ 10198128601SRob Herring CPUState *cs = CPU(cpu); 10298128601SRob Herring CPUARMState *env = &cpu->env; 10398128601SRob Herring uint64_t param[4]; 10498128601SRob Herring uint64_t context_id, mpidr; 10598128601SRob Herring target_ulong entry; 10698128601SRob Herring int32_t ret = 0; 10798128601SRob Herring int i; 10898128601SRob Herring 10998128601SRob Herring for (i = 0; i < 4; i++) { 11098128601SRob Herring /* 11198128601SRob Herring * All PSCI functions take explicit 32-bit or native int sized 11298128601SRob Herring * arguments so we can simply zero-extend all arguments regardless 11398128601SRob Herring * of which exact function we are about to call. 11498128601SRob Herring */ 11598128601SRob Herring param[i] = is_a64(env) ? env->xregs[i] : env->regs[i]; 11698128601SRob Herring } 11798128601SRob Herring 11898128601SRob Herring if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) { 11998128601SRob Herring ret = QEMU_PSCI_RET_INVALID_PARAMS; 12098128601SRob Herring goto err; 12198128601SRob Herring } 12298128601SRob Herring 12398128601SRob Herring switch (param[0]) { 12498128601SRob Herring CPUState *target_cpu_state; 12598128601SRob Herring ARMCPU *target_cpu; 12698128601SRob Herring CPUClass *target_cpu_class; 12798128601SRob Herring 12898128601SRob Herring case QEMU_PSCI_0_2_FN_PSCI_VERSION: 12998128601SRob Herring ret = QEMU_PSCI_0_2_RET_VERSION_0_2; 13098128601SRob Herring break; 13198128601SRob Herring case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 13298128601SRob Herring ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ 13398128601SRob Herring break; 13498128601SRob Herring case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 13598128601SRob Herring case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 13698128601SRob Herring mpidr = param[1]; 13798128601SRob Herring 13898128601SRob Herring switch (param[2]) { 13998128601SRob Herring case 0: 140eb5e1d3cSPavel Fedin target_cpu_state = get_cpu_by_id(mpidr); 14198128601SRob Herring if (!target_cpu_state) { 14298128601SRob Herring ret = QEMU_PSCI_RET_INVALID_PARAMS; 14398128601SRob Herring break; 14498128601SRob Herring } 14598128601SRob Herring target_cpu = ARM_CPU(target_cpu_state); 14698128601SRob Herring ret = target_cpu->powered_off ? 1 : 0; 14798128601SRob Herring break; 14898128601SRob Herring default: 14998128601SRob Herring /* Everything above affinity level 0 is always on. */ 15098128601SRob Herring ret = 0; 15198128601SRob Herring } 15298128601SRob Herring break; 15398128601SRob Herring case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 15498128601SRob Herring qemu_system_reset_request(); 15598128601SRob Herring /* QEMU reset and shutdown are async requests, but PSCI 15698128601SRob Herring * mandates that we never return from the reset/shutdown 15798128601SRob Herring * call, so power the CPU off now so it doesn't execute 15898128601SRob Herring * anything further. 15998128601SRob Herring */ 16098128601SRob Herring goto cpu_off; 16198128601SRob Herring case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 16298128601SRob Herring qemu_system_shutdown_request(); 16398128601SRob Herring goto cpu_off; 16498128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_ON: 16598128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_ON: 16698128601SRob Herring case QEMU_PSCI_0_2_FN64_CPU_ON: 16798128601SRob Herring mpidr = param[1]; 16898128601SRob Herring entry = param[2]; 16998128601SRob Herring context_id = param[3]; 17098128601SRob Herring 17198128601SRob Herring /* change to the cpu we are powering up */ 172eb5e1d3cSPavel Fedin target_cpu_state = get_cpu_by_id(mpidr); 17398128601SRob Herring if (!target_cpu_state) { 17498128601SRob Herring ret = QEMU_PSCI_RET_INVALID_PARAMS; 17598128601SRob Herring break; 17698128601SRob Herring } 17798128601SRob Herring target_cpu = ARM_CPU(target_cpu_state); 17898128601SRob Herring if (!target_cpu->powered_off) { 17998128601SRob Herring ret = QEMU_PSCI_RET_ALREADY_ON; 18098128601SRob Herring break; 18198128601SRob Herring } 18298128601SRob Herring target_cpu_class = CPU_GET_CLASS(target_cpu); 18398128601SRob Herring 18498128601SRob Herring /* Initialize the cpu we are turning on */ 18598128601SRob Herring cpu_reset(target_cpu_state); 18698128601SRob Herring target_cpu->powered_off = false; 18798128601SRob Herring target_cpu_state->halted = 0; 18898128601SRob Herring 18998128601SRob Herring /* 19098128601SRob Herring * The PSCI spec mandates that newly brought up CPUs enter the 19198128601SRob Herring * exception level of the caller in the same execution mode as 19298128601SRob Herring * the caller, with context_id in x0/r0, respectively. 19398128601SRob Herring * 19498128601SRob Herring * For now, it is sufficient to assert() that CPUs come out of 19598128601SRob Herring * reset in the same mode as the calling CPU, since we only 19698128601SRob Herring * implement EL1, which means that 19798128601SRob Herring * (a) there is no EL2 for the calling CPU to trap into to change 19898128601SRob Herring * its state 19998128601SRob Herring * (b) the newly brought up CPU enters EL1 immediately after coming 20098128601SRob Herring * out of reset in the default state 20198128601SRob Herring */ 20298128601SRob Herring assert(is_a64(env) == is_a64(&target_cpu->env)); 20398128601SRob Herring if (is_a64(env)) { 20498128601SRob Herring if (entry & 1) { 20598128601SRob Herring ret = QEMU_PSCI_RET_INVALID_PARAMS; 20698128601SRob Herring break; 20798128601SRob Herring } 20898128601SRob Herring target_cpu->env.xregs[0] = context_id; 20998128601SRob Herring } else { 21098128601SRob Herring target_cpu->env.regs[0] = context_id; 21198128601SRob Herring target_cpu->env.thumb = entry & 1; 21298128601SRob Herring } 21398128601SRob Herring target_cpu_class->set_pc(target_cpu_state, entry); 21498128601SRob Herring 21598128601SRob Herring ret = 0; 21698128601SRob Herring break; 21798128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_OFF: 21898128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_OFF: 21998128601SRob Herring goto cpu_off; 22098128601SRob Herring case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 22198128601SRob Herring case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 22298128601SRob Herring case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 22398128601SRob Herring /* Affinity levels are not supported in QEMU */ 22498128601SRob Herring if (param[1] & 0xfffe0000) { 22598128601SRob Herring ret = QEMU_PSCI_RET_INVALID_PARAMS; 22698128601SRob Herring break; 22798128601SRob Herring } 22898128601SRob Herring /* Powerdown is not supported, we always go into WFI */ 22998128601SRob Herring if (is_a64(env)) { 23098128601SRob Herring env->xregs[0] = 0; 23198128601SRob Herring } else { 23298128601SRob Herring env->regs[0] = 0; 23398128601SRob Herring } 23498128601SRob Herring helper_wfi(env); 23598128601SRob Herring break; 23698128601SRob Herring case QEMU_PSCI_0_1_FN_MIGRATE: 23798128601SRob Herring case QEMU_PSCI_0_2_FN_MIGRATE: 23898128601SRob Herring ret = QEMU_PSCI_RET_NOT_SUPPORTED; 23998128601SRob Herring break; 24098128601SRob Herring default: 24198128601SRob Herring g_assert_not_reached(); 24298128601SRob Herring } 24398128601SRob Herring 24498128601SRob Herring err: 24598128601SRob Herring if (is_a64(env)) { 24698128601SRob Herring env->xregs[0] = ret; 24798128601SRob Herring } else { 24898128601SRob Herring env->regs[0] = ret; 24998128601SRob Herring } 25098128601SRob Herring return; 25198128601SRob Herring 25298128601SRob Herring cpu_off: 25398128601SRob Herring cpu->powered_off = true; 25498128601SRob Herring cs->halted = 1; 25598128601SRob Herring cs->exception_index = EXCP_HLT; 25698128601SRob Herring cpu_loop_exit(cs); 25798128601SRob Herring /* notreached */ 25898128601SRob Herring } 259