This patch adds Kvm put/get msgint CSRs and check msgint feature.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 5 ++-
target/loongarch/cpu.h | 1 +
target/loongarch/kvm/kvm.c | 69 ++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index e22568c84a..fe60c9b92b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -443,9 +443,6 @@ static void loongarch_max_initfn(Object *obj)
cpu->ptw = ON_OFF_AUTO_AUTO;
if (tcg_enabled()) {
- cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
- cpu->msgint = ON_OFF_AUTO_AUTO;
-
uint32_t data = cpu->env.cpucfg[2];
data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
/* Enable LA v1.1 instructions */
@@ -456,6 +453,8 @@ static void loongarch_max_initfn(Object *obj)
data = FIELD_DP32(data, CPUCFG2, SCQ, 1);
cpu->env.cpucfg[2] = data;
}
+ cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
+ cpu->msgint = ON_OFF_AUTO_AUTO;
}
#if defined(CONFIG_KVM)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 096d778928..e6bbcded95 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -301,6 +301,7 @@ enum loongarch_features {
LOONGARCH_FEATURE_PV_IPI,
LOONGARCH_FEATURE_STEALTIME,
LOONGARCH_FEATURE_PTW,
+ LOONGARCH_FEATURE_MSGINT,
};
typedef struct LoongArchBT {
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 9d844c4905..dad260636a 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -35,6 +35,13 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
+static bool kvm_cpu_has_msgint(CPUState *cs)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+ return FIELD_EX64(cpu->env.cpucfg[1], CPUCFG1, MSG_INT);
+}
+
static int kvm_get_stealtime(CPUState *cs)
{
CPULoongArchState *env = cpu_env(cs);
@@ -358,6 +365,20 @@ static int kvm_loongarch_get_csr(CPUState *cs)
ret |= kvm_loongarch_get_pmu(cs);
+ if (kvm_cpu_has_msgint(cs)) {
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
+ &env->CSR_MSGIS[0]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
+ &env->CSR_MSGIS[1]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
+ &env->CSR_MSGIS[2]);
+
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
+ &env->CSR_MSGIS[3]);
+ }
+
ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
&env->CSR_TVAL);
@@ -533,6 +554,20 @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level)
ret |= kvm_loongarch_put_pmu(cs);
+ if (kvm_cpu_has_msgint(cs)) {
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
+ &env->CSR_MSGIS[0]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
+ &env->CSR_MSGIS[1]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
+ &env->CSR_MSGIS[2]);
+
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
+ &env->CSR_MSGIS[3]);
+ }
+
/*
* timer cfg must be put at last since it is used to enable
* guest timer
@@ -982,6 +1017,12 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
return (ret == 0);
+ case LOONGARCH_FEATURE_MSGINT:
+ attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
+ attr.attr = KVM_LOONGARCH_VM_FEAT_MSGINT;
+ ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+ return (ret == 0);
+
default:
return false;
}
@@ -1155,6 +1196,28 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
return 0;
}
+static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
+{
+ CPULoongArchState *env = cpu_env(cs);
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ bool kvm_supported;
+
+ kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_MSGINT);
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 0);
+ if (cpu->msgint == ON_OFF_AUTO_ON) {
+ if (kvm_supported) {
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
+ } else {
+ error_setg(errp, "'msgint' feature not supported by KVM on this host");
+ return -ENOTSUP;
+ }
+ } else if ((cpu->msgint == ON_OFF_AUTO_AUTO) && kvm_supported) {
+ env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
+ }
+
+ return 0;
+}
+
int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
{
return 0;
@@ -1210,6 +1273,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
return ret;
}
+ ret = kvm_cpu_check_msgint(cs, &local_err);
+ if (ret < 0) {
+ error_report_err(local_err);
+ return ret;
+ }
+
return 0;
}
--
2.54.0
On 2026/5/7 下午5:23, Song Gao wrote:
> This patch adds Kvm put/get msgint CSRs and check msgint feature.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu.c | 5 ++-
> target/loongarch/cpu.h | 1 +
> target/loongarch/kvm/kvm.c | 69 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 72 insertions(+), 3 deletions(-)
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index e22568c84a..fe60c9b92b 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -443,9 +443,6 @@ static void loongarch_max_initfn(Object *obj)
>
> cpu->ptw = ON_OFF_AUTO_AUTO;
> if (tcg_enabled()) {
> - cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
> - cpu->msgint = ON_OFF_AUTO_AUTO;
> -
> uint32_t data = cpu->env.cpucfg[2];
> data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
> /* Enable LA v1.1 instructions */
> @@ -456,6 +453,8 @@ static void loongarch_max_initfn(Object *obj)
> data = FIELD_DP32(data, CPUCFG2, SCQ, 1);
> cpu->env.cpucfg[2] = data;
> }
> + cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
> + cpu->msgint = ON_OFF_AUTO_AUTO;
> }
>
> #if defined(CONFIG_KVM)
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 096d778928..e6bbcded95 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -301,6 +301,7 @@ enum loongarch_features {
> LOONGARCH_FEATURE_PV_IPI,
> LOONGARCH_FEATURE_STEALTIME,
> LOONGARCH_FEATURE_PTW,
> + LOONGARCH_FEATURE_MSGINT,
> };
>
> typedef struct LoongArchBT {
> diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
> index 9d844c4905..dad260636a 100644
> --- a/target/loongarch/kvm/kvm.c
> +++ b/target/loongarch/kvm/kvm.c
> @@ -35,6 +35,13 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> KVM_CAP_LAST_INFO
> };
>
> +static bool kvm_cpu_has_msgint(CPUState *cs)
> +{
> + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> +
> + return FIELD_EX64(cpu->env.cpucfg[1], CPUCFG1, MSG_INT);
> +}
> +
> static int kvm_get_stealtime(CPUState *cs)
> {
> CPULoongArchState *env = cpu_env(cs);
> @@ -358,6 +365,20 @@ static int kvm_loongarch_get_csr(CPUState *cs)
>
> ret |= kvm_loongarch_get_pmu(cs);
>
> + if (kvm_cpu_has_msgint(cs)) {
Would you like to add some comments that CSR register MSGIS getting must
be put after CSR register CSR_ESTAT? Since register CSR_ESTAT will sync
software pending MSGINT status to hardware register and modify HW CSR
MSGIS registers.
So this piece of code should put after CSR_ESTAT register reading.
Regards
Bibo Mao
> + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
> + &env->CSR_MSGIS[0]);
> +
> + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
> + &env->CSR_MSGIS[1]);
> +
> + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
> + &env->CSR_MSGIS[2]);
> +
> + ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
> + &env->CSR_MSGIS[3]);
> + }
> +
> ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
> &env->CSR_TVAL);
>
> @@ -533,6 +554,20 @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level)
>
> ret |= kvm_loongarch_put_pmu(cs);
>
> + if (kvm_cpu_has_msgint(cs)) {
> + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
> + &env->CSR_MSGIS[0]);
> +
> + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
> + &env->CSR_MSGIS[1]);
> +
> + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
> + &env->CSR_MSGIS[2]);
> +
> + ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
> + &env->CSR_MSGIS[3]);
> + }
> +
> /*
> * timer cfg must be put at last since it is used to enable
> * guest timer
> @@ -982,6 +1017,12 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
> ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
> return (ret == 0);
>
> + case LOONGARCH_FEATURE_MSGINT:
> + attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
> + attr.attr = KVM_LOONGARCH_VM_FEAT_MSGINT;
> + ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
> + return (ret == 0);
> +
> default:
> return false;
> }
> @@ -1155,6 +1196,28 @@ static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
> return 0;
> }
>
> +static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
> +{
> + CPULoongArchState *env = cpu_env(cs);
> + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
> + bool kvm_supported;
> +
> + kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_MSGINT);
> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 0);
> + if (cpu->msgint == ON_OFF_AUTO_ON) {
> + if (kvm_supported) {
> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
> + } else {
> + error_setg(errp, "'msgint' feature not supported by KVM on this host");
> + return -ENOTSUP;
> + }
> + } else if ((cpu->msgint == ON_OFF_AUTO_AUTO) && kvm_supported) {
> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 1);
> + }
> +
> + return 0;
> +}
> +
> int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
> {
> return 0;
> @@ -1210,6 +1273,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
> return ret;
> }
>
> + ret = kvm_cpu_check_msgint(cs, &local_err);
> + if (ret < 0) {
> + error_report_err(local_err);
> + return ret;
> + }
> +
> return 0;
> }
>
>
在 2026/5/20 下午2:44, Bibo Mao 写道:
>
>
> On 2026/5/7 下午5:23, Song Gao wrote:
>> This patch adds Kvm put/get msgint CSRs and check msgint feature.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> target/loongarch/cpu.c | 5 ++-
>> target/loongarch/cpu.h | 1 +
>> target/loongarch/kvm/kvm.c | 69 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 72 insertions(+), 3 deletions(-)
>>
>> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
>> index e22568c84a..fe60c9b92b 100644
>> --- a/target/loongarch/cpu.c
>> +++ b/target/loongarch/cpu.c
>> @@ -443,9 +443,6 @@ static void loongarch_max_initfn(Object *obj)
>> cpu->ptw = ON_OFF_AUTO_AUTO;
>> if (tcg_enabled()) {
>> - cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1,
>> MSG_INT, 1);
>> - cpu->msgint = ON_OFF_AUTO_AUTO;
>> -
>> uint32_t data = cpu->env.cpucfg[2];
>> data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
>> /* Enable LA v1.1 instructions */
>> @@ -456,6 +453,8 @@ static void loongarch_max_initfn(Object *obj)
>> data = FIELD_DP32(data, CPUCFG2, SCQ, 1);
>> cpu->env.cpucfg[2] = data;
>> }
>> + cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1,
>> MSG_INT, 1);
>> + cpu->msgint = ON_OFF_AUTO_AUTO;
>> }
>> #if defined(CONFIG_KVM)
>> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
>> index 096d778928..e6bbcded95 100644
>> --- a/target/loongarch/cpu.h
>> +++ b/target/loongarch/cpu.h
>> @@ -301,6 +301,7 @@ enum loongarch_features {
>> LOONGARCH_FEATURE_PV_IPI,
>> LOONGARCH_FEATURE_STEALTIME,
>> LOONGARCH_FEATURE_PTW,
>> + LOONGARCH_FEATURE_MSGINT,
>> };
>> typedef struct LoongArchBT {
>> diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
>> index 9d844c4905..dad260636a 100644
>> --- a/target/loongarch/kvm/kvm.c
>> +++ b/target/loongarch/kvm/kvm.c
>> @@ -35,6 +35,13 @@ const KVMCapabilityInfo
>> kvm_arch_required_capabilities[] = {
>> KVM_CAP_LAST_INFO
>> };
>> +static bool kvm_cpu_has_msgint(CPUState *cs)
>> +{
>> + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
>> +
>> + return FIELD_EX64(cpu->env.cpucfg[1], CPUCFG1, MSG_INT);
>> +}
>> +
>> static int kvm_get_stealtime(CPUState *cs)
>> {
>> CPULoongArchState *env = cpu_env(cs);
>> @@ -358,6 +365,20 @@ static int kvm_loongarch_get_csr(CPUState *cs)
>> ret |= kvm_loongarch_get_pmu(cs);
>> + if (kvm_cpu_has_msgint(cs)) {
> Would you like to add some comments that CSR register MSGIS getting
> must be put after CSR register CSR_ESTAT? Since register CSR_ESTAT
> will sync software pending MSGINT status to hardware register and
> modify HW CSR MSGIS registers.
>
> So this piece of code should put after CSR_ESTAT register reading.
>
I will correct it on v3.
Thanks.
Song Gao
> Regards
> Bibo Mao
>
>> + ret |= kvm_get_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
>> + &env->CSR_MSGIS[0]);
>> +
>> + ret |= kvm_get_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
>> + &env->CSR_MSGIS[1]);
>> +
>> + ret |= kvm_get_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
>> + &env->CSR_MSGIS[2]);
>> +
>> + ret |= kvm_get_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
>> + &env->CSR_MSGIS[3]);
>> + }
>> +
>> ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
>> &env->CSR_TVAL);
>> @@ -533,6 +554,20 @@ static int kvm_loongarch_put_csr(CPUState *cs,
>> KvmPutState level)
>> ret |= kvm_loongarch_put_pmu(cs);
>> + if (kvm_cpu_has_msgint(cs)) {
>> + ret |= kvm_set_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(0)),
>> + &env->CSR_MSGIS[0]);
>> +
>> + ret |= kvm_set_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(1)),
>> + &env->CSR_MSGIS[1]);
>> +
>> + ret |= kvm_set_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(2)),
>> + &env->CSR_MSGIS[2]);
>> +
>> + ret |= kvm_set_one_reg(cs,
>> KVM_IOC_CSRID(LOONGARCH_CSR_MSGIS(3)),
>> + &env->CSR_MSGIS[3]);
>> + }
>> +
>> /*
>> * timer cfg must be put at last since it is used to enable
>> * guest timer
>> @@ -982,6 +1017,12 @@ static bool kvm_feature_supported(CPUState *cs,
>> enum loongarch_features feature)
>> ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
>> return (ret == 0);
>> + case LOONGARCH_FEATURE_MSGINT:
>> + attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
>> + attr.attr = KVM_LOONGARCH_VM_FEAT_MSGINT;
>> + ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
>> + return (ret == 0);
>> +
>> default:
>> return false;
>> }
>> @@ -1155,6 +1196,28 @@ static int kvm_cpu_check_pv_features(CPUState
>> *cs, Error **errp)
>> return 0;
>> }
>> +static int kvm_cpu_check_msgint(CPUState *cs, Error **errp)
>> +{
>> + CPULoongArchState *env = cpu_env(cs);
>> + LoongArchCPU *cpu = LOONGARCH_CPU(cs);
>> + bool kvm_supported;
>> +
>> + kvm_supported = kvm_feature_supported(cs,
>> LOONGARCH_FEATURE_MSGINT);
>> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1, MSG_INT, 0);
>> + if (cpu->msgint == ON_OFF_AUTO_ON) {
>> + if (kvm_supported) {
>> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1,
>> MSG_INT, 1);
>> + } else {
>> + error_setg(errp, "'msgint' feature not supported by KVM
>> on this host");
>> + return -ENOTSUP;
>> + }
>> + } else if ((cpu->msgint == ON_OFF_AUTO_AUTO) && kvm_supported) {
>> + env->cpucfg[1] = FIELD_DP32(env->cpucfg[1], CPUCFG1,
>> MSG_INT, 1);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
>> {
>> return 0;
>> @@ -1210,6 +1273,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
>> return ret;
>> }
>> + ret = kvm_cpu_check_msgint(cs, &local_err);
>> + if (ret < 0) {
>> + error_report_err(local_err);
>> + return ret;
>> + }
>> +
>> return 0;
>> }
>>
© 2016 - 2026 Red Hat, Inc.