Skip to content

Commit 1612673

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Remove SW timer switch when vcpu is halt polling
With halt-polling supported, there is checking for pending events or interrupts when vcpu executes idle instruction. Pending interrupts include injected SW interrupts and passthrough HW interrupts, such as HW timer interrupts, since HW timer works still even if vcpu exists from VM mode. Since HW timer pending interrupt can be set directly with CSR status register, and pending HW timer interrupt checking is used in vcpu block checking function, it is not necessary to switch to SW timer during halt-polling. This patch adds preemption disabling in function kvm_cpu_has_pending_timer(), and removes SW timer switching in idle instruction emulation function. Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 7ab6fb5 commit 1612673

3 files changed

Lines changed: 19 additions & 15 deletions

File tree

arch/loongarch/kvm/exit.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,8 @@ int kvm_emu_idle(struct kvm_vcpu *vcpu)
200200
++vcpu->stat.idle_exits;
201201
trace_kvm_exit_idle(vcpu, KVM_TRACE_EXIT_IDLE);
202202

203-
if (!kvm_arch_vcpu_runnable(vcpu)) {
204-
/*
205-
* Switch to the software timer before halt-polling/blocking as
206-
* the guest's timer may be a break event for the vCPU, and the
207-
* hypervisor timer runs only when the CPU is in guest mode.
208-
* Switch before halt-polling so that KVM recognizes an expired
209-
* timer before blocking.
210-
*/
211-
kvm_save_timer(vcpu);
212-
kvm_vcpu_block(vcpu);
213-
}
203+
if (!kvm_arch_vcpu_runnable(vcpu))
204+
kvm_vcpu_halt(vcpu);
214205

215206
return EMULATE_DONE;
216207
}

arch/loongarch/kvm/timer.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,17 @@ static void _kvm_save_timer(struct kvm_vcpu *vcpu)
155155
*/
156156
hrtimer_cancel(&vcpu->arch.swtimer);
157157
hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
158-
} else
158+
} else if (vcpu->stat.generic.blocking) {
159159
/*
160-
* Inject timer interrupt so that hall polling can dectect and exit
160+
* Inject timer interrupt so that halt polling can dectect and exit.
161+
* VCPU is scheduled out already and sleeps in rcuwait queue and
162+
* will not poll pending events again. kvm_queue_irq() is not enough,
163+
* hrtimer swtimer should be used here.
161164
*/
162-
kvm_queue_irq(vcpu, INT_TI);
165+
expire = ktime_add_ns(ktime_get(), 10);
166+
vcpu->arch.expire = expire;
167+
hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
168+
}
163169
}
164170

165171
/*

arch/loongarch/kvm/vcpu.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,15 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
187187

188188
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
189189
{
190-
return kvm_pending_timer(vcpu) ||
190+
int ret;
191+
192+
/* Protect from TOD sync and vcpu_load/put() */
193+
preempt_disable();
194+
ret = kvm_pending_timer(vcpu) ||
191195
kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT) & (1 << INT_TI);
196+
preempt_enable();
197+
198+
return ret;
192199
}
193200

194201
int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)

0 commit comments

Comments
 (0)