Skip to content

Commit db1ecca

Browse files
zhaotianrui-loongsonchenhuacai
authored andcommitted
LoongArch: KVM: Add LSX (128bit SIMD) support
This patch adds LSX (128bit SIMD) support for LoongArch KVM. There will be LSX exception in KVM when guest use the LSX instructions. KVM will enable LSX and restore the vector registers for guest and then return to guest to continue running. Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 5b3d524 commit db1ecca

8 files changed

Lines changed: 280 additions & 8 deletions

File tree

arch/loongarch/include/asm/kvm_host.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ enum emulation_result {
9595
};
9696

9797
#define KVM_LARCH_FPU (0x1 << 0)
98-
#define KVM_LARCH_SWCSR_LATEST (0x1 << 1)
99-
#define KVM_LARCH_HWCSR_USABLE (0x1 << 2)
98+
#define KVM_LARCH_LSX (0x1 << 1)
99+
#define KVM_LARCH_SWCSR_LATEST (0x1 << 2)
100+
#define KVM_LARCH_HWCSR_USABLE (0x1 << 3)
100101

101102
struct kvm_vcpu_arch {
102103
/*
@@ -178,6 +179,16 @@ static inline void writel_sw_gcsr(struct loongarch_csrs *csr, int reg, unsigned
178179
csr->csrs[reg] = val;
179180
}
180181

182+
static inline bool kvm_guest_has_fpu(struct kvm_vcpu_arch *arch)
183+
{
184+
return arch->cpucfg[2] & CPUCFG2_FP;
185+
}
186+
187+
static inline bool kvm_guest_has_lsx(struct kvm_vcpu_arch *arch)
188+
{
189+
return arch->cpucfg[2] & CPUCFG2_LSX;
190+
}
191+
181192
/* Debug: dump vcpu state */
182193
int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
183194

arch/loongarch/include/asm/kvm_vcpu.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ void kvm_save_fpu(struct loongarch_fpu *fpu);
5555
void kvm_restore_fpu(struct loongarch_fpu *fpu);
5656
void kvm_restore_fcsr(struct loongarch_fpu *fpu);
5757

58+
#ifdef CONFIG_CPU_HAS_LSX
59+
int kvm_own_lsx(struct kvm_vcpu *vcpu);
60+
void kvm_save_lsx(struct loongarch_fpu *fpu);
61+
void kvm_restore_lsx(struct loongarch_fpu *fpu);
62+
#else
63+
static inline int kvm_own_lsx(struct kvm_vcpu *vcpu) { }
64+
static inline void kvm_save_lsx(struct loongarch_fpu *fpu) { }
65+
static inline void kvm_restore_lsx(struct loongarch_fpu *fpu) { }
66+
#endif
67+
5868
void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);
5969
void kvm_reset_timer(struct kvm_vcpu *vcpu);
6070
void kvm_save_timer(struct kvm_vcpu *vcpu);

arch/loongarch/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct kvm_fpu {
7979
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
8080
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
8181
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)
82+
#define KVM_LOONGARCH_VCPU_CPUCFG 0
8283

8384
struct kvm_debug_exit_arch {
8485
};

arch/loongarch/kernel/fpu.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ SYM_FUNC_START(_restore_lsx_upper)
349349
lsx_restore_all_upper a0 t0 t1
350350
jr ra
351351
SYM_FUNC_END(_restore_lsx_upper)
352+
EXPORT_SYMBOL(_restore_lsx_upper)
352353

353354
SYM_FUNC_START(_init_lsx_upper)
354355
lsx_init_all_upper t1

arch/loongarch/kvm/exit.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,11 @@ static int kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
634634
{
635635
struct kvm_run *run = vcpu->run;
636636

637+
if (!kvm_guest_has_fpu(&vcpu->arch)) {
638+
kvm_queue_exception(vcpu, EXCCODE_INE, 0);
639+
return RESUME_GUEST;
640+
}
641+
637642
/*
638643
* If guest FPU not present, the FPU operation should have been
639644
* treated as a reserved instruction!
@@ -650,6 +655,21 @@ static int kvm_handle_fpu_disabled(struct kvm_vcpu *vcpu)
650655
return RESUME_GUEST;
651656
}
652657

658+
/*
659+
* kvm_handle_lsx_disabled() - Guest used LSX while disabled in root.
660+
* @vcpu: Virtual CPU context.
661+
*
662+
* Handle when the guest attempts to use LSX when it is disabled in the root
663+
* context.
664+
*/
665+
static int kvm_handle_lsx_disabled(struct kvm_vcpu *vcpu)
666+
{
667+
if (kvm_own_lsx(vcpu))
668+
kvm_queue_exception(vcpu, EXCCODE_INE, 0);
669+
670+
return RESUME_GUEST;
671+
}
672+
653673
/*
654674
* LoongArch KVM callback handling for unimplemented guest exiting
655675
*/
@@ -678,6 +698,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = {
678698
[EXCCODE_TLBS] = kvm_handle_write_fault,
679699
[EXCCODE_TLBM] = kvm_handle_write_fault,
680700
[EXCCODE_FPDIS] = kvm_handle_fpu_disabled,
701+
[EXCCODE_LSXDIS] = kvm_handle_lsx_disabled,
681702
[EXCCODE_GSPR] = kvm_handle_gspr,
682703
};
683704

arch/loongarch/kvm/switch.S

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,22 @@ SYM_FUNC_START(kvm_restore_fpu)
245245
jr ra
246246
SYM_FUNC_END(kvm_restore_fpu)
247247

248+
#ifdef CONFIG_CPU_HAS_LSX
249+
SYM_FUNC_START(kvm_save_lsx)
250+
fpu_save_csr a0 t1
251+
fpu_save_cc a0 t1 t2
252+
lsx_save_data a0 t1
253+
jr ra
254+
SYM_FUNC_END(kvm_save_lsx)
255+
256+
SYM_FUNC_START(kvm_restore_lsx)
257+
lsx_restore_data a0 t1
258+
fpu_restore_cc a0 t1 t2
259+
fpu_restore_csr a0 t1 t2
260+
jr ra
261+
SYM_FUNC_END(kvm_restore_lsx)
262+
#endif
263+
248264
.section ".rodata"
249265
SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
250266
SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)

arch/loongarch/kvm/trace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ TRACE_EVENT(kvm_exit_gspr,
102102
#define KVM_TRACE_AUX_DISCARD 4
103103

104104
#define KVM_TRACE_AUX_FPU 1
105+
#define KVM_TRACE_AUX_LSX 2
105106

106107
#define kvm_trace_symbol_aux_op \
107108
{ KVM_TRACE_AUX_SAVE, "save" }, \
@@ -111,7 +112,8 @@ TRACE_EVENT(kvm_exit_gspr,
111112
{ KVM_TRACE_AUX_DISCARD, "discard" }
112113

113114
#define kvm_trace_symbol_aux_state \
114-
{ KVM_TRACE_AUX_FPU, "FPU" }
115+
{ KVM_TRACE_AUX_FPU, "FPU" }, \
116+
{ KVM_TRACE_AUX_LSX, "LSX" }
115117

116118
TRACE_EVENT(kvm_aux,
117119
TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op,

0 commit comments

Comments
 (0)