aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-10-19 14:28:29 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2015-12-14 06:30:40 -0500
commitc209ec85a2a7d2fd38bca0a44b7e70abd079c178 (patch)
tree04a66f17cee2f78c6d497466c8bb136380193ee5
parent6d6ec20fcf2830ca10c1b7c8efd7e2592c40e3d6 (diff)
arm64: KVM: Implement 32bit system register save/restore
Implement the 32bit system register save/restore as a direct translation of the assembly code version. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--arch/arm64/kvm/hyp/hyp.h2
-rw-r--r--arch/arm64/kvm/hyp/sysreg-sr.c47
2 files changed, 49 insertions, 0 deletions
diff --git a/arch/arm64/kvm/hyp/hyp.h b/arch/arm64/kvm/hyp/hyp.h
index 778d56d41f9b..bffd30834eb8 100644
--- a/arch/arm64/kvm/hyp/hyp.h
+++ b/arch/arm64/kvm/hyp/hyp.h
@@ -40,6 +40,8 @@ void __timer_restore_state(struct kvm_vcpu *vcpu);
40 40
41void __sysreg_save_state(struct kvm_cpu_context *ctxt); 41void __sysreg_save_state(struct kvm_cpu_context *ctxt);
42void __sysreg_restore_state(struct kvm_cpu_context *ctxt); 42void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
43void __sysreg32_save_state(struct kvm_vcpu *vcpu);
44void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
43 45
44#endif /* __ARM64_KVM_HYP_H__ */ 46#endif /* __ARM64_KVM_HYP_H__ */
45 47
diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
index add8fcb6516f..eb05afb77ee8 100644
--- a/arch/arm64/kvm/hyp/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/sysreg-sr.c
@@ -88,3 +88,50 @@ void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
88 write_sysreg(ctxt->gp_regs.elr_el1, elr_el1); 88 write_sysreg(ctxt->gp_regs.elr_el1, elr_el1);
89 write_sysreg(ctxt->gp_regs.spsr[KVM_SPSR_EL1], spsr_el1); 89 write_sysreg(ctxt->gp_regs.spsr[KVM_SPSR_EL1], spsr_el1);
90} 90}
91
92void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
93{
94 u64 *spsr, *sysreg;
95
96 if (read_sysreg(hcr_el2) & HCR_RW)
97 return;
98
99 spsr = vcpu->arch.ctxt.gp_regs.spsr;
100 sysreg = vcpu->arch.ctxt.sys_regs;
101
102 spsr[KVM_SPSR_ABT] = read_sysreg(spsr_abt);
103 spsr[KVM_SPSR_UND] = read_sysreg(spsr_und);
104 spsr[KVM_SPSR_IRQ] = read_sysreg(spsr_irq);
105 spsr[KVM_SPSR_FIQ] = read_sysreg(spsr_fiq);
106
107 sysreg[DACR32_EL2] = read_sysreg(dacr32_el2);
108 sysreg[IFSR32_EL2] = read_sysreg(ifsr32_el2);
109
110 if (!(read_sysreg(cptr_el2) & CPTR_EL2_TFP))
111 sysreg[FPEXC32_EL2] = read_sysreg(fpexc32_el2);
112
113 if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
114 sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2);
115}
116
117void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu)
118{
119 u64 *spsr, *sysreg;
120
121 if (read_sysreg(hcr_el2) & HCR_RW)
122 return;
123
124 spsr = vcpu->arch.ctxt.gp_regs.spsr;
125 sysreg = vcpu->arch.ctxt.sys_regs;
126
127 write_sysreg(spsr[KVM_SPSR_ABT], spsr_abt);
128 write_sysreg(spsr[KVM_SPSR_UND], spsr_und);
129 write_sysreg(spsr[KVM_SPSR_IRQ], spsr_irq);
130 write_sysreg(spsr[KVM_SPSR_FIQ], spsr_fiq);
131
132 write_sysreg(sysreg[DACR32_EL2], dacr32_el2);
133 write_sysreg(sysreg[IFSR32_EL2], ifsr32_el2);
134
135 if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
136 write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2);
137}