public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/3] KVM: fix apic timer save/migration when inactive
@ 2007-09-06  8:38 He, Qing
       [not found] ` <37E52D09333DE2469A03574C88DBF40FA9C208-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: He, Qing @ 2007-09-06  8:38 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

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

    
    When local apic timer is inactive or is expired in oneshot mode, it
    should not be restarted in save/restore or hrtimer migration. This
    patch fixes this.

    Signed-off-by: Eddie (Yaozu) Dong <eddie.dong-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
    Signed-off-by: Qing He <qing.he-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>


---
 drivers/kvm/irq.h      |    2 ++
 drivers/kvm/kvm_main.c |    1 +
 drivers/kvm/lapic.c    |   41 +++++++++++++++++++++++++++++++++++------
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 5f97e25..68d454c 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -110,6 +110,7 @@ struct kvm_lapic {
 	struct kvm_io_device dev;
 	struct {
 		atomic_t pending;
+		atomic_t active;
 		s64 period;	/* unit: ns */
 		u32 divide_count;
 		ktime_t last_update;
@@ -150,6 +151,7 @@ int kvm_apic_match_physical_addr(struct kvm_lapic
*apic, u16 dest);
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
 int kvm_apic_set_irq(struct kvm_lapic *apic, u8 vec, u8 trig);
+void kvm_apic_pre_state_save(struct kvm_vcpu *vcpu);
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
 int kvm_ioapic_init(struct kvm *kvm);
 void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index f101430..694fe1e 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2679,6 +2679,7 @@ static int kvm_vcpu_ioctl_get_lapic(struct
kvm_vcpu *vcpu,
 				    struct kvm_lapic_state *s)
 {
 	vcpu_load(vcpu);
+	kvm_apic_pre_state_save(vcpu);
 	memcpy(s->regs, vcpu->apic->regs, sizeof *s);
 	vcpu_put(vcpu);
 
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index 57810fa..ae85eb0 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -603,6 +603,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 	apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
 		    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
 	atomic_set(&apic->timer.pending, 0);
+	atomic_set(&apic->timer.active, 1);
 	hrtimer_start(&apic->timer.dev,
 		      ktime_add_ns(now, apic->timer.period),
 		      HRTIMER_MODE_ABS);
@@ -750,6 +751,7 @@ void kvm_free_apic(struct kvm_lapic *apic)
 	if (!apic)
 		return;
 
+	atomic_set(&apic->timer.active, 0);
 	hrtimer_cancel(&apic->timer.dev);
 
 	if (apic->regs_page) {
@@ -828,6 +830,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 	ASSERT(apic != NULL);
 
 	/* Stop the timer in case it's a reset to an active apic */
+	atomic_set(&apic->timer.active, 0);
 	hrtimer_cancel(&apic->timer.dev);
 
 	apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
@@ -900,6 +903,9 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 					apic->timer.dev.expires,
 					apic->timer.period);
 	}
+	else
+		atomic_set(&apic->timer.active, 0);
+		
 	return result;
 }
 
@@ -1018,9 +1024,23 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 	return vector;
 }
 
+void kvm_apic_pre_state_save(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->apic;
+	u32 tmict;
+
+	tmict = apic_get_reg(apic, APIC_TMICT);
+
+	if (atomic_read(&apic->timer.active))
+		apic_set_reg(apic, APIC_TMCCT, tmict);
+	else
+		apic_set_reg(apic, APIC_TMCCT, 0);
+}
+
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
+	u32 tmcct;
 
 	apic->base_address = vcpu->apic_base &
 			     MSR_IA32_APICBASE_BASE;
@@ -1028,7 +1048,13 @@ void kvm_apic_post_state_restore(struct kvm_vcpu
*vcpu)
 	apic_update_ppr(apic);
 	hrtimer_cancel(&apic->timer.dev);
 	update_divide_count(apic);
-	start_apic_timer(apic);
+	tmcct = apic_get_reg(apic, APIC_TMCCT);
+	if (tmcct) {
+		atomic_set(&apic->timer.active, 1);
+		start_apic_timer(apic);
+	}
+	else
+		atomic_set(&apic->timer.active, 0);
 }
 
 void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
@@ -1036,11 +1062,14 @@ void kvm_migrate_apic_timer(struct kvm_vcpu
*vcpu)
 	struct kvm_lapic *apic = vcpu->apic;
 	struct hrtimer *timer;
 
-	if (apic) {
-		timer = &apic->timer.dev;
-		hrtimer_cancel(timer);
-		hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
-	}
+	if (!apic)
+		return;
+
+	timer = &apic->timer.dev;
+	hrtimer_cancel(timer);
+	if (atomic_read(&apic->timer.active))
+		hrtimer_start(timer, timer->expires,
+			      HRTIMER_MODE_ABS);
 }
 EXPORT_SYMBOL_GPL(kvm_migrate_apic_timer);
 


[-- Attachment #2: 02-kvm-inactive-apic-timer-sr.patch --]
[-- Type: application/octet-stream, Size: 4428 bytes --]

    KVM: fix apic timer save/migration when inactive
    
    When local apic timer is inactive or is expired in oneshot mode, it
    should not be restarted in save/restore or hrtimer migration. This
    patch fixes this.

    Signed-off-by: Eddie (Yaozu) Dong <eddie.dong@intel.com>
    Signed-off-by: Qing He <qing.he@intel.com>


---
 drivers/kvm/irq.h      |    2 ++
 drivers/kvm/kvm_main.c |    1 +
 drivers/kvm/lapic.c    |   41 +++++++++++++++++++++++++++++++++++------
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 5f97e25..68d454c 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -110,6 +110,7 @@ struct kvm_lapic {
 	struct kvm_io_device dev;
 	struct {
 		atomic_t pending;
+		atomic_t active;
 		s64 period;	/* unit: ns */
 		u32 divide_count;
 		ktime_t last_update;
@@ -150,6 +151,7 @@ int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
 int kvm_apic_set_irq(struct kvm_lapic *apic, u8 vec, u8 trig);
+void kvm_apic_pre_state_save(struct kvm_vcpu *vcpu);
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
 int kvm_ioapic_init(struct kvm *kvm);
 void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index f101430..694fe1e 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2679,6 +2679,7 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
 				    struct kvm_lapic_state *s)
 {
 	vcpu_load(vcpu);
+	kvm_apic_pre_state_save(vcpu);
 	memcpy(s->regs, vcpu->apic->regs, sizeof *s);
 	vcpu_put(vcpu);
 
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index 57810fa..ae85eb0 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -603,6 +603,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 	apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
 		    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
 	atomic_set(&apic->timer.pending, 0);
+	atomic_set(&apic->timer.active, 1);
 	hrtimer_start(&apic->timer.dev,
 		      ktime_add_ns(now, apic->timer.period),
 		      HRTIMER_MODE_ABS);
@@ -750,6 +751,7 @@ void kvm_free_apic(struct kvm_lapic *apic)
 	if (!apic)
 		return;
 
+	atomic_set(&apic->timer.active, 0);
 	hrtimer_cancel(&apic->timer.dev);
 
 	if (apic->regs_page) {
@@ -828,6 +830,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 	ASSERT(apic != NULL);
 
 	/* Stop the timer in case it's a reset to an active apic */
+	atomic_set(&apic->timer.active, 0);
 	hrtimer_cancel(&apic->timer.dev);
 
 	apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
@@ -900,6 +903,9 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 					apic->timer.dev.expires,
 					apic->timer.period);
 	}
+	else
+		atomic_set(&apic->timer.active, 0);
+		
 	return result;
 }
 
@@ -1018,9 +1024,23 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 	return vector;
 }
 
+void kvm_apic_pre_state_save(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->apic;
+	u32 tmict;
+
+	tmict = apic_get_reg(apic, APIC_TMICT);
+
+	if (atomic_read(&apic->timer.active))
+		apic_set_reg(apic, APIC_TMCCT, tmict);
+	else
+		apic_set_reg(apic, APIC_TMCCT, 0);
+}
+
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
+	u32 tmcct;
 
 	apic->base_address = vcpu->apic_base &
 			     MSR_IA32_APICBASE_BASE;
@@ -1028,7 +1048,13 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 	apic_update_ppr(apic);
 	hrtimer_cancel(&apic->timer.dev);
 	update_divide_count(apic);
-	start_apic_timer(apic);
+	tmcct = apic_get_reg(apic, APIC_TMCCT);
+	if (tmcct) {
+		atomic_set(&apic->timer.active, 1);
+		start_apic_timer(apic);
+	}
+	else
+		atomic_set(&apic->timer.active, 0);
 }
 
 void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
@@ -1036,11 +1062,14 @@ void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
 	struct kvm_lapic *apic = vcpu->apic;
 	struct hrtimer *timer;
 
-	if (apic) {
-		timer = &apic->timer.dev;
-		hrtimer_cancel(timer);
-		hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS);
-	}
+	if (!apic)
+		return;
+
+	timer = &apic->timer.dev;
+	hrtimer_cancel(timer);
+	if (atomic_read(&apic->timer.active))
+		hrtimer_start(timer, timer->expires,
+			      HRTIMER_MODE_ABS);
 }
 EXPORT_SYMBOL_GPL(kvm_migrate_apic_timer);
 


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

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

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

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-09-10  7:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-06  8:38 [PATCH 2/3] KVM: fix apic timer save/migration when inactive He, Qing
     [not found] ` <37E52D09333DE2469A03574C88DBF40FA9C208-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-09-06  9:15   ` Avi Kivity
     [not found]     ` <46DFC523.7090806-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-06  9:47       ` Avi Kivity
     [not found]         ` <46DFCCAE.3040507-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-07  3:26           ` He, Qing
     [not found]             ` <37E52D09333DE2469A03574C88DBF40FA9C20B-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-09-09  7:39               ` Avi Kivity
     [not found]                 ` <46E3A31E.7060107-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-10  5:58                   ` He, Qing
     [not found]                     ` <37E52D09333DE2469A03574C88DBF40FA9C21C-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-09-10  6:01                       ` [PATCH 2/3] KVM: fix apic timer save/migration wheninactive He, Qing
     [not found]                         ` <37E52D09333DE2469A03574C88DBF40FA9C21D-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-09-10  7:27                           ` Avi Kivity
     [not found]                             ` <46E4F1E0.8090805-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-09-10  7:50                               ` He, Qing

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox