From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Alex Bennée" <alex.bennee@linaro.org>
Subject: [Qemu-devel] [PATCH v2 02/10] target-arm/cpu.h: common pstate save/restore
Date: Thu, 10 Jul 2014 16:49:59 +0100 [thread overview]
Message-ID: <1405007407-23549-3-git-send-email-alex.bennee@linaro.org> (raw)
In-Reply-To: <1405007407-23549-1-git-send-email-alex.bennee@linaro.org>
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 <alex.bennee@linaro.org>
---
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
next prev parent reply other threads:[~2014-07-10 15:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-10 15:49 [Qemu-devel] [PATCH v2 00/10] aarch64 migration for TCG and KVM Alex Bennée
2014-07-10 15:49 ` [Qemu-devel] [PATCH v2 01/10] target-arm/cpu.h: document various program state functions Alex Bennée
2014-08-04 12:28 ` Peter Maydell
2014-07-10 15:49 ` Alex Bennée [this message]
2014-08-04 12:47 ` [Qemu-devel] [PATCH v2 02/10] target-arm/cpu.h: common pstate save/restore Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 03/10] target-arm: Support save/load for 64 bit CPUs Alex Bennée
2014-08-04 12:50 ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 04/10] target-arm: replace cpsr/xpsr/pstate_read calls Alex Bennée
2014-07-15 13:40 ` Riku Voipio
2014-08-04 12:59 ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 05/10] arm/nwfps: replace cpsr_write with set_condition_codes Alex Bennée
2014-07-15 13:41 ` Riku Voipio
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 06/10] linux-user/main.c: __kernel_cmpxchg set env->CF directly Alex Bennée
2014-07-15 13:39 ` Riku Voipio
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 07/10] target-arm: remove last users of cpsr_write Alex Bennée
2014-07-15 13:43 ` Riku Voipio
2014-08-04 13:01 ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 08/10] target-arm: remove final users of pstate_write Alex Bennée
2014-07-15 13:44 ` Riku Voipio
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 09/10] target-arm/kvm.c: better error reporting Alex Bennée
2014-08-04 13:03 ` Peter Maydell
2014-07-10 15:50 ` [Qemu-devel] [PATCH v2 10/10] target-arm/kvm: make reg sync code common between kvm32/64 Alex Bennée
2014-08-04 13:04 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1405007407-23549-3-git-send-email-alex.bennee@linaro.org \
--to=alex.bennee@linaro.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).