Commit 065a7b60 authored by Tianrui Zhao's avatar Tianrui Zhao Committed by Xianglai Li
Browse files

LoongArch: KVM: Add LASX (256bit SIMD) support

mainline inclusion
from mainline-v6.8-rc1
commit 118e10cd893d57df55b3302dfd188a981b6e6d1c
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I94LRF


CVE: NA

--------------------------------

This patch adds LASX (256bit SIMD) support for LoongArch KVM.

There will be LASX exception in KVM when guest use the LASX instructions.
KVM will enable LASX and restore the vector registers for guest and then
return to guest to continue running.

Reviewed-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarTianrui Zhao <zhaotianrui@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
Signed-off-by: default avatarXianglai Li <lixianglai@loongson.cn>
parent 9f93e466
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -96,8 +96,9 @@ enum emulation_result {

#define KVM_LARCH_FPU		(0x1 << 0)
#define KVM_LARCH_LSX		(0x1 << 1)
#define KVM_LARCH_SWCSR_LATEST	(0x1 << 2)
#define KVM_LARCH_HWCSR_USABLE	(0x1 << 3)
#define KVM_LARCH_LASX		(0x1 << 2)
#define KVM_LARCH_SWCSR_LATEST	(0x1 << 3)
#define KVM_LARCH_HWCSR_USABLE	(0x1 << 4)

struct kvm_vcpu_arch {
	/*
@@ -189,6 +190,11 @@ static inline bool kvm_guest_has_lsx(struct kvm_vcpu_arch *arch)
	return arch->cpucfg[2] & CPUCFG2_LSX;
}

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);

+10 −0
Original line number Diff line number Diff line
@@ -65,6 +65,16 @@ static inline void kvm_save_lsx(struct loongarch_fpu *fpu) { }
static inline void kvm_restore_lsx(struct loongarch_fpu *fpu) { }
#endif

#ifdef CONFIG_CPU_HAS_LASX
int 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 int 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_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);
void kvm_reset_timer(struct kvm_vcpu *vcpu);
void kvm_save_timer(struct kvm_vcpu *vcpu);
+1 −0
Original line number Diff line number Diff line
@@ -385,6 +385,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)

SYM_FUNC_START(_init_lasx_upper)
	lasx_init_all_upper t1
+16 −0
Original line number Diff line number Diff line
@@ -670,6 +670,21 @@ static int kvm_handle_lsx_disabled(struct kvm_vcpu *vcpu)
	return RESUME_GUEST;
}

/*
 * 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 root
 * context.
 */
static int kvm_handle_lasx_disabled(struct kvm_vcpu *vcpu)
{
	if (kvm_own_lasx(vcpu))
		kvm_queue_exception(vcpu, EXCCODE_INE, 0);

	return RESUME_GUEST;
}

/*
 * LoongArch KVM callback handling for unimplemented guest exiting
 */
@@ -699,6 +714,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = {
	[EXCCODE_TLBM]			= kvm_handle_write_fault,
	[EXCCODE_FPDIS]			= kvm_handle_fpu_disabled,
	[EXCCODE_LSXDIS]		= kvm_handle_lsx_disabled,
	[EXCCODE_LASXDIS]		= kvm_handle_lasx_disabled,
	[EXCCODE_GSPR]			= kvm_handle_gspr,
};

+15 −0
Original line number Diff line number Diff line
@@ -261,6 +261,21 @@ SYM_FUNC_START(kvm_restore_lsx)
SYM_FUNC_END(kvm_restore_lsx)
#endif

#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
	jr              ra
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 t2
	jr                ra
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)
Loading