summaryrefslogtreecommitdiffstats
path: root/arch/arm64/include/asm/kvm_emulate.h
diff options
context:
space:
mode:
authorChristoffer Dall2017-12-27 20:01:52 +0100
committerMarc Zyngier2018-03-19 11:53:17 +0100
commit00536ec476601a60d976eebf6aeb9633d4fb37d9 (patch)
tree97e75b07520e9f3b444a6d535ec9d41e797776cc /arch/arm64/include/asm/kvm_emulate.h
parentKVM: arm64: Introduce framework for accessing deferred sysregs (diff)
downloadkernel-qcow2-linux-00536ec476601a60d976eebf6aeb9633d4fb37d9.tar.gz
kernel-qcow2-linux-00536ec476601a60d976eebf6aeb9633d4fb37d9.tar.xz
kernel-qcow2-linux-00536ec476601a60d976eebf6aeb9633d4fb37d9.zip
KVM: arm/arm64: Prepare to handle deferred save/restore of SPSR_EL1
SPSR_EL1 is not used by a VHE host kernel and can be deferred, but we need to rework the accesses to this register to access the latest value depending on whether or not guest system registers are loaded on the CPU or only reside in memory. The handling of accessing the various banked SPSRs for 32-bit VMs is a bit clunky, but this will be improved in following patches which will first prepare and subsequently implement deferred save/restore of the 32-bit registers, including the 32-bit SPSRs. Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Reviewed-by: Andrew Jones <drjones@redhat.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64/include/asm/kvm_emulate.h')
-rw-r--r--arch/arm64/include/asm/kvm_emulate.h41
1 files changed, 36 insertions, 5 deletions
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index d313aaae5c38..f32640132e26 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -26,6 +26,7 @@
#include <asm/esr.h>
#include <asm/kvm_arm.h>
+#include <asm/kvm_hyp.h>
#include <asm/kvm_mmio.h>
#include <asm/ptrace.h>
#include <asm/cputype.h>
@@ -143,13 +144,43 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
vcpu_gp_regs(vcpu)->regs.regs[reg_num] = val;
}
-/* Get vcpu SPSR for current mode */
-static inline unsigned long *vcpu_spsr(const struct kvm_vcpu *vcpu)
+static inline unsigned long vcpu_read_spsr(const struct kvm_vcpu *vcpu)
{
- if (vcpu_mode_is_32bit(vcpu))
- return vcpu_spsr32(vcpu);
+ unsigned long *p = (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
+
+ if (vcpu_mode_is_32bit(vcpu)) {
+ unsigned long *p_32bit = vcpu_spsr32(vcpu);
+
+ /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
+ if (p_32bit != p)
+ return *p_32bit;
+ }
+
+ if (vcpu->arch.sysregs_loaded_on_cpu)
+ return read_sysreg_el1(spsr);
+ else
+ return *p;
+}
- return (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
+static inline void vcpu_write_spsr(const struct kvm_vcpu *vcpu, unsigned long v)
+{
+ unsigned long *p = (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
+
+ /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
+ if (vcpu_mode_is_32bit(vcpu)) {
+ unsigned long *p_32bit = vcpu_spsr32(vcpu);
+
+ /* KVM_SPSR_SVC aliases KVM_SPSR_EL1 */
+ if (p_32bit != p) {
+ *p_32bit = v;
+ return;
+ }
+ }
+
+ if (vcpu->arch.sysregs_loaded_on_cpu)
+ write_sysreg_el1(v, spsr);
+ else
+ *p = v;
}
static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)