Re: [patch 1/2] KVM: hlt emulation should take in-kernel APIC/PIT timers into account

Yang, Sheng
2008-05-09T07:49:20Z

[-- Attachment #1: Type: text/plain, Size: 3958 bytes --]

On Sunday 13 April 2008 17:28:22 Avi Kivity wrote:
> Marcelo Tosatti wrote:
> > On Fri, Apr 11, 2008 at 03:12:41PM +0300, Avi Kivity wrote:
> >> This breaks ia64 (and shouldn't s390 use this too?)
> >>
> >>> * We will block until either an interrupt or a signal wakes us up
> >>> */
> >>> while (!kvm_cpu_has_interrupt(vcpu)
> >>> + && !kvm_cpu_has_pending_timer(vcpu)
> >>
> >> I guess the fix is to stub this out for the other archs.
> >
> > Agreed. How's this.
>
> Better :); applied.

Hi, Marcelo

This patch got into trouble when OS don't use PIT/LAPIC timer and don't
disable them. Then the pending counters would keep increasing, but the HLT
emulation can't be executed. And this would resulted in mass a lot (above
220,000 per second) halt_exit for the Windows XP that using RTC as the
clocksource (and keep PIT enabled after bios did, just mask the pin) idle,
and the cpu utilize would be about 100% of QEmu process.

The following patch used another way to fix the issue, though not very formal.

From 4d08ef3173084a6f0b7b76a0727e04ff42b614ba Mon Sep 17 00:00:00 2001
From: Sheng Yang <sheng.yang@intel.com>
Date: Fri, 9 May 2008 15:36:27 +0800
Subject: [PATCH] KVM: Fix CPU utilize hit 100% when emulate HLT in some OS

Signed-off-by: Sheng Yang <sheng.yang@intel.com>
---
arch/x86/kvm/i8254.c | 2 ++
arch/x86/kvm/lapic.c | 2 ++
include/asm-x86/kvm_host.h | 2 ++
virt/kvm/kvm_main.c | 2 +-
4 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index fba0e4e..b2b9eb7 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -199,6 +199,7 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
struct kvm_kpit_timer *pt = &ps->pit_timer;

atomic_inc(&pt->pending);
+ vcpu0->arch.timer_pending_updated = 1;
smp_mb__after_atomic_inc();
/* FIXME: handle case where the guest is in guest mode */
if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
@@ -577,6 +578,7 @@ void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
struct kvm *kvm = vcpu->kvm;
struct kvm_kpit_state *ps;

+ kvm->vcpus[0]->arch.timer_pending_updated = 0;
if (vcpu && pit) {
ps = &pit->pit_state;

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 7652f88..b919f3f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -944,6 +944,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
wait_queue_head_t *q = &apic->vcpu->wq;

atomic_inc(&apic->timer.pending);
+ apic->vcpu->arch.timer_pending_updated = 1;
if (waitqueue_active(q)) {
apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
wake_up_interruptible(q);
@@ -1067,6 +1068,7 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;

+ vcpu->arch.timer_pending_updated = 0;
if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
atomic_read(&apic->timer.pending) > 0) {
if (__inject_apic_timer_irq(apic))
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index 1d8cd01..5eded7b 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {
struct kvm_vcpu_time_info hv_clock;
unsigned int time_offset;
struct page *time_page;
+
+ bool timer_check_pending;
};

struct kvm_mem_alias {
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0846d3d..ff635e3 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -791,7 +791,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
* We will block until either an interrupt or a signal wakes us up
*/
while (!kvm_cpu_has_interrupt(vcpu)
- && !kvm_cpu_has_pending_timer(vcpu)
+ && !vcpu->arch.timer_pending_updated
&& !signal_pending(current)
&& !kvm_arch_vcpu_runnable(vcpu)) {
set_current_state(TASK_INTERRUPTIBLE);
--
1.5.5

[-- Attachment #2: 0001-KVM-Fix-CPU-utilize-hit-100-when-emulate-HLT-in-so.patch --]
[-- Type: text/x-diff, Size: 2913 bytes --]

From 4d08ef3173084a6f0b7b76a0727e04ff42b614ba Mon Sep 17 00:00:00 2001
From: Sheng Yang <sheng.yang@intel.com>
Date: Fri, 9 May 2008 15:36:27 +0800
Subject: [PATCH] KVM: Fix CPU utilize hit 100% when emulate HLT in some OS

Signed-off-by: Sheng Yang <sheng.yang@intel.com>
---
arch/x86/kvm/i8254.c | 2 ++
arch/x86/kvm/lapic.c | 2 ++
include/asm-x86/kvm_host.h | 2 ++
virt/kvm/kvm_main.c | 2 +-
4 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index fba0e4e..b2b9eb7 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -199,6 +199,7 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
struct kvm_kpit_timer *pt = &ps->pit_timer;

atomic_inc(&pt->pending);
+ vcpu0->arch.timer_pending_updated = 1;
smp_mb__after_atomic_inc();
/* FIXME: handle case where the guest is in guest mode */
if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
@@ -577,6 +578,7 @@ void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
struct kvm *kvm = vcpu->kvm;
struct kvm_kpit_state *ps;

+ kvm->vcpus[0]->arch.timer_pending_updated = 0;
if (vcpu && pit) {
ps = &pit->pit_state;

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 7652f88..b919f3f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -944,6 +944,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
wait_queue_head_t *q = &apic->vcpu->wq;

atomic_inc(&apic->timer.pending);
+ apic->vcpu->arch.timer_pending_updated = 1;
if (waitqueue_active(q)) {
apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
wake_up_interruptible(q);
@@ -1067,6 +1068,7 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;

+ vcpu->arch.timer_pending_updated = 0;
if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
atomic_read(&apic->timer.pending) > 0) {
if (__inject_apic_timer_irq(apic))
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index 1d8cd01..5eded7b 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -285,6 +285,8 @@ struct kvm_vcpu_arch {
struct kvm_vcpu_time_info hv_clock;
unsigned int time_offset;
struct page *time_page;
+
+ bool timer_check_pending;
};

struct kvm_mem_alias {
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0846d3d..ff635e3 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -791,7 +791,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
* We will block until either an interrupt or a signal wakes us up
*/
while (!kvm_cpu_has_interrupt(vcpu)
- && !kvm_cpu_has_pending_timer(vcpu)
+ && !vcpu->arch.timer_pending_updated
&& !signal_pending(current)
&& !kvm_arch_vcpu_runnable(vcpu)) {
set_current_state(TASK_INTERRUPTIBLE);
--
1.5.5

[-- Attachment #3: Type: text/plain, Size: 320 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone

[-- Attachment #4: Type: text/plain, Size: 158 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net