Skip to content

Commit de5a6e5

Browse files
bibo-maogregkh
authored andcommitted
LoongArch: KVM: Fix HW timer interrupt lost when inject interrupt by software
commit 2433f3f upstream. With passthrough HW timer, timer interrupt is injected by HW. When inject emulated CPU interrupt by software such SIP0/SIP1/IPI, HW timer interrupt may be lost. Here check whether there is timer tick value inversion before and after injecting emulated CPU interrupt by software, timer enabling by reading timer cfg register is skipped. If the timer tick value is detected with changing, then timer should be enabled. And inject a timer interrupt by software if there is. Cc: <stable@vger.kernel.org> Fixes: f45ad5b ("LoongArch: KVM: Implement vcpu interrupt operations"). Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8f38465 commit de5a6e5

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

arch/loongarch/kvm/interrupt.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
2727
static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
2828
{
2929
unsigned int irq = 0;
30+
unsigned long old, new;
3031

3132
clear_bit(priority, &vcpu->arch.irq_pending);
3233
if (priority < EXCCODE_INT_NUM)
@@ -42,7 +43,13 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
4243
case INT_IPI:
4344
case INT_SWI0:
4445
case INT_SWI1:
46+
old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
4547
set_gcsr_estat(irq);
48+
new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
49+
50+
/* Inject TI if TVAL inverted */
51+
if (new > old)
52+
set_gcsr_estat(CPU_TIMER);
4653
break;
4754

4855
case INT_HWI0 ... INT_HWI7:
@@ -59,6 +66,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
5966
static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
6067
{
6168
unsigned int irq = 0;
69+
unsigned long old, new;
6270

6371
clear_bit(priority, &vcpu->arch.irq_clear);
6472
if (priority < EXCCODE_INT_NUM)
@@ -74,7 +82,13 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
7482
case INT_IPI:
7583
case INT_SWI0:
7684
case INT_SWI1:
85+
old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
7786
clear_gcsr_estat(irq);
87+
new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
88+
89+
/* Inject TI if TVAL inverted */
90+
if (new > old)
91+
set_gcsr_estat(CPU_TIMER);
7892
break;
7993

8094
case INT_HWI0 ... INT_HWI7:

0 commit comments

Comments
 (0)