fpsimd.c (6e2b347d42e54282e4c6cfa08272db462b178f7f) fpsimd.c (e9ada6c208c15c907afe5afb1aa82e23e81eb8ba)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * arch/arm64/kvm/fpsimd.c: Guest/host FPSIMD context coordination helpers
4 *
5 * Copyright 2018 Arm Limited
6 * Author: Dave Martin <Dave.Martin@arm.com>
7 */
8#include <linux/irqflags.h>

--- 66 unchanged lines hidden (view full) ---

75void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
76{
77 BUG_ON(!current->mm);
78 BUG_ON(test_thread_flag(TIF_SVE));
79
80 vcpu->arch.flags &= ~KVM_ARM64_FP_ENABLED;
81 vcpu->arch.flags |= KVM_ARM64_FP_HOST;
82
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * arch/arm64/kvm/fpsimd.c: Guest/host FPSIMD context coordination helpers
4 *
5 * Copyright 2018 Arm Limited
6 * Author: Dave Martin <Dave.Martin@arm.com>
7 */
8#include <linux/irqflags.h>

--- 66 unchanged lines hidden (view full) ---

75void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
76{
77 BUG_ON(!current->mm);
78 BUG_ON(test_thread_flag(TIF_SVE));
79
80 vcpu->arch.flags &= ~KVM_ARM64_FP_ENABLED;
81 vcpu->arch.flags |= KVM_ARM64_FP_HOST;
82
83 vcpu->arch.flags &= ~KVM_ARM64_HOST_SVE_ENABLED;
83 if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
84 vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
85
86 /*
87 * We don't currently support SME guests but if we leave
88 * things in streaming mode then when the guest starts running
89 * FPSIMD or SVE code it may generate SME traps so as a
90 * special case if we are in streaming mode we force the host
91 * state to be saved now and exit streaming mode so that we
92 * don't have to handle any SME traps for valid guest
93 * operations. Do this for ZA as well for now for simplicity.
94 */
95 if (system_supports_sme()) {
84 if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
85 vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
86
87 /*
88 * We don't currently support SME guests but if we leave
89 * things in streaming mode then when the guest starts running
90 * FPSIMD or SVE code it may generate SME traps so as a
91 * special case if we are in streaming mode we force the host
92 * state to be saved now and exit streaming mode so that we
93 * don't have to handle any SME traps for valid guest
94 * operations. Do this for ZA as well for now for simplicity.
95 */
96 if (system_supports_sme()) {
97 vcpu->arch.flags &= ~KVM_ARM64_HOST_SME_ENABLED;
96 if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
97 vcpu->arch.flags |= KVM_ARM64_HOST_SME_ENABLED;
98
99 if (read_sysreg_s(SYS_SVCR) &
100 (SVCR_SM_MASK | SVCR_ZA_MASK)) {
101 vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
102 fpsimd_save_and_flush_cpu_state();
103 }
104 }
105}
106
107/*
98 if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
99 vcpu->arch.flags |= KVM_ARM64_HOST_SME_ENABLED;
100
101 if (read_sysreg_s(SYS_SVCR) &
102 (SVCR_SM_MASK | SVCR_ZA_MASK)) {
103 vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
104 fpsimd_save_and_flush_cpu_state();
105 }
106 }
107}
108
109/*
108 * Called just before entering the guest once we are no longer
109 * preemptable. Syncs the host's TIF_FOREIGN_FPSTATE with the KVM
110 * mirror of the flag used by the hypervisor.
110 * Called just before entering the guest once we are no longer preemptable
111 * and interrupts are disabled. If we have managed to run anything using
112 * FP while we were preemptible (such as off the back of an interrupt),
113 * then neither the host nor the guest own the FP hardware (and it was the
114 * responsibility of the code that used FP to save the existing state).
115 *
116 * Note that not supporting FP is basically the same thing as far as the
117 * hypervisor is concerned (nothing to save).
111 */
112void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu)
113{
118 */
119void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu)
120{
114 if (test_thread_flag(TIF_FOREIGN_FPSTATE))
115 vcpu->arch.flags |= KVM_ARM64_FP_FOREIGN_FPSTATE;
116 else
117 vcpu->arch.flags &= ~KVM_ARM64_FP_FOREIGN_FPSTATE;
121 if (!system_supports_fpsimd() || test_thread_flag(TIF_FOREIGN_FPSTATE))
122 vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_FP_HOST);
118}
119
120/*
121 * Called just after exiting the guest. If the guest FPSIMD state
122 * was loaded, update the host's context tracking data mark the CPU
123 * FPSIMD regs as dirty and belonging to vcpu so that they will be
124 * written back if the kernel clobbers them due to kernel-mode NEON
125 * before re-entry into the guest.

--- 77 unchanged lines hidden ---
123}
124
125/*
126 * Called just after exiting the guest. If the guest FPSIMD state
127 * was loaded, update the host's context tracking data mark the CPU
128 * FPSIMD regs as dirty and belonging to vcpu so that they will be
129 * written back if the kernel clobbers them due to kernel-mode NEON
130 * before re-entry into the guest.

--- 77 unchanged lines hidden ---