diff options
author | Dave Martin <Dave.Martin@arm.com> | 2018-05-02 14:18:02 +0100 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2018-05-25 12:28:31 +0100 |
commit | cf412b0070221032c02c4564cd11dc83238b2ad2 (patch) | |
tree | 7f5f01f1ab575c0bae10eaddee73e93447413850 /arch/arm64/kvm/hyp/switch.c | |
parent | 7846b3119e24fe8d726535d6aa7489253797700c (diff) | |
download | linux-cf412b0070221032c02c4564cd11dc83238b2ad2.tar.bz2 |
KVM: arm64: Invoke FPSIMD context switch trap from C
The conversion of the FPSIMD context switch trap code to C has added
some overhead to calling it, due to the need to save registers that
the procedure call standard defines as caller-saved.
So, perhaps it is no longer worth invoking this trap handler quite
so early.
Instead, we can invoke it from fixup_guest_exit(), with little
likelihood of increasing the overhead much further.
As a convenience, this patch gives __hyp_switch_fpsimd() the same
return semantics fixup_guest_exit(). For now there is no
possibility of a spurious FPSIMD trap, so the function always
returns true, but this allows it to be tail-called with a single
return statement.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64/kvm/hyp/switch.c')
-rw-r--r-- | arch/arm64/kvm/hyp/switch.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 4fbee9502162..2d45bd719a5d 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -328,8 +328,7 @@ static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu) } } -void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused, - struct kvm_vcpu *vcpu) +static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu) { struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state; @@ -369,6 +368,8 @@ void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused, fpexc32_el2); vcpu->arch.flags |= KVM_ARM64_FP_ENABLED; + + return true; } /* @@ -390,6 +391,16 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) if (*exit_code != ARM_EXCEPTION_TRAP) goto exit; + /* + * We trap the first access to the FP/SIMD to save the host context + * and restore the guest context lazily. + * If FP/SIMD is not implemented, handle the trap and inject an + * undefined instruction exception to the guest. + */ + if (system_supports_fpsimd() && + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD) + return __hyp_switch_fpsimd(vcpu); + if (!__populate_fault_info(vcpu)) return true; |