From nobody Tue Dec 30 15:00:05 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02D11C47072 for ; Wed, 15 Nov 2023 09:32:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234802AbjKOJc2 (ORCPT ); Wed, 15 Nov 2023 04:32:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234793AbjKOJc0 (ORCPT ); Wed, 15 Nov 2023 04:32:26 -0500 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 68F39116; Wed, 15 Nov 2023 01:32:22 -0800 (PST) Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8BxXeskkFRlZTw6AA--.44269S3; Wed, 15 Nov 2023 17:32:20 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Bx7twhkFRlq99CAA--.16093S4; Wed, 15 Nov 2023 17:32:19 +0800 (CST) From: Tianrui Zhao To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Paolo Bonzini , Huacai Chen , WANG Xuerui , Greg Kroah-Hartman , loongarch@lists.linux.dev, Jens Axboe , Mark Brown , Alex Deucher , Oliver Upton , maobibo@loongson.cn, Xi Ruoyao , zhaotianrui@loongson.cn Subject: [PATCH v1 2/2] LoongArch: KVM: Add lasx support Date: Wed, 15 Nov 2023 17:19:21 +0800 Message-Id: <20231115091921.85516-3-zhaotianrui@loongson.cn> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20231115091921.85516-1-zhaotianrui@loongson.cn> References: <20231115091921.85516-1-zhaotianrui@loongson.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8Bx7twhkFRlq99CAA--.16093S4 X-CM-SenderInfo: p2kd03xldq233l6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This patch adds LASX support for LoongArch KVM. The LASX means=20 LoongArch 256-bits vector instruction.=20 There will be LASX exception in KVM when guest use the LASX=20 instruction. KVM will enable LASX and restore the vector=20 registers for guest then return to guest to continue running. Signed-off-by: Tianrui Zhao --- arch/loongarch/include/asm/kvm_host.h | 6 ++++ arch/loongarch/include/asm/kvm_vcpu.h | 10 +++++++ arch/loongarch/kernel/fpu.S | 1 + arch/loongarch/kvm/exit.c | 18 +++++++++++ arch/loongarch/kvm/switch.S | 16 ++++++++++ arch/loongarch/kvm/trace.h | 4 ++- arch/loongarch/kvm/vcpu.c | 43 ++++++++++++++++++++++++++- 7 files changed, 96 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include= /asm/kvm_host.h index 6c65c25169..4c05b5eca0 100644 --- a/arch/loongarch/include/asm/kvm_host.h +++ b/arch/loongarch/include/asm/kvm_host.h @@ -95,6 +95,7 @@ enum emulation_result { #define KVM_LARCH_SWCSR_LATEST (0x1 << 1) #define KVM_LARCH_HWCSR_USABLE (0x1 << 2) #define KVM_LARCH_LSX (0x1 << 3) +#define KVM_LARCH_LASX (0x1 << 4) =20 struct kvm_vcpu_arch { /* @@ -181,6 +182,11 @@ static inline bool kvm_guest_has_lsx(struct kvm_vcpu_a= rch *arch) return arch->cpucfg[2] & CPUCFG2_LSX; } =20 +static inline bool kvm_guest_has_lasx(struct kvm_vcpu_arch *arch) +{ + return arch->cpucfg[2] & CPUCFG2_LASX; +} + /* Debug: dump vcpu state */ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu); =20 diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include= /asm/kvm_vcpu.h index c629771e12..4f87f16018 100644 --- a/arch/loongarch/include/asm/kvm_vcpu.h +++ b/arch/loongarch/include/asm/kvm_vcpu.h @@ -67,6 +67,16 @@ static inline void kvm_restore_lsx(struct loongarch_fpu = *fpu) { } static inline void kvm_restore_lsx_upper(struct loongarch_fpu *fpu) { } #endif =20 +#ifdef CONFIG_CPU_HAS_LASX +void kvm_own_lasx(struct kvm_vcpu *vcpu); +void kvm_save_lasx(struct loongarch_fpu *fpu); +void kvm_restore_lasx(struct loongarch_fpu *fpu); +#else +static inline void kvm_own_lasx(struct kvm_vcpu *vcpu) { } +static inline void kvm_save_lasx(struct loongarch_fpu *fpu) { } +static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { } +#endif + void kvm_acquire_timer(struct kvm_vcpu *vcpu); void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz); void kvm_reset_timer(struct kvm_vcpu *vcpu); diff --git a/arch/loongarch/kernel/fpu.S b/arch/loongarch/kernel/fpu.S index d53ab10f46..f4524fe866 100644 --- a/arch/loongarch/kernel/fpu.S +++ b/arch/loongarch/kernel/fpu.S @@ -384,6 +384,7 @@ SYM_FUNC_START(_restore_lasx_upper) lasx_restore_all_upper a0 t0 t1 jr ra SYM_FUNC_END(_restore_lasx_upper) +EXPORT_SYMBOL(_restore_lasx_upper) =20 SYM_FUNC_START(_init_lasx_upper) lasx_init_all_upper t1 diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index 1b1c58ccc8..57bd5bf562 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -676,6 +676,23 @@ static int kvm_handle_lsx_disabled(struct kvm_vcpu *vc= pu) return RESUME_GUEST; } =20 +/* + * kvm_handle_lasx_disabled() - Guest used LASX while disabled in root. + * @vcpu: Virtual CPU context. + * + * Handle when the guest attempts to use LASX when it is disabled in the r= oot + * context. + */ +static int kvm_handle_lasx_disabled(struct kvm_vcpu *vcpu) +{ + if (!kvm_guest_has_lasx(&vcpu->arch)) + kvm_queue_exception(vcpu, EXCCODE_INE, 0); + else + kvm_own_lasx(vcpu); + + return RESUME_GUEST; +} + /* * LoongArch KVM callback handling for unimplemented guest exiting */ @@ -705,6 +722,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_STAR= T] =3D { [EXCCODE_TLBM] =3D kvm_handle_write_fault, [EXCCODE_FPDIS] =3D kvm_handle_fpu_disabled, [EXCCODE_LSXDIS] =3D kvm_handle_lsx_disabled, + [EXCCODE_LASXDIS] =3D kvm_handle_lasx_disabled, [EXCCODE_GSPR] =3D kvm_handle_gspr, }; =20 diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S index 32ba092a44..a129f8e82c 100644 --- a/arch/loongarch/kvm/switch.S +++ b/arch/loongarch/kvm/switch.S @@ -267,6 +267,22 @@ SYM_FUNC_START(kvm_restore_lsx_upper) SYM_FUNC_END(kvm_restore_lsx_upper) #endif =20 +#ifdef CONFIG_CPU_HAS_LASX +SYM_FUNC_START(kvm_save_lasx) + fpu_save_csr a0 t1 + fpu_save_cc a0 t1 t2 + lasx_save_data a0 t1 + + jirl zero, ra, 0 +SYM_FUNC_END(kvm_save_lasx) + +SYM_FUNC_START(kvm_restore_lasx) + lasx_restore_data a0 t1 + fpu_restore_cc a0 t1 t2 + fpu_restore_csr a0 t1 + jirl zero, ra, 0 +SYM_FUNC_END(kvm_restore_lasx) +#endif .section ".rodata" SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry) SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest) diff --git a/arch/loongarch/kvm/trace.h b/arch/loongarch/kvm/trace.h index 7da4e230e8..c2484ad4cf 100644 --- a/arch/loongarch/kvm/trace.h +++ b/arch/loongarch/kvm/trace.h @@ -103,6 +103,7 @@ TRACE_EVENT(kvm_exit_gspr, =20 #define KVM_TRACE_AUX_FPU 1 #define KVM_TRACE_AUX_LSX 2 +#define KVM_TRACE_AUX_LASX 3 =20 #define kvm_trace_symbol_aux_op \ { KVM_TRACE_AUX_SAVE, "save" }, \ @@ -113,7 +114,8 @@ TRACE_EVENT(kvm_exit_gspr, =20 #define kvm_trace_symbol_aux_state \ { KVM_TRACE_AUX_FPU, "FPU" }, \ - { KVM_TRACE_AUX_LSX, "LSX" } + { KVM_TRACE_AUX_LSX, "LSX" }, \ + { KVM_TRACE_AUX_LASX, "LASX" } =20 TRACE_EVENT(kvm_aux, TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op, diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index f0bb583353..204654a359 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -384,6 +384,10 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, vcpu->arch.cpucfg[id] &=3D ~CPUCFG2_LSX; ret =3D -EINVAL; } + if (id =3D=3D 2 && v & CPUCFG2_LASX && !cpu_has_lasx) { + vcpu->arch.cpucfg[id] &=3D ~CPUCFG2_LASX; + ret =3D -EINVAL; + } } else ret =3D -EINVAL; break; @@ -595,12 +599,49 @@ void kvm_own_lsx(struct kvm_vcpu *vcpu) } #endif =20 +#ifdef CONFIG_CPU_HAS_LASX +/* Enable LASX for guest and restore context */ +void kvm_own_lasx(struct kvm_vcpu *vcpu) +{ + preempt_disable(); + + set_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN); + switch (vcpu->arch.aux_inuse & (KVM_LARCH_FPU | KVM_LARCH_LSX)) { + case KVM_LARCH_LSX | KVM_LARCH_FPU: + case KVM_LARCH_LSX: + /* Guest LSX state already loaded, only restore upper LASX state */ + _restore_lasx_upper(&vcpu->arch.fpu); + break; + case KVM_LARCH_FPU: + /* Guest FP state already loaded, only restore 64~256 LASX state */ + kvm_restore_lsx_upper(&vcpu->arch.fpu); + _restore_lasx_upper(&vcpu->arch.fpu); + break; + default: + /* Neither FP or LSX already active, restore full LASX state */ + kvm_restore_lasx(&vcpu->arch.fpu); + break; + } + + trace_kvm_aux(vcpu, KVM_TRACE_AUX_RESTORE, KVM_TRACE_AUX_LASX); + vcpu->arch.aux_inuse |=3D KVM_LARCH_LASX | KVM_LARCH_LSX | KVM_LARCH_FPU; + preempt_enable(); +} +#endif + /* Save context and disable FPU */ void kvm_lose_fpu(struct kvm_vcpu *vcpu) { preempt_disable(); =20 - if (vcpu->arch.aux_inuse & KVM_LARCH_LSX) { + if (vcpu->arch.aux_inuse & KVM_LARCH_LASX) { + kvm_save_lasx(&vcpu->arch.fpu); + vcpu->arch.aux_inuse &=3D ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LA= SX); + trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LASX); + + /* Disable LASX & LSX & FPU */ + clear_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN); + } else if (vcpu->arch.aux_inuse & KVM_LARCH_LSX) { kvm_save_lsx(&vcpu->arch.fpu); vcpu->arch.aux_inuse &=3D ~(KVM_LARCH_LSX | KVM_LARCH_FPU); trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LSX); --=20 2.39.1