qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 02/10] target-arm/cpu.h: common pstate save/resto


From: Alex Bennée
Subject: [Qemu-devel] [PATCH v2 02/10] target-arm/cpu.h: common pstate save/restore
Date: Thu, 10 Jul 2014 16:49:59 +0100

This adds a universal program state save and restore function. This is
intended to simplify the migration serialisation functionality and avoid
special casing depending on the mode of the CPU at serialisation time.

Signed-off-by: Alex Bennée <address@hidden>

---
v2:
  - reword commentary for restore_state_from_spsr
  - rm commented out code
  - add set_condition_codes for flags
  - add xpsr_read functionality

v3:
  - rebase
  - checkpatch.pl issues

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c2312d0..fe4d4f3 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -453,19 +453,24 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr 
address, int rw,
 #define PSTATE_SP (1U)
 #define PSTATE_M (0xFU)
 #define PSTATE_nRW (1U << 4)
+#define PSTATE_T (1U << 5)
 #define PSTATE_F (1U << 6)
 #define PSTATE_I (1U << 7)
 #define PSTATE_A (1U << 8)
 #define PSTATE_D (1U << 9)
 #define PSTATE_IL (1U << 20)
 #define PSTATE_SS (1U << 21)
+#define PSTATE_Q (1U << 27)
 #define PSTATE_V (1U << 28)
 #define PSTATE_C (1U << 29)
 #define PSTATE_Z (1U << 30)
 #define PSTATE_N (1U << 31)
 #define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
-#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
-#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
+#define PSTATE_AIF  (PSTATE_A | PSTATE_I | PSTATE_F)
+#define PSTATE_DAIF (PSTATE_D | PSTATE_AIF)
+#define AARCH64_CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
+#define AARCH32_CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_Q | PSTATE_AIF \
+                                    | CACHED_CPSR_BITS)
 /* Mode values for AArch64 */
 #define PSTATE_MODE_EL3h 13
 #define PSTATE_MODE_EL3t 12
@@ -508,7 +513,7 @@ static inline void pstate_write(CPUARMState *env, uint32_t 
val)
     env->CF = (val >> 29) & 1;
     env->VF = (val << 3) & 0x80000000;
     env->daif = val & PSTATE_DAIF;
-    env->pstate = val & ~CACHED_PSTATE_BITS;
+    env->pstate = val & ~AARCH64_CACHED_PSTATE_BITS;
 }
 
 /* ARMv7-AR ARM B1.3.3 Current Program Status Register, CPSR
@@ -698,6 +703,137 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int 
el)
     return arm_feature(env, ARM_FEATURE_AARCH64);
 }
 
+/* ARMv8 ARM D1.6.4, Saved Program Status Registers
+ *
+ * These are formats used to save program status when exceptions are
+ * taken. There are two forms:
+ *
+ * AArch64 -> AArch64 Exception
+ *  31  30  28  29  27  22  21   20  19  10  9   8   7   6   5  4   3      0
+ * +---+---+---+---+------+----+----+------+---+---+---+---+---+------------+
+ * | N | Z | C | V | RES0 | SS | IL | RES0 | D | A | I | F | 0 | 0 | M[3:0] |
+ * +---+---+---+---+------+----+----+------+---+---+---+---+---+------------+
+ *
+ * AArch32 -> AArch64 Exception
+ * (see also ARMv7-AR ARM B1.3.3 CSPR/SPSR formats)
+ *  31  30  29  28  27  26     25 24  23  22  21   20  19     16
+ * +---+---+---+---+---+---------+---+------+----+----+---------+
+ * | N | Z | C | V | Q | IT[1:0] | J | RES0 | SS | IL | GE[3:0] |
+ * +---+---+---+---+---+---------+---+------+----+----+---------+
+ *  15     10  9   8   7   6   5   4  3      0
+ * +---------+---+---+---+---+---+---+--------+
+ * | IT[7:2] | E | A | I | F | T | 1 | M[3:0] |
+ * +---------+---+---+---+---+---+---+--------+
+ *
+ * M[4] = nRW - 0 = 64bit, 1 = 32bit
+ * Bit definitions for ARMv8 SPSR (PSTATE) format.
+ * Only these are valid when in AArch64 mode; in
+ * AArch32 mode SPSRs are basically CPSR-format.
+ *
+ * Also ARMv7-M ARM B1.4.2, special purpose program status register xPSR
+ */
+
+/* Save the program state */
+static inline uint32_t save_state_to_spsr(CPUARMState *env)
+{
+    uint32_t final_spsr = 0;
+
+    /* Calculate integer flags */
+    final_spsr |= (env->NF & 0x80000000) ? PSTATE_N : 0; /* bit 31 */
+    final_spsr |= (env->ZF == 0) ? PSTATE_Z : 0;
+    final_spsr |= env->CF ? PSTATE_C : 0;                /* or env->CF << 29 */
+    final_spsr |= (env->VF & 0x80000000) ? PSTATE_V : 0; /* bit 31 */
+
+    if (is_a64(env)) {
+        /* SS - Software Step */
+        /* IL - Illegal execution state */
+        /* DAIF flags - should we mask?*/
+        final_spsr |= (env->daif & PSTATE_DAIF);
+        /* And the final un-cached bits */
+        final_spsr |= (env->pstate & ~AARCH64_CACHED_PSTATE_BITS);
+    } else {
+        /* condexec_bits is split over two parts */
+        final_spsr |= ((env->condexec_bits & 3) << 25);
+        final_spsr |= ((env->condexec_bits & 0xfc) << 8);
+
+        if (arm_feature(env, ARM_FEATURE_M)) {
+            final_spsr |= (env->thumb << 24);   /* alt pos */
+            final_spsr |= env->v7m.exception;
+        } else {
+            final_spsr |= env->QF ? PSTATE_Q : 0;
+            /* GE needs shifting into place */
+            final_spsr |= (env->GE << 16);
+            /* AIF is a a subset of DAIF */
+            final_spsr |= (env->daif & PSTATE_AIF);
+            final_spsr |= env->thumb ? PSTATE_T : 0;
+
+            final_spsr |= PSTATE_nRW;
+
+            /* And the final un-cached bits */
+            final_spsr |= (env->uncached_cpsr & ~AARCH32_CACHED_PSTATE_BITS);
+        }
+    }
+    return final_spsr;
+}
+
+/* Restore the program state.
+ *
+ * This restores the program execution state including it's current
+ * execution mode. However validation of mode changes and additional
+ * registers and state that need changing should be done by the
+ * calling function.
+ *
+ * The simple set_condition_codes() function can be used just to
+ * update the cached integer flags which are quite often manipulated
+ * alone.
+ */
+
+/* Only update the cached condition codes. */
+static inline void set_condition_codes(CPUARMState *env, uint32_t new_flags)
+{
+    /* Process the integer flags directly */
+    env->ZF = (~new_flags) & CPSR_Z;
+    env->NF = new_flags;
+    env->CF = (new_flags >> 29) & 1;
+    env->VF = (new_flags << 3) & 0x80000000;
+}
+
+/* Restore the complete program state */
+static inline void restore_state_from_spsr(CPUARMState *env,
+                                           uint32_t saved_state)
+{
+    set_condition_codes(env, saved_state);
+
+    /* the rest depends on the mode we end up in */
+    env->aarch64 = (saved_state & PSTATE_nRW) ? 0 : 1;
+
+    if (is_a64(env)) {
+        env->daif = saved_state & PSTATE_DAIF;
+        env->pstate = (saved_state & ~AARCH64_CACHED_PSTATE_BITS);
+    } else {
+        if (arm_feature(env, ARM_FEATURE_M)) {
+            fprintf(stderr, "%s: M state not yet implmented\n", __func__);
+        } else {
+            env->QF = saved_state & PSTATE_Q ? 1 : 0;
+            /* condexec_bits is split over two parts */
+            env->condexec_bits = (saved_state & CPSR_IT_0_1) >> 25;
+            env->condexec_bits |= (saved_state & CPSR_IT_2_7) >> 8;
+
+            /* GE needs shifting into place */
+            env->GE = (saved_state >> 16) & 0xf;
+
+            /* AIF is a a subset of DAIF */
+            env->daif = (saved_state & PSTATE_AIF);
+
+            env->thumb = saved_state & PSTATE_T ? 1 : 0;
+
+            /* And the final un-cached bits */
+            env->uncached_cpsr = saved_state & ~AARCH32_CACHED_PSTATE_BITS;
+        }
+    }
+}
+
+
 void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
 /* Interface between CPU and Interrupt controller.  */
-- 
2.0.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]