qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
@ 2014-10-09 14:30 Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 1/7] target-arm: add powered off cpu state Peter Maydell
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

This series adds PSCI support to ARM and AArch64 system emulation
when running in TCG mode. It's an update of the patchsent Ard
sent out earlier in September which in turn is based on work
by Rob Herring.

Changes v5->v6:
 * minor rebasing
 * redid the way that PSCI is plumbed into SMC/HVC handling,
   to fit into the support for EL2/EL3 which has landed since
   v5. In particular we now test for whether this is a PSCI
   call as a separate step from actually doing the call, since
   we want to prefer doing PSCI to UNDEF, but UNDEF will happen
   first if it happens at all.

NB: this works for the virt board for both 32 bit and 64 bit
CPUs. There is one bug I've seen where if you have an SMP
configuration of 32 bit CPUs and do a guest reset then the
guest misbehaves (segfaults, etc) after the reboot when it
gets up to userspace. I'm not sure if this is the fault of
these patches or just a revealed bug, so I'm sending them
out for review anyway and will investigate further...

thanks
-- PMM

Ard Biesheuvel (1):
  target-arm: add missing PSCI constants needed for PSCI emulation

Peter Maydell (2):
  target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers
  target-arm: Add support for A32 and T32 HVC and SMC insns

Rob Herring (4):
  target-arm: add powered off cpu state
  target-arm: do not set do_interrupt handlers for ARM and AArch64 user
    modes
  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       |   7 ++
 target-arm/cpu.c           |  20 +++-
 target-arm/cpu.h           |   6 ++
 target-arm/cpu64.c         |   2 +
 target-arm/helper-a64.c    |   9 ++
 target-arm/helper.c        |  11 ++-
 target-arm/internals.h     |  22 +++++
 target-arm/kvm-consts.h    |  40 ++++++++
 target-arm/machine.c       |   5 +-
 target-arm/op_helper.c     |  33 +++++--
 target-arm/psci.c          | 242 +++++++++++++++++++++++++++++++++++++++++++++
 target-arm/translate-a64.c |   4 +-
 target-arm/translate.c     | 103 ++++++++++++++++---
 target-arm/translate.h     |   2 +
 16 files changed, 513 insertions(+), 76 deletions(-)
 create mode 100644 target-arm/psci.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 1/7] target-arm: add powered off cpu state
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 2/7] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Peter Maydell
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

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>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu-qom.h | 2 ++
 target-arm/cpu.c     | 8 +++++++-
 target-arm/machine.c | 5 +++--
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 96a3da9..aeb7e1d 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 edfd586..67cd176 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -40,7 +40,10 @@ 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_VFIQ | CPU_INTERRUPT_VIRQ
          | CPU_INTERRUPT_EXITTB);
@@ -93,6 +96,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 ddb7d05..5776ee0 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,8 +222,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[]) {
@@ -263,6 +263,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.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 2/7] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 1/7] target-arm: add powered off cpu state Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 3/7] target-arm: add missing PSCI constants needed for PSCI emulation Peter Maydell
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

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>
Signed-off-by: Peter Maydell <peter.maydell@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 67cd176..2061cb7 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1109,7 +1109,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->cpu_exec_interrupt = arm_cpu_exec_interrupt;
     cc->dump_state = arm_cpu_dump_state;
     cc->set_pc = arm_cpu_set_pc;
@@ -1118,6 +1117,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 c30f47e..a95367a 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->cpu_exec_interrupt = arm_cpu_exec_interrupt;
     cc->set_pc = aarch64_cpu_set_pc;
     cc->gdb_read_register = aarch64_cpu_gdb_read_register;
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index 8228e29..7ae84f6 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)
 {
@@ -518,3 +520,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 2669e15..497178a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3644,11 +3644,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.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 3/7] target-arm: add missing PSCI constants needed for PSCI emulation
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 1/7] target-arm: add powered off cpu state Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 2/7] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 4/7] target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers Peter Maydell
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

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>
Signed-off-by: Peter Maydell <peter.maydell@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 091c126..aea12f1 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.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 4/7] target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
                   ` (2 preceding siblings ...)
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 3/7] target-arm: add missing PSCI constants needed for PSCI emulation Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 5/7] target-arm: Add support for A32 and T32 HVC and SMC insns Peter Maydell
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

SMC must UNDEF if EL3 is not implemented; similarly HVC UNDEFs
if EL2 is not implemented. Move the handling of this from
translate-a64.c into the pre_smc and pre_hvc helper functions.
This is necessary because use of these instructions for PSCI
takes precedence over this UNDEF case, and we can't tell if
this is a PSCI call until runtime.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/op_helper.c     | 17 ++++++++++-------
 target-arm/translate-a64.c |  4 ++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 03ac92a..5652096 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -392,10 +392,11 @@ void HELPER(pre_hvc)(CPUARMState *env)
     bool secure = false;
     bool undef;
 
-    /* We've already checked that EL2 exists at translation time.
-     * EL3.HCE has priority over EL2.HCD.
-     */
-    if (arm_feature(env, ARM_FEATURE_EL3)) {
+    if (!arm_feature(env, ARM_FEATURE_EL2)) {
+        /* If EL2 doesn't exist, HVC always UNDEFs */
+        undef = true;
+    } else if (arm_feature(env, ARM_FEATURE_EL3)) {
+        /* EL3.HCE has priority over EL2.HCD. */
         undef = !(env->cp15.scr_el3 & SCR_HCE);
     } else {
         undef = env->cp15.hcr_el2 & HCR_HCD;
@@ -429,13 +430,15 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
      */
     bool undef = is_a64(env) ? smd : (!secure && smd);
 
-    /* In NS EL1, HCR controlled routing to EL2 has priority over SMD.  */
-    if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+    if (!arm_feature(env, ARM_FEATURE_EL3)) {
+        /* If we have no EL3 then SMC always UNDEFs */
+        undef = true;
+    } else if (!secure && cur_el == 1 && (env->cp15.hcr_el2 & HCR_TSC)) {
+        /* In NS EL1, HCR controlled routing to EL2 has priority over SMD. */
         env->exception.syndrome = syndrome;
         raise_exception(env, EXCP_HYP_TRAP);
     }
 
-    /* We've already checked that EL3 exists at translation time.  */
     if (undef) {
         env->exception.syndrome = syn_uncategorized();
         raise_exception(env, EXCP_UDEF);
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 35ae3ea..b15261b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1485,7 +1485,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
             break;
         case 2:
-            if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_pl == 0) {
+            if (s->current_pl == 0) {
                 unallocated_encoding(s);
                 break;
             }
@@ -1498,7 +1498,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
             gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
             break;
         case 3:
-            if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->current_pl == 0) {
+            if (s->current_pl == 0) {
                 unallocated_encoding(s);
                 break;
             }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 5/7] target-arm: Add support for A32 and T32 HVC and SMC insns
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
                   ` (3 preceding siblings ...)
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 4/7] target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 6/7] target-arm: add emulation of PSCI calls for system emulation Peter Maydell
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

Add support for HVC and SMC instructions to the A32 and
T32 decoder. Using these for real exceptions to EL2 or EL3
is currently not supported (the do_interrupt routine does
not handle them) but we require the instruction support to
implement PSCI.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/internals.h |  10 +++++
 target-arm/translate.c | 103 +++++++++++++++++++++++++++++++++++++++++++------
 target-arm/translate.h |   2 +
 3 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/target-arm/internals.h b/target-arm/internals.h
index b7547bb..e46de71 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -236,6 +236,16 @@ static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
         | (is_thumb ? 0 : ARM_EL_IL);
 }
 
+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_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.c b/target-arm/translate.c
index 8a2994f..4e764d3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -941,6 +941,39 @@ static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
     tcg_gen_movi_i32(cpu_R[15], val);
 }
 
+static inline void gen_hvc(DisasContext *s, int imm16)
+{
+    /* The pre HVC helper handles cases when HVC gets trapped
+     * as an undefined insn by runtime configuration (ie before
+     * the insn really executes).
+     */
+    gen_set_pc_im(s, s->pc - 4);
+    gen_helper_pre_hvc(cpu_env);
+    /* Otherwise we will treat this as a real exception which
+     * happens after execution of the insn. (The distinction matters
+     * for the PC value reported to the exception handler and also
+     * for single stepping.)
+     */
+    s->svc_imm = imm16;
+    gen_set_pc_im(s, s->pc);
+    s->is_jmp = DISAS_HVC;
+}
+
+static inline void gen_smc(DisasContext *s)
+{
+    /* As with HVC, we may take an exception either before or after
+     * the insn executes.
+     */
+    TCGv_i32 tmp;
+
+    gen_set_pc_im(s, s->pc - 4);
+    tmp = tcg_const_i32(syn_aa32_smc());
+    gen_helper_pre_smc(cpu_env, tmp);
+    tcg_temp_free_i32(tmp);
+    gen_set_pc_im(s, s->pc);
+    s->is_jmp = DISAS_SMC;
+}
+
 static inline void
 gen_set_condexec (DisasContext *s)
 {
@@ -7872,15 +7905,32 @@ 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;
+                }
+                gen_hvc(s, imm16);
+                break;
+            case 3:
+                /* Secure monitor call (v6+) */
+                ARCH(6K);
+                if (IS_USER(s)) {
+                    goto illegal_op;
+                }
+                gen_smc(s);
+                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 */
@@ -9710,10 +9760,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) */
+                        int imm16 = extract32(insn, 16, 4) << 12
+                            | extract32(insn, 0, 12);
+                        ARCH(7);
+                        if (IS_USER(s)) {
+                            goto illegal_op;
+                        }
+                        gen_hvc(s, imm16);
+                    } else {
+                        /* Secure monitor call (v6+) */
+                        ARCH(6K);
+                        if (IS_USER(s)) {
+                            goto illegal_op;
+                        }
+                        gen_smc(s);
+                    }
                 } else {
                     op = (insn >> 20) & 7;
                     switch (op) {
@@ -11148,6 +11211,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
             if (dc->is_jmp == DISAS_SWI) {
                 gen_ss_advance(dc);
                 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+            } else if (dc->is_jmp == DISAS_HVC) {
+                gen_ss_advance(dc);
+                gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
+            } else if (dc->is_jmp == DISAS_SMC) {
+                gen_ss_advance(dc);
+                gen_exception(EXCP_SMC, syn_aa32_smc());
             } else if (dc->ss_active) {
                 gen_step_complete_exception(dc);
             } else {
@@ -11163,6 +11232,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
         if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
             gen_ss_advance(dc);
             gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+        } else if (dc->is_jmp == DISAS_HVC && !dc->condjmp) {
+            gen_ss_advance(dc);
+            gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
+        } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) {
+            gen_ss_advance(dc);
+            gen_exception(EXCP_SMC, syn_aa32_smc());
         } else if (dc->ss_active) {
             gen_step_complete_exception(dc);
         } else {
@@ -11202,6 +11277,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 85c6f9d..83fbf38 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -84,6 +84,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.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 6/7] target-arm: add emulation of PSCI calls for system emulation
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
                   ` (4 preceding siblings ...)
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 5/7] target-arm: Add support for A32 and T32 HVC and SMC insns Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 7/7] arm/virt: enable PSCI emulation support " Peter Maydell
  2014-10-10 10:42 ` [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

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>
[PMM: made system reset/off PSCI functions power down the CPU so
 we obey the PSCI API requirement never to return from them;
 rearranged how the code is plumbed into the exception system,
 so that we split "is this a valid call?" from "do the call"]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/Makefile.objs |   1 +
 target-arm/cpu-qom.h     |   5 +
 target-arm/cpu.c         |  10 +-
 target-arm/cpu.h         |   6 ++
 target-arm/helper-a64.c  |   6 ++
 target-arm/helper.c      |   6 ++
 target-arm/internals.h   |  12 +++
 target-arm/op_helper.c   |  16 ++++
 target-arm/psci.c        | 242 +++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 301 insertions(+), 3 deletions(-)
 create mode 100644 target-arm/psci.c

diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index dcd167e..9460b40 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 aeb7e1d..dcfda7d 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.
      */
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 2061cb7..e837f64 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -334,9 +334,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();
+        }
     }
 }
 
@@ -1090,6 +1093,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 65a3417..690686c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1484,4 +1484,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-a64.c b/target-arm/helper-a64.c
index 7ae84f6..daf5adc 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -468,6 +468,12 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
                       env->exception.syndrome);
     }
 
+    if (arm_is_psci_call(cpu, cs->exception_index)) {
+        arm_handle_psci_call(cpu);
+        qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
+        return;
+    }
+
     switch (cs->exception_index) {
     case EXCP_PREFETCH_ABORT:
     case EXCP_DATA_ABORT:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 497178a..d837820 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3970,6 +3970,12 @@ void arm_cpu_do_interrupt(CPUState *cs)
 
     arm_log_exception(cs->exception_index);
 
+    if (arm_is_psci_call(cpu, cs->exception_index)) {
+        arm_handle_psci_call(cpu);
+        qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
+        return;
+    }
+
     /* If this is a debug exception we must update the DBGDSCR.MOE bits */
     switch (env->exception.syndrome >> ARM_EL_EC_SHIFT) {
     case EC_BREAKPOINT:
diff --git a/target-arm/internals.h b/target-arm/internals.h
index e46de71..51c5c16 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -366,4 +366,16 @@ void hw_breakpoint_update_all(ARMCPU *cpu);
 /* Callback function for when a watchpoint or breakpoint triggers. */
 void arm_debug_excp_handler(CPUState *cs);
 
+#ifdef CONFIG_USER_ONLY
+static inline bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
+{
+    return false;
+}
+#else
+/* Return true if the r0/x0 value indicates that this SMC/HVC is a PSCI call. */
+bool arm_is_psci_call(ARMCPU *cpu, int excp_type);
+/* Actually handle a PSCI call */
+void arm_handle_psci_call(ARMCPU *cpu);
+#endif
+
 #endif
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 5652096..464a5ce 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -387,11 +387,19 @@ void HELPER(clear_pstate_ss)(CPUARMState *env)
 
 void HELPER(pre_hvc)(CPUARMState *env)
 {
+    ARMCPU *cpu = arm_env_get_cpu(env);
     int cur_el = arm_current_pl(env);
     /* FIXME: Use actual secure state.  */
     bool secure = false;
     bool undef;
 
+    if (arm_is_psci_call(cpu, EXCP_HVC)) {
+        /* If PSCI is enabled and this looks like a valid PSCI call then
+         * that overrides the architecturally mandated HVC behaviour.
+         */
+        return;
+    }
+
     if (!arm_feature(env, ARM_FEATURE_EL2)) {
         /* If EL2 doesn't exist, HVC always UNDEFs */
         undef = true;
@@ -419,6 +427,7 @@ void HELPER(pre_hvc)(CPUARMState *env)
 
 void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
 {
+    ARMCPU *cpu = arm_env_get_cpu(env);
     int cur_el = arm_current_pl(env);
     /* FIXME: Use real secure state.  */
     bool secure = false;
@@ -430,6 +439,13 @@ void HELPER(pre_smc)(CPUARMState *env, uint32_t syndrome)
      */
     bool undef = is_a64(env) ? smd : (!secure && smd);
 
+    if (arm_is_psci_call(cpu, EXCP_SMC)) {
+        /* If PSCI is enabled and this looks like a valid PSCI call then
+         * that overrides the architecturally mandated SMC behaviour.
+         */
+        return;
+    }
+
     if (!arm_feature(env, ARM_FEATURE_EL3)) {
         /* If we have no EL3 then SMC always UNDEFs */
         undef = true;
diff --git a/target-arm/psci.c b/target-arm/psci.c
new file mode 100644
index 0000000..d8fafab
--- /dev/null
+++ b/target-arm/psci.c
@@ -0,0 +1,242 @@
+/*
+ * 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>
+#include "internals.h"
+
+bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
+{
+    /* Return true if the r0/x0 value indicates a PSCI call and
+     * 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).
+     */
+    CPUARMState *env = &cpu->env;
+    uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0];
+
+    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;
+    }
+
+    switch (param) {
+    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_0_1_FN_MIGRATE:
+    case QEMU_PSCI_0_2_FN_MIGRATE:
+        return true;
+    default:
+        return false;
+    }
+}
+
+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 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)
+     */
+    CPUState *cs = CPU(cpu);
+    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();
+        /* 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();
+        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:
+        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:
+        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);
+        break;
+    case QEMU_PSCI_0_1_FN_MIGRATE:
+    case QEMU_PSCI_0_2_FN_MIGRATE:
+        ret = QEMU_PSCI_RET_NOT_SUPPORTED;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+err:
+    if (is_a64(env)) {
+        env->xregs[0] = ret;
+    } else {
+        env->regs[0] = ret;
+    }
+    return;
+
+cpu_off:
+    cpu->powered_off = true;
+    cs->halted = 1;
+    cs->exception_index = EXCP_HLT;
+    cpu_loop_exit(cs);
+    /* notreached */
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v5 7/7] arm/virt: enable PSCI emulation support for system emulation
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
                   ` (5 preceding siblings ...)
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 6/7] target-arm: add emulation of PSCI calls for system emulation Peter Maydell
@ 2014-10-09 14:30 ` Peter Maydell
  2014-10-10 10:42 ` [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
  7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2014-10-09 14:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Bellows, Ard Biesheuvel, patches

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>
Signed-off-by: Peter Maydell <peter.maydell@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 8c6b171..6cfd4bf 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -190,47 +190,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)
@@ -537,16 +538,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);
@@ -565,6 +556,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.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
  2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
                   ` (6 preceding siblings ...)
  2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 7/7] arm/virt: enable PSCI emulation support " Peter Maydell
@ 2014-10-10 10:42 ` Ard Biesheuvel
  2014-10-10 10:56   ` Peter Maydell
  7 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2014-10-10 10:42 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Greg Bellows, QEMU Developers, Patch Tracking

On 9 October 2014 16:30, Peter Maydell <peter.maydell@linaro.org> wrote:
> This series adds PSCI support to ARM and AArch64 system emulation
> when running in TCG mode. It's an update of the patchsent Ard
> sent out earlier in September which in turn is based on work
> by Rob Herring.
>
> Changes v5->v6:
>  * minor rebasing
>  * redid the way that PSCI is plumbed into SMC/HVC handling,
>    to fit into the support for EL2/EL3 which has landed since
>    v5. In particular we now test for whether this is a PSCI
>    call as a separate step from actually doing the call, since
>    we want to prefer doing PSCI to UNDEF, but UNDEF will happen
>    first if it happens at all.
>
> NB: this works for the virt board for both 32 bit and 64 bit
> CPUs. There is one bug I've seen where if you have an SMP
> configuration of 32 bit CPUs and do a guest reset then the
> guest misbehaves (segfaults, etc) after the reboot when it
> gets up to userspace. I'm not sure if this is the fault of
> these patches or just a revealed bug, so I'm sending them
> out for review anyway and will investigate further...
>

Hello Peter,

Thanks for picking this up while I was away. I have tested your
version of the series, and my test cases still appear to work
correctly.
However, we still haven't addressed the CPU reset case, so issuing the
PSCI reset under -bios does nothing.

Latest is here
http://marc.info/?l=qemu-devel&m=140993015009810&w=2

-- 
Ard.


> Ard Biesheuvel (1):
>   target-arm: add missing PSCI constants needed for PSCI emulation
>
> Peter Maydell (2):
>   target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers
>   target-arm: Add support for A32 and T32 HVC and SMC insns
>
> Rob Herring (4):
>   target-arm: add powered off cpu state
>   target-arm: do not set do_interrupt handlers for ARM and AArch64 user
>     modes
>   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       |   7 ++
>  target-arm/cpu.c           |  20 +++-
>  target-arm/cpu.h           |   6 ++
>  target-arm/cpu64.c         |   2 +
>  target-arm/helper-a64.c    |   9 ++
>  target-arm/helper.c        |  11 ++-
>  target-arm/internals.h     |  22 +++++
>  target-arm/kvm-consts.h    |  40 ++++++++
>  target-arm/machine.c       |   5 +-
>  target-arm/op_helper.c     |  33 +++++--
>  target-arm/psci.c          | 242 +++++++++++++++++++++++++++++++++++++++++++++
>  target-arm/translate-a64.c |   4 +-
>  target-arm/translate.c     | 103 ++++++++++++++++---
>  target-arm/translate.h     |   2 +
>  16 files changed, 513 insertions(+), 76 deletions(-)
>  create mode 100644 target-arm/psci.c
>
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
  2014-10-10 10:42 ` [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
@ 2014-10-10 10:56   ` Peter Maydell
  2014-10-10 11:02     ` Ard Biesheuvel
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Maydell @ 2014-10-10 10:56 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: Greg Bellows, QEMU Developers, Patch Tracking

On 10 October 2014 11:42, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Thanks for picking this up while I was away. I have tested your
> version of the series, and my test cases still appear to work
> correctly.

Do you see the odd behaviour after guest reset for 32
bit SMP cores?

> However, we still haven't addressed the CPU reset case, so issuing the
> PSCI reset under -bios does nothing.
>
> Latest is here
> http://marc.info/?l=qemu-devel&m=140993015009810&w=2

Yep, that's also on my todo list, but it's orthogonal to
this patch series. We probably want this variant, though,
right?

http://marc.info/?l=qemu-devel&m=141099155616120&w=2

-- PMM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
  2014-10-10 10:56   ` Peter Maydell
@ 2014-10-10 11:02     ` Ard Biesheuvel
  2014-10-10 11:22       ` Peter Maydell
  0 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2014-10-10 11:02 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Greg Bellows, QEMU Developers, Patch Tracking

On 10 October 2014 12:56, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 10 October 2014 11:42, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> Thanks for picking this up while I was away. I have tested your
>> version of the series, and my test cases still appear to work
>> correctly.
>
> Do you see the odd behaviour after guest reset for 32
> bit SMP cores?
>

I will try to reproduce it. I haven't tried, and I wasn't aware that
SMP on TCG is supposed to be stable now otherwise.

>> However, we still haven't addressed the CPU reset case, so issuing the
>> PSCI reset under -bios does nothing.
>>
>> Latest is here
>> http://marc.info/?l=qemu-devel&m=140993015009810&w=2
>
> Yep, that's also on my todo list, but it's orthogonal to
> this patch series. We probably want this variant, though,
> right?
>
> http://marc.info/?l=qemu-devel&m=141099155616120&w=2

Yes, you're right, I had forgotten about sending that out.

-- 
Ard.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
  2014-10-10 11:02     ` Ard Biesheuvel
@ 2014-10-10 11:22       ` Peter Maydell
  2014-10-10 11:34         ` Ard Biesheuvel
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Maydell @ 2014-10-10 11:22 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: Greg Bellows, QEMU Developers, Patch Tracking

On 10 October 2014 12:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 10 October 2014 12:56, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Do you see the odd behaviour after guest reset for 32
>> bit SMP cores?
>>
>
> I will try to reproduce it. I haven't tried, and I wasn't aware that
> SMP on TCG is supposed to be stable now otherwise.

It has always been *supposed* to be stable, the only reason
we didn't have it enabled on the AArch64 virt board was
that we didn't have PSCI implemented. There were some
bugs that we fixed recently. Anything else obviously needs
to be reported as a bug and investigated so we can fix it...

(32 bit TCG SMP support on boards like vexpress has been
supported for a long time. It just doesn't often make
much practical sense to use an SMP config because it will
inevitably be slower than the single-CPU config.)

>>> However, we still haven't addressed the CPU reset case, so issuing the
>>> PSCI reset under -bios does nothing.

>> Yep, that's also on my todo list, but it's orthogonal to
>> this patch series. We probably want this variant, though,
>> right?
>>
>> http://marc.info/?l=qemu-devel&m=141099155616120&w=2
>
> Yes, you're right, I had forgotten about sending that out.

Can I get you to send out that as a proper patch then,
please?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode
  2014-10-10 11:22       ` Peter Maydell
@ 2014-10-10 11:34         ` Ard Biesheuvel
  0 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2014-10-10 11:34 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Greg Bellows, QEMU Developers, Patch Tracking

On 10 October 2014 13:22, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 10 October 2014 12:02, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> On 10 October 2014 12:56, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> Do you see the odd behaviour after guest reset for 32
>>> bit SMP cores?
>>>
>>
>> I will try to reproduce it. I haven't tried, and I wasn't aware that
>> SMP on TCG is supposed to be stable now otherwise.
>
> It has always been *supposed* to be stable, the only reason
> we didn't have it enabled on the AArch64 virt board was
> that we didn't have PSCI implemented. There were some
> bugs that we fixed recently. Anything else obviously needs
> to be reported as a bug and investigated so we can fix it...
>
> (32 bit TCG SMP support on boards like vexpress has been
> supported for a long time. It just doesn't often make
> much practical sense to use an SMP config because it will
> inevitably be slower than the single-CPU config.)
>

OK

>>>> However, we still haven't addressed the CPU reset case, so issuing the
>>>> PSCI reset under -bios does nothing.
>
>>> Yep, that's also on my todo list, but it's orthogonal to
>>> this patch series. We probably want this variant, though,
>>> right?
>>>
>>> http://marc.info/?l=qemu-devel&m=141099155616120&w=2
>>
>> Yes, you're right, I had forgotten about sending that out.
>
> Can I get you to send out that as a proper patch then,
> please?
>

Of course.

-- 
Ard.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2014-10-10 11:42 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-09 14:30 [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 1/7] target-arm: add powered off cpu state Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 2/7] target-arm: do not set do_interrupt handlers for ARM and AArch64 user modes Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 3/7] target-arm: add missing PSCI constants needed for PSCI emulation Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 4/7] target-arm: Handle SMC/HVC undef-if-no-ELx in pre_* helpers Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 5/7] target-arm: Add support for A32 and T32 HVC and SMC insns Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 6/7] target-arm: add emulation of PSCI calls for system emulation Peter Maydell
2014-10-09 14:30 ` [Qemu-devel] [PATCH v5 7/7] arm/virt: enable PSCI emulation support " Peter Maydell
2014-10-10 10:42 ` [Qemu-devel] [PATCH v5 0/7] ARM: add PSCI 0.2 support in TCG mode Ard Biesheuvel
2014-10-10 10:56   ` Peter Maydell
2014-10-10 11:02     ` Ard Biesheuvel
2014-10-10 11:22       ` Peter Maydell
2014-10-10 11:34         ` 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).