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(-)
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
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;
>
在 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;
>>
>
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;
>>>
>>
>
在 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;
>>>>
>>>
>>
© 2016 - 2025 Red Hat, Inc.