* [Qemu-devel] [PATCH 1/5] target-arm: add powered off cpu state
2014-09-01 7:53 [Qemu-devel] [PATCH 0/5] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
@ 2014-09-01 7:53 ` Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 2/5] target-arm: support AArch64 for arm_cpu_set_pc Ard Biesheuvel
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2014-09-01 7:53 UTC (permalink / raw)
To: qemu-devel, peter.maydell, rob.herring; +Cc: Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
Add tracking of cpu power state in order to support powering off of
cores in system emuluation. The initial state is determined by the
start-powered-off QOM property.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/cpu-qom.h | 1 +
target-arm/cpu.c | 7 ++++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 07f3c9e86639..f71f6a4ccc6b 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -98,6 +98,7 @@ typedef struct ARMCPU {
/* Should CPU start in PSCI powered-off state? */
bool start_powered_off;
+ bool powered_off;
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 8199f32e3267..b4c06c17cf87 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -40,7 +40,9 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
static bool arm_cpu_has_work(CPUState *cs)
{
- return cs->interrupt_request &
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ return !cpu->powered_off && cs->interrupt_request &
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
}
@@ -91,6 +93,9 @@ static void arm_cpu_reset(CPUState *s)
env->vfp.xregs[ARM_VFP_MVFR1] = cpu->mvfr1;
env->vfp.xregs[ARM_VFP_MVFR2] = cpu->mvfr2;
+ cpu->powered_off = cpu->start_powered_off;
+ s->halted = cpu->start_powered_off;
+
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/5] target-arm: support AArch64 for arm_cpu_set_pc
2014-09-01 7:53 [Qemu-devel] [PATCH 0/5] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 1/5] target-arm: add powered off cpu state Ard Biesheuvel
@ 2014-09-01 7:53 ` Ard Biesheuvel
2014-09-01 9:09 ` Peter Maydell
2014-09-01 7:53 ` [Qemu-devel] [PATCH 3/5] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2014-09-01 7:53 UTC (permalink / raw)
To: qemu-devel, peter.maydell, rob.herring; +Cc: Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
Add AArch64 support to arm_cpu_set_pc and make it available to other files.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/cpu.c | 7 -------
target-arm/cpu.h | 12 ++++++++++++
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b4c06c17cf87..633a533af716 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -31,13 +31,6 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
-static void arm_cpu_set_pc(CPUState *cs, vaddr value)
-{
- ARMCPU *cpu = ARM_CPU(cs);
-
- cpu->env.regs[15] = value;
-}
-
static bool arm_cpu_has_work(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 51bedc826299..5fa91b4f1d6c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1348,4 +1348,16 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
}
}
+static inline void arm_cpu_set_pc(CPUState *cs, vaddr value)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (is_a64(&cpu->env)) {
+ cpu->env.pc = value;
+ } else {
+ cpu->env.regs[15] = value;
+ }
+
+}
+
#endif
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 3/5] target-arm: add hvc and smc exception emulation handling infrastructure
2014-09-01 7:53 [Qemu-devel] [PATCH 0/5] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 1/5] target-arm: add powered off cpu state Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 2/5] target-arm: support AArch64 for arm_cpu_set_pc Ard Biesheuvel
@ 2014-09-01 7:53 ` Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 4/5] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 5/5] arm/virt: enable PSCI emulation support " Ard Biesheuvel
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2014-09-01 7:53 UTC (permalink / raw)
To: qemu-devel, peter.maydell, rob.herring; +Cc: Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
Add the infrastructure to handle and emulate hvc and smc exceptions.
This will enable emulation of things such as PSCI calls. This commit
does not change the behavior and will exit with unknown exception.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/cpu-qom.h | 3 +++
target-arm/cpu.h | 2 ++
target-arm/helper-a64.c | 11 +++++++++++
target-arm/helper.c | 21 +++++++++++++++++++++
target-arm/internals.h | 15 +++++++++++++++
target-arm/translate-a64.c | 26 +++++++++++++++++---------
target-arm/translate.c | 24 +++++++++++++++++-------
7 files changed, 86 insertions(+), 16 deletions(-)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index f71f6a4ccc6b..bcdd1e0edb55 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -191,6 +191,9 @@ extern const struct VMStateDescription vmstate_arm_cpu;
void register_cp_regs_for_features(ARMCPU *cpu);
void init_cpreg_list(ARMCPU *cpu);
+bool arm_cpu_do_hvc(CPUState *cs);
+bool arm_cpu_do_smc(CPUState *cs);
+
void arm_cpu_do_interrupt(CPUState *cpu);
void arm_v7m_cpu_do_interrupt(CPUState *cpu);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 5fa91b4f1d6c..4c336b342553 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -51,6 +51,8 @@
#define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
#define EXCP_STREX 10
+#define EXCP_HVC 11
+#define EXCP_SMC 12
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64786ae..54700e729711 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -483,6 +483,17 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
case EXCP_FIQ:
addr += 0x100;
break;
+ case EXCP_HVC:
+ if (arm_cpu_do_hvc(cs)) {
+ return;
+ }
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+ return;
+ case EXCP_SMC:
+ if (arm_cpu_do_smc(cs)) {
+ return;
+ }
+ /* Fall-though */
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2b95f33872cb..3e29d08ae182 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3497,6 +3497,16 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
env->thumb = addr & 1;
}
+bool arm_cpu_do_hvc(CPUState *cs)
+{
+ return false;
+}
+
+bool arm_cpu_do_smc(CPUState *cs)
+{
+ return false;
+}
+
/* Handle a CPU exception. */
void arm_cpu_do_interrupt(CPUState *cs)
{
@@ -3599,6 +3609,17 @@ void arm_cpu_do_interrupt(CPUState *cs)
mask = CPSR_A | CPSR_I | CPSR_F;
offset = 4;
break;
+ case EXCP_HVC:
+ if (arm_cpu_do_hvc(cs)) {
+ return;
+ }
+ cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
+ return;
+ case EXCP_SMC:
+ if (arm_cpu_do_smc(cs)) {
+ return;
+ }
+ /* Fall-though */
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
return; /* Never happens. Keep compiler happy. */
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 53c2e3cf3e7e..37fd740526a2 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -210,6 +210,21 @@ static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
| (is_thumb ? 0 : ARM_EL_IL);
}
+static inline uint32_t syn_aa64_hvc(uint32_t imm16)
+{
+ return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_hvc(uint32_t imm16)
+{
+ return (EC_AA32_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa64_smc(uint32_t imm16)
+{
+ return (EC_AA64_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
{
return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 8e66b6c97282..9fd204694e7a 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1473,20 +1473,28 @@ static void disas_exc(DisasContext *s, uint32_t insn)
switch (opc) {
case 0:
- /* SVC, HVC, SMC; since we don't support the Virtualization
- * or TrustZone extensions these all UNDEF except SVC.
- */
- if (op2_ll != 1) {
- unallocated_encoding(s);
- break;
- }
/* For SVC, HVC and SMC we advance the single-step state
* machine before taking the exception. This is architecturally
* mandated, to ensure that single-stepping a system call
* instruction works properly.
*/
- gen_ss_advance(s);
- gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+ switch (op2_ll) {
+ case 1:
+ gen_ss_advance(s);
+ gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+ break;
+ case 2:
+ gen_ss_advance(s);
+ gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_smc(imm16));
+ break;
+ case 3:
+ gen_ss_advance(s);
+ gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_hvc(imm16));
+ break;
+ default:
+ unallocated_encoding(s);
+ break;
+ }
break;
case 1:
if (op2_ll != 0) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2c0b1deaea81..3bef34264298 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7871,9 +7871,14 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
case 7:
{
int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
- /* SMC instruction (op1 == 3)
- and undefined instructions (op1 == 0 || op1 == 2)
- will trap */
+ /* HVC and SMC instructions */
+ if (op1 == 2) {
+ gen_exception_insn(s, 0, EXCP_HVC, imm16);
+ break;
+ } else if (op1 == 3) {
+ gen_exception_insn(s, 0, EXCP_SMC, 0);
+ break;
+ }
if (op1 != 1) {
goto illegal_op;
}
@@ -9709,10 +9714,15 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
goto illegal_op;
if (insn & (1 << 26)) {
- /* Secure monitor call (v6Z) */
- qemu_log_mask(LOG_UNIMP,
- "arm: unimplemented secure monitor call\n");
- goto illegal_op; /* not implemented. */
+ if (!(insn & (1 << 20))) {
+ /* Hypervisor call (v7) */
+ uint32_t imm16 = extract32(insn, 16, 4);
+ imm16 |= extract32(insn, 0, 12) << 4;
+ gen_exception_insn(s, 0, EXCP_HVC, imm16);
+ } else {
+ /* Secure monitor call (v6+) */
+ gen_exception_insn(s, 0, EXCP_SMC, 0);
+ }
} else {
op = (insn >> 20) & 7;
switch (op) {
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 4/5] target-arm: add emulation of PSCI calls for system emulation
2014-09-01 7:53 [Qemu-devel] [PATCH 0/5] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
` (2 preceding siblings ...)
2014-09-01 7:53 ` [Qemu-devel] [PATCH 3/5] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
@ 2014-09-01 7:53 ` Ard Biesheuvel
2014-09-01 7:53 ` [Qemu-devel] [PATCH 5/5] arm/virt: enable PSCI emulation support " Ard Biesheuvel
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2014-09-01 7:53 UTC (permalink / raw)
To: qemu-devel, peter.maydell, rob.herring; +Cc: Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
Add support for handling PSCI calls in system emulation. Both version
0.1 and 0.2 of the PSCI spec are supported. Platforms can enable support
by setting "psci-method" QOM property on the cpus to SMC or HVC
emulation and having PSCI binding in their dtb.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/Makefile.objs | 1 +
target-arm/cpu-qom.h | 6 ++
target-arm/cpu.c | 10 +++-
target-arm/cpu.h | 6 ++
target-arm/helper.c | 12 ++++
target-arm/psci.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 184 insertions(+), 3 deletions(-)
create mode 100644 target-arm/psci.c
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index dcd167e0d880..deda9f49fec3 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -7,5 +7,6 @@ obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
obj-y += gdbstub.o
+obj-y += psci.o
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
obj-y += crypto_helper.o
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index bcdd1e0edb55..b1c96b2d194e 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -100,6 +100,11 @@ typedef struct ARMCPU {
bool start_powered_off;
bool powered_off;
+ /* PSCI emulation state
+ * 0 - disabled, 1 - smc, 2 - hvc
+ */
+ uint32_t psci_method;
+
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
*/
@@ -191,6 +196,7 @@ extern const struct VMStateDescription vmstate_arm_cpu;
void register_cp_regs_for_features(ARMCPU *cpu);
void init_cpreg_list(ARMCPU *cpu);
+bool arm_handle_psci(CPUState *cs);
bool arm_cpu_do_hvc(CPUState *cs);
bool arm_cpu_do_smc(CPUState *cs);
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 633a533af716..cbd56be5149b 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -261,9 +261,12 @@ static void arm_cpu_initfn(Object *obj)
cpu->psci_version = 1; /* By default assume PSCI v0.1 */
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
- if (tcg_enabled() && !inited) {
- inited = true;
- arm_translate_init();
+ if (tcg_enabled()) {
+ cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
+ if (!inited) {
+ inited = true;
+ arm_translate_init();
+ }
}
}
@@ -1017,6 +1020,7 @@ static const ARMCPUInfo arm_cpus[] = {
static Property arm_cpu_properties[] = {
DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
+ DEFINE_PROP_UINT32("psci-method", ARMCPU, psci_method, 0),
DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4c336b342553..645d97357f28 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1362,4 +1362,10 @@ static inline void arm_cpu_set_pc(CPUState *cs, vaddr value)
}
+enum {
+ QEMU_PSCI_METHOD_DISABLED = 0,
+ QEMU_PSCI_METHOD_SMC = 1,
+ QEMU_PSCI_METHOD_HVC = 2,
+};
+
#endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3e29d08ae182..ea8d85bd8d53 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3499,11 +3499,23 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
bool arm_cpu_do_hvc(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (cpu->psci_method == QEMU_PSCI_METHOD_HVC) {
+ return arm_handle_psci(cs);
+ }
+
return false;
}
bool arm_cpu_do_smc(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (cpu->psci_method == QEMU_PSCI_METHOD_SMC) {
+ return arm_handle_psci(cs);
+ }
+
return false;
}
diff --git a/target-arm/psci.c b/target-arm/psci.c
new file mode 100644
index 000000000000..b7ca3e0b1113
--- /dev/null
+++ b/target-arm/psci.c
@@ -0,0 +1,152 @@
+/*
+ * 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 <cpu.h>
+#include <cpu-qom.h>
+#include <kvm-consts.h>
+#include <sysemu/sysemu.h>
+#include <linux/psci.h>
+
+#if !defined(CONFIG_USER_ONLY)
+
+bool arm_handle_psci(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ 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++) {
+ param[i] = is_a64(env) ? env->xregs[i] : env->regs[i];
+ }
+
+ if ((param[0] & PSCI_0_2_64BIT) && !is_a64(env)) {
+ ret = PSCI_RET_INVALID_PARAMS;
+ goto err;
+ }
+
+ switch (param[0]) {
+ case PSCI_0_2_FN_PSCI_VERSION:
+ ret = PSCI_VERSION_MAJOR(0) | PSCI_VERSION_MINOR(2);
+ break;
+ case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+ ret = PSCI_0_2_TOS_MP; /* No trusted OS */
+ break;
+ case PSCI_0_2_FN_AFFINITY_INFO:
+ case PSCI_0_2_FN64_AFFINITY_INFO:
+ mpidr = param[1];
+
+ switch (param[2]) {
+ case 0:
+ cs = qemu_get_cpu(mpidr & 0xff);
+ if (!cs) {
+ ret = PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ cpu = ARM_CPU(cs);
+ ret = cpu->powered_off ? 1 : 0;
+ break;
+ default:
+ /* Everything above affinity level 0 is always on. */
+ ret = 0;
+ }
+ break;
+ case PSCI_0_2_FN_SYSTEM_RESET:
+ qemu_system_reset_request();
+ break;
+ case PSCI_0_2_FN_SYSTEM_OFF:
+ qemu_system_shutdown_request();
+ break;
+ case QEMU_PSCI_0_1_FN_CPU_ON:
+ case PSCI_0_2_FN_CPU_ON:
+ case PSCI_0_2_FN64_CPU_ON:
+ mpidr = param[1];
+ entry = param[2];
+ context_id = param[3];
+
+ /* change to the cpu we are powering up */
+ cs = qemu_get_cpu(mpidr & 0xff);
+ if (!cs) {
+ ret = PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ cpu = ARM_CPU(cs);
+
+ if (!cpu->powered_off) {
+ ret = PSCI_RET_ALREADY_ON;
+ break;
+ }
+
+ /* Initialize the cpu we are turning on */
+ cpu_reset(cs);
+ arm_cpu_set_pc(cs, entry);
+ cpu->powered_off = false;
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+
+ /* Set the context_id in r0/x0 */
+ if (is_a64(env)) {
+ cpu->env.xregs[0] = context_id;
+ } else {
+ cpu->env.regs[0] = context_id;
+ }
+
+ ret = 0;
+ break;
+ case QEMU_PSCI_0_1_FN_CPU_OFF:
+ case PSCI_0_2_FN_CPU_OFF:
+ cpu->powered_off = true;
+ cs->exit_request = 1;
+ cs->halted = 1;
+
+ /* CPU_OFF should never return, but if it does return an error */
+ ret = PSCI_RET_DENIED;
+ break;
+ case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
+ case PSCI_0_2_FN_CPU_SUSPEND:
+ case PSCI_0_2_FN64_CPU_SUSPEND:
+ /* Affinity levels are not supported in QEMU */
+ if (param[1] & 0xfffe0000) {
+ ret = PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ /* Powerdown is not supported, we always go into WFI */
+ cs->halted = 1;
+ cs->exit_request = 1;
+
+ /* Return success when we wakeup */
+ ret = 0;
+ break;
+ case QEMU_PSCI_0_1_FN_MIGRATE:
+ case PSCI_0_2_FN_MIGRATE:
+ ret = PSCI_RET_NOT_SUPPORTED;
+ break;
+ default:
+ return false;
+ }
+
+err:
+ if (is_a64(env)) {
+ env->xregs[0] = ret;
+ } else {
+ env->regs[0] = ret;
+ }
+ return true;
+}
+#endif
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 5/5] arm/virt: enable PSCI emulation support for system emulation
2014-09-01 7:53 [Qemu-devel] [PATCH 0/5] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
` (3 preceding siblings ...)
2014-09-01 7:53 ` [Qemu-devel] [PATCH 4/5] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
@ 2014-09-01 7:53 ` Ard Biesheuvel
4 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2014-09-01 7:53 UTC (permalink / raw)
To: qemu-devel, peter.maydell, rob.herring; +Cc: Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
Now that we have PSCI emulation, enable it for the virt platform.
This simplifies the virt machine a bit now that PSCI no longer
needs to be a KVM only feature.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
hw/arm/virt.c | 70 +++++++++++++++++++++++++++++------------------------------
1 file changed, 34 insertions(+), 36 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d6fffc75bda0..fefe80219d2f 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -189,47 +189,43 @@ static void create_fdt(VirtBoardInfo *vbi)
static void fdt_add_psci_node(const VirtBoardInfo *vbi)
{
+ uint32_t cpu_suspend_fn;
+ uint32_t cpu_off_fn;
+ uint32_t cpu_on_fn;
+ uint32_t migrate_fn;
void *fdt = vbi->fdt;
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
- /* No PSCI for TCG yet */
- if (kvm_enabled()) {
- uint32_t cpu_suspend_fn;
- uint32_t cpu_off_fn;
- uint32_t cpu_on_fn;
- uint32_t migrate_fn;
-
- qemu_fdt_add_subnode(fdt, "/psci");
- if (armcpu->psci_version == 2) {
- const char comp[] = "arm,psci-0.2\0arm,psci";
- qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
-
- cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
- if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
- cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
- cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
- migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
- } else {
- cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
- cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
- migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
- }
- } else {
- qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+ qemu_fdt_add_subnode(fdt, "/psci");
+ if (armcpu->psci_version == 2) {
+ const char comp[] = "arm,psci-0.2\0arm,psci";
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
- cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
- cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
- cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
- migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
+ cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
+ if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
+ cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
+ } else {
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
+ cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
}
+ } else {
+ qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
- qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
-
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
+ cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
+ cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
+ cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
}
+
+ qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
+
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
}
static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
@@ -468,8 +464,7 @@ static void machvirt_init(MachineState *machine)
vbi->smp_cpus = smp_cpus;
/*
- * Only supported method of starting secondary CPUs is PSCI and
- * PSCI is not yet supported with TCG, so limit smp_cpus to 1
+ * SMP is not yet supported with TCG, so limit smp_cpus to 1
* if we're not using KVM.
*/
if (!kvm_enabled() && smp_cpus > 1) {
@@ -495,6 +490,9 @@ static void machvirt_init(MachineState *machine)
}
cpuobj = object_new(object_class_get_name(oc));
+ object_property_set_int(cpuobj, QEMU_PSCI_METHOD_HVC, "psci-method",
+ NULL);
+
/* Secondary CPUs start in PSCI powered-down state */
if (n > 0) {
object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread