From: Bibo Mao <maobibo@loongson.cn>
To: Huacai Chen <chenhuacai@kernel.org>
Cc: kernel@xen0n.name, kvm@vger.kernel.org,
loongarch@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH v2 5/5] LoongArch: KVM: Simple interrupt status acquire interface
Date: Thu, 14 May 2026 14:28:24 +0800 [thread overview]
Message-ID: <20260514062824.1378373-6-maobibo@loongson.cn> (raw)
In-Reply-To: <20260514062824.1378373-1-maobibo@loongson.cn>
When VM is migrating, interrupts status are stored in software CSR estat
register, also new injected interrupts are cached in
vcpu::arch::irq_pending.
With interrupt status acquire interface, there is expensive vcpu_load()
and vcpu_put() function call to sync cached vcpu::arch::irq_pending.
Here new internal API kvm_vcpu_sync_intr() is added to sync cached
pending irq to software CSR estat register.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
arch/loongarch/include/asm/kvm_vcpu.h | 1 +
arch/loongarch/kvm/interrupt.c | 42 +++++++++++++++++++++++++++
arch/loongarch/kvm/vcpu.c | 15 ++++++----
3 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h
index efe26b04b35f..e78bb2527329 100644
--- a/arch/loongarch/include/asm/kvm_vcpu.h
+++ b/arch/loongarch/include/asm/kvm_vcpu.h
@@ -64,6 +64,7 @@ int kvm_emu_idle(struct kvm_vcpu *vcpu);
int kvm_pending_timer(struct kvm_vcpu *vcpu);
int kvm_handle_fault(struct kvm_vcpu *vcpu, int fault);
void kvm_deliver_intr(struct kvm_vcpu *vcpu);
+void kvm_vcpu_sync_intr(struct kvm_vcpu *vcpu);
void kvm_deliver_exception(struct kvm_vcpu *vcpu);
void kvm_own_fpu(struct kvm_vcpu *vcpu);
diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
index 380aabb3d4d0..24925c238a65 100644
--- a/arch/loongarch/kvm/interrupt.c
+++ b/arch/loongarch/kvm/interrupt.c
@@ -71,6 +71,48 @@ void kvm_deliver_intr(struct kvm_vcpu *vcpu)
}
}
+void kvm_vcpu_sync_intr(struct kvm_vcpu *vcpu)
+{
+ struct loongarch_csrs *csr = vcpu->arch.csr;
+ unsigned long mask, val;
+
+ if (!csr)
+ return;
+
+ mask = READ_ONCE(vcpu->arch.irq_clear);
+ if (mask) {
+ mask = xchg_relaxed(&vcpu->arch.irq_clear, 0);
+
+ /*
+ * sync cached irq_clear to sw state
+ *
+ * When VM is migrated to other physical machines or
+ * snapshot is created, cached irq pending state should
+ * be synced
+ */
+ val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT);
+ val &= ~(mask & KVM_ESTAT_IRQ_MASK);
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, val);
+
+ val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC);
+ val &= ~((mask >> 2) & KVM_GINTC_IRQ_MASK);
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_GINTC, val);
+ }
+
+ mask = READ_ONCE(vcpu->arch.irq_pending);
+ if (mask) {
+ mask = xchg_relaxed(&vcpu->arch.irq_pending, 0);
+ /* sync cached irq_pending to sw state */
+ val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_ESTAT);
+ val |= (mask & KVM_ESTAT_IRQ_MASK);
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_ESTAT, val);
+
+ val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_GINTC);
+ val |= (mask >> 2) & KVM_GINTC_IRQ_MASK;
+ kvm_write_sw_gcsr(csr, LOONGARCH_CSR_GINTC, val);
+ }
+}
+
int kvm_pending_timer(struct kvm_vcpu *vcpu)
{
return test_bit(INT_TI, &vcpu->arch.irq_pending);
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 2f4fd6fa5b0e..5f94360e8a4b 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -610,14 +610,11 @@ static int _kvm_getcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 *val)
if (id == LOONGARCH_CSR_ESTAT) {
preempt_disable();
- vcpu_load(vcpu);
/*
* Sync pending interrupts into ESTAT so that interrupt
* remains during VM migration stage
*/
- kvm_deliver_intr(vcpu);
- vcpu->arch.aux_inuse &= ~KVM_LARCH_SWCSR_LATEST;
- vcpu_put(vcpu);
+ kvm_vcpu_sync_intr(vcpu);
preempt_enable();
/* ESTAT IP0~IP7 get from GINTC */
@@ -1649,6 +1646,14 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
/* Restore timer state regardless */
kvm_restore_timer(vcpu);
+
+ /*
+ * Restore Root.GINTC from unused Guest.GINTC register
+ *
+ * SW state about LOONGARCH_CSR_GINTC is updated with get_csr()
+ * ioctl command only. Update HW state from changed SW state.
+ */
+ write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
/* Don't bother restoring registers multiple times unless necessary */
@@ -1711,8 +1716,6 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_ISR3);
}
- /* Restore Root.GINTC from unused Guest.GINTC register */
- write_csr_gintc(csr->csrs[LOONGARCH_CSR_GINTC]);
write_csr_gstat(csr->csrs[LOONGARCH_CSR_GSTAT]);
/*
--
2.39.3
prev parent reply other threads:[~2026-05-14 6:28 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-14 6:28 [PATCH v2 0/5] LoongArch: KVM: Small enhancement about interrupt injection Bibo Mao
2026-05-14 6:28 ` [PATCH v2 1/5] LoongArch: KVM: Check irq validility in kvm_vcpu_ioctl_interrupt() Bibo Mao
2026-05-14 6:28 ` [PATCH v2 2/5] LoongArch: KVM: Use existing macro about interrupt bit mask Bibo Mao
2026-05-14 6:28 ` [PATCH v2 3/5] LoongArch: KVM: Inject interrupt with batch method Bibo Mao
2026-05-14 6:28 ` [PATCH v2 4/5] LoongArch: KVM: Add valid bit check when set ESTAT CSR register Bibo Mao
2026-05-14 6:28 ` Bibo Mao [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260514062824.1378373-6-maobibo@loongson.cn \
--to=maobibo@loongson.cn \
--cc=chenhuacai@kernel.org \
--cc=kernel@xen0n.name \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=loongarch@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).