* [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