diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2015-10-19 14:28:29 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2015-12-14 06:30:40 -0500 |
commit | c209ec85a2a7d2fd38bca0a44b7e70abd079c178 (patch) | |
tree | 04a66f17cee2f78c6d497466c8bb136380193ee5 | |
parent | 6d6ec20fcf2830ca10c1b7c8efd7e2592c40e3d6 (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.h | 2 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/sysreg-sr.c | 47 |
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 | ||
41 | void __sysreg_save_state(struct kvm_cpu_context *ctxt); | 41 | void __sysreg_save_state(struct kvm_cpu_context *ctxt); |
42 | void __sysreg_restore_state(struct kvm_cpu_context *ctxt); | 42 | void __sysreg_restore_state(struct kvm_cpu_context *ctxt); |
43 | void __sysreg32_save_state(struct kvm_vcpu *vcpu); | ||
44 | void __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 | |||
92 | void __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 | |||
117 | void __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 | } | ||