History

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

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.

Tianrui Zhao committed 2 years ago

Commit 118e10c1 parent db1ecca7 files · +103 −4Browse files

Unified · Split

7 files
  1. arch/loongarch/include/asm/kvm_host.h +8 −2
  2. arch/loongarch/include/asm/kvm_vcpu.h +10 −0
  3. arch/loongarch/kernel/fpu.S +1 −0
  4. arch/loongarch/kvm/exit.c +16 −0
  5. arch/loongarch/kvm/switch.S +15 −0
  6. arch/loongarch/kvm/trace.h +3 −1
  7. arch/loongarch/kvm/vcpu.c +50 −1
arch/loongarch/include/asm/kvm_host.h+8−2
@@ -96,8 +96,9 @@ enum emulation_result { · 95 unmodified lines
96 96
97#define KVM_LARCH_FPU (0x1 << 0)97#define KVM_LARCH_FPU (0x1 << 0)
98#define KVM_LARCH_LSX (0x1 << 1)98#define KVM_LARCH_LSX (0x1 << 1)
99#define KVM_LARCH_SWCSR_LATEST (0x1 << 2)99#define KVM_LARCH_LASX (0x1 << 2)
100#define KVM_LARCH_HWCSR_USABLE (0x1 << 3)100#define KVM_LARCH_SWCSR_LATEST (0x1 << 3)
101#define KVM_LARCH_HWCSR_USABLE (0x1 << 4)
101 102
102struct kvm_vcpu_arch {103struct kvm_vcpu_arch {
103 /*104 /*
@@ -189,6 +190,11 @@ static inline bool kvm_guest_has_lsx(struct kvm_vcpu_arch *arch) · 85 unmodified lines
189 return arch->cpucfg[2] & CPUCFG2_LSX;190 return arch->cpucfg[2] & CPUCFG2_LSX;
190}191}
191 192
193static inline bool kvm_guest_has_lasx(struct kvm_vcpu_arch *arch)
194{
195 return arch->cpucfg[2] & CPUCFG2_LASX;
196}
197
192/* Debug: dump vcpu state */198/* Debug: dump vcpu state */
193int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);199int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);
194 200
arch/loongarch/include/asm/kvm_vcpu.h+10−0
@@ -65,6 +65,16 @@ static inline void kvm_save_lsx(struct loongarch_fpu *fpu) { } · 64 unmodified lines
65static inline void kvm_restore_lsx(struct loongarch_fpu *fpu) { }65static inline void kvm_restore_lsx(struct loongarch_fpu *fpu) { }
66#endif66#endif
67 67
68#ifdef CONFIG_CPU_HAS_LASX
69int kvm_own_lasx(struct kvm_vcpu *vcpu);
70void kvm_save_lasx(struct loongarch_fpu *fpu);
71void kvm_restore_lasx(struct loongarch_fpu *fpu);
72#else
73static inline int kvm_own_lasx(struct kvm_vcpu *vcpu) { }
74static inline void kvm_save_lasx(struct loongarch_fpu *fpu) { }
75static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { }
76#endif
77
68void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);78void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);
69void kvm_reset_timer(struct kvm_vcpu *vcpu);79void kvm_reset_timer(struct kvm_vcpu *vcpu);
70void kvm_save_timer(struct kvm_vcpu *vcpu);80void kvm_save_timer(struct kvm_vcpu *vcpu);
arch/loongarch/kernel/fpu.S+1−0
@@ -385,6 +385,7 @@ SYM_FUNC_START(_restore_lasx_upper) · 384 unmodified lines
385 lasx_restore_all_upper a0 t0 t1385 lasx_restore_all_upper a0 t0 t1
386 jr ra386 jr ra
387SYM_FUNC_END(_restore_lasx_upper)387SYM_FUNC_END(_restore_lasx_upper)
388EXPORT_SYMBOL(_restore_lasx_upper)
388 389
389SYM_FUNC_START(_init_lasx_upper)390SYM_FUNC_START(_init_lasx_upper)
390 lasx_init_all_upper t1391 lasx_init_all_upper t1
arch/loongarch/kvm/exit.c+16−0
@@ -670,6 +670,21 @@ static int kvm_handle_lsx_disabled(struct kvm_vcpu *vcpu) · 669 unmodified lines
670 return RESUME_GUEST;670 return RESUME_GUEST;
671}671}
672 672
673/*
674 * kvm_handle_lasx_disabled() - Guest used LASX while disabled in root.
675 * @vcpu: Virtual CPU context.
676 *
677 * Handle when the guest attempts to use LASX when it is disabled in the root
678 * context.
679 */
680static int kvm_handle_lasx_disabled(struct kvm_vcpu *vcpu)
681{
682 if (kvm_own_lasx(vcpu))
683 kvm_queue_exception(vcpu, EXCCODE_INE, 0);
684
685 return RESUME_GUEST;
686}
687
673/*688/*
674 * LoongArch KVM callback handling for unimplemented guest exiting689 * LoongArch KVM callback handling for unimplemented guest exiting
675 */690 */
@@ -699,6 +714,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = { · 23 unmodified lines
699 [EXCCODE_TLBM] = kvm_handle_write_fault,714 [EXCCODE_TLBM] = kvm_handle_write_fault,
700 [EXCCODE_FPDIS] = kvm_handle_fpu_disabled,715 [EXCCODE_FPDIS] = kvm_handle_fpu_disabled,
701 [EXCCODE_LSXDIS] = kvm_handle_lsx_disabled,716 [EXCCODE_LSXDIS] = kvm_handle_lsx_disabled,
717 [EXCCODE_LASXDIS] = kvm_handle_lasx_disabled,
702 [EXCCODE_GSPR] = kvm_handle_gspr,718 [EXCCODE_GSPR] = kvm_handle_gspr,
703};719};
704 720
arch/loongarch/kvm/switch.S+15−0
@@ -261,6 +261,21 @@ SYM_FUNC_START(kvm_restore_lsx) · 260 unmodified lines
261SYM_FUNC_END(kvm_restore_lsx)261SYM_FUNC_END(kvm_restore_lsx)
262#endif262#endif
263 263
264#ifdef CONFIG_CPU_HAS_LASX
265SYM_FUNC_START(kvm_save_lasx)
266 fpu_save_csr a0 t1
267 fpu_save_cc a0 t1 t2
268 lasx_save_data a0 t1
269 jr ra
270SYM_FUNC_END(kvm_save_lasx)
271
272SYM_FUNC_START(kvm_restore_lasx)
273 lasx_restore_data a0 t1
274 fpu_restore_cc a0 t1 t2
275 fpu_restore_csr a0 t1 t2
276 jr ra
277SYM_FUNC_END(kvm_restore_lasx)
278#endif
264 .section ".rodata"279 .section ".rodata"
265SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)280SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
266SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)281SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
arch/loongarch/kvm/trace.h+3−1
@@ -103,6 +103,7 @@ TRACE_EVENT(kvm_exit_gspr, · 102 unmodified lines
103 103
104#define KVM_TRACE_AUX_FPU 1104#define KVM_TRACE_AUX_FPU 1
105#define KVM_TRACE_AUX_LSX 2105#define KVM_TRACE_AUX_LSX 2
106#define KVM_TRACE_AUX_LASX 3
106 107
107#define kvm_trace_symbol_aux_op \108#define kvm_trace_symbol_aux_op \
108 { KVM_TRACE_AUX_SAVE, "save" }, \109 { KVM_TRACE_AUX_SAVE, "save" }, \
@@ -113,7 +114,8 @@ TRACE_EVENT(kvm_exit_gspr, · 4 unmodified lines
113 114
114#define kvm_trace_symbol_aux_state \115#define kvm_trace_symbol_aux_state \
115 { KVM_TRACE_AUX_FPU, "FPU" }, \116 { KVM_TRACE_AUX_FPU, "FPU" }, \
116 { KVM_TRACE_AUX_LSX, "LSX" }117 { KVM_TRACE_AUX_LSX, "LSX" }, \
118 { KVM_TRACE_AUX_LASX, "LASX" }
117 119
118TRACE_EVENT(kvm_aux,120TRACE_EVENT(kvm_aux,
119 TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op,121 TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op,
arch/loongarch/kvm/vcpu.c+50−1
@@ -317,6 +317,13 @@ static int _kvm_get_cpucfg(int id, u64 *v) · 316 unmodified lines
317 */317 */
318 if (cpu_has_lsx)318 if (cpu_has_lsx)
319 *v |= CPUCFG2_LSX;319 *v |= CPUCFG2_LSX;
320 /*
321 * if LASX is supported by CPU, it is also supported by KVM,
322 * as we implement it.
323 */
324 if (cpu_has_lasx)
325 *v |= CPUCFG2_LASX;
326
320 break;327 break;
321 default:328 default:
322 ret = -EINVAL;329 ret = -EINVAL;
@@ -753,12 +760,54 @@ int kvm_own_lsx(struct kvm_vcpu *vcpu) · 430 unmodified lines
753}760}
754#endif761#endif
755 762
763#ifdef CONFIG_CPU_HAS_LASX
764/* Enable LASX and restore context */
765int kvm_own_lasx(struct kvm_vcpu *vcpu)
766{
767 if (!kvm_guest_has_fpu(&vcpu->arch) || !kvm_guest_has_lsx(&vcpu->arch) || !kvm_guest_has_lasx(&vcpu->arch))
768 return -EINVAL;
769
770 preempt_disable();
771
772 set_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
773 switch (vcpu->arch.aux_inuse & (KVM_LARCH_FPU | KVM_LARCH_LSX)) {
774 case KVM_LARCH_LSX:
775 case KVM_LARCH_LSX | KVM_LARCH_FPU:
776 /* Guest LSX state already loaded, only restore upper LASX state */
777 _restore_lasx_upper(&vcpu->arch.fpu);
778 break;
779 case KVM_LARCH_FPU:
780 /* Guest FP state already loaded, only restore upper LSX & LASX state */
781 _restore_lsx_upper(&vcpu->arch.fpu);
782 _restore_lasx_upper(&vcpu->arch.fpu);
783 break;
784 default:
785 /* Neither FP or LSX already active, restore full LASX state */
786 kvm_restore_lasx(&vcpu->arch.fpu);
787 break;
788 }
789
790 trace_kvm_aux(vcpu, KVM_TRACE_AUX_RESTORE, KVM_TRACE_AUX_LASX);
791 vcpu->arch.aux_inuse |= KVM_LARCH_LASX | KVM_LARCH_LSX | KVM_LARCH_FPU;
792 preempt_enable();
793
794 return 0;
795}
796#endif
797
756/* Save context and disable FPU */798/* Save context and disable FPU */
757void kvm_lose_fpu(struct kvm_vcpu *vcpu)799void kvm_lose_fpu(struct kvm_vcpu *vcpu)
758{800{
759 preempt_disable();801 preempt_disable();
760 802
761 if (vcpu->arch.aux_inuse & KVM_LARCH_LSX) {803 if (vcpu->arch.aux_inuse & KVM_LARCH_LASX) {
804 kvm_save_lasx(&vcpu->arch.fpu);
805 vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LASX);
806 trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LASX);
807
808 /* Disable LASX & LSX & FPU */
809 clear_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
810 } else if (vcpu->arch.aux_inuse & KVM_LARCH_LSX) {
762 kvm_save_lsx(&vcpu->arch.fpu);811 kvm_save_lsx(&vcpu->arch.fpu);
763 vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU);812 vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU);
764 trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LSX);813 trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LSX);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t