Re: [PATCH v6 5/6] LoongArch: KVM: Add valid bit check when set ESTAT CSR register
From: Huacai Chen
Date: Thu Jun 11 2026 - 06:09:56 EST
Hi, Bibo,
On Thu, Jun 11, 2026 at 2:58 PM Bibo Mao <maobibo@xxxxxxxxxxx> wrote:
>
> When set ESTAT CSR register in function _kvm_setcsr(), valid bit check
> is added here. Also interrupt CPU_AVEC is checked by msgint feature.
>
> Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx>
> ---
> arch/loongarch/kvm/vcpu.c | 25 ++++++++++++++++---------
> 1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index e986146d2272..4f67eefbd4f1 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -602,7 +602,7 @@ struct kvm_vcpu *kvm_get_vcpu_by_cpuid(struct kvm *kvm, int cpuid)
>
> static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val)
> {
> - unsigned long gintc;
> + unsigned long gintc, estat;
> struct loongarch_csrs *csr = vcpu->arch.csr;
>
> if (get_gcsr_flag(id) & INVALID_GCSR)
> @@ -621,8 +621,9 @@ static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val)
> preempt_enable();
>
> /* ESTAT IP0~IP7 get from GINTC */
> - gintc = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC) & 0xff;
> - *val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT) | (gintc << 2);
> + gintc = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC) & KVM_GINTC_IRQ_MASK;
> + estat = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT) & ~KVM_ESTAT_EXTI_MASK;
> + *val = estat | (gintc << VIP_DELTA);
> return 0;
> }
>
> @@ -637,7 +638,8 @@ static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val)
>
> static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val)
> {
> - int ret = 0, gintc;
> + int ret = 0;
> + unsigned long gintc, estat;
> struct loongarch_csrs *csr = vcpu->arch.csr;
>
> if (get_gcsr_flag(id) & INVALID_GCSR)
> @@ -648,11 +650,16 @@ static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val)
>
> if (id == LOONGARCH_CSR_ESTAT) {
> /* ESTAT IP0~IP7 inject through GINTC */
> - gintc = (val >> 2) & 0xff;
> - kvm_set_sw_gcsr(csr, LOONGARCH_CSR_GINTC, gintc);
> -
> - gintc = val & ~(0xffUL << 2);
> - kvm_set_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, gintc);
> + gintc = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC) & ~KVM_GINTC_IRQ_MASK;
> + gintc |= (val >> VIP_DELTA) & KVM_GINTC_IRQ_MASK;
> + kvm_write_sw_gcsr(csr, LOONGARCH_CSR_GINTC, gintc);
I think read & write can be combined, which means it can be simplified as:
gintc = (val >> VIP_DELTA) & KVM_GINTC_IRQ_MASK;
kvm_set_sw_gcsr(csr, LOONGARCH_CSR_GINTC, gintc);
> +
> + /* only set valid ESTAT bits */
> + estat = val & ~KVM_ESTAT_EXTI_MASK;
> + estat &= CSR_ESTAT_IS | CSR_ESTAT_EXC | CSR_ESTAT_ESUBCODE;
> + if (!kvm_guest_has_msgint(&vcpu->arch))
> + estat &= ~CPU_AVEC;
> + kvm_write_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, estat);
I think write csr may lose bits from the original value, so
kvm_write_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, estat)
should be
kvm_set_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, estat)
If you agree, I will change it when I apply because all others look good to me.
Huacai
>
> return ret;
> }
> --
> 2.39.3
>