aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-03-05 14:15:20 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-05-25 14:28:56 +0100
commit35ef7b60d6381333f6b3f2184e0b778b35b45e92 (patch)
tree45217418d4b3603f7c78e8156ded4d31a83bb5c7
parent626451be7cfb9789f6710d758d0d0426654d0265 (diff)
downloadqemu-arm-35ef7b60d6381333f6b3f2184e0b778b35b45e92.tar.gz
target/arm: Propagate S/NS cpreg flag to/from KVM register ID
In QEMU we have two encoding forms for Arm coprocessor and system registers: a 32 bit internal form which is the key into the coprocessor register hashtable, and a 64 bit form which matches the kernel's encoding for KVM_SET_ONE_REG/KVM_GET_ONE_REG ioctls. The on-the-wire migration data uses the 64 bit form. The functions cpreg_to_kvm_id() and kvm_to_cpreg_id() perform the (mostly trivial) conversion between them. Unfortunately the 64 bit form doesn't currently have any way to encode whether the register is the secure or non-secure banked version of an AArch32 register, because for KVM the guest is always running non-secure and there are no secure registers. Our conversion functions were handling this with "ignore S/NS bit when converting cpreg->kvm ID; always mark as NS when converting kvm ID->cpreg". This works for KVM, but breaks migration of guests that use TrustZone in an emulated CPU, because we end up migrating the state of the NonSecure register when we intended to migrate the Secure register. To fix this, we define an S/NS indication in the KVM ID format. This is defined in the upstream kernel headers using the KVM_REG_ARM_SECURE_MASK/SHIFT constants. Rather than converting from our existing internal form's definitions for AA64/AA32 and S/NS (which use bit 28 == 1 for AArch32, and bit 29 == 1 for NonSecure), we update the internal form to follow the KVM format (with bit 28 == 1 for Secure), and move the AA64/AA32 bit to bit 29. TODO: other problems: * TTBR0_EL3(S) AArch32 should be ALIAS, because there's a TTBR0_EL3 record in el3_cp_reginfo * TTBR1_EL3(S) AArch32 needs to not be ALIAS (even if V8) because there is no AArch64 TTBR1_EL3 to hold the state Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target/arm/cpu.h18
1 files changed, 3 insertions, 15 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 8488273c5b..f8db605170 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1747,18 +1747,11 @@ static inline bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
* IDs the AArch64/32 distinction is the KVM_REG_ARM/ARM64
* in the upper bits of the 64 bit ID.
*/
-#define CP_REG_AA64_SHIFT 28
+#define CP_REG_AA64_SHIFT 29
#define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT)
-/* To enable banking of coprocessor registers depending on ns-bit we
- * add a bit to distinguish between secure and non-secure cpregs in the
- * hashtable.
- */
-#define CP_REG_NS_SHIFT 29
-#define CP_REG_NS_MASK (1 << CP_REG_NS_SHIFT)
-
#define ENCODE_CP_REG(cp, is64, ns, crn, crm, opc1, opc2) \
- ((ns) << CP_REG_NS_SHIFT | ((cp) << 16) | ((is64) << 15) | \
+ (!(ns) << CP_REG_ARM_SECURE_SHIFT | ((cp) << 16) | ((is64) << 15) | \
((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2))
#define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
@@ -1771,7 +1764,7 @@ static inline bool armv7m_nvic_neg_prio_requested(void *opaque, bool secure)
((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT))
/* Convert a full 64 bit KVM register ID to the truncated 32 bit
- * version used as a key for the coprocessor register hashtable
+ * version used as a key for the coprocessor register hashtable.
*/
static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
{
@@ -1782,11 +1775,6 @@ static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
cpregid |= (1 << 15);
}
-
- /* KVM is always non-secure so add the NS flag on AArch32 register
- * entries.
- */
- cpregid |= 1 << CP_REG_NS_SHIFT;
}
return cpregid;
}