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>
1 file changed