[v1,2/2] LoongArch: KVM: Add lasx support
Commit Message
This patch adds LASX support for LoongArch KVM. The LASX means
LoongArch 256-bits vector instruction.
There will be LASX exception in KVM when guest use the LASX
instruction. KVM will enable LASX and restore the vector
registers for guest then return to guest to continue running.
Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
---
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(-)
Comments
On 11/15/23 17:19, Tianrui Zhao wrote:
> This patch adds LASX support for LoongArch KVM. The LASX means
> LoongArch 256-bits vector instruction.
> There will be LASX exception in KVM when guest use the LASX
> instruction. KVM will enable LASX and restore the vector
> registers for guest then return to guest to continue running.
>
> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> ---
> 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)
>
> struct kvm_vcpu_arch {
> /*
> @@ -181,6 +182,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);
>
> 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
>
> +#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)
Why the added export? It doesn't seem necessary, given the previous
patch doesn't have a similar export added for _restore_lsx_upper. (Or if
it's truly needed it should probably become EXPORT_SYMBOL_GPL.)
在 2023/11/16 下午3:19, WANG Xuerui 写道:
> On 11/15/23 17:19, Tianrui Zhao wrote:
>> This patch adds LASX support for LoongArch KVM. The LASX means
>> LoongArch 256-bits vector instruction.
>> There will be LASX exception in KVM when guest use the LASX
>> instruction. KVM will enable LASX and restore the vector
>> registers for guest then return to guest to continue running.
>>
>> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
>> ---
>> 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)
>> struct kvm_vcpu_arch {
>> /*
>> @@ -181,6 +182,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);
>> 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
>> +#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)
>
> Why the added export? It doesn't seem necessary, given the previous
> patch doesn't have a similar export added for _restore_lsx_upper. (Or
> if it's truly needed it should probably become EXPORT_SYMBOL_GPL.)
It is needed to be exported, as it is called by kvm_own_lasx. However
the "_restore_lsx_upper" is not used in kvm.
Thanks
Tianrui Zhao
On Tue, Nov 21, 2023 at 5:59 PM zhaotianrui <zhaotianrui@loongson.cn> wrote:
>
>
> 在 2023/11/16 下午3:19, WANG Xuerui 写道:
> > On 11/15/23 17:19, Tianrui Zhao wrote:
> >> This patch adds LASX support for LoongArch KVM. The LASX means
> >> LoongArch 256-bits vector instruction.
> >> There will be LASX exception in KVM when guest use the LASX
> >> instruction. KVM will enable LASX and restore the vector
> >> registers for guest then return to guest to continue running.
> >>
> >> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
> >> ---
> >> 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)
> >> struct kvm_vcpu_arch {
> >> /*
> >> @@ -181,6 +182,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);
> >> 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
> >> +#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)
> >
> > Why the added export? It doesn't seem necessary, given the previous
> > patch doesn't have a similar export added for _restore_lsx_upper. (Or
> > if it's truly needed it should probably become EXPORT_SYMBOL_GPL.)
> It is needed to be exported, as it is called by kvm_own_lasx. However
> the "_restore_lsx_upper" is not used in kvm.
To keep consistency it is better to export both.
Huacai
>
> Thanks
> Tianrui Zhao
>
在 2023/11/21 下午7:55, Huacai Chen 写道:
> On Tue, Nov 21, 2023 at 5:59 PM zhaotianrui <zhaotianrui@loongson.cn> wrote:
>>
>> 在 2023/11/16 下午3:19, WANG Xuerui 写道:
>>> On 11/15/23 17:19, Tianrui Zhao wrote:
>>>> This patch adds LASX support for LoongArch KVM. The LASX means
>>>> LoongArch 256-bits vector instruction.
>>>> There will be LASX exception in KVM when guest use the LASX
>>>> instruction. KVM will enable LASX and restore the vector
>>>> registers for guest then return to guest to continue running.
>>>>
>>>> Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
>>>> ---
>>>> 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)
>>>> struct kvm_vcpu_arch {
>>>> /*
>>>> @@ -181,6 +182,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);
>>>> 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
>>>> +#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)
>>> Why the added export? It doesn't seem necessary, given the previous
>>> patch doesn't have a similar export added for _restore_lsx_upper. (Or
>>> if it's truly needed it should probably become EXPORT_SYMBOL_GPL.)
>> It is needed to be exported, as it is called by kvm_own_lasx. However
>> the "_restore_lsx_upper" is not used in kvm.
> To keep consistency it is better to export both.
>
> Huacai
Thanks, I will export both functions.
Tianrui Zhao
>
>> Thanks
>> Tianrui Zhao
>>
@@ -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)
struct kvm_vcpu_arch {
/*
@@ -181,6 +182,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);
@@ -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
+#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);
@@ -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)
SYM_FUNC_START(_init_lasx_upper)
lasx_init_all_upper t1
@@ -676,6 +676,23 @@ 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_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_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,
};
@@ -267,6 +267,22 @@ SYM_FUNC_START(kvm_restore_lsx_upper)
SYM_FUNC_END(kvm_restore_lsx_upper)
#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
+
+ 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)
@@ -103,6 +103,7 @@ TRACE_EVENT(kvm_exit_gspr,
#define KVM_TRACE_AUX_FPU 1
#define KVM_TRACE_AUX_LSX 2
+#define KVM_TRACE_AUX_LASX 3
#define kvm_trace_symbol_aux_op \
{ KVM_TRACE_AUX_SAVE, "save" }, \
@@ -113,7 +114,8 @@ TRACE_EVENT(kvm_exit_gspr,
#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" }
TRACE_EVENT(kvm_aux,
TP_PROTO(struct kvm_vcpu *vcpu, unsigned int op,
@@ -384,6 +384,10 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
vcpu->arch.cpucfg[id] &= ~CPUCFG2_LSX;
ret = -EINVAL;
}
+ if (id == 2 && v & CPUCFG2_LASX && !cpu_has_lasx) {
+ vcpu->arch.cpucfg[id] &= ~CPUCFG2_LASX;
+ ret = -EINVAL;
+ }
} else
ret = -EINVAL;
break;
@@ -595,12 +599,49 @@ void kvm_own_lsx(struct kvm_vcpu *vcpu)
}
#endif
+#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 |= 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();
- 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 &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LASX);
+ 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 &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU);
trace_kvm_aux(vcpu, KVM_TRACE_AUX_SAVE, KVM_TRACE_AUX_LSX);