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

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

     
    This patch splits out local apic timer start and divide config
    
    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/lapic.c |  104
+++++++++++++++++++++++---------------------------
 1 files changed, 48 insertions(+), 56 deletions(-)

diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index f19cdbe..57810fa 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -581,6 +581,43 @@ static void apic_mmio_read(struct kvm_io_device
*this,
 	}
 }
 
+static void update_divide_count(struct kvm_lapic *apic)
+{
+	u32 tmp1, tmp2, tdcr;
+
+	tdcr = apic_get_reg(apic, APIC_TDCR);
+	tmp1 = tdcr & 0xf;
+	tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
+	apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
+
+	apic_debug("timer divide count is 0x%x\n",
+				   apic->timer.divide_count);
+}
+
+static void start_apic_timer(struct kvm_lapic *apic)
+{
+	ktime_t now = apic->timer.dev.base->get_time();
+
+	apic->timer.last_update = now;
+
+	apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
+		    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
+	atomic_set(&apic->timer.pending, 0);
+	hrtimer_start(&apic->timer.dev,
+		      ktime_add_ns(now, apic->timer.period),
+		      HRTIMER_MODE_ABS);
+
+	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+			   PRIx64 ", "
+			   "timer initial count 0x%x, period %lldns, "
+			   "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
+			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
+			   apic_get_reg(apic, APIC_TMICT),
+			   apic->timer.period,
+			   ktime_to_ns(ktime_add_ns(now,
+					apic->timer.period)));
+}
+
 static void apic_mmio_write(struct kvm_io_device *this,
 			    gpa_t address, int len, const void *data)
 {
@@ -674,48 +711,16 @@ static void apic_mmio_write(struct kvm_io_device
*this,
 		break;
 
 	case APIC_TMICT:
-		{
-			ktime_t now = apic->timer.dev.base->get_time();
-
-			apic_set_reg(apic, APIC_TMICT, val);
-			apic->timer.last_update = now;
-			apic->timer.period =
-			    APIC_BUS_CYCLE_NS * apic->timer.divide_count
* val;
-
-			/* Make sure the lock ordering is coherent */
-			hrtimer_cancel(&apic->timer.dev);
-			atomic_set(&apic->timer.pending, 0);
-			hrtimer_start(&apic->timer.dev,
-				      ktime_add_ns(now,
apic->timer.period),
-				      HRTIMER_MODE_ABS);
-
-			apic_debug("%s: bus cycle is %" PRId64 "ns, now
0x%016"
-				   PRIx64 ", "
-				   "timer initial count 0x%x, period
%lldns, "
-				   "expire @ 0x%016" PRIx64 ".\n",
__FUNCTION__,
-				   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-				   apic_get_reg(apic, APIC_TMICT),
-				   apic->timer.period,
-				   ktime_to_ns(ktime_add_ns(now,
-						apic->timer.period)));
-		}
+		hrtimer_cancel(&apic->timer.dev);
+		apic_set_reg(apic, APIC_TMICT, val);
+		start_apic_timer(apic);
 		return;
 
 	case APIC_TDCR:
-		{
-			unsigned int tmp1, tmp2;
-
-			if (val & 4)
-				printk(KERN_ERR "KVM_WRITE:TDCR %x\n",
val);
-			tmp1 = val & 0xf;
-			tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
-			apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
-
-			apic_set_reg(apic, APIC_TDCR, val);
-
-			apic_debug("timer divide count is 0x%x\n",
-				   apic->timer.divide_count);
-		}
+		if (val & 4)
+			printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
+		apic_set_reg(apic, APIC_TDCR, val);
+		update_divide_count(apic);
 		break;
 
 	default:
@@ -982,7 +987,8 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu
*vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
 
-	if (apic && atomic_read(&apic->timer.pending) > 0) {
+	if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
+		atomic_read(&apic->timer.pending) > 0) {
 		if (__inject_apic_timer_irq(apic))
 			atomic_dec(&apic->timer.pending);
 	}
@@ -1015,28 +1021,14 @@ int kvm_get_apic_interrupt(struct kvm_vcpu
*vcpu)
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
-	ktime_t now;
-	u32 offset, val, tmp;
 
 	apic->base_address = vcpu->apic_base &
 			     MSR_IA32_APICBASE_BASE;
 	apic_set_reg(apic, APIC_LVR, APIC_VERSION);
-	val = apic_get_reg(apic, APIC_TMICT);
 	apic_update_ppr(apic);
-
-	/* TODO: following code can be in a common API */
 	hrtimer_cancel(&apic->timer.dev);
-	atomic_set(&apic->timer.pending, 0);
-	val = apic_get_reg(apic, APIC_TDCR);
-	tmp = ((val & 0x3) | ((val & 0x8) >> 1)) + 1;
-	apic->timer.divide_count = 0x1 << (tmp & 0x7);
-	now = apic->timer.dev.base->get_time();
-	apic->timer.last_update = now;
-	val = apic_get_reg(apic, APIC_TMICT);
-	offset = APIC_BUS_CYCLE_NS * apic->timer.divide_count * val;
-	hrtimer_start(&apic->timer.dev,
-		      ktime_add_ns(now, offset),
-		      HRTIMER_MODE_ABS);
+	update_divide_count(apic);
+	start_apic_timer(apic);
 }
 
 void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)


[-- Attachment #2: 01-kvm-apic-tdcr-tmict-cleanup.patch --]
[-- Type: application/octet-stream, Size: 4803 bytes --]

    KVM: local apic timer control cleanup
    
    This patch splits out local apic timer start and divide config
    
    Signed-off-by: Eddie (Yaozu) Dong <eddie.dong@intel.com>
    Signed-off-by: Qing He <qing.he@intel.com>


---
 drivers/kvm/lapic.c |  104 +++++++++++++++++++++++---------------------------
 1 files changed, 48 insertions(+), 56 deletions(-)

diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index f19cdbe..57810fa 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -581,6 +581,43 @@ static void apic_mmio_read(struct kvm_io_device *this,
 	}
 }
 
+static void update_divide_count(struct kvm_lapic *apic)
+{
+	u32 tmp1, tmp2, tdcr;
+
+	tdcr = apic_get_reg(apic, APIC_TDCR);
+	tmp1 = tdcr & 0xf;
+	tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
+	apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
+
+	apic_debug("timer divide count is 0x%x\n",
+				   apic->timer.divide_count);
+}
+
+static void start_apic_timer(struct kvm_lapic *apic)
+{
+	ktime_t now = apic->timer.dev.base->get_time();
+
+	apic->timer.last_update = now;
+
+	apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
+		    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
+	atomic_set(&apic->timer.pending, 0);
+	hrtimer_start(&apic->timer.dev,
+		      ktime_add_ns(now, apic->timer.period),
+		      HRTIMER_MODE_ABS);
+
+	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+			   PRIx64 ", "
+			   "timer initial count 0x%x, period %lldns, "
+			   "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
+			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
+			   apic_get_reg(apic, APIC_TMICT),
+			   apic->timer.period,
+			   ktime_to_ns(ktime_add_ns(now,
+					apic->timer.period)));
+}
+
 static void apic_mmio_write(struct kvm_io_device *this,
 			    gpa_t address, int len, const void *data)
 {
@@ -674,48 +711,16 @@ static void apic_mmio_write(struct kvm_io_device *this,
 		break;
 
 	case APIC_TMICT:
-		{
-			ktime_t now = apic->timer.dev.base->get_time();
-
-			apic_set_reg(apic, APIC_TMICT, val);
-			apic->timer.last_update = now;
-			apic->timer.period =
-			    APIC_BUS_CYCLE_NS * apic->timer.divide_count * val;
-
-			/* Make sure the lock ordering is coherent */
-			hrtimer_cancel(&apic->timer.dev);
-			atomic_set(&apic->timer.pending, 0);
-			hrtimer_start(&apic->timer.dev,
-				      ktime_add_ns(now, apic->timer.period),
-				      HRTIMER_MODE_ABS);
-
-			apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
-				   PRIx64 ", "
-				   "timer initial count 0x%x, period %lldns, "
-				   "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
-				   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-				   apic_get_reg(apic, APIC_TMICT),
-				   apic->timer.period,
-				   ktime_to_ns(ktime_add_ns(now,
-						apic->timer.period)));
-		}
+		hrtimer_cancel(&apic->timer.dev);
+		apic_set_reg(apic, APIC_TMICT, val);
+		start_apic_timer(apic);
 		return;
 
 	case APIC_TDCR:
-		{
-			unsigned int tmp1, tmp2;
-
-			if (val & 4)
-				printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
-			tmp1 = val & 0xf;
-			tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
-			apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
-
-			apic_set_reg(apic, APIC_TDCR, val);
-
-			apic_debug("timer divide count is 0x%x\n",
-				   apic->timer.divide_count);
-		}
+		if (val & 4)
+			printk(KERN_ERR "KVM_WRITE:TDCR %x\n", val);
+		apic_set_reg(apic, APIC_TDCR, val);
+		update_divide_count(apic);
 		break;
 
 	default:
@@ -982,7 +987,8 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
 
-	if (apic && atomic_read(&apic->timer.pending) > 0) {
+	if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
+		atomic_read(&apic->timer.pending) > 0) {
 		if (__inject_apic_timer_irq(apic))
 			atomic_dec(&apic->timer.pending);
 	}
@@ -1015,28 +1021,14 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->apic;
-	ktime_t now;
-	u32 offset, val, tmp;
 
 	apic->base_address = vcpu->apic_base &
 			     MSR_IA32_APICBASE_BASE;
 	apic_set_reg(apic, APIC_LVR, APIC_VERSION);
-	val = apic_get_reg(apic, APIC_TMICT);
 	apic_update_ppr(apic);
-
-	/* TODO: following code can be in a common API */
 	hrtimer_cancel(&apic->timer.dev);
-	atomic_set(&apic->timer.pending, 0);
-	val = apic_get_reg(apic, APIC_TDCR);
-	tmp = ((val & 0x3) | ((val & 0x8) >> 1)) + 1;
-	apic->timer.divide_count = 0x1 << (tmp & 0x7);
-	now = apic->timer.dev.base->get_time();
-	apic->timer.last_update = now;
-	val = apic_get_reg(apic, APIC_TMICT);
-	offset = APIC_BUS_CYCLE_NS * apic->timer.divide_count * val;
-	hrtimer_start(&apic->timer.dev,
-		      ktime_add_ns(now, offset),
-		      HRTIMER_MODE_ABS);
+	update_divide_count(apic);
+	start_apic_timer(apic);
 }
 
 void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)


[-- 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] 2+ messages in thread

* Re: [PATCH 1/3]  KVM: local apic timer control cleanup
       [not found] ` <37E52D09333DE2469A03574C88DBF40FA9C207-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2007-09-06  9:24   ` Avi Kivity
  0 siblings, 0 replies; 2+ messages in thread
From: Avi Kivity @ 2007-09-06  9:24 UTC (permalink / raw)
  To: He, Qing; +Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

He, Qing wrote:
>      
>     This patch splits out local apic timer start and divide config
>     
>   

Applied, thanks.

-- 
Any sufficiently difficult bug is indistinguishable from a feature.


-------------------------------------------------------------------------
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/

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

end of thread, other threads:[~2007-09-06  9:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-06  8:37 [PATCH 1/3] KVM: local apic timer control cleanup He, Qing
     [not found] ` <37E52D09333DE2469A03574C88DBF40FA9C207-wq7ZOvIWXbM/UvCtAeCM4rfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-09-06  9:24   ` Avi Kivity

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