19def656eSClaudio Fontana /*
29def656eSClaudio Fontana * Copyright (C) 2014 - Linaro
39def656eSClaudio Fontana * Author: Rob Herring <rob.herring@linaro.org>
49def656eSClaudio Fontana *
59def656eSClaudio Fontana * This program is free software; you can redistribute it and/or modify
69def656eSClaudio Fontana * it under the terms of the GNU General Public License as published by
79def656eSClaudio Fontana * the Free Software Foundation; either version 2 of the License, or
89def656eSClaudio Fontana * (at your option) any later version.
99def656eSClaudio Fontana *
109def656eSClaudio Fontana * This program is distributed in the hope that it will be useful,
119def656eSClaudio Fontana * but WITHOUT ANY WARRANTY; without even the implied warranty of
129def656eSClaudio Fontana * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
139def656eSClaudio Fontana * GNU General Public License for more details.
149def656eSClaudio Fontana *
159def656eSClaudio Fontana * You should have received a copy of the GNU General Public License
169def656eSClaudio Fontana * along with this program; if not, see <http://www.gnu.org/licenses/>.
179def656eSClaudio Fontana */
189def656eSClaudio Fontana
199def656eSClaudio Fontana #include "qemu/osdep.h"
209def656eSClaudio Fontana #include "cpu.h"
219def656eSClaudio Fontana #include "exec/helper-proto.h"
229def656eSClaudio Fontana #include "kvm-consts.h"
239def656eSClaudio Fontana #include "qemu/main-loop.h"
249def656eSClaudio Fontana #include "sysemu/runstate.h"
259def656eSClaudio Fontana #include "internals.h"
269def656eSClaudio Fontana #include "arm-powerctl.h"
27*e2d8cf9bSPhilippe Mathieu-Daudé #include "target/arm/multiprocessing.h"
289def656eSClaudio Fontana
arm_is_psci_call(ARMCPU * cpu,int excp_type)299def656eSClaudio Fontana bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
309def656eSClaudio Fontana {
319def656eSClaudio Fontana /*
329def656eSClaudio Fontana * Return true if the exception type matches the configured PSCI conduit.
339def656eSClaudio Fontana * This is called before the SMC/HVC instruction is executed, to decide
349def656eSClaudio Fontana * whether we should treat it as a PSCI call or with the architecturally
359def656eSClaudio Fontana * defined behaviour for an SMC or HVC (which might be UNDEF or trap
369def656eSClaudio Fontana * to EL2 or to EL3).
379def656eSClaudio Fontana */
389def656eSClaudio Fontana
399def656eSClaudio Fontana switch (excp_type) {
409def656eSClaudio Fontana case EXCP_HVC:
419def656eSClaudio Fontana if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_HVC) {
429def656eSClaudio Fontana return false;
439def656eSClaudio Fontana }
449def656eSClaudio Fontana break;
459def656eSClaudio Fontana case EXCP_SMC:
469def656eSClaudio Fontana if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
479def656eSClaudio Fontana return false;
489def656eSClaudio Fontana }
499def656eSClaudio Fontana break;
509def656eSClaudio Fontana default:
519def656eSClaudio Fontana return false;
529def656eSClaudio Fontana }
539def656eSClaudio Fontana
549def656eSClaudio Fontana return true;
559def656eSClaudio Fontana }
569def656eSClaudio Fontana
arm_handle_psci_call(ARMCPU * cpu)579def656eSClaudio Fontana void arm_handle_psci_call(ARMCPU *cpu)
589def656eSClaudio Fontana {
599def656eSClaudio Fontana /*
609def656eSClaudio Fontana * This function partially implements the logic for dispatching Power State
619def656eSClaudio Fontana * Coordination Interface (PSCI) calls (as described in ARM DEN 0022D.b),
629def656eSClaudio Fontana * to the extent required for bringing up and taking down secondary cores,
639def656eSClaudio Fontana * and for handling reset and poweroff requests.
649def656eSClaudio Fontana * Additional information about the calling convention used is available in
659def656eSClaudio Fontana * the document 'SMC Calling Convention' (ARM DEN 0028)
669def656eSClaudio Fontana */
679def656eSClaudio Fontana CPUARMState *env = &cpu->env;
689def656eSClaudio Fontana uint64_t param[4];
699def656eSClaudio Fontana uint64_t context_id, mpidr;
709def656eSClaudio Fontana target_ulong entry;
719def656eSClaudio Fontana int32_t ret = 0;
729def656eSClaudio Fontana int i;
739def656eSClaudio Fontana
749def656eSClaudio Fontana for (i = 0; i < 4; i++) {
759def656eSClaudio Fontana /*
769def656eSClaudio Fontana * All PSCI functions take explicit 32-bit or native int sized
779def656eSClaudio Fontana * arguments so we can simply zero-extend all arguments regardless
789def656eSClaudio Fontana * of which exact function we are about to call.
799def656eSClaudio Fontana */
809def656eSClaudio Fontana param[i] = is_a64(env) ? env->xregs[i] : env->regs[i];
819def656eSClaudio Fontana }
829def656eSClaudio Fontana
839def656eSClaudio Fontana if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) {
849def656eSClaudio Fontana ret = QEMU_PSCI_RET_NOT_SUPPORTED;
859def656eSClaudio Fontana goto err;
869def656eSClaudio Fontana }
879def656eSClaudio Fontana
889def656eSClaudio Fontana switch (param[0]) {
899def656eSClaudio Fontana CPUState *target_cpu_state;
909def656eSClaudio Fontana ARMCPU *target_cpu;
919def656eSClaudio Fontana
929def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_PSCI_VERSION:
939def656eSClaudio Fontana ret = QEMU_PSCI_VERSION_1_1;
949def656eSClaudio Fontana break;
959def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
969def656eSClaudio Fontana ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
979def656eSClaudio Fontana break;
989def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
999def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
1009def656eSClaudio Fontana mpidr = param[1];
1019def656eSClaudio Fontana
1029def656eSClaudio Fontana switch (param[2]) {
1039def656eSClaudio Fontana case 0:
1049def656eSClaudio Fontana target_cpu_state = arm_get_cpu_by_id(mpidr);
1059def656eSClaudio Fontana if (!target_cpu_state) {
1069def656eSClaudio Fontana ret = QEMU_PSCI_RET_INVALID_PARAMS;
1079def656eSClaudio Fontana break;
1089def656eSClaudio Fontana }
1099def656eSClaudio Fontana target_cpu = ARM_CPU(target_cpu_state);
1109def656eSClaudio Fontana
111195801d7SStefan Hajnoczi g_assert(bql_locked());
1129def656eSClaudio Fontana ret = target_cpu->power_state;
1139def656eSClaudio Fontana break;
1149def656eSClaudio Fontana default:
1159def656eSClaudio Fontana /* Everything above affinity level 0 is always on. */
1169def656eSClaudio Fontana ret = 0;
1179def656eSClaudio Fontana }
1189def656eSClaudio Fontana break;
1199def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
1209def656eSClaudio Fontana qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
1219def656eSClaudio Fontana /* QEMU reset and shutdown are async requests, but PSCI
1229def656eSClaudio Fontana * mandates that we never return from the reset/shutdown
1239def656eSClaudio Fontana * call, so power the CPU off now so it doesn't execute
1249def656eSClaudio Fontana * anything further.
1259def656eSClaudio Fontana */
1269def656eSClaudio Fontana goto cpu_off;
1279def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
1289def656eSClaudio Fontana qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
1299def656eSClaudio Fontana goto cpu_off;
1309def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_ON:
1319def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_ON:
1329def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_CPU_ON:
1339def656eSClaudio Fontana {
1349def656eSClaudio Fontana /* The PSCI spec mandates that newly brought up CPUs start
1359def656eSClaudio Fontana * in the highest exception level which exists and is enabled
1369def656eSClaudio Fontana * on the calling CPU. Since the QEMU PSCI implementation is
1379def656eSClaudio Fontana * acting as a "fake EL3" or "fake EL2" firmware, this for us
1389def656eSClaudio Fontana * means that we want to start at the highest NS exception level
1399def656eSClaudio Fontana * that we are providing to the guest.
1409def656eSClaudio Fontana * The execution mode should be that which is currently in use
1419def656eSClaudio Fontana * by the same exception level on the calling CPU.
1429def656eSClaudio Fontana * The CPU should be started with the context_id value
1439def656eSClaudio Fontana * in x0 (if AArch64) or r0 (if AArch32).
1449def656eSClaudio Fontana */
1459def656eSClaudio Fontana int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
1469def656eSClaudio Fontana bool target_aarch64 = arm_el_is_aa64(env, target_el);
1479def656eSClaudio Fontana
1489def656eSClaudio Fontana mpidr = param[1];
1499def656eSClaudio Fontana entry = param[2];
1509def656eSClaudio Fontana context_id = param[3];
1519def656eSClaudio Fontana ret = arm_set_cpu_on(mpidr, entry, context_id,
1529def656eSClaudio Fontana target_el, target_aarch64);
1539def656eSClaudio Fontana break;
1549def656eSClaudio Fontana }
1559def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_OFF:
1569def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_OFF:
1579def656eSClaudio Fontana goto cpu_off;
1589def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
1599def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
1609def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
1619def656eSClaudio Fontana /* Affinity levels are not supported in QEMU */
1629def656eSClaudio Fontana if (param[1] & 0xfffe0000) {
1639def656eSClaudio Fontana ret = QEMU_PSCI_RET_INVALID_PARAMS;
1649def656eSClaudio Fontana break;
1659def656eSClaudio Fontana }
1669def656eSClaudio Fontana /* Powerdown is not supported, we always go into WFI */
1679def656eSClaudio Fontana if (is_a64(env)) {
1689def656eSClaudio Fontana env->xregs[0] = 0;
1699def656eSClaudio Fontana } else {
1709def656eSClaudio Fontana env->regs[0] = 0;
1719def656eSClaudio Fontana }
1729def656eSClaudio Fontana helper_wfi(env, 4);
1739def656eSClaudio Fontana break;
1749def656eSClaudio Fontana case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
1759def656eSClaudio Fontana switch (param[1]) {
1769def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_PSCI_VERSION:
1779def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
1789def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
1799def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
1809def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
1819def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
1829def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_ON:
1839def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_ON:
1849def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_CPU_ON:
1859def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_OFF:
1869def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_OFF:
1879def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
1889def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
1899def656eSClaudio Fontana case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
1909def656eSClaudio Fontana case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
1919def656eSClaudio Fontana if (!(param[1] & QEMU_PSCI_0_2_64BIT) || is_a64(env)) {
1929def656eSClaudio Fontana ret = 0;
1939def656eSClaudio Fontana break;
1949def656eSClaudio Fontana }
1959def656eSClaudio Fontana /* fallthrough */
1969def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_MIGRATE:
1979def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_MIGRATE:
1989def656eSClaudio Fontana default:
1999def656eSClaudio Fontana ret = QEMU_PSCI_RET_NOT_SUPPORTED;
2009def656eSClaudio Fontana break;
2019def656eSClaudio Fontana }
2029def656eSClaudio Fontana break;
2039def656eSClaudio Fontana case QEMU_PSCI_0_1_FN_MIGRATE:
2049def656eSClaudio Fontana case QEMU_PSCI_0_2_FN_MIGRATE:
2059def656eSClaudio Fontana default:
2069def656eSClaudio Fontana ret = QEMU_PSCI_RET_NOT_SUPPORTED;
2079def656eSClaudio Fontana break;
2089def656eSClaudio Fontana }
2099def656eSClaudio Fontana
2109def656eSClaudio Fontana err:
2119def656eSClaudio Fontana if (is_a64(env)) {
2129def656eSClaudio Fontana env->xregs[0] = ret;
2139def656eSClaudio Fontana } else {
2149def656eSClaudio Fontana env->regs[0] = ret;
2159def656eSClaudio Fontana }
2169def656eSClaudio Fontana return;
2179def656eSClaudio Fontana
2189def656eSClaudio Fontana cpu_off:
219c4380f7bSRichard Henderson ret = arm_set_cpu_off(arm_cpu_mp_affinity(cpu));
2209def656eSClaudio Fontana /* notreached */
2219def656eSClaudio Fontana /* sanity check in case something failed */
2229def656eSClaudio Fontana assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
2239def656eSClaudio Fontana }
224