[PATCH v2] LoongArch: KVM: Add AVEC support

Song Gao posted 1 patch 2 months, 1 week ago
arch/loongarch/include/asm/kvm_host.h |  4 ++++
arch/loongarch/include/asm/kvm_vcpu.h |  1 +
arch/loongarch/include/uapi/asm/kvm.h |  1 +
arch/loongarch/kvm/interrupt.c        |  3 +++
arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
arch/loongarch/kvm/vm.c               |  4 ++++
6 files changed, 30 insertions(+), 2 deletions(-)
[PATCH v2] LoongArch: KVM: Add AVEC support
Posted by Song Gao 2 months, 1 week ago
Add cpu_has_msgint() to check whether the host cpu supported avec,
and restore/save CSR_MSGIS0-CSR_MSGIS3.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
Based-on: https://patchew.org/linux/20250930093741.2734974-1-maobibo@loongson.cn/
v2: fix build error.

 arch/loongarch/include/asm/kvm_host.h |  4 ++++
 arch/loongarch/include/asm/kvm_vcpu.h |  1 +
 arch/loongarch/include/uapi/asm/kvm.h |  1 +
 arch/loongarch/kvm/interrupt.c        |  3 +++
 arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
 arch/loongarch/kvm/vm.c               |  4 ++++
 6 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 392480c9b958..446f1104d59d 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -285,6 +285,10 @@ static inline bool kvm_guest_has_lbt(struct kvm_vcpu_arch *arch)
 	return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | CPUCFG2_MIPSBT);
 }
 
+static inline bool cpu_has_msgint(void)
+{
+	return read_cpucfg(LOONGARCH_CPUCFG1) & CPUCFG1_MSGINT;
+}
 static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch)
 {
 	return arch->cpucfg[6] & CPUCFG6_PMP;
diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h
index f1efd7cfbc20..3784ab4ccdb5 100644
--- a/arch/loongarch/include/asm/kvm_vcpu.h
+++ b/arch/loongarch/include/asm/kvm_vcpu.h
@@ -15,6 +15,7 @@
 #define CPU_PMU				(_ULCAST_(1) << 10)
 #define CPU_TIMER			(_ULCAST_(1) << 11)
 #define CPU_IPI				(_ULCAST_(1) << 12)
+#define CPU_AVEC                        (_ULCAST_(1) << 14)
 
 /* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
 #define CPU_IP0				(_ULCAST_(1))
diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index 57ba1a563bb1..de6c3f18e40a 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -104,6 +104,7 @@ struct kvm_fpu {
 #define  KVM_LOONGARCH_VM_FEAT_PV_IPI		6
 #define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME	7
 #define  KVM_LOONGARCH_VM_FEAT_PTW		8
+#define  KVM_LOONGARCH_VM_FEAT_MSGINT		9
 
 /* Device Control API on vcpu fd */
 #define KVM_LOONGARCH_VCPU_CPUCFG	0
diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
index 8462083f0301..adc278fb3cb9 100644
--- a/arch/loongarch/kvm/interrupt.c
+++ b/arch/loongarch/kvm/interrupt.c
@@ -21,6 +21,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
 	[INT_HWI5]	= CPU_IP5,
 	[INT_HWI6]	= CPU_IP6,
 	[INT_HWI7]	= CPU_IP7,
+	[INT_AVEC]	= CPU_AVEC,
 };
 
 static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
@@ -36,6 +37,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 	case INT_IPI:
 	case INT_SWI0:
 	case INT_SWI1:
+	case INT_AVEC:
 		set_gcsr_estat(irq);
 		break;
 
@@ -63,6 +65,7 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
 	case INT_IPI:
 	case INT_SWI0:
 	case INT_SWI1:
+	case INT_AVEC:
 		clear_gcsr_estat(irq);
 		break;
 
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 30e3b089a596..226c735155be 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -657,8 +657,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
 		*v = GENMASK(31, 0);
 		return 0;
 	case LOONGARCH_CPUCFG1:
-		/* CPUCFG1_MSGINT is not supported by KVM */
-		*v = GENMASK(25, 0);
+		*v = GENMASK(26, 0);
 		return 0;
 	case LOONGARCH_CPUCFG2:
 		/* CPUCFG2 features unconditionally supported by KVM */
@@ -726,6 +725,10 @@ static int kvm_check_cpucfg(int id, u64 val)
 		return -EINVAL;
 
 	switch (id) {
+	case LOONGARCH_CPUCFG1:
+		if ((val & CPUCFG1_MSGINT) && (!cpu_has_msgint()))
+			return -EINVAL;
+		return 0;
 	case LOONGARCH_CPUCFG2:
 		if (!(val & CPUCFG2_LLFTP))
 			/* Guests must have a constant timer */
@@ -1658,6 +1661,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
 	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
 	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
+	if (cpu_has_msgint()) {
+		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
+		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
+		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
+		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
+	}
 
 	/* Restore Root.GINTC from unused Guest.GINTC register */
 	write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
@@ -1747,6 +1756,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
 	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
 	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
 	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
+	if (cpu_has_msgint()) {
+		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
+		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
+		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
+		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
+	}
 
 	vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
 
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
index d8c813e2d72e..438885b6f2b1 100644
--- a/arch/loongarch/kvm/vm.c
+++ b/arch/loongarch/kvm/vm.c
@@ -37,6 +37,9 @@ static void kvm_vm_init_features(struct kvm *kvm)
 		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
 	}
 
+	if (cpu_has_msgint())
+		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_MSGINT);
+
 	val = read_csr_gcfg();
 	if (val & CSR_GCFG_GPMP)
 		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU);
@@ -153,6 +156,7 @@ static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr
 	case KVM_LOONGARCH_VM_FEAT_PMU:
 	case KVM_LOONGARCH_VM_FEAT_PV_IPI:
 	case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
+        case KVM_LOONGARCH_VM_FEAT_MSGINT:
 		if (kvm_vm_support(&kvm->arch, attr->attr))
 			return 0;
 		return -ENXIO;
-- 
2.39.3
Re: [PATCH v2] LoongArch: KVM: Add AVEC support
Posted by Bibo Mao 2 months, 1 week ago

On 2025/10/10 下午2:48, Song Gao wrote:
> Add cpu_has_msgint() to check whether the host cpu supported avec,
> and restore/save CSR_MSGIS0-CSR_MSGIS3.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> Based-on: https://patchew.org/linux/20250930093741.2734974-1-maobibo@loongson.cn/
> v2: fix build error.
It is not necessary based on this patch, you can base it on master 
branch. The later merged patch need based on previous version in general.

> 
>   arch/loongarch/include/asm/kvm_host.h |  4 ++++
>   arch/loongarch/include/asm/kvm_vcpu.h |  1 +
>   arch/loongarch/include/uapi/asm/kvm.h |  1 +
>   arch/loongarch/kvm/interrupt.c        |  3 +++
>   arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
>   arch/loongarch/kvm/vm.c               |  4 ++++
>   6 files changed, 30 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
> index 392480c9b958..446f1104d59d 100644
> --- a/arch/loongarch/include/asm/kvm_host.h
> +++ b/arch/loongarch/include/asm/kvm_host.h
> @@ -285,6 +285,10 @@ static inline bool kvm_guest_has_lbt(struct kvm_vcpu_arch *arch)
>   	return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | CPUCFG2_MIPSBT);
>   }
>   
> +static inline bool cpu_has_msgint(void)
> +{
> +	return read_cpucfg(LOONGARCH_CPUCFG1) & CPUCFG1_MSGINT;
> +}
>   static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch)
>   {
>   	return arch->cpucfg[6] & CPUCFG6_PMP;
> diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h
> index f1efd7cfbc20..3784ab4ccdb5 100644
> --- a/arch/loongarch/include/asm/kvm_vcpu.h
> +++ b/arch/loongarch/include/asm/kvm_vcpu.h
> @@ -15,6 +15,7 @@
>   #define CPU_PMU				(_ULCAST_(1) << 10)
>   #define CPU_TIMER			(_ULCAST_(1) << 11)
>   #define CPU_IPI				(_ULCAST_(1) << 12)
> +#define CPU_AVEC                        (_ULCAST_(1) << 14)
>   
>   /* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
>   #define CPU_IP0				(_ULCAST_(1))
> diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
> index 57ba1a563bb1..de6c3f18e40a 100644
> --- a/arch/loongarch/include/uapi/asm/kvm.h
> +++ b/arch/loongarch/include/uapi/asm/kvm.h
> @@ -104,6 +104,7 @@ struct kvm_fpu {
>   #define  KVM_LOONGARCH_VM_FEAT_PV_IPI		6
>   #define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME	7
>   #define  KVM_LOONGARCH_VM_FEAT_PTW		8
> +#define  KVM_LOONGARCH_VM_FEAT_MSGINT		9
>   
>   /* Device Control API on vcpu fd */
>   #define KVM_LOONGARCH_VCPU_CPUCFG	0
> diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
> index 8462083f0301..adc278fb3cb9 100644
> --- a/arch/loongarch/kvm/interrupt.c
> +++ b/arch/loongarch/kvm/interrupt.c
> @@ -21,6 +21,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
>   	[INT_HWI5]	= CPU_IP5,
>   	[INT_HWI6]	= CPU_IP6,
>   	[INT_HWI7]	= CPU_IP7,
> +	[INT_AVEC]	= CPU_AVEC,
>   };
>   
>   static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
> @@ -36,6 +37,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
>   	case INT_IPI:
>   	case INT_SWI0:
>   	case INT_SWI1:
> +	case INT_AVEC:
>   		set_gcsr_estat(irq);
Do we need cpu_has_msgint() here ? It is impossible that VMM inject 
INT_AVEC interrrupt on non-msgint machine such as 3C5000.

>   		break;
>   
> @@ -63,6 +65,7 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
>   	case INT_IPI:
>   	case INT_SWI0:
>   	case INT_SWI1:
> +	case INT_AVEC:
>   		clear_gcsr_estat(irq);
Ditto.

The others look good to me.

Regards
Bibo Mao
>   		break;
>   
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 30e3b089a596..226c735155be 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -657,8 +657,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
>   		*v = GENMASK(31, 0);
>   		return 0;
>   	case LOONGARCH_CPUCFG1:
> -		/* CPUCFG1_MSGINT is not supported by KVM */
> -		*v = GENMASK(25, 0);
> +		*v = GENMASK(26, 0);
>   		return 0;
>   	case LOONGARCH_CPUCFG2:
>   		/* CPUCFG2 features unconditionally supported by KVM */
> @@ -726,6 +725,10 @@ static int kvm_check_cpucfg(int id, u64 val)
>   		return -EINVAL;
>   
>   	switch (id) {
> +	case LOONGARCH_CPUCFG1:
> +		if ((val & CPUCFG1_MSGINT) && (!cpu_has_msgint()))
> +			return -EINVAL;
> +		return 0;
>   	case LOONGARCH_CPUCFG2:
>   		if (!(val & CPUCFG2_LLFTP))
>   			/* Guests must have a constant timer */
> @@ -1658,6 +1661,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>   	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>   	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>   	kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
> +	if (cpu_has_msgint()) {
> +		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
> +		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
> +		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
> +		kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
> +	}
>   
>   	/* Restore Root.GINTC from unused Guest.GINTC register */
>   	write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
> @@ -1747,6 +1756,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu *vcpu, int cpu)
>   	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
>   	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>   	kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
> +	if (cpu_has_msgint()) {
> +		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
> +		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
> +		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
> +		kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
> +	}
>   
>   	vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
>   
> diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
> index d8c813e2d72e..438885b6f2b1 100644
> --- a/arch/loongarch/kvm/vm.c
> +++ b/arch/loongarch/kvm/vm.c
> @@ -37,6 +37,9 @@ static void kvm_vm_init_features(struct kvm *kvm)
>   		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
>   	}
>   
> +	if (cpu_has_msgint())
> +		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_MSGINT);
> +
>   	val = read_csr_gcfg();
>   	if (val & CSR_GCFG_GPMP)
>   		kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU);
> @@ -153,6 +156,7 @@ static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr
>   	case KVM_LOONGARCH_VM_FEAT_PMU:
>   	case KVM_LOONGARCH_VM_FEAT_PV_IPI:
>   	case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
> +        case KVM_LOONGARCH_VM_FEAT_MSGINT:
>   		if (kvm_vm_support(&kvm->arch, attr->attr))
>   			return 0;
>   		return -ENXIO;
> 

Re: [PATCH v2] LoongArch: KVM: Add AVEC support
Posted by gaosong 2 months, 1 week ago
在 2025/10/11 上午9:29, Bibo Mao 写道:
>
>
> On 2025/10/10 下午2:48, Song Gao wrote:
>> Add cpu_has_msgint() to check whether the host cpu supported avec,
>> and restore/save CSR_MSGIS0-CSR_MSGIS3.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> Based-on: 
>> https://patchew.org/linux/20250930093741.2734974-1-maobibo@loongson.cn/
>> v2: fix build error.
> It is not necessary based on this patch, you can base it on master 
> branch. The later merged patch need based on previous version in general.
>
Got it.
>>
>>   arch/loongarch/include/asm/kvm_host.h |  4 ++++
>>   arch/loongarch/include/asm/kvm_vcpu.h |  1 +
>>   arch/loongarch/include/uapi/asm/kvm.h |  1 +
>>   arch/loongarch/kvm/interrupt.c        |  3 +++
>>   arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
>>   arch/loongarch/kvm/vm.c               |  4 ++++
>>   6 files changed, 30 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/loongarch/include/asm/kvm_host.h 
>> b/arch/loongarch/include/asm/kvm_host.h
>> index 392480c9b958..446f1104d59d 100644
>> --- a/arch/loongarch/include/asm/kvm_host.h
>> +++ b/arch/loongarch/include/asm/kvm_host.h
>> @@ -285,6 +285,10 @@ static inline bool kvm_guest_has_lbt(struct 
>> kvm_vcpu_arch *arch)
>>       return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | 
>> CPUCFG2_MIPSBT);
>>   }
>>   +static inline bool cpu_has_msgint(void)
>> +{
>> +    return read_cpucfg(LOONGARCH_CPUCFG1) & CPUCFG1_MSGINT;
>> +}
>>   static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch)
>>   {
>>       return arch->cpucfg[6] & CPUCFG6_PMP;
>> diff --git a/arch/loongarch/include/asm/kvm_vcpu.h 
>> b/arch/loongarch/include/asm/kvm_vcpu.h
>> index f1efd7cfbc20..3784ab4ccdb5 100644
>> --- a/arch/loongarch/include/asm/kvm_vcpu.h
>> +++ b/arch/loongarch/include/asm/kvm_vcpu.h
>> @@ -15,6 +15,7 @@
>>   #define CPU_PMU                (_ULCAST_(1) << 10)
>>   #define CPU_TIMER            (_ULCAST_(1) << 11)
>>   #define CPU_IPI                (_ULCAST_(1) << 12)
>> +#define CPU_AVEC                        (_ULCAST_(1) << 14)
>>     /* Controlled by 0x52 guest exception VIP aligned to estat bit 
>> 5~12 */
>>   #define CPU_IP0                (_ULCAST_(1))
>> diff --git a/arch/loongarch/include/uapi/asm/kvm.h 
>> b/arch/loongarch/include/uapi/asm/kvm.h
>> index 57ba1a563bb1..de6c3f18e40a 100644
>> --- a/arch/loongarch/include/uapi/asm/kvm.h
>> +++ b/arch/loongarch/include/uapi/asm/kvm.h
>> @@ -104,6 +104,7 @@ struct kvm_fpu {
>>   #define  KVM_LOONGARCH_VM_FEAT_PV_IPI        6
>>   #define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME    7
>>   #define  KVM_LOONGARCH_VM_FEAT_PTW        8
>> +#define  KVM_LOONGARCH_VM_FEAT_MSGINT        9
>>     /* Device Control API on vcpu fd */
>>   #define KVM_LOONGARCH_VCPU_CPUCFG    0
>> diff --git a/arch/loongarch/kvm/interrupt.c 
>> b/arch/loongarch/kvm/interrupt.c
>> index 8462083f0301..adc278fb3cb9 100644
>> --- a/arch/loongarch/kvm/interrupt.c
>> +++ b/arch/loongarch/kvm/interrupt.c
>> @@ -21,6 +21,7 @@ static unsigned int 
>> priority_to_irq[EXCCODE_INT_NUM] = {
>>       [INT_HWI5]    = CPU_IP5,
>>       [INT_HWI6]    = CPU_IP6,
>>       [INT_HWI7]    = CPU_IP7,
>> +    [INT_AVEC]    = CPU_AVEC,
>>   };
>>     static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int 
>> priority)
>> @@ -36,6 +37,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
>> unsigned int priority)
>>       case INT_IPI:
>>       case INT_SWI0:
>>       case INT_SWI1:
>> +    case INT_AVEC:
>>           set_gcsr_estat(irq);
> Do we need cpu_has_msgint() here ? It is impossible that VMM inject 
> INT_AVEC interrrupt on non-msgint machine such as 3C5000.
>
yes we need , how about this?

@@ -31,6 +32,11 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
unsigned int priority)
         if (priority < EXCCODE_INT_NUM)
                 irq = priority_to_irq[priority];

+        if (cpu_has_msgint() && (priority == INT_AVEC)) {
+                set_gcsr_estat(irq);
+                return 1;
+        }
+
         switch (priority) {
         case INT_TI:
         case INT_IPI:

Thanks.
Song Gao


>>           break;
>>   @@ -63,6 +65,7 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, 
>> unsigned int priority)
>>       case INT_IPI:
>>       case INT_SWI0:
>>       case INT_SWI1:
>> +    case INT_AVEC:
>>           clear_gcsr_estat(irq);
> Ditto.
>
> The others look good to me.
>
> Regards
> Bibo Mao
>>           break;
>>   diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>> index 30e3b089a596..226c735155be 100644
>> --- a/arch/loongarch/kvm/vcpu.c
>> +++ b/arch/loongarch/kvm/vcpu.c
>> @@ -657,8 +657,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
>>           *v = GENMASK(31, 0);
>>           return 0;
>>       case LOONGARCH_CPUCFG1:
>> -        /* CPUCFG1_MSGINT is not supported by KVM */
>> -        *v = GENMASK(25, 0);
>> +        *v = GENMASK(26, 0);
>>           return 0;
>>       case LOONGARCH_CPUCFG2:
>>           /* CPUCFG2 features unconditionally supported by KVM */
>> @@ -726,6 +725,10 @@ static int kvm_check_cpucfg(int id, u64 val)
>>           return -EINVAL;
>>         switch (id) {
>> +    case LOONGARCH_CPUCFG1:
>> +        if ((val & CPUCFG1_MSGINT) && (!cpu_has_msgint()))
>> +            return -EINVAL;
>> +        return 0;
>>       case LOONGARCH_CPUCFG2:
>>           if (!(val & CPUCFG2_LLFTP))
>>               /* Guests must have a constant timer */
>> @@ -1658,6 +1661,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu 
>> *vcpu, int cpu)
>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
>> +    if (cpu_has_msgint()) {
>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>> +    }
>>         /* Restore Root.GINTC from unused Guest.GINTC register */
>>       write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
>> @@ -1747,6 +1756,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu 
>> *vcpu, int cpu)
>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>> +    if (cpu_has_msgint()) {
>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>> +    }
>>         vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
>>   diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
>> index d8c813e2d72e..438885b6f2b1 100644
>> --- a/arch/loongarch/kvm/vm.c
>> +++ b/arch/loongarch/kvm/vm.c
>> @@ -37,6 +37,9 @@ static void kvm_vm_init_features(struct kvm *kvm)
>>           kvm->arch.support_features |= 
>> BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
>>       }
>>   +    if (cpu_has_msgint())
>> +        kvm->arch.support_features |= 
>> BIT(KVM_LOONGARCH_VM_FEAT_MSGINT);
>> +
>>       val = read_csr_gcfg();
>>       if (val & CSR_GCFG_GPMP)
>>           kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU);
>> @@ -153,6 +156,7 @@ static int kvm_vm_feature_has_attr(struct kvm 
>> *kvm, struct kvm_device_attr *attr
>>       case KVM_LOONGARCH_VM_FEAT_PMU:
>>       case KVM_LOONGARCH_VM_FEAT_PV_IPI:
>>       case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
>> +        case KVM_LOONGARCH_VM_FEAT_MSGINT:
>>           if (kvm_vm_support(&kvm->arch, attr->attr))
>>               return 0;
>>           return -ENXIO;
>>
>

Re: [PATCH v2] LoongArch: KVM: Add AVEC support
Posted by Bibo Mao 2 months, 1 week ago

On 2025/10/13 上午11:18, gaosong wrote:
> 在 2025/10/11 上午9:29, Bibo Mao 写道:
>>
>>
>> On 2025/10/10 下午2:48, Song Gao wrote:
>>> Add cpu_has_msgint() to check whether the host cpu supported avec,
>>> and restore/save CSR_MSGIS0-CSR_MSGIS3.
>>>
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>> Based-on: 
>>> https://patchew.org/linux/20250930093741.2734974-1-maobibo@loongson.cn/
>>> v2: fix build error.
>> It is not necessary based on this patch, you can base it on master 
>> branch. The later merged patch need based on previous version in general.
>>
> Got it.
>>>
>>>   arch/loongarch/include/asm/kvm_host.h |  4 ++++
>>>   arch/loongarch/include/asm/kvm_vcpu.h |  1 +
>>>   arch/loongarch/include/uapi/asm/kvm.h |  1 +
>>>   arch/loongarch/kvm/interrupt.c        |  3 +++
>>>   arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
>>>   arch/loongarch/kvm/vm.c               |  4 ++++
>>>   6 files changed, 30 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/loongarch/include/asm/kvm_host.h 
>>> b/arch/loongarch/include/asm/kvm_host.h
>>> index 392480c9b958..446f1104d59d 100644
>>> --- a/arch/loongarch/include/asm/kvm_host.h
>>> +++ b/arch/loongarch/include/asm/kvm_host.h
>>> @@ -285,6 +285,10 @@ static inline bool kvm_guest_has_lbt(struct 
>>> kvm_vcpu_arch *arch)
>>>       return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | 
>>> CPUCFG2_MIPSBT);
>>>   }
>>>   +static inline bool cpu_has_msgint(void)
>>> +{
>>> +    return read_cpucfg(LOONGARCH_CPUCFG1) & CPUCFG1_MSGINT;
>>> +}
>>>   static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch)
>>>   {
>>>       return arch->cpucfg[6] & CPUCFG6_PMP;
>>> diff --git a/arch/loongarch/include/asm/kvm_vcpu.h 
>>> b/arch/loongarch/include/asm/kvm_vcpu.h
>>> index f1efd7cfbc20..3784ab4ccdb5 100644
>>> --- a/arch/loongarch/include/asm/kvm_vcpu.h
>>> +++ b/arch/loongarch/include/asm/kvm_vcpu.h
>>> @@ -15,6 +15,7 @@
>>>   #define CPU_PMU                (_ULCAST_(1) << 10)
>>>   #define CPU_TIMER            (_ULCAST_(1) << 11)
>>>   #define CPU_IPI                (_ULCAST_(1) << 12)
>>> +#define CPU_AVEC                        (_ULCAST_(1) << 14)
>>>     /* Controlled by 0x52 guest exception VIP aligned to estat bit 
>>> 5~12 */
>>>   #define CPU_IP0                (_ULCAST_(1))
>>> diff --git a/arch/loongarch/include/uapi/asm/kvm.h 
>>> b/arch/loongarch/include/uapi/asm/kvm.h
>>> index 57ba1a563bb1..de6c3f18e40a 100644
>>> --- a/arch/loongarch/include/uapi/asm/kvm.h
>>> +++ b/arch/loongarch/include/uapi/asm/kvm.h
>>> @@ -104,6 +104,7 @@ struct kvm_fpu {
>>>   #define  KVM_LOONGARCH_VM_FEAT_PV_IPI        6
>>>   #define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME    7
>>>   #define  KVM_LOONGARCH_VM_FEAT_PTW        8
>>> +#define  KVM_LOONGARCH_VM_FEAT_MSGINT        9
>>>     /* Device Control API on vcpu fd */
>>>   #define KVM_LOONGARCH_VCPU_CPUCFG    0
>>> diff --git a/arch/loongarch/kvm/interrupt.c 
>>> b/arch/loongarch/kvm/interrupt.c
>>> index 8462083f0301..adc278fb3cb9 100644
>>> --- a/arch/loongarch/kvm/interrupt.c
>>> +++ b/arch/loongarch/kvm/interrupt.c
>>> @@ -21,6 +21,7 @@ static unsigned int 
>>> priority_to_irq[EXCCODE_INT_NUM] = {
>>>       [INT_HWI5]    = CPU_IP5,
>>>       [INT_HWI6]    = CPU_IP6,
>>>       [INT_HWI7]    = CPU_IP7,
>>> +    [INT_AVEC]    = CPU_AVEC,
>>>   };
>>>     static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int 
>>> priority)
>>> @@ -36,6 +37,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
>>> unsigned int priority)
>>>       case INT_IPI:
>>>       case INT_SWI0:
>>>       case INT_SWI1:
>>> +    case INT_AVEC:
>>>           set_gcsr_estat(irq);
>> Do we need cpu_has_msgint() here ? It is impossible that VMM inject 
>> INT_AVEC interrrupt on non-msgint machine such as 3C5000.
>>
> yes we need , how about this?
> 
> @@ -31,6 +32,11 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
> unsigned int priority)
>          if (priority < EXCCODE_INT_NUM)
>                  irq = priority_to_irq[priority];
> 
> +        if (cpu_has_msgint() && (priority == INT_AVEC)) {
> +                set_gcsr_estat(irq);
> +                return 1;
> +        }
> +
>          switch (priority) {
>          case INT_TI:
>          case INT_IPI:
This is workable. Another way is to add checking in irq inject root 
source function kvm_vcpu_ioctl_interrupt(). Both works for me.

BTW, I think that there should be modification with function 
kvm_deliver_intr() also. max irq bit is *INT_IPI + 1* where there will 
be problem with INT_AVEC. Should it be modified as *EXCCODE_INT_NUM*?

void kvm_deliver_intr(struct kvm_vcpu *vcpu)
{
         unsigned int priority;
         unsigned long *pending = &vcpu->arch.irq_pending;
         unsigned long *pending_clr = &vcpu->arch.irq_clear;

         for_each_set_bit(priority, pending_clr, INT_IPI + 1)
                 kvm_irq_clear(vcpu, priority);

         for_each_set_bit(priority, pending, INT_IPI + 1)
                 kvm_irq_deliver(vcpu, priority);
}

Regards
Bibo Mao
> 
> Thanks.
> Song Gao
> 
> 
>>>           break;
>>>   @@ -63,6 +65,7 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, 
>>> unsigned int priority)
>>>       case INT_IPI:
>>>       case INT_SWI0:
>>>       case INT_SWI1:
>>> +    case INT_AVEC:
>>>           clear_gcsr_estat(irq);
>> Ditto.
>>
>> The others look good to me.
>>
>> Regards
>> Bibo Mao
>>>           break;
>>>   diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>> index 30e3b089a596..226c735155be 100644
>>> --- a/arch/loongarch/kvm/vcpu.c
>>> +++ b/arch/loongarch/kvm/vcpu.c
>>> @@ -657,8 +657,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
>>>           *v = GENMASK(31, 0);
>>>           return 0;
>>>       case LOONGARCH_CPUCFG1:
>>> -        /* CPUCFG1_MSGINT is not supported by KVM */
>>> -        *v = GENMASK(25, 0);
>>> +        *v = GENMASK(26, 0);
>>>           return 0;
>>>       case LOONGARCH_CPUCFG2:
>>>           /* CPUCFG2 features unconditionally supported by KVM */
>>> @@ -726,6 +725,10 @@ static int kvm_check_cpucfg(int id, u64 val)
>>>           return -EINVAL;
>>>         switch (id) {
>>> +    case LOONGARCH_CPUCFG1:
>>> +        if ((val & CPUCFG1_MSGINT) && (!cpu_has_msgint()))
>>> +            return -EINVAL;
>>> +        return 0;
>>>       case LOONGARCH_CPUCFG2:
>>>           if (!(val & CPUCFG2_LLFTP))
>>>               /* Guests must have a constant timer */
>>> @@ -1658,6 +1661,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu 
>>> *vcpu, int cpu)
>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
>>> +    if (cpu_has_msgint()) {
>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>>> +    }
>>>         /* Restore Root.GINTC from unused Guest.GINTC register */
>>>       write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
>>> @@ -1747,6 +1756,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu 
>>> *vcpu, int cpu)
>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>>> +    if (cpu_has_msgint()) {
>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>>> +    }
>>>         vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
>>>   diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
>>> index d8c813e2d72e..438885b6f2b1 100644
>>> --- a/arch/loongarch/kvm/vm.c
>>> +++ b/arch/loongarch/kvm/vm.c
>>> @@ -37,6 +37,9 @@ static void kvm_vm_init_features(struct kvm *kvm)
>>>           kvm->arch.support_features |= 
>>> BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
>>>       }
>>>   +    if (cpu_has_msgint())
>>> +        kvm->arch.support_features |= 
>>> BIT(KVM_LOONGARCH_VM_FEAT_MSGINT);
>>> +
>>>       val = read_csr_gcfg();
>>>       if (val & CSR_GCFG_GPMP)
>>>           kvm->arch.support_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU);
>>> @@ -153,6 +156,7 @@ static int kvm_vm_feature_has_attr(struct kvm 
>>> *kvm, struct kvm_device_attr *attr
>>>       case KVM_LOONGARCH_VM_FEAT_PMU:
>>>       case KVM_LOONGARCH_VM_FEAT_PV_IPI:
>>>       case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
>>> +        case KVM_LOONGARCH_VM_FEAT_MSGINT:
>>>           if (kvm_vm_support(&kvm->arch, attr->attr))
>>>               return 0;
>>>           return -ENXIO;
>>>
>>
> 

Re: [PATCH v2] LoongArch: KVM: Add AVEC support
Posted by gaosong 2 months ago
在 2025/10/13 下午12:07, Bibo Mao 写道:
>
>
> On 2025/10/13 上午11:18, gaosong wrote:
>> 在 2025/10/11 上午9:29, Bibo Mao 写道:
>>>
>>>
>>> On 2025/10/10 下午2:48, Song Gao wrote:
>>>> Add cpu_has_msgint() to check whether the host cpu supported avec,
>>>> and restore/save CSR_MSGIS0-CSR_MSGIS3.
>>>>
>>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>>> ---
>>>> Based-on: 
>>>> https://patchew.org/linux/20250930093741.2734974-1-maobibo@loongson.cn/ 
>>>>
>>>> v2: fix build error.
>>> It is not necessary based on this patch, you can base it on master 
>>> branch. The later merged patch need based on previous version in 
>>> general.
>>>
>> Got it.
>>>>
>>>>   arch/loongarch/include/asm/kvm_host.h |  4 ++++
>>>>   arch/loongarch/include/asm/kvm_vcpu.h |  1 +
>>>>   arch/loongarch/include/uapi/asm/kvm.h |  1 +
>>>>   arch/loongarch/kvm/interrupt.c        |  3 +++
>>>>   arch/loongarch/kvm/vcpu.c             | 19 +++++++++++++++++--
>>>>   arch/loongarch/kvm/vm.c               |  4 ++++
>>>>   6 files changed, 30 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/arch/loongarch/include/asm/kvm_host.h 
>>>> b/arch/loongarch/include/asm/kvm_host.h
>>>> index 392480c9b958..446f1104d59d 100644
>>>> --- a/arch/loongarch/include/asm/kvm_host.h
>>>> +++ b/arch/loongarch/include/asm/kvm_host.h
>>>> @@ -285,6 +285,10 @@ static inline bool kvm_guest_has_lbt(struct 
>>>> kvm_vcpu_arch *arch)
>>>>       return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | 
>>>> CPUCFG2_MIPSBT);
>>>>   }
>>>>   +static inline bool cpu_has_msgint(void)
>>>> +{
>>>> +    return read_cpucfg(LOONGARCH_CPUCFG1) & CPUCFG1_MSGINT;
>>>> +}
>>>>   static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch)
>>>>   {
>>>>       return arch->cpucfg[6] & CPUCFG6_PMP;
>>>> diff --git a/arch/loongarch/include/asm/kvm_vcpu.h 
>>>> b/arch/loongarch/include/asm/kvm_vcpu.h
>>>> index f1efd7cfbc20..3784ab4ccdb5 100644
>>>> --- a/arch/loongarch/include/asm/kvm_vcpu.h
>>>> +++ b/arch/loongarch/include/asm/kvm_vcpu.h
>>>> @@ -15,6 +15,7 @@
>>>>   #define CPU_PMU                (_ULCAST_(1) << 10)
>>>>   #define CPU_TIMER            (_ULCAST_(1) << 11)
>>>>   #define CPU_IPI                (_ULCAST_(1) << 12)
>>>> +#define CPU_AVEC                        (_ULCAST_(1) << 14)
>>>>     /* Controlled by 0x52 guest exception VIP aligned to estat bit 
>>>> 5~12 */
>>>>   #define CPU_IP0                (_ULCAST_(1))
>>>> diff --git a/arch/loongarch/include/uapi/asm/kvm.h 
>>>> b/arch/loongarch/include/uapi/asm/kvm.h
>>>> index 57ba1a563bb1..de6c3f18e40a 100644
>>>> --- a/arch/loongarch/include/uapi/asm/kvm.h
>>>> +++ b/arch/loongarch/include/uapi/asm/kvm.h
>>>> @@ -104,6 +104,7 @@ struct kvm_fpu {
>>>>   #define  KVM_LOONGARCH_VM_FEAT_PV_IPI        6
>>>>   #define  KVM_LOONGARCH_VM_FEAT_PV_STEALTIME    7
>>>>   #define  KVM_LOONGARCH_VM_FEAT_PTW        8
>>>> +#define  KVM_LOONGARCH_VM_FEAT_MSGINT        9
>>>>     /* Device Control API on vcpu fd */
>>>>   #define KVM_LOONGARCH_VCPU_CPUCFG    0
>>>> diff --git a/arch/loongarch/kvm/interrupt.c 
>>>> b/arch/loongarch/kvm/interrupt.c
>>>> index 8462083f0301..adc278fb3cb9 100644
>>>> --- a/arch/loongarch/kvm/interrupt.c
>>>> +++ b/arch/loongarch/kvm/interrupt.c
>>>> @@ -21,6 +21,7 @@ static unsigned int 
>>>> priority_to_irq[EXCCODE_INT_NUM] = {
>>>>       [INT_HWI5]    = CPU_IP5,
>>>>       [INT_HWI6]    = CPU_IP6,
>>>>       [INT_HWI7]    = CPU_IP7,
>>>> +    [INT_AVEC]    = CPU_AVEC,
>>>>   };
>>>>     static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int 
>>>> priority)
>>>> @@ -36,6 +37,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
>>>> unsigned int priority)
>>>>       case INT_IPI:
>>>>       case INT_SWI0:
>>>>       case INT_SWI1:
>>>> +    case INT_AVEC:
>>>>           set_gcsr_estat(irq);
>>> Do we need cpu_has_msgint() here ? It is impossible that VMM inject 
>>> INT_AVEC interrrupt on non-msgint machine such as 3C5000.
>>>
>> yes we need , how about this?
>>
>> @@ -31,6 +32,11 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, 
>> unsigned int priority)
>>          if (priority < EXCCODE_INT_NUM)
>>                  irq = priority_to_irq[priority];
>>
>> +        if (cpu_has_msgint() && (priority == INT_AVEC)) {
>> +                set_gcsr_estat(irq);
>> +                return 1;
>> +        }
>> +
>>          switch (priority) {
>>          case INT_TI:
>>          case INT_IPI:
> This is workable. Another way is to add checking in irq inject root 
> source function kvm_vcpu_ioctl_interrupt(). Both works for me.
>
> BTW, I think that there should be modification with function 
> kvm_deliver_intr() also. max irq bit is *INT_IPI + 1* where there will 
> be problem with INT_AVEC. Should it be modified as *EXCCODE_INT_NUM*?
>
Yes , we should.
> void kvm_deliver_intr(struct kvm_vcpu *vcpu)
> {
>         unsigned int priority;
>         unsigned long *pending = &vcpu->arch.irq_pending;
>         unsigned long *pending_clr = &vcpu->arch.irq_clear;
>
>         for_each_set_bit(priority, pending_clr, INT_IPI + 1)
>                 kvm_irq_clear(vcpu, priority);
>
>         for_each_set_bit(priority, pending, INT_IPI + 1)
>                 kvm_irq_deliver(vcpu, priority);
> }
>
  I'll corrrect it on v3.

Thanks.
Song Gao
> Regards
> Bibo Mao
>>
>> Thanks.
>> Song Gao
>>
>>
>>>>           break;
>>>>   @@ -63,6 +65,7 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, 
>>>> unsigned int priority)
>>>>       case INT_IPI:
>>>>       case INT_SWI0:
>>>>       case INT_SWI1:
>>>> +    case INT_AVEC:
>>>>           clear_gcsr_estat(irq);
>>> Ditto.
>>>
>>> The others look good to me.
>>>
>>> Regards
>>> Bibo Mao
>>>>           break;
>>>>   diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>>>> index 30e3b089a596..226c735155be 100644
>>>> --- a/arch/loongarch/kvm/vcpu.c
>>>> +++ b/arch/loongarch/kvm/vcpu.c
>>>> @@ -657,8 +657,7 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
>>>>           *v = GENMASK(31, 0);
>>>>           return 0;
>>>>       case LOONGARCH_CPUCFG1:
>>>> -        /* CPUCFG1_MSGINT is not supported by KVM */
>>>> -        *v = GENMASK(25, 0);
>>>> +        *v = GENMASK(26, 0);
>>>>           return 0;
>>>>       case LOONGARCH_CPUCFG2:
>>>>           /* CPUCFG2 features unconditionally supported by KVM */
>>>> @@ -726,6 +725,10 @@ static int kvm_check_cpucfg(int id, u64 val)
>>>>           return -EINVAL;
>>>>         switch (id) {
>>>> +    case LOONGARCH_CPUCFG1:
>>>> +        if ((val & CPUCFG1_MSGINT) && (!cpu_has_msgint()))
>>>> +            return -EINVAL;
>>>> +        return 0;
>>>>       case LOONGARCH_CPUCFG2:
>>>>           if (!(val & CPUCFG2_LLFTP))
>>>>               /* Guests must have a constant timer */
>>>> @@ -1658,6 +1661,12 @@ static int _kvm_vcpu_load(struct kvm_vcpu 
>>>> *vcpu, int cpu)
>>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>>>>       kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_LLBCTL);
>>>> +    if (cpu_has_msgint()) {
>>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>>>> +        kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>>>> +    }
>>>>         /* Restore Root.GINTC from unused Guest.GINTC register */
>>>>       write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
>>>> @@ -1747,6 +1756,12 @@ static int _kvm_vcpu_put(struct kvm_vcpu 
>>>> *vcpu, int cpu)
>>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN1);
>>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN2);
>>>>       kvm_save_hw_gcsr(csr, LOONGARCH_CSR_DMWIN3);
>>>> +    if (cpu_has_msgint()) {
>>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR0);
>>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR1);
>>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR2);
>>>> +        kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
>>>> +    }
>>>>         vcpu->arch.aux_inuse |= KVM_LARCH_SWCSR_LATEST;
>>>>   diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
>>>> index d8c813e2d72e..438885b6f2b1 100644
>>>> --- a/arch/loongarch/kvm/vm.c
>>>> +++ b/arch/loongarch/kvm/vm.c
>>>> @@ -37,6 +37,9 @@ static void kvm_vm_init_features(struct kvm *kvm)
>>>>           kvm->arch.support_features |= 
>>>> BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
>>>>       }
>>>>   +    if (cpu_has_msgint())
>>>> +        kvm->arch.support_features |= 
>>>> BIT(KVM_LOONGARCH_VM_FEAT_MSGINT);
>>>> +
>>>>       val = read_csr_gcfg();
>>>>       if (val & CSR_GCFG_GPMP)
>>>>           kvm->arch.support_features |= 
>>>> BIT(KVM_LOONGARCH_VM_FEAT_PMU);
>>>> @@ -153,6 +156,7 @@ static int kvm_vm_feature_has_attr(struct kvm 
>>>> *kvm, struct kvm_device_attr *attr
>>>>       case KVM_LOONGARCH_VM_FEAT_PMU:
>>>>       case KVM_LOONGARCH_VM_FEAT_PV_IPI:
>>>>       case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
>>>> +        case KVM_LOONGARCH_VM_FEAT_MSGINT:
>>>>           if (kvm_vm_support(&kvm->arch, attr->attr))
>>>>               return 0;
>>>>           return -ENXIO;
>>>>
>>>
>>