target/arm: Move psci.c into the tcg directory
authorClaudio Fontana <cfontana@suse.de>
Fri, 17 Feb 2023 20:11:31 +0000 (17:11 -0300)
committerPeter Maydell <peter.maydell@linaro.org>
Mon, 27 Feb 2023 13:27:04 +0000 (13:27 +0000)
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
target/arm/meson.build
target/arm/psci.c [deleted file]
target/arm/tcg/meson.build
target/arm/tcg/psci.c [new file with mode: 0644]

index 3e2f40300567f0b34f4c9b24497312c51330e18f..a5191b57e1c98624d03beab9e67af2094bc281c5 100644 (file)
@@ -22,7 +22,6 @@ arm_softmmu_ss.add(files(
   'arm-powerctl.c',
   'machine.c',
   'monitor.c',
-  'psci.c',
   'ptw.c',
 ))
 
diff --git a/target/arm/psci.c b/target/arm/psci.c
deleted file mode 100644 (file)
index 6c1239b..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2014 - Linaro
- * Author: Rob Herring <rob.herring@linaro.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/helper-proto.h"
-#include "kvm-consts.h"
-#include "qemu/main-loop.h"
-#include "sysemu/runstate.h"
-#include "internals.h"
-#include "arm-powerctl.h"
-
-bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
-{
-    /*
-     * Return true if the exception type matches the configured PSCI conduit.
-     * This is called before the SMC/HVC instruction is executed, to decide
-     * whether we should treat it as a PSCI call or with the architecturally
-     * defined behaviour for an SMC or HVC (which might be UNDEF or trap
-     * to EL2 or to EL3).
-     */
-
-    switch (excp_type) {
-    case EXCP_HVC:
-        if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_HVC) {
-            return false;
-        }
-        break;
-    case EXCP_SMC:
-        if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
-            return false;
-        }
-        break;
-    default:
-        return false;
-    }
-
-    return true;
-}
-
-void arm_handle_psci_call(ARMCPU *cpu)
-{
-    /*
-     * This function partially implements the logic for dispatching Power State
-     * Coordination Interface (PSCI) calls (as described in ARM DEN 0022D.b),
-     * to the extent required for bringing up and taking down secondary cores,
-     * and for handling reset and poweroff requests.
-     * Additional information about the calling convention used is available in
-     * the document 'SMC Calling Convention' (ARM DEN 0028)
-     */
-    CPUARMState *env = &cpu->env;
-    uint64_t param[4];
-    uint64_t context_id, mpidr;
-    target_ulong entry;
-    int32_t ret = 0;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        /*
-         * All PSCI functions take explicit 32-bit or native int sized
-         * arguments so we can simply zero-extend all arguments regardless
-         * of which exact function we are about to call.
-         */
-        param[i] = is_a64(env) ? env->xregs[i] : env->regs[i];
-    }
-
-    if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) {
-        ret = QEMU_PSCI_RET_NOT_SUPPORTED;
-        goto err;
-    }
-
-    switch (param[0]) {
-        CPUState *target_cpu_state;
-        ARMCPU *target_cpu;
-
-    case QEMU_PSCI_0_2_FN_PSCI_VERSION:
-        ret = QEMU_PSCI_VERSION_1_1;
-        break;
-    case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
-        ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
-        break;
-    case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
-    case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
-        mpidr = param[1];
-
-        switch (param[2]) {
-        case 0:
-            target_cpu_state = arm_get_cpu_by_id(mpidr);
-            if (!target_cpu_state) {
-                ret = QEMU_PSCI_RET_INVALID_PARAMS;
-                break;
-            }
-            target_cpu = ARM_CPU(target_cpu_state);
-
-            g_assert(qemu_mutex_iothread_locked());
-            ret = target_cpu->power_state;
-            break;
-        default:
-            /* Everything above affinity level 0 is always on. */
-            ret = 0;
-        }
-        break;
-    case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
-        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
-        /* QEMU reset and shutdown are async requests, but PSCI
-         * mandates that we never return from the reset/shutdown
-         * call, so power the CPU off now so it doesn't execute
-         * anything further.
-         */
-        goto cpu_off;
-    case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
-        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
-        goto cpu_off;
-    case QEMU_PSCI_0_1_FN_CPU_ON:
-    case QEMU_PSCI_0_2_FN_CPU_ON:
-    case QEMU_PSCI_0_2_FN64_CPU_ON:
-    {
-        /* The PSCI spec mandates that newly brought up CPUs start
-         * in the highest exception level which exists and is enabled
-         * on the calling CPU. Since the QEMU PSCI implementation is
-         * acting as a "fake EL3" or "fake EL2" firmware, this for us
-         * means that we want to start at the highest NS exception level
-         * that we are providing to the guest.
-         * The execution mode should be that which is currently in use
-         * by the same exception level on the calling CPU.
-         * The CPU should be started with the context_id value
-         * in x0 (if AArch64) or r0 (if AArch32).
-         */
-        int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
-        bool target_aarch64 = arm_el_is_aa64(env, target_el);
-
-        mpidr = param[1];
-        entry = param[2];
-        context_id = param[3];
-        ret = arm_set_cpu_on(mpidr, entry, context_id,
-                             target_el, target_aarch64);
-        break;
-    }
-    case QEMU_PSCI_0_1_FN_CPU_OFF:
-    case QEMU_PSCI_0_2_FN_CPU_OFF:
-        goto cpu_off;
-    case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
-    case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
-    case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
-        /* Affinity levels are not supported in QEMU */
-        if (param[1] & 0xfffe0000) {
-            ret = QEMU_PSCI_RET_INVALID_PARAMS;
-            break;
-        }
-        /* Powerdown is not supported, we always go into WFI */
-        if (is_a64(env)) {
-            env->xregs[0] = 0;
-        } else {
-            env->regs[0] = 0;
-        }
-        helper_wfi(env, 4);
-        break;
-    case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
-        switch (param[1]) {
-        case QEMU_PSCI_0_2_FN_PSCI_VERSION:
-        case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
-        case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
-        case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
-        case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
-        case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
-        case QEMU_PSCI_0_1_FN_CPU_ON:
-        case QEMU_PSCI_0_2_FN_CPU_ON:
-        case QEMU_PSCI_0_2_FN64_CPU_ON:
-        case QEMU_PSCI_0_1_FN_CPU_OFF:
-        case QEMU_PSCI_0_2_FN_CPU_OFF:
-        case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
-        case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
-        case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
-        case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
-            if (!(param[1] & QEMU_PSCI_0_2_64BIT) || is_a64(env)) {
-                ret = 0;
-                break;
-            }
-            /* fallthrough */
-        case QEMU_PSCI_0_1_FN_MIGRATE:
-        case QEMU_PSCI_0_2_FN_MIGRATE:
-        default:
-            ret = QEMU_PSCI_RET_NOT_SUPPORTED;
-            break;
-        }
-        break;
-    case QEMU_PSCI_0_1_FN_MIGRATE:
-    case QEMU_PSCI_0_2_FN_MIGRATE:
-    default:
-        ret = QEMU_PSCI_RET_NOT_SUPPORTED;
-        break;
-    }
-
-err:
-    if (is_a64(env)) {
-        env->xregs[0] = ret;
-    } else {
-        env->regs[0] = ret;
-    }
-    return;
-
-cpu_off:
-    ret = arm_set_cpu_off(cpu->mp_affinity);
-    /* notreached */
-    /* sanity check in case something failed */
-    assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
-}
index 1f27ba1272e265d574c6c8f15d09ec754e6a8353..fa8a9eab93319f3269f3987d3e9c90d80b0081b4 100644 (file)
@@ -43,3 +43,7 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
   'sme_helper.c',
   'sve_helper.c',
 ))
+
+arm_softmmu_ss.add(files(
+  'psci.c',
+))
diff --git a/target/arm/tcg/psci.c b/target/arm/tcg/psci.c
new file mode 100644 (file)
index 0000000..6c1239b
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2014 - Linaro
+ * Author: Rob Herring <rob.herring@linaro.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "kvm-consts.h"
+#include "qemu/main-loop.h"
+#include "sysemu/runstate.h"
+#include "internals.h"
+#include "arm-powerctl.h"
+
+bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
+{
+    /*
+     * Return true if the exception type matches the configured PSCI conduit.
+     * This is called before the SMC/HVC instruction is executed, to decide
+     * whether we should treat it as a PSCI call or with the architecturally
+     * defined behaviour for an SMC or HVC (which might be UNDEF or trap
+     * to EL2 or to EL3).
+     */
+
+    switch (excp_type) {
+    case EXCP_HVC:
+        if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_HVC) {
+            return false;
+        }
+        break;
+    case EXCP_SMC:
+        if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
+            return false;
+        }
+        break;
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+void arm_handle_psci_call(ARMCPU *cpu)
+{
+    /*
+     * This function partially implements the logic for dispatching Power State
+     * Coordination Interface (PSCI) calls (as described in ARM DEN 0022D.b),
+     * to the extent required for bringing up and taking down secondary cores,
+     * and for handling reset and poweroff requests.
+     * Additional information about the calling convention used is available in
+     * the document 'SMC Calling Convention' (ARM DEN 0028)
+     */
+    CPUARMState *env = &cpu->env;
+    uint64_t param[4];
+    uint64_t context_id, mpidr;
+    target_ulong entry;
+    int32_t ret = 0;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        /*
+         * All PSCI functions take explicit 32-bit or native int sized
+         * arguments so we can simply zero-extend all arguments regardless
+         * of which exact function we are about to call.
+         */
+        param[i] = is_a64(env) ? env->xregs[i] : env->regs[i];
+    }
+
+    if ((param[0] & QEMU_PSCI_0_2_64BIT) && !is_a64(env)) {
+        ret = QEMU_PSCI_RET_NOT_SUPPORTED;
+        goto err;
+    }
+
+    switch (param[0]) {
+        CPUState *target_cpu_state;
+        ARMCPU *target_cpu;
+
+    case QEMU_PSCI_0_2_FN_PSCI_VERSION:
+        ret = QEMU_PSCI_VERSION_1_1;
+        break;
+    case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+        ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
+        break;
+    case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
+    case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
+        mpidr = param[1];
+
+        switch (param[2]) {
+        case 0:
+            target_cpu_state = arm_get_cpu_by_id(mpidr);
+            if (!target_cpu_state) {
+                ret = QEMU_PSCI_RET_INVALID_PARAMS;
+                break;
+            }
+            target_cpu = ARM_CPU(target_cpu_state);
+
+            g_assert(qemu_mutex_iothread_locked());
+            ret = target_cpu->power_state;
+            break;
+        default:
+            /* Everything above affinity level 0 is always on. */
+            ret = 0;
+        }
+        break;
+    case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+        /* QEMU reset and shutdown are async requests, but PSCI
+         * mandates that we never return from the reset/shutdown
+         * call, so power the CPU off now so it doesn't execute
+         * anything further.
+         */
+        goto cpu_off;
+    case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+        goto cpu_off;
+    case QEMU_PSCI_0_1_FN_CPU_ON:
+    case QEMU_PSCI_0_2_FN_CPU_ON:
+    case QEMU_PSCI_0_2_FN64_CPU_ON:
+    {
+        /* The PSCI spec mandates that newly brought up CPUs start
+         * in the highest exception level which exists and is enabled
+         * on the calling CPU. Since the QEMU PSCI implementation is
+         * acting as a "fake EL3" or "fake EL2" firmware, this for us
+         * means that we want to start at the highest NS exception level
+         * that we are providing to the guest.
+         * The execution mode should be that which is currently in use
+         * by the same exception level on the calling CPU.
+         * The CPU should be started with the context_id value
+         * in x0 (if AArch64) or r0 (if AArch32).
+         */
+        int target_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
+        bool target_aarch64 = arm_el_is_aa64(env, target_el);
+
+        mpidr = param[1];
+        entry = param[2];
+        context_id = param[3];
+        ret = arm_set_cpu_on(mpidr, entry, context_id,
+                             target_el, target_aarch64);
+        break;
+    }
+    case QEMU_PSCI_0_1_FN_CPU_OFF:
+    case QEMU_PSCI_0_2_FN_CPU_OFF:
+        goto cpu_off;
+    case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
+    case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
+    case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
+        /* Affinity levels are not supported in QEMU */
+        if (param[1] & 0xfffe0000) {
+            ret = QEMU_PSCI_RET_INVALID_PARAMS;
+            break;
+        }
+        /* Powerdown is not supported, we always go into WFI */
+        if (is_a64(env)) {
+            env->xregs[0] = 0;
+        } else {
+            env->regs[0] = 0;
+        }
+        helper_wfi(env, 4);
+        break;
+    case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
+        switch (param[1]) {
+        case QEMU_PSCI_0_2_FN_PSCI_VERSION:
+        case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+        case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
+        case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
+        case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
+        case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
+        case QEMU_PSCI_0_1_FN_CPU_ON:
+        case QEMU_PSCI_0_2_FN_CPU_ON:
+        case QEMU_PSCI_0_2_FN64_CPU_ON:
+        case QEMU_PSCI_0_1_FN_CPU_OFF:
+        case QEMU_PSCI_0_2_FN_CPU_OFF:
+        case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
+        case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
+        case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
+        case QEMU_PSCI_1_0_FN_PSCI_FEATURES:
+            if (!(param[1] & QEMU_PSCI_0_2_64BIT) || is_a64(env)) {
+                ret = 0;
+                break;
+            }
+            /* fallthrough */
+        case QEMU_PSCI_0_1_FN_MIGRATE:
+        case QEMU_PSCI_0_2_FN_MIGRATE:
+        default:
+            ret = QEMU_PSCI_RET_NOT_SUPPORTED;
+            break;
+        }
+        break;
+    case QEMU_PSCI_0_1_FN_MIGRATE:
+    case QEMU_PSCI_0_2_FN_MIGRATE:
+    default:
+        ret = QEMU_PSCI_RET_NOT_SUPPORTED;
+        break;
+    }
+
+err:
+    if (is_a64(env)) {
+        env->xregs[0] = ret;
+    } else {
+        env->regs[0] = ret;
+    }
+    return;
+
+cpu_off:
+    ret = arm_set_cpu_off(cpu->mp_affinity);
+    /* notreached */
+    /* sanity check in case something failed */
+    assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
+}