* [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode
@ 2014-09-10 7:02 Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 1/6] target-arm: add powered off cpu state Ard Biesheuvel
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: christoffer.dall, Ard Biesheuvel
This series adds PSCI support to ARM and AArch64 system emulation when running
in TCG mode. As PSCI calls can be made using either hypervisor call (HVC) or
secure monitor call (SMC) instructions, support is added for handling those
in patch #3 before patch #5 adds the actual PSCI dispatch logic. Patch #6
enables PSCI for the mach-virt platform.
Changes since v3:
- added some R-b's
- remove user mode interrupt handler for AArch32 as well
- update the SMC and HVC handling logic to
. take feature bits for EL2 and EL3 into account
. deal with conditional execution state in A32/T32
. add ARCH() and IS_USER()/current_pl tests where appropriate
- added some missing () in the PSCI constants
- update the PSCI dispatch logic to
. CPU_ON: take bit 0 of the entry point into account to either set the Thumb
state or return an error, and assert that the onlined CPU is in the same
mode as the calling CPU
. CPU_OFF: call cpu_loop_exit() directly
. CPU_SUSPEND; use helper_wfi()
. follow the PSCI spec and adopt the name 'conduit' to refer to the type of
instruction used to invoke PSCI functions
. check the conduit in the translation stage to avoid advancing the single
step state machine inadvertently
- remove smp restriction from mach-virt running in TCG mode
Changes since v2:
- added path #4 to introduce QEMU counterparts of the kernel PSCI constants we
refer to in the PSCI emulation, this is needed so QEMU can be built in
environments that don't supply the PSCI header file.
Changes since v1:
- processed first round of review, that was already given when this series was
sent out by Rob himself back in May
*** BLURB HERE ***
Ard Biesheuvel (1):
target-arm: add missing PSCI constants needed for PSCI emulation
Rob Herring (5):
target-arm: add powered off cpu state
target-arm: do not set do_interrupt handlers for ARM and AArch64 user
modes
target-arm: add hvc and smc exception emulation handling
infrastructure
target-arm: add emulation of PSCI calls for system emulation
arm/virt: enable PSCI emulation support for system emulation
hw/arm/virt.c | 82 ++++++++++----------
target-arm/Makefile.objs | 1 +
target-arm/cpu-qom.h | 11 +++
target-arm/cpu.c | 19 +++--
target-arm/cpu.h | 8 ++
target-arm/cpu64.c | 2 +
target-arm/helper-a64.c | 19 +++++
target-arm/helper.c | 40 ++++++++--
target-arm/internals.h | 20 +++++
target-arm/kvm-consts.h | 40 ++++++++++
target-arm/machine.c | 5 +-
target-arm/psci.c | 183 +++++++++++++++++++++++++++++++++++++++++++++
target-arm/translate-a64.c | 38 +++++++---
target-arm/translate.c | 59 ++++++++++++---
target-arm/translate.h | 4 +
15 files changed, 455 insertions(+), 76 deletions(-)
create mode 100644 target-arm/psci.c
--
1.8.3.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 1/6] target-arm: add powered off cpu state
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 2/6] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Ard Biesheuvel
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: Rob Herring, christoffer.dall, 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>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/cpu-qom.h | 2 ++
target-arm/cpu.c | 7 ++++++-
target-arm/machine.c | 5 +++--
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 07f3c9e86639..eae0a7b9c908 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -98,6 +98,8 @@ typedef struct ARMCPU {
/* Should CPU start in PSCI powered-off state? */
bool start_powered_off;
+ /* CPU currently in PSCI powered-off state */
+ 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';
}
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 3bcc7cc833e0..63329ebd551f 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -218,8 +218,8 @@ static int cpu_post_load(void *opaque, int version_id)
const VMStateDescription vmstate_arm_cpu = {
.name = "cpu",
- .version_id = 20,
- .minimum_version_id = 20,
+ .version_id = 21,
+ .minimum_version_id = 21,
.pre_save = cpu_pre_save,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
@@ -259,6 +259,7 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
+ VMSTATE_BOOL(powered_off, ARMCPU),
VMSTATE_END_OF_LIST()
},
.subsections = (VMStateSubsection[]) {
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 2/6] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 1/6] target-arm: add powered off cpu state Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: Rob Herring, christoffer.dall, Ard Biesheuvel
From: Rob Herring <rob.herring@linaro.org>
User mode emulation should never get interrupts and thus should not
use the system emulation exception handler function. Remove the reference,
and '#ifndef USER_MODE_ONLY' the function itself as well, so that we can add
system mode only functionality to it.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/cpu.c | 2 +-
target-arm/cpu64.c | 2 ++
target-arm/helper-a64.c | 3 +++
target-arm/helper.c | 5 -----
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b4c06c17cf87..55479ec8b226 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1043,7 +1043,6 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = arm_cpu_class_by_name;
cc->has_work = arm_cpu_has_work;
- cc->do_interrupt = arm_cpu_do_interrupt;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
cc->gdb_read_register = arm_cpu_gdb_read_register;
@@ -1051,6 +1050,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
#ifdef CONFIG_USER_ONLY
cc->handle_mmu_fault = arm_cpu_handle_mmu_fault;
#else
+ cc->do_interrupt = arm_cpu_do_interrupt;
cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_arm_cpu;
#endif
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index aa42803959be..9f88b9f4eea0 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -196,7 +196,9 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
+#if !defined(CONFIG_USER_ONLY)
cc->do_interrupt = aarch64_cpu_do_interrupt;
+#endif
cc->set_pc = aarch64_cpu_set_pc;
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 2e9ef64786ae..89b913ee9396 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -438,6 +438,8 @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes)
return crc32c(acc, buf, bytes) ^ 0xffffffff;
}
+#if !defined(CONFIG_USER_ONLY)
+
/* Handle a CPU exception. */
void aarch64_cpu_do_interrupt(CPUState *cs)
{
@@ -512,3 +514,4 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
env->pc = addr;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
+#endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2b95f33872cb..9c129c8b080c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3237,11 +3237,6 @@ uint32_t HELPER(rbit)(uint32_t x)
#if defined(CONFIG_USER_ONLY)
-void arm_cpu_do_interrupt(CPUState *cs)
-{
- cs->exception_index = -1;
-}
-
int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
int mmu_idx)
{
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 1/6] target-arm: add powered off cpu state Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 2/6] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
2014-09-26 10:17 ` Peter Maydell
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 4/6] target-arm: add missing PSCI constants needed for PSCI emulation Ard Biesheuvel
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: Rob Herring, christoffer.dall, 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 | 16 +++++++++++++
target-arm/helper.c | 23 ++++++++++++++++++
target-arm/internals.h | 20 ++++++++++++++++
target-arm/translate-a64.c | 35 ++++++++++++++++++++-------
target-arm/translate.c | 59 +++++++++++++++++++++++++++++++++++++---------
target-arm/translate.h | 2 ++
8 files changed, 140 insertions(+), 20 deletions(-)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index eae0a7b9c908..104cc67e82d2 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -192,6 +192,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 51bedc826299..d235929f4c12 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 89b913ee9396..1f8072ab141b 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -485,6 +485,22 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
case EXCP_FIQ:
addr += 0x100;
break;
+ case EXCP_HVC:
+ if (arm_cpu_do_hvc(cs)) {
+ return;
+ }
+ /* Treat as unallocated encoding */
+ qemu_log_mask(LOG_GUEST_ERROR, "HVC not implemented on this CPU\n");
+ env->exception.syndrome = syn_uncategorized();
+ break;
+ case EXCP_SMC:
+ if (arm_cpu_do_smc(cs)) {
+ return;
+ }
+ /* Treat as unallocated encoding */
+ qemu_log_mask(LOG_GUEST_ERROR, "SMC not implemented on this CPU\n");
+ env->exception.syndrome = syn_uncategorized();
+ break;
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 9c129c8b080c..64bd49ecdaf9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3492,6 +3492,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)
{
@@ -3508,6 +3518,19 @@ void arm_cpu_do_interrupt(CPUState *cs)
/* TODO: Vectored interrupt controller. */
switch (cs->exception_index) {
+ case EXCP_HVC:
+ if (arm_cpu_do_hvc(cs)) {
+ return;
+ }
+ qemu_log_mask(LOG_GUEST_ERROR, "HVC not implemented on this CPU\n");
+ goto hvc_unallocated;
+ case EXCP_SMC:
+ if (arm_cpu_do_smc(cs)) {
+ return;
+ }
+ qemu_log_mask(LOG_GUEST_ERROR, "SMC not implemented on this CPU\n");
+ hvc_unallocated:
+ /* Fall through -- treat as unallocated encoding */
case EXCP_UDEF:
new_mode = ARM_CPU_MODE_UND;
addr = 0x04;
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 53c2e3cf3e7e..caab98e6b508 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -210,6 +210,26 @@ 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_aa32_smc(void)
+{
+ return (EC_AA32_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
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..e5fb775c4a50 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1473,20 +1473,37 @@ 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:
+ if (s->current_pl != 0
+ && arm_dc_feature(s, ARM_FEATURE_EL2)) {
+ gen_ss_advance(s);
+ gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
+ break;
+ }
+ unallocated_encoding(s);
+ break;
+ case 3:
+ if (s->current_pl != 0
+ && arm_dc_feature(s, ARM_FEATURE_EL3)) {
+ gen_ss_advance(s);
+ gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16));
+ break;
+ }
+ /* fall through */
+ 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..aefe01142762 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7871,15 +7871,33 @@ 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 */
- if (op1 != 1) {
+ switch (op1) {
+ case 1:
+ /* bkpt */
+ ARCH(5);
+ gen_exception_insn(s, 4, EXCP_BKPT,
+ syn_aa32_bkpt(imm16, false));
+ break;
+ case 2:
+ /* Hypervisor call (v7) */
+ ARCH(7);
+ if (IS_USER(s))
+ goto illegal_op;
+ s->svc_imm = imm16;
+ gen_set_pc_im(s, s->pc);
+ s->is_jmp = DISAS_HVC;
+ break;
+ case 3:
+ /* Secure monitor call (v6+) */
+ ARCH(6K);
+ if (IS_USER(s))
+ goto illegal_op;
+ gen_set_pc_im(s, s->pc);
+ s->is_jmp = DISAS_SMC;
+ break;
+ default:
goto illegal_op;
}
- /* bkpt */
- ARCH(5);
- gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
break;
}
case 0x8: /* signed multiply */
@@ -9709,10 +9727,23 @@ 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) */
+ ARCH(7);
+ if (IS_USER(s))
+ goto illegal_op;
+ s->svc_imm = extract32(insn, 16, 4) << 12 |
+ extract32(insn, 0, 12);
+ gen_set_pc_im(s, s->pc);
+ s->is_jmp = DISAS_HVC;
+ } else {
+ /* Secure monitor call (v6+) */
+ ARCH(6K);
+ if (IS_USER(s))
+ goto illegal_op;
+ gen_set_pc_im(s, s->pc);
+ s->is_jmp = DISAS_SMC;
+ }
} else {
op = (insn >> 20) & 7;
switch (op) {
@@ -11200,6 +11231,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
case DISAS_SWI:
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
break;
+ case DISAS_HVC:
+ gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
+ break;
+ case DISAS_SMC:
+ gen_exception(EXCP_SMC, syn_aa32_smc());
+ break;
}
if (dc->condjmp) {
gen_set_label(dc->condlabel);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index b90d27514d52..50c4d6ef4ab6 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -82,6 +82,8 @@ static inline int get_mem_index(DisasContext *s)
#define DISAS_EXC 6
/* WFE */
#define DISAS_WFE 7
+#define DISAS_HVC 8
+#define DISAS_SMC 9
#ifdef TARGET_AARCH64
void a64_translate_init(void);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 4/6] target-arm: add missing PSCI constants needed for PSCI emulation
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
` (2 preceding siblings ...)
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 6/6] arm/virt: enable PSCI emulation support " Ard Biesheuvel
5 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: christoffer.dall, Ard Biesheuvel
This adds some PSCI function IDs and symbolic return codes that are needed
to implement PSCI emulation in TCG mode.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
target-arm/kvm-consts.h | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/target-arm/kvm-consts.h b/target-arm/kvm-consts.h
index 091c1267d659..aea12f1bc4c5 100644
--- a/target-arm/kvm-consts.h
+++ b/target-arm/kvm-consts.h
@@ -59,14 +59,21 @@ MISMATCH_CHECK(QEMU_PSCI_0_1_FN_MIGRATE, KVM_PSCI_FN_MIGRATE)
(QEMU_PSCI_0_2_FN_BASE + QEMU_PSCI_0_2_64BIT)
#define QEMU_PSCI_0_2_FN64(n) (QEMU_PSCI_0_2_FN64_BASE + (n))
+#define QEMU_PSCI_0_2_FN_PSCI_VERSION QEMU_PSCI_0_2_FN(0)
#define QEMU_PSCI_0_2_FN_CPU_SUSPEND QEMU_PSCI_0_2_FN(1)
#define QEMU_PSCI_0_2_FN_CPU_OFF QEMU_PSCI_0_2_FN(2)
#define QEMU_PSCI_0_2_FN_CPU_ON QEMU_PSCI_0_2_FN(3)
+#define QEMU_PSCI_0_2_FN_AFFINITY_INFO QEMU_PSCI_0_2_FN(4)
#define QEMU_PSCI_0_2_FN_MIGRATE QEMU_PSCI_0_2_FN(5)
+#define QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE QEMU_PSCI_0_2_FN(6)
+#define QEMU_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU QEMU_PSCI_0_2_FN(7)
+#define QEMU_PSCI_0_2_FN_SYSTEM_OFF QEMU_PSCI_0_2_FN(8)
+#define QEMU_PSCI_0_2_FN_SYSTEM_RESET QEMU_PSCI_0_2_FN(9)
#define QEMU_PSCI_0_2_FN64_CPU_SUSPEND QEMU_PSCI_0_2_FN64(1)
#define QEMU_PSCI_0_2_FN64_CPU_OFF QEMU_PSCI_0_2_FN64(2)
#define QEMU_PSCI_0_2_FN64_CPU_ON QEMU_PSCI_0_2_FN64(3)
+#define QEMU_PSCI_0_2_FN64_AFFINITY_INFO QEMU_PSCI_0_2_FN64(4)
#define QEMU_PSCI_0_2_FN64_MIGRATE QEMU_PSCI_0_2_FN64(5)
MISMATCH_CHECK(QEMU_PSCI_0_2_FN_CPU_SUSPEND, PSCI_0_2_FN_CPU_SUSPEND)
@@ -77,6 +84,39 @@ MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_SUSPEND, PSCI_0_2_FN64_CPU_SUSPEND)
MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_CPU_ON, PSCI_0_2_FN64_CPU_ON)
MISMATCH_CHECK(QEMU_PSCI_0_2_FN64_MIGRATE, PSCI_0_2_FN64_MIGRATE)
+/* PSCI v0.2 return values used by TCG emulation of PSCI */
+
+/* No Trusted OS migration to worry about when offlining CPUs */
+#define QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED 2
+
+/* We implement version 0.2 only */
+#define QEMU_PSCI_0_2_RET_VERSION_0_2 2
+
+MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP)
+MISMATCH_CHECK(QEMU_PSCI_0_2_RET_VERSION_0_2,
+ (PSCI_VERSION_MAJOR(0) | PSCI_VERSION_MINOR(2)))
+
+/* PSCI return values (inclusive of all PSCI versions) */
+#define QEMU_PSCI_RET_SUCCESS 0
+#define QEMU_PSCI_RET_NOT_SUPPORTED -1
+#define QEMU_PSCI_RET_INVALID_PARAMS -2
+#define QEMU_PSCI_RET_DENIED -3
+#define QEMU_PSCI_RET_ALREADY_ON -4
+#define QEMU_PSCI_RET_ON_PENDING -5
+#define QEMU_PSCI_RET_INTERNAL_FAILURE -6
+#define QEMU_PSCI_RET_NOT_PRESENT -7
+#define QEMU_PSCI_RET_DISABLED -8
+
+MISMATCH_CHECK(QEMU_PSCI_RET_SUCCESS, PSCI_RET_SUCCESS)
+MISMATCH_CHECK(QEMU_PSCI_RET_NOT_SUPPORTED, PSCI_RET_NOT_SUPPORTED)
+MISMATCH_CHECK(QEMU_PSCI_RET_INVALID_PARAMS, PSCI_RET_INVALID_PARAMS)
+MISMATCH_CHECK(QEMU_PSCI_RET_DENIED, PSCI_RET_DENIED)
+MISMATCH_CHECK(QEMU_PSCI_RET_ALREADY_ON, PSCI_RET_ALREADY_ON)
+MISMATCH_CHECK(QEMU_PSCI_RET_ON_PENDING, PSCI_RET_ON_PENDING)
+MISMATCH_CHECK(QEMU_PSCI_RET_INTERNAL_FAILURE, PSCI_RET_INTERNAL_FAILURE)
+MISMATCH_CHECK(QEMU_PSCI_RET_NOT_PRESENT, PSCI_RET_NOT_PRESENT)
+MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED)
+
/* Note that KVM uses overlapping values for AArch32 and AArch64
* target CPU numbers. AArch32 targets:
*/
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
` (3 preceding siblings ...)
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 4/6] target-arm: add missing PSCI constants needed for PSCI emulation Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
2014-09-26 9:10 ` Peter Maydell
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 6/6] arm/virt: enable PSCI emulation support " Ard Biesheuvel
5 siblings, 1 reply; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: Rob Herring, christoffer.dall, 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 the "psci-conduit" QOM property on the cpus to SMC or HVC
emulation and having a 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 | 183 +++++++++++++++++++++++++++++++++++++++++++++
target-arm/translate-a64.c | 7 +-
target-arm/translate.h | 2 +
8 files changed, 222 insertions(+), 5 deletions(-)
create mode 100644 target-arm/psci.c
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index dcd167e0d880..9460b409a5a1 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-$(CONFIG_SOFTMMU) += 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 104cc67e82d2..bed7190bae57 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -101,6 +101,11 @@ typedef struct ARMCPU {
/* CPU currently in PSCI powered-off state */
bool powered_off;
+ /* PSCI conduit used to invoke PSCI methods
+ * 0 - disabled, 1 - smc, 2 - hvc
+ */
+ uint32_t psci_conduit;
+
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
*/
@@ -192,6 +197,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 55479ec8b226..eba0271a852e 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -268,9 +268,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();
+ }
}
}
@@ -1024,6 +1027,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-conduit", ARMCPU, psci_conduit, 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 d235929f4c12..a69d69254af4 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1350,4 +1350,10 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
}
}
+enum {
+ QEMU_PSCI_CONDUIT_DISABLED = 0,
+ QEMU_PSCI_CONDUIT_SMC = 1,
+ QEMU_PSCI_CONDUIT_HVC = 2,
+};
+
#endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 64bd49ecdaf9..2df34adc0ff7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3494,11 +3494,23 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
bool arm_cpu_do_hvc(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) {
+ return arm_handle_psci(cs);
+ }
+
return false;
}
bool arm_cpu_do_smc(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ if (cpu->psci_conduit == QEMU_PSCI_CONDUIT_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..7347cbdc17ef
--- /dev/null
+++ b/target-arm/psci.c
@@ -0,0 +1,183 @@
+/*
+ * 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 <exec/helper-proto.h>
+#include <kvm-consts.h>
+#include <sysemu/sysemu.h>
+
+bool arm_handle_psci(CPUState *cs)
+{
+ /*
+ * This function partially implements the logic for dispatching Power State
+ * Coordination Interface (PSCI) calls (as described in ARM DEN 0022B.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)
+ */
+ 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++) {
+ /*
+ * 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_INVALID_PARAMS;
+ goto err;
+ }
+
+ switch (param[0]) {
+ CPUState *target_cpu_state;
+ ARMCPU *target_cpu;
+ CPUClass *target_cpu_class;
+
+ case QEMU_PSCI_0_2_FN_PSCI_VERSION:
+ ret = QEMU_PSCI_0_2_RET_VERSION_0_2;
+ 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 = qemu_get_cpu(mpidr & 0xff);
+ if (!target_cpu_state) {
+ ret = QEMU_PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ target_cpu = ARM_CPU(target_cpu_state);
+ ret = target_cpu->powered_off ? 1 : 0;
+ 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();
+ break;
+ case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
+ qemu_system_shutdown_request();
+ break;
+ case QEMU_PSCI_0_1_FN_CPU_ON:
+ case QEMU_PSCI_0_2_FN_CPU_ON:
+ case QEMU_PSCI_0_2_FN64_CPU_ON:
+ mpidr = param[1];
+ entry = param[2];
+ context_id = param[3];
+
+ /* change to the cpu we are powering up */
+ target_cpu_state = qemu_get_cpu(mpidr & 0xff);
+ if (!target_cpu_state) {
+ ret = QEMU_PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ target_cpu = ARM_CPU(target_cpu_state);
+ if (!target_cpu->powered_off) {
+ ret = QEMU_PSCI_RET_ALREADY_ON;
+ break;
+ }
+ target_cpu_class = CPU_GET_CLASS(target_cpu);
+
+ /* Initialize the cpu we are turning on */
+ cpu_reset(target_cpu_state);
+ target_cpu->powered_off = false;
+ target_cpu_state->halted = 0;
+
+ /*
+ * The PSCI spec mandates that newly brought up CPUs enter the
+ * exception level of the caller in the same execution mode as
+ * the caller, with context_id in x0/r0, respectively.
+ *
+ * For now, it is sufficient to assert() that CPUs come out of
+ * reset in the same mode as the calling CPU, since we only
+ * implement EL1, which means that
+ * (a) there is no EL2 for the calling CPU to trap into to change
+ * its state
+ * (b) the newly brought up CPU enters EL1 immediately after coming
+ * out of reset in the default state
+ */
+ assert(is_a64(env) == is_a64(&target_cpu->env));
+ if (is_a64(env)) {
+ if (entry & 1) {
+ ret = QEMU_PSCI_RET_INVALID_PARAMS;
+ break;
+ }
+ target_cpu->env.xregs[0] = context_id;
+ } else {
+ target_cpu->env.regs[0] = context_id;
+ target_cpu->env.thumb = entry & 1;
+ }
+ target_cpu_class->set_pc(target_cpu_state, entry);
+
+ ret = 0;
+ break;
+ case QEMU_PSCI_0_1_FN_CPU_OFF:
+ case QEMU_PSCI_0_2_FN_CPU_OFF:
+ cpu->powered_off = true;
+ cs->halted = 1;
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
+ /* notreached */
+ 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);
+ break;
+ case QEMU_PSCI_0_1_FN_MIGRATE:
+ case QEMU_PSCI_0_2_FN_MIGRATE:
+ ret = QEMU_PSCI_RET_NOT_SUPPORTED;
+ break;
+ default:
+ return false;
+ }
+
+err:
+ if (is_a64(env)) {
+ env->xregs[0] = ret;
+ } else {
+ env->regs[0] = ret;
+ }
+ return true;
+}
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e5fb775c4a50..fa5c82ee37a8 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1485,7 +1485,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
break;
case 2:
if (s->current_pl != 0
- && arm_dc_feature(s, ARM_FEATURE_EL2)) {
+ && (arm_dc_feature(s, ARM_FEATURE_EL2)
+ || s->psci_conduit == QEMU_PSCI_CONDUIT_HVC)) {
gen_ss_advance(s);
gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
break;
@@ -1494,7 +1495,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
break;
case 3:
if (s->current_pl != 0
- && arm_dc_feature(s, ARM_FEATURE_EL3)) {
+ && (arm_dc_feature(s, ARM_FEATURE_EL3)
+ || s->psci_conduit == QEMU_PSCI_CONDUIT_SMC)) {
gen_ss_advance(s);
gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16));
break;
@@ -10943,6 +10945,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->pstate_ss = ARM_TBFLAG_AA64_PSTATE_SS(tb->flags);
dc->is_ldex = false;
dc->ss_same_el = (arm_debug_target_el(env) == dc->current_pl);
+ dc->psci_conduit = cpu->psci_conduit;
init_tmp_a64_array(dc);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 50c4d6ef4ab6..7babe79e123d 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -52,6 +52,8 @@ typedef struct DisasContext {
bool is_ldex;
/* True if a single-step exception will be taken to the current EL */
bool ss_same_el;
+ /* Conduit used for PSCI method calls, either HVC or SMC (or disabled) */
+ uint32_t psci_conduit;
#define TMP_A64_MAX 16
int tmp_a64_count;
TCGv_i64 tmp_a64[TMP_A64_MAX];
--
1.8.3.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PACTH v4 6/6] arm/virt: enable PSCI emulation support for system emulation
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
` (4 preceding siblings ...)
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
@ 2014-09-10 7:02 ` Ard Biesheuvel
5 siblings, 0 replies; 10+ messages in thread
From: Ard Biesheuvel @ 2014-09-10 7:02 UTC (permalink / raw)
To: peter.maydell, qemu-devel; +Cc: Rob Herring, christoffer.dall, 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 | 82 +++++++++++++++++++++++++++--------------------------------
1 file changed, 38 insertions(+), 44 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d6fffc75bda0..6537b58f2af8 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -189,47 +189,48 @@ 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;
}
+
+ /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
+ * to the instruction that should be used to invoke PSCI functions.
+ * However, the device tree binding uses 'method' instead, so that is
+ * what we should use here.
+ */
+ 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)
@@ -467,16 +468,6 @@ 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
- * if we're not using KVM.
- */
- if (!kvm_enabled() && smp_cpus > 1) {
- error_report("mach-virt: must enable KVM to use multiple CPUs");
- exit(1);
- }
-
if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
error_report("mach-virt: cannot model more than 30GB RAM");
exit(1);
@@ -495,6 +486,9 @@ static void machvirt_init(MachineState *machine)
}
cpuobj = object_new(object_class_get_name(oc));
+ object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit",
+ 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] 10+ messages in thread
* Re: [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
@ 2014-09-26 9:10 ` Peter Maydell
2014-09-26 15:34 ` Paolo Bonzini
0 siblings, 1 reply; 10+ messages in thread
From: Peter Maydell @ 2014-09-26 9:10 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: Rob Herring, QEMU Developers, Christoffer Dall
On 10 September 2014 08:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 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 the "psci-conduit" QOM property on the cpus to SMC or HVC
> emulation and having a PSCI binding in their dtb.
>
> Signed-off-by: Rob Herring <rob.herring@linaro.org>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> + case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
> + qemu_system_reset_request();
> + break;
> + case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
> + qemu_system_shutdown_request();
> + break;
I just realised that this isn't quite right: PSCI
mandates that the SYSTEM_RESET and SYSTEM_OFF
functions never return to the caller, but the QEMU
qemu_system_*_request() functions are just requests
which the main loop will later handle asynchronously.
So we should put the calling CPU into power off
(and rely on CPU reset to power it up again if it's
CPU 0; we don't care if we're shutting down, obviously).
I propose to apply the following fixup patch to
deal with this (since this patchset is very nearly
ready and I know Ard's not going to be back to
deal with it for a few weeks):
diff --git a/target-arm/psci.c b/target-arm/psci.c
index 7347cbd..1cda7d3 100644
--- a/target-arm/psci.c
+++ b/target-arm/psci.c
@@ -85,10 +85,15 @@ bool arm_handle_psci(CPUState *cs)
break;
case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
qemu_system_reset_request();
- break;
+ /* 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();
- break;
+ 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:
@@ -144,11 +149,7 @@ bool arm_handle_psci(CPUState *cs)
break;
case QEMU_PSCI_0_1_FN_CPU_OFF:
case QEMU_PSCI_0_2_FN_CPU_OFF:
- cpu->powered_off = true;
- cs->halted = 1;
- cs->exception_index = EXCP_HLT;
- cpu_loop_exit(cs);
- /* notreached */
+ 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:
@@ -180,4 +181,11 @@ err:
env->regs[0] = ret;
}
return true;
+
+cpu_off:
+ cpu->powered_off = true;
+ cs->halted = 1;
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
+ /* notreached */
}
thanks
-- PMM
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
@ 2014-09-26 10:17 ` Peter Maydell
0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2014-09-26 10:17 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: Rob Herring, QEMU Developers, Christoffer Dall
On 10 September 2014 08:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 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>
> diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
> index 89b913ee9396..1f8072ab141b 100644
> --- a/target-arm/helper-a64.c
> +++ b/target-arm/helper-a64.c
> @@ -485,6 +485,22 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
> case EXCP_FIQ:
> addr += 0x100;
> break;
> + case EXCP_HVC:
> + if (arm_cpu_do_hvc(cs)) {
> + return;
> + }
> + /* Treat as unallocated encoding */
> + qemu_log_mask(LOG_GUEST_ERROR, "HVC not implemented on this CPU\n");
> + env->exception.syndrome = syn_uncategorized();
> + break;
> + case EXCP_SMC:
> + if (arm_cpu_do_smc(cs)) {
> + return;
> + }
> + /* Treat as unallocated encoding */
> + qemu_log_mask(LOG_GUEST_ERROR, "SMC not implemented on this CPU\n");
> + env->exception.syndrome = syn_uncategorized();
> + break;
Looking again at this there are some issues with this,
notably that we don't do anything to ensure that the PC
is pointing at the instruction we're claiming to be UNDEF
rather than just after it.
The best approach seems to me to be to figure out at
translate time whether we're going to call this SMC
UNDEF or not.
We also seem to only generate the SMC and HVC exception
if the CPU has the FEATURE_EL2/3 bit set, which confuses
me because our CPUs don't set that and so I'm not sure
how this works at all...
I think the best way to fix this is going to be to rebase
this on top of Edgar's EL2/EL3 support patches, which
already deal with most of those problems (albeit only
for AArch64 currently). I'll do that and send out a
fixed version.
thanks
-- PMM
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation
2014-09-26 9:10 ` Peter Maydell
@ 2014-09-26 15:34 ` Paolo Bonzini
0 siblings, 0 replies; 10+ messages in thread
From: Paolo Bonzini @ 2014-09-26 15:34 UTC (permalink / raw)
To: Peter Maydell, Ard Biesheuvel
Cc: Rob Herring, QEMU Developers, Christoffer Dall
Il 26/09/2014 11:10, Peter Maydell ha scritto:
> On 10 September 2014 08:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> 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 the "psci-conduit" QOM property on the cpus to SMC or HVC
>> emulation and having a PSCI binding in their dtb.
>>
>> Signed-off-by: Rob Herring <rob.herring@linaro.org>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
>> + case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
>> + qemu_system_reset_request();
>> + break;
>> + case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
>> + qemu_system_shutdown_request();
>> + break;
>
> I just realised that this isn't quite right: PSCI
> mandates that the SYSTEM_RESET and SYSTEM_OFF
> functions never return to the caller, but the QEMU
> qemu_system_*_request() functions are just requests
> which the main loop will later handle asynchronously.
> So we should put the calling CPU into power off
> (and rely on CPU reset to power it up again if it's
> CPU 0; we don't care if we're shutting down, obviously).
>
> I propose to apply the following fixup patch to
> deal with this (since this patchset is very nearly
> ready and I know Ard's not going to be back to
> deal with it for a few weeks):
FWIW, looks good.
Thanks,
Paolo
> diff --git a/target-arm/psci.c b/target-arm/psci.c
> index 7347cbd..1cda7d3 100644
> --- a/target-arm/psci.c
> +++ b/target-arm/psci.c
> @@ -85,10 +85,15 @@ bool arm_handle_psci(CPUState *cs)
> break;
> case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
> qemu_system_reset_request();
> - break;
> + /* 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();
> - break;
> + 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:
> @@ -144,11 +149,7 @@ bool arm_handle_psci(CPUState *cs)
> break;
> case QEMU_PSCI_0_1_FN_CPU_OFF:
> case QEMU_PSCI_0_2_FN_CPU_OFF:
> - cpu->powered_off = true;
> - cs->halted = 1;
> - cs->exception_index = EXCP_HLT;
> - cpu_loop_exit(cs);
> - /* notreached */
> + 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:
> @@ -180,4 +181,11 @@ err:
> env->regs[0] = ret;
> }
> return true;
> +
> +cpu_off:
> + cpu->powered_off = true;
> + cs->halted = 1;
> + cs->exception_index = EXCP_HLT;
> + cpu_loop_exit(cs);
> + /* notreached */
> }
>
> thanks
> -- PMM
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-09-26 15:34 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-10 7:02 [Qemu-devel] [PACTH v4 0/6] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 1/6] target-arm: add powered off cpu state Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 2/6] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 3/6] target-arm: add hvc and smc exception emulation handling infrastructure Ard Biesheuvel
2014-09-26 10:17 ` Peter Maydell
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 4/6] target-arm: add missing PSCI constants needed for PSCI emulation Ard Biesheuvel
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 5/6] target-arm: add emulation of PSCI calls for system emulation Ard Biesheuvel
2014-09-26 9:10 ` Peter Maydell
2014-09-26 15:34 ` Paolo Bonzini
2014-09-10 7:02 ` [Qemu-devel] [PACTH v4 6/6] arm/virt: enable PSCI emulation support " Ard Biesheuvel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).