All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-22  8:55 ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-22  8:55 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti, kvm, qemu-devel; +Cc: Tian, Kevin, Liu, Jinsong

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

>From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Thu, 22 Sep 2011 14:00:08 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 +++++-
 5 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4..66b64b8 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -135,9 +135,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +180,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -570,6 +584,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +681,32 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
+				apic->lapic_timer.period = NSEC_PER_MSEC/2;
+		}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +715,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +825,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +838,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+		       hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+		       val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -883,6 +940,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b..10c6ee6 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -41,6 +41,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6

[-- Attachment #2: kvm-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 10119 bytes --]

From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Thu, 22 Sep 2011 14:00:08 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 +++++-
 5 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4..66b64b8 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -135,9 +135,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +180,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -570,6 +584,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +681,32 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
+				apic->lapic_timer.period = NSEC_PER_MSEC/2;
+		}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +715,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +825,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +838,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+		       hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+		       val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -883,6 +940,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b..10c6ee6 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -41,6 +41,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6


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

* [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-22  8:55 ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-22  8:55 UTC (permalink / raw)
  To: Avi Kivity, Marcelo Tosatti, kvm, qemu-devel; +Cc: Liu, Jinsong, Tian, Kevin

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

>From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Thu, 22 Sep 2011 14:00:08 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 +++++-
 5 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4..66b64b8 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -135,9 +135,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +180,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -570,6 +584,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +681,32 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
+				apic->lapic_timer.period = NSEC_PER_MSEC/2;
+		}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +715,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +825,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +838,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+		       hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+		       val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -883,6 +940,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b..10c6ee6 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -41,6 +41,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6

[-- Attachment #2: kvm-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 10119 bytes --]

From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Thu, 22 Sep 2011 14:00:08 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 +++++-
 5 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 57dcbd4..66b64b8 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -135,9 +135,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -166,7 +180,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -570,6 +584,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -664,29 +681,32 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
-			apic->lapic_timer.period = NSEC_PER_MSEC/2;
-	}
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			if (apic->lapic_timer.period < NSEC_PER_MSEC/2)
+				apic->lapic_timer.period = NSEC_PER_MSEC/2;
+		}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -695,6 +715,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -782,7 +825,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -796,7 +838,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+		       hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+		       val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -883,6 +940,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 52c9e6b..10c6ee6 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -41,6 +41,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6


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

* Re: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-22  8:55 ` [Qemu-devel] " Liu, Jinsong
@ 2011-09-22 14:48   ` Marcelo Tosatti
  -1 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-22 14:48 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
> From: Liu, Jinsong <jinsong.liu@intel.com>
> Date: Thu, 22 Sep 2011 14:00:08 +0800
> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> 
> This patch emulate lapic tsc deadline timer for guest:
> Enumerate tsc deadline timer capability by CPUID;
> Enable tsc deadline timer mode by lapic MMIO;
> Start tsc deadline timer by WRMSR;
> 
> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
> ---
>  arch/x86/include/asm/kvm_host.h |    2 +
>  arch/x86/kvm/kvm_timer.h        |    2 +
>  arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
>  arch/x86/kvm/lapic.h            |    3 +
>  arch/x86/kvm/x86.c              |   16 +++++-
>  5 files changed, 123 insertions(+), 23 deletions(-)

Looks good, please rebase against branch master of

git://github.com/avikivity/kvm.git 


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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-22 14:48   ` Marcelo Tosatti
  0 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-22 14:48 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00 2001
> From: Liu, Jinsong <jinsong.liu@intel.com>
> Date: Thu, 22 Sep 2011 14:00:08 +0800
> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> 
> This patch emulate lapic tsc deadline timer for guest:
> Enumerate tsc deadline timer capability by CPUID;
> Enable tsc deadline timer mode by lapic MMIO;
> Start tsc deadline timer by WRMSR;
> 
> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
> ---
>  arch/x86/include/asm/kvm_host.h |    2 +
>  arch/x86/kvm/kvm_timer.h        |    2 +
>  arch/x86/kvm/lapic.c            |  123 ++++++++++++++++++++++++++++++++-------
>  arch/x86/kvm/lapic.h            |    3 +
>  arch/x86/kvm/x86.c              |   16 +++++-
>  5 files changed, 123 insertions(+), 23 deletions(-)

Looks good, please rebase against branch master of

git://github.com/avikivity/kvm.git 

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

* RE: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-22 14:48   ` [Qemu-devel] " Marcelo Tosatti
@ 2011-09-22 15:22     ` Liu, Jinsong
  -1 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-22 15:22 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

Marcelo Tosatti wrote:
> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>> 2001 
>> From: Liu, Jinsong <jinsong.liu@intel.com>
>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
>> 
>> This patch emulate lapic tsc deadline timer for guest:
>> Enumerate tsc deadline timer capability by CPUID;
>> Enable tsc deadline timer mode by lapic MMIO;
>> Start tsc deadline timer by WRMSR;
>> 
>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>  arch/x86/include/asm/kvm_host.h |    2 +
>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>  arch/x86/kvm/lapic.c            |  123
>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>  5 files changed, 123 insertions(+), 23 deletions(-)
> 
> Looks good, please rebase against branch master of
> 
> git://github.com/avikivity/kvm.git

Thanks!

And, for qemu patch rebase, I guess below address, which one is right?
git://github.com/avikivity/qemu-kvm.git   or
git://github.com/avikivity/qemu.git

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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-22 15:22     ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-22 15:22 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

Marcelo Tosatti wrote:
> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>> 2001 
>> From: Liu, Jinsong <jinsong.liu@intel.com>
>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
>> 
>> This patch emulate lapic tsc deadline timer for guest:
>> Enumerate tsc deadline timer capability by CPUID;
>> Enable tsc deadline timer mode by lapic MMIO;
>> Start tsc deadline timer by WRMSR;
>> 
>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>  arch/x86/include/asm/kvm_host.h |    2 +
>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>  arch/x86/kvm/lapic.c            |  123
>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>  5 files changed, 123 insertions(+), 23 deletions(-)
> 
> Looks good, please rebase against branch master of
> 
> git://github.com/avikivity/kvm.git

Thanks!

And, for qemu patch rebase, I guess below address, which one is right?
git://github.com/avikivity/qemu-kvm.git   or
git://github.com/avikivity/qemu.git

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

* Re: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-22 15:22     ` [Qemu-devel] " Liu, Jinsong
@ 2011-09-22 21:31       ` Marcelo Tosatti
  -1 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-22 21:31 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

On Thu, Sep 22, 2011 at 11:22:02PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>> 2001 
> >> From: Liu, Jinsong <jinsong.liu@intel.com>
> >> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> >> 
> >> This patch emulate lapic tsc deadline timer for guest:
> >> Enumerate tsc deadline timer capability by CPUID;
> >> Enable tsc deadline timer mode by lapic MMIO;
> >> Start tsc deadline timer by WRMSR;
> >> 
> >> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>  arch/x86/include/asm/kvm_host.h |    2 +
> >>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>  arch/x86/kvm/lapic.c            |  123
> >>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
> >>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>  5 files changed, 123 insertions(+), 23 deletions(-)
> > 
> > Looks good, please rebase against branch master of
> > 
> > git://github.com/avikivity/kvm.git
> 
> Thanks!
> 
> And, for qemu patch rebase, I guess below address, which one is right?
> git://github.com/avikivity/qemu-kvm.git   or
> git://github.com/avikivity/qemu.git

qemu.git. 

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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-22 21:31       ` Marcelo Tosatti
  0 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-22 21:31 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

On Thu, Sep 22, 2011 at 11:22:02PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>> 2001 
> >> From: Liu, Jinsong <jinsong.liu@intel.com>
> >> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> >> 
> >> This patch emulate lapic tsc deadline timer for guest:
> >> Enumerate tsc deadline timer capability by CPUID;
> >> Enable tsc deadline timer mode by lapic MMIO;
> >> Start tsc deadline timer by WRMSR;
> >> 
> >> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>  arch/x86/include/asm/kvm_host.h |    2 +
> >>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>  arch/x86/kvm/lapic.c            |  123
> >>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
> >>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>  5 files changed, 123 insertions(+), 23 deletions(-)
> > 
> > Looks good, please rebase against branch master of
> > 
> > git://github.com/avikivity/kvm.git
> 
> Thanks!
> 
> And, for qemu patch rebase, I guess below address, which one is right?
> git://github.com/avikivity/qemu-kvm.git   or
> git://github.com/avikivity/qemu.git

qemu.git. 

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

* RE: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-22 14:48   ` [Qemu-devel] " Marcelo Tosatti
@ 2011-09-23  8:25     ` Liu, Jinsong
  -1 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-23  8:25 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

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

Marcelo Tosatti wrote:
> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>> 2001 
>> From: Liu, Jinsong <jinsong.liu@intel.com>
>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
>> 
>> This patch emulate lapic tsc deadline timer for guest:
>> Enumerate tsc deadline timer capability by CPUID;
>> Enable tsc deadline timer mode by lapic MMIO;
>> Start tsc deadline timer by WRMSR;
>> 
>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>  arch/x86/include/asm/kvm_host.h |    2 +
>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>  arch/x86/kvm/lapic.c            |  123
>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>  5 files changed, 123 insertions(+), 23 deletions(-)
> 
> Looks good, please rebase against branch master of
> 
> git://github.com/avikivity/kvm.git

Rebased as attached.

Thanks,
Jinsong

[-- Attachment #2: qemu-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 2630 bytes --]

From 79466a72314a63a6c1efa0ee014a754c785d6650 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 15:25:35 +0800
Subject: [PATCH] Qemu co-operation with kvm tsc deadline timer

KVM add emulation of lapic tsc deadline timer for guest.
This patch is co-operation work at qemu side.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 target-i386/cpu.h     |    2 ++
 target-i386/kvm.c     |    7 +++++++
 target-i386/machine.c |    1 +
 3 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4a6f675..b5909b7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -283,6 +283,7 @@
 #define MSR_IA32_APICBASE_BSP           (1<<8)
 #define MSR_IA32_APICBASE_ENABLE        (1<<11)
 #define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
+#define MSR_IA32_TSCDEADLINE            0x6e0
 
 #define MSR_MTRRcap			0xfe
 #define MSR_MTRRcap_VCNT		8
@@ -687,6 +688,7 @@ typedef struct CPUX86State {
     uint64_t async_pf_en_msr;
 
     uint64_t tsc;
+    uint64_t tsc_deadline;
 
     uint64_t mcg_status;
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 22b1dd0..fc2683d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -924,6 +924,8 @@ static int kvm_put_msrs(CPUState *env, int level)
         }
     }
 
+    kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
+
     msr_data.info.nmsrs = n;
 
     return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
@@ -1155,6 +1157,8 @@ static int kvm_get_msrs(CPUState *env)
         }
     }
 
+    msrs[n++].index = MSR_IA32_TSCDEADLINE;
+
     msr_data.info.nmsrs = n;
     ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
     if (ret < 0) {
@@ -1195,6 +1199,9 @@ static int kvm_get_msrs(CPUState *env)
         case MSR_IA32_TSC:
             env->tsc = msrs[i].data;
             break;
+        case MSR_IA32_TSCDEADLINE:
+            env->tsc_deadline = msrs[i].data;
+            break;
         case MSR_VM_HSAVE_PA:
             env->vm_hsave = msrs[i].data;
             break;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 9aca8e0..25fa97d 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -410,6 +410,7 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(xcr0, CPUState, 12),
         VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
         VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
+        VMSTATE_UINT64_V(tsc_deadline, CPUState, 13),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
-- 
1.6.5.6


[-- Attachment #3: Add-some-pre-defination.patch --]
[-- Type: application/octet-stream, Size: 2247 bytes --]

From 1f9c899601d0addff2c3e198ad63db073bbd55e1 Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 13:33:43 +0800
Subject: [PATCH 1/2] Subject: [PATCH 1/2] Add some pre-defination

This pre-defination is preparing for KVM tsc deadline timer emulation, but theirself are no-kvm-specific.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/apicdef.h    |    2 ++
 arch/x86/include/asm/cpufeature.h |    1 +
 arch/x86/include/asm/msr-index.h  |    2 ++
 3 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 34595d5..3925d80 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -100,7 +100,9 @@
 #define		APIC_TIMER_BASE_CLKIN		0x0
 #define		APIC_TIMER_BASE_TMBASE		0x1
 #define		APIC_TIMER_BASE_DIV		0x2
+#define		APIC_LVT_TIMER_ONESHOT		(0 << 17)
 #define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
+#define		APIC_LVT_TIMER_TSCDEADLINE	(2 << 17)
 #define		APIC_LVT_MASKED			(1 << 16)
 #define		APIC_LVT_LEVEL_TRIGGER		(1 << 15)
 #define		APIC_LVT_REMOTE_IRR		(1 << 14)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 4258aac..823c4b6 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -120,6 +120,7 @@
 #define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
 #define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
 #define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER	(4*32+24) /* Tsc deadline timer */
 #define X86_FEATURE_AES		(4*32+25) /* AES instructions */
 #define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index d52609a..a6962d9 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -229,6 +229,8 @@
 #define MSR_IA32_APICBASE_ENABLE	(1<<11)
 #define MSR_IA32_APICBASE_BASE		(0xfffff<<12)
 
+#define MSR_IA32_TSCDEADLINE		0x000006e0
+
 #define MSR_IA32_UCODE_WRITE		0x00000079
 #define MSR_IA32_UCODE_REV		0x0000008b
 
-- 
1.6.5.6


[-- Attachment #4: kvm-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 10583 bytes --]

From e32a56204b95abc43d6fd6e4d594aa718d2cf6f5 Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 16:00:20 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  137 ++++++++++++++++++++++++++++++--------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 ++++-
 5 files changed, 130 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2fb20ca..f9385ec 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -138,9 +138,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -169,7 +183,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -572,6 +586,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -666,37 +683,40 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		s64 min_period = min_timer_period_us * 1000LL;
-
-		if (apic->lapic_timer.period < min_period) {
-			pr_info_ratelimited(
-				"kvm: vcpu %i: requested %lld ns "
-				"lapic timer period limited to %lld ns\n",
-				apic->vcpu->vcpu_id, apic->lapic_timer.period,
-				min_period);
-			apic->lapic_timer.period = min_period;
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			s64 min_period = min_timer_period_us * 1000LL;
+
+			if (apic->lapic_timer.period < min_period) {
+				pr_info_ratelimited(
+				    "kvm: vcpu %i: requested %lld ns "
+				    "lapic timer period limited to %lld ns\n",
+				    apic->vcpu->vcpu_id,
+				    apic->lapic_timer.period, min_period);
+				apic->lapic_timer.period = min_period;
+			}
 		}
-	}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -705,6 +725,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -792,7 +835,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -806,7 +848,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+			hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+			val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -902,6 +959,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 8287243..138e8cc 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -42,6 +42,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6


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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-23  8:25     ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-23  8:25 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

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

Marcelo Tosatti wrote:
> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>> 2001 
>> From: Liu, Jinsong <jinsong.liu@intel.com>
>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
>> 
>> This patch emulate lapic tsc deadline timer for guest:
>> Enumerate tsc deadline timer capability by CPUID;
>> Enable tsc deadline timer mode by lapic MMIO;
>> Start tsc deadline timer by WRMSR;
>> 
>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>  arch/x86/include/asm/kvm_host.h |    2 +
>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>  arch/x86/kvm/lapic.c            |  123
>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>  5 files changed, 123 insertions(+), 23 deletions(-)
> 
> Looks good, please rebase against branch master of
> 
> git://github.com/avikivity/kvm.git

Rebased as attached.

Thanks,
Jinsong

[-- Attachment #2: qemu-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 2630 bytes --]

From 79466a72314a63a6c1efa0ee014a754c785d6650 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 15:25:35 +0800
Subject: [PATCH] Qemu co-operation with kvm tsc deadline timer

KVM add emulation of lapic tsc deadline timer for guest.
This patch is co-operation work at qemu side.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 target-i386/cpu.h     |    2 ++
 target-i386/kvm.c     |    7 +++++++
 target-i386/machine.c |    1 +
 3 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4a6f675..b5909b7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -283,6 +283,7 @@
 #define MSR_IA32_APICBASE_BSP           (1<<8)
 #define MSR_IA32_APICBASE_ENABLE        (1<<11)
 #define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
+#define MSR_IA32_TSCDEADLINE            0x6e0
 
 #define MSR_MTRRcap			0xfe
 #define MSR_MTRRcap_VCNT		8
@@ -687,6 +688,7 @@ typedef struct CPUX86State {
     uint64_t async_pf_en_msr;
 
     uint64_t tsc;
+    uint64_t tsc_deadline;
 
     uint64_t mcg_status;
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 22b1dd0..fc2683d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -924,6 +924,8 @@ static int kvm_put_msrs(CPUState *env, int level)
         }
     }
 
+    kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
+
     msr_data.info.nmsrs = n;
 
     return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
@@ -1155,6 +1157,8 @@ static int kvm_get_msrs(CPUState *env)
         }
     }
 
+    msrs[n++].index = MSR_IA32_TSCDEADLINE;
+
     msr_data.info.nmsrs = n;
     ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
     if (ret < 0) {
@@ -1195,6 +1199,9 @@ static int kvm_get_msrs(CPUState *env)
         case MSR_IA32_TSC:
             env->tsc = msrs[i].data;
             break;
+        case MSR_IA32_TSCDEADLINE:
+            env->tsc_deadline = msrs[i].data;
+            break;
         case MSR_VM_HSAVE_PA:
             env->vm_hsave = msrs[i].data;
             break;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 9aca8e0..25fa97d 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -410,6 +410,7 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(xcr0, CPUState, 12),
         VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
         VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
+        VMSTATE_UINT64_V(tsc_deadline, CPUState, 13),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
-- 
1.6.5.6


[-- Attachment #3: Add-some-pre-defination.patch --]
[-- Type: application/octet-stream, Size: 2247 bytes --]

From 1f9c899601d0addff2c3e198ad63db073bbd55e1 Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 13:33:43 +0800
Subject: [PATCH 1/2] Subject: [PATCH 1/2] Add some pre-defination

This pre-defination is preparing for KVM tsc deadline timer emulation, but theirself are no-kvm-specific.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/apicdef.h    |    2 ++
 arch/x86/include/asm/cpufeature.h |    1 +
 arch/x86/include/asm/msr-index.h  |    2 ++
 3 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 34595d5..3925d80 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -100,7 +100,9 @@
 #define		APIC_TIMER_BASE_CLKIN		0x0
 #define		APIC_TIMER_BASE_TMBASE		0x1
 #define		APIC_TIMER_BASE_DIV		0x2
+#define		APIC_LVT_TIMER_ONESHOT		(0 << 17)
 #define		APIC_LVT_TIMER_PERIODIC		(1 << 17)
+#define		APIC_LVT_TIMER_TSCDEADLINE	(2 << 17)
 #define		APIC_LVT_MASKED			(1 << 16)
 #define		APIC_LVT_LEVEL_TRIGGER		(1 << 15)
 #define		APIC_LVT_REMOTE_IRR		(1 << 14)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 4258aac..823c4b6 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -120,6 +120,7 @@
 #define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
 #define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
 #define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER	(4*32+24) /* Tsc deadline timer */
 #define X86_FEATURE_AES		(4*32+25) /* AES instructions */
 #define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index d52609a..a6962d9 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -229,6 +229,8 @@
 #define MSR_IA32_APICBASE_ENABLE	(1<<11)
 #define MSR_IA32_APICBASE_BASE		(0xfffff<<12)
 
+#define MSR_IA32_TSCDEADLINE		0x000006e0
+
 #define MSR_IA32_UCODE_WRITE		0x00000079
 #define MSR_IA32_UCODE_REV		0x0000008b
 
-- 
1.6.5.6


[-- Attachment #4: kvm-tsc-deadline-timer.patch --]
[-- Type: application/octet-stream, Size: 10583 bytes --]

From e32a56204b95abc43d6fd6e4d594aa718d2cf6f5 Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Fri, 23 Sep 2011 16:00:20 +0800
Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest

This patch emulate lapic tsc deadline timer for guest:
Enumerate tsc deadline timer capability by CPUID;
Enable tsc deadline timer mode by lapic MMIO;
Start tsc deadline timer by WRMSR;

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +
 arch/x86/kvm/kvm_timer.h        |    2 +
 arch/x86/kvm/lapic.c            |  137 ++++++++++++++++++++++++++++++--------
 arch/x86/kvm/lapic.h            |    3 +
 arch/x86/kvm/x86.c              |   16 ++++-
 5 files changed, 130 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6ab4241..b9d4291 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -673,6 +673,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
 /* minimum supported tsc_khz for guests */
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
index 64bc6ea..497dbaa 100644
--- a/arch/x86/kvm/kvm_timer.h
+++ b/arch/x86/kvm/kvm_timer.h
@@ -2,6 +2,8 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
 	atomic_t pending;			/* accumulated triggered timers */
 	bool reinject;
 	struct kvm_timer_ops *t_ops;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2fb20ca..f9385ec 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -138,9 +138,23 @@ static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
+static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
+}
+
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
+}
+
+static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
+{
+	return ((apic_get_reg(apic, APIC_LVTT) &
+		apic->lapic_timer.timer_mode_mask) ==
+			APIC_LVT_TIMER_TSCDEADLINE);
 }
 
 static inline int apic_lvt_nmi_mode(u32 lvt_val)
@@ -169,7 +183,7 @@ static inline int apic_x2apic_mode(struct kvm_lapic *apic)
 }
 
 static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
-	LVT_MASK | APIC_LVT_TIMER_PERIODIC,	/* LVTT */
+	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
 	LINT_MASK, LINT_MASK,	/* LVT0-1 */
@@ -572,6 +586,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 		break;
 
 	case APIC_TMCCT:	/* Timer CCR */
+		if (apic_lvtt_tscdeadline(apic))
+			return 0;
+
 		val = apic_get_tmcct(apic);
 		break;
 
@@ -666,37 +683,40 @@ static void update_divide_count(struct kvm_lapic *apic)
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->lapic_timer.timer.base->get_time();
-
-	apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	ktime_t now;
 	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->lapic_timer.period)
-		return;
-	/*
-	 * Do not allow the guest to program periodic timers with small
-	 * interval, since the hrtimers are not throttled by the host
-	 * scheduler.
-	 */
-	if (apic_lvtt_period(apic)) {
-		s64 min_period = min_timer_period_us * 1000LL;
-
-		if (apic->lapic_timer.period < min_period) {
-			pr_info_ratelimited(
-				"kvm: vcpu %i: requested %lld ns "
-				"lapic timer period limited to %lld ns\n",
-				apic->vcpu->vcpu_id, apic->lapic_timer.period,
-				min_period);
-			apic->lapic_timer.period = min_period;
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
+		/* lapic timer in oneshot or peroidic mode */
+		now = apic->lapic_timer.timer.base->get_time();
+		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+			    * APIC_BUS_CYCLE_NS * apic->divide_count;
+
+		if (!apic->lapic_timer.period)
+			return;
+		/*
+		 * Do not allow the guest to program periodic timers with small
+		 * interval, since the hrtimers are not throttled by the host
+		 * scheduler.
+		 */
+		if (apic_lvtt_period(apic)) {
+			s64 min_period = min_timer_period_us * 1000LL;
+
+			if (apic->lapic_timer.period < min_period) {
+				pr_info_ratelimited(
+				    "kvm: vcpu %i: requested %lld ns "
+				    "lapic timer period limited to %lld ns\n",
+				    apic->vcpu->vcpu_id,
+				    apic->lapic_timer.period, min_period);
+				apic->lapic_timer.period = min_period;
+			}
 		}
-	}
 
-	hrtimer_start(&apic->lapic_timer.timer,
-		      ktime_add_ns(now, apic->lapic_timer.period),
-		      HRTIMER_MODE_ABS);
+		hrtimer_start(&apic->lapic_timer.timer,
+			      ktime_add_ns(now, apic->lapic_timer.period),
+			      HRTIMER_MODE_ABS);
 
-	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
+		apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 			   PRIx64 ", "
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
@@ -705,6 +725,29 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
+	} else if (apic_lvtt_tscdeadline(apic)) {
+		/* lapic timer in tsc deadline mode */
+		u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
+		u64 ns = 0;
+		struct kvm_vcpu *vcpu = apic->vcpu;
+		unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+		unsigned long flags;
+
+		if (unlikely(!tscdeadline || !this_tsc_khz))
+			return;
+
+		local_irq_save(flags);
+
+		now = apic->lapic_timer.timer.base->get_time();
+		guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+		if (likely(tscdeadline > guest_tsc))
+			ns = (tscdeadline - guest_tsc)
+				* 1000000L / this_tsc_khz;
+		hrtimer_start(&apic->lapic_timer.timer,
+			ktime_add_ns(now, ns), HRTIMER_MODE_ABS);
+
+		local_irq_restore(flags);
+	}
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -792,7 +835,6 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LVT0:
 		apic_manage_nmi_watchdog(apic, val);
-	case APIC_LVTT:
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
@@ -806,7 +848,22 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 		break;
 
+	case APIC_LVTT:
+		if ((apic_get_reg(apic, APIC_LVTT) &
+		    apic->lapic_timer.timer_mode_mask) !=
+		   (val & apic->lapic_timer.timer_mode_mask))
+			hrtimer_cancel(&apic->lapic_timer.timer);
+
+		if (!apic_sw_enabled(apic))
+			val |= APIC_LVT_MASKED;
+		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
+		apic_set_reg(apic, APIC_LVTT, val);
+		break;
+
 	case APIC_TMICT:
+		if (apic_lvtt_tscdeadline(apic))
+			break;
+
 		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
@@ -902,6 +959,28 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
  *----------------------------------------------------------------------
  */
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
+
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+		return;
+
+	hrtimer_cancel(&apic->lapic_timer.timer);
+	apic->lapic_timer.tscdeadline = data;
+	start_apic_timer(apic);
+}
+
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 8287243..138e8cc 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -42,6 +42,9 @@ int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
 bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
+void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6b37f18..382c0b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -610,6 +610,13 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= bit(X86_FEATURE_OSXSAVE);
 	}
+
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+		best->function == 0x1) {
+		best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER);
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (3 << 17);
+	} else
+		vcpu->arch.apic->lapic_timer.timer_mode_mask = (1 << 17);
 }
 
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -825,6 +832,7 @@ static u32 msrs_to_save[] = {
 static unsigned num_msrs_to_save;
 
 static u32 emulated_msrs[] = {
+	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
 	MSR_IA32_MCG_CTL,
@@ -1000,7 +1008,7 @@ static inline int kvm_tsc_changes_freq(void)
 	return ret;
 }
 
-static u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
 {
 	if (vcpu->arch.virtual_tsc_khz)
 		return vcpu->arch.virtual_tsc_khz;
@@ -1564,6 +1572,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
+	case MSR_IA32_TSCDEADLINE:
+		kvm_set_lapic_tscdeadline_msr(vcpu, data);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		vcpu->arch.ia32_misc_enable_msr = data;
 		break;
@@ -1893,6 +1904,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
 		return kvm_x2apic_msr_read(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_TSCDEADLINE:
+		data = kvm_get_lapic_tscdeadline_msr(vcpu);
+		break;
 	case MSR_IA32_MISC_ENABLE:
 		data = vcpu->arch.ia32_misc_enable_msr;
 		break;
-- 
1.6.5.6


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

* Re: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-23  8:25     ` [Qemu-devel] " Liu, Jinsong
@ 2011-09-23 13:08       ` Marcelo Tosatti
  -1 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-23 13:08 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>> 2001 
> >> From: Liu, Jinsong <jinsong.liu@intel.com>
> >> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> >> 
> >> This patch emulate lapic tsc deadline timer for guest:
> >> Enumerate tsc deadline timer capability by CPUID;
> >> Enable tsc deadline timer mode by lapic MMIO;
> >> Start tsc deadline timer by WRMSR;
> >> 
> >> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>  arch/x86/include/asm/kvm_host.h |    2 +
> >>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>  arch/x86/kvm/lapic.c            |  123
> >>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
> >>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>  5 files changed, 123 insertions(+), 23 deletions(-)
> > 
> > Looks good, please rebase against branch master of
> > 
> > git://github.com/avikivity/kvm.git
> 
> Rebased as attached.
> 
> Thanks,
> Jinsong

Please write a simple test case to arm a lapic timer via wrmsr (see
https://github.com/avikivity/kvm-unit-tests).

Kernel patches have been applied, thanks.


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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-23 13:08       ` Marcelo Tosatti
  0 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-09-23 13:08 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>> 2001 
> >> From: Liu, Jinsong <jinsong.liu@intel.com>
> >> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for guest
> >> 
> >> This patch emulate lapic tsc deadline timer for guest:
> >> Enumerate tsc deadline timer capability by CPUID;
> >> Enable tsc deadline timer mode by lapic MMIO;
> >> Start tsc deadline timer by WRMSR;
> >> 
> >> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>  arch/x86/include/asm/kvm_host.h |    2 +
> >>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>  arch/x86/kvm/lapic.c            |  123
> >>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h       
> >>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>  5 files changed, 123 insertions(+), 23 deletions(-)
> > 
> > Looks good, please rebase against branch master of
> > 
> > git://github.com/avikivity/kvm.git
> 
> Rebased as attached.
> 
> Thanks,
> Jinsong

Please write a simple test case to arm a lapic timer via wrmsr (see
https://github.com/avikivity/kvm-unit-tests).

Kernel patches have been applied, thanks.

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

* RE: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-23 13:08       ` [Qemu-devel] " Marcelo Tosatti
@ 2011-09-25 14:47         ` Liu, Jinsong
  -1 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-25 14:47 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

Marcelo Tosatti wrote:
> On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
>> Marcelo Tosatti wrote:
>>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>>>> 2001
>>>> From: Liu, Jinsong <jinsong.liu@intel.com>
>>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
>>>> guest 
>>>> 
>>>> This patch emulate lapic tsc deadline timer for guest:
>>>> Enumerate tsc deadline timer capability by CPUID;
>>>> Enable tsc deadline timer mode by lapic MMIO;
>>>> Start tsc deadline timer by WRMSR;
>>>> 
>>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>>>  arch/x86/include/asm/kvm_host.h |    2 +
>>>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>>>  arch/x86/kvm/lapic.c            |  123
>>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
>>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>>>  5 files changed, 123 insertions(+), 23 deletions(-)
>>> 
>>> Looks good, please rebase against branch master of
>>> 
>>> git://github.com/avikivity/kvm.git
>> 
>> Rebased as attached.
>> 
>> Thanks,
>> Jinsong
> 
> Please write a simple test case to arm a lapic timer via wrmsr (see
> https://github.com/avikivity/kvm-unit-tests).
> 
> Kernel patches have been applied, thanks.

Marcelo,

I'm not quite clear the purpose and usage of test case of the kvm-unit-tests.
Can you give me some hint?

Thanks,
Jinsong

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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-09-25 14:47         ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-09-25 14:47 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

Marcelo Tosatti wrote:
> On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
>> Marcelo Tosatti wrote:
>>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
>>>>> 2001
>>>> From: Liu, Jinsong <jinsong.liu@intel.com>
>>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
>>>> guest 
>>>> 
>>>> This patch emulate lapic tsc deadline timer for guest:
>>>> Enumerate tsc deadline timer capability by CPUID;
>>>> Enable tsc deadline timer mode by lapic MMIO;
>>>> Start tsc deadline timer by WRMSR;
>>>> 
>>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>>>  arch/x86/include/asm/kvm_host.h |    2 +
>>>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>>>  arch/x86/kvm/lapic.c            |  123
>>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
>>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>>>  5 files changed, 123 insertions(+), 23 deletions(-)
>>> 
>>> Looks good, please rebase against branch master of
>>> 
>>> git://github.com/avikivity/kvm.git
>> 
>> Rebased as attached.
>> 
>> Thanks,
>> Jinsong
> 
> Please write a simple test case to arm a lapic timer via wrmsr (see
> https://github.com/avikivity/kvm-unit-tests).
> 
> Kernel patches have been applied, thanks.

Marcelo,

I'm not quite clear the purpose and usage of test case of the kvm-unit-tests.
Can you give me some hint?

Thanks,
Jinsong

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

* Re: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-09-25 14:47         ` [Qemu-devel] " Liu, Jinsong
@ 2011-10-03 16:36           ` Marcelo Tosatti
  -1 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-10-03 16:36 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

On Sun, Sep 25, 2011 at 10:47:46PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
> >> Marcelo Tosatti wrote:
> >>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>>>> 2001
> >>>> From: Liu, Jinsong <jinsong.liu@intel.com>
> >>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
> >>>> guest 
> >>>> 
> >>>> This patch emulate lapic tsc deadline timer for guest:
> >>>> Enumerate tsc deadline timer capability by CPUID;
> >>>> Enable tsc deadline timer mode by lapic MMIO;
> >>>> Start tsc deadline timer by WRMSR;
> >>>> 
> >>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>>>  arch/x86/include/asm/kvm_host.h |    2 +
> >>>>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>>>  arch/x86/kvm/lapic.c            |  123
> >>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
> >>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>>>  5 files changed, 123 insertions(+), 23 deletions(-)
> >>> 
> >>> Looks good, please rebase against branch master of
> >>> 
> >>> git://github.com/avikivity/kvm.git
> >> 
> >> Rebased as attached.
> >> 
> >> Thanks,
> >> Jinsong
> > 
> > Please write a simple test case to arm a lapic timer via wrmsr (see
> > https://github.com/avikivity/kvm-unit-tests).
> > 
> > Kernel patches have been applied, thanks.
> 
> Marcelo,
> 
> I'm not quite clear the purpose and usage of test case of the kvm-unit-tests.
> Can you give me some hint?

The purpose is to add unit tests for new features (such as lapic
deadline timer). There are examples that make it relatively easy to
construct new test case (or modify existing ones to accomodate new
tests).

Please add a new test case for lapic deadline timer, thanks.


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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-10-03 16:36           ` Marcelo Tosatti
  0 siblings, 0 replies; 18+ messages in thread
From: Marcelo Tosatti @ 2011-10-03 16:36 UTC (permalink / raw)
  To: Liu, Jinsong; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

On Sun, Sep 25, 2011 at 10:47:46PM +0800, Liu, Jinsong wrote:
> Marcelo Tosatti wrote:
> > On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
> >> Marcelo Tosatti wrote:
> >>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
> >>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17 00:00:00
> >>>>> 2001
> >>>> From: Liu, Jinsong <jinsong.liu@intel.com>
> >>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
> >>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
> >>>> guest 
> >>>> 
> >>>> This patch emulate lapic tsc deadline timer for guest:
> >>>> Enumerate tsc deadline timer capability by CPUID;
> >>>> Enable tsc deadline timer mode by lapic MMIO;
> >>>> Start tsc deadline timer by WRMSR;
> >>>> 
> >>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
> >>>>  arch/x86/include/asm/kvm_host.h |    2 +
> >>>>  arch/x86/kvm/kvm_timer.h        |    2 +
> >>>>  arch/x86/kvm/lapic.c            |  123
> >>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
> >>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
> >>>>  5 files changed, 123 insertions(+), 23 deletions(-)
> >>> 
> >>> Looks good, please rebase against branch master of
> >>> 
> >>> git://github.com/avikivity/kvm.git
> >> 
> >> Rebased as attached.
> >> 
> >> Thanks,
> >> Jinsong
> > 
> > Please write a simple test case to arm a lapic timer via wrmsr (see
> > https://github.com/avikivity/kvm-unit-tests).
> > 
> > Kernel patches have been applied, thanks.
> 
> Marcelo,
> 
> I'm not quite clear the purpose and usage of test case of the kvm-unit-tests.
> Can you give me some hint?

The purpose is to add unit tests for new features (such as lapic
deadline timer). There are examples that make it relatively easy to
construct new test case (or modify existing ones to accomodate new
tests).

Please add a new test case for lapic deadline timer, thanks.

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

* RE: [PATCH] KVM: emulate lapic tsc deadline timer for guest
  2011-10-03 16:36           ` [Qemu-devel] " Marcelo Tosatti
@ 2011-10-05 17:18             ` Liu, Jinsong
  -1 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-10-05 17:18 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Avi Kivity, kvm, qemu-devel, Tian, Kevin

Marcelo Tosatti wrote:
> On Sun, Sep 25, 2011 at 10:47:46PM +0800, Liu, Jinsong wrote:
>> Marcelo Tosatti wrote:
>>> On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
>>>> Marcelo Tosatti wrote:
>>>>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>>>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17
>>>>>>> 00:00:00 2001
>>>>>> From: Liu, Jinsong <jinsong.liu@intel.com>
>>>>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>>>>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
>>>>>> guest 
>>>>>> 
>>>>>> This patch emulate lapic tsc deadline timer for guest:
>>>>>> Enumerate tsc deadline timer capability by CPUID;
>>>>>> Enable tsc deadline timer mode by lapic MMIO;
>>>>>> Start tsc deadline timer by WRMSR;
>>>>>> 
>>>>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>>>>>  arch/x86/include/asm/kvm_host.h |    2 +
>>>>>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>>>>>  arch/x86/kvm/lapic.c            |  123
>>>>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
>>>>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>>>>>  5 files changed, 123 insertions(+), 23 deletions(-)
>>>>> 
>>>>> Looks good, please rebase against branch master of
>>>>> 
>>>>> git://github.com/avikivity/kvm.git
>>>> 
>>>> Rebased as attached.
>>>> 
>>>> Thanks,
>>>> Jinsong
>>> 
>>> Please write a simple test case to arm a lapic timer via wrmsr (see
>>> https://github.com/avikivity/kvm-unit-tests).
>>> 
>>> Kernel patches have been applied, thanks.
>> 
>> Marcelo,
>> 
>> I'm not quite clear the purpose and usage of test case of the
>> kvm-unit-tests. Can you give me some hint?
> 
> The purpose is to add unit tests for new features (such as lapic
> deadline timer). There are examples that make it relatively easy to
> construct new test case (or modify existing ones to accomodate new
> tests).
> 
> Please add a new test case for lapic deadline timer, thanks.


Thanks Marcelo. I will add the test case. Sorry for slow email reply because of holiday.

Regards,
Jinsong

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

* Re: [Qemu-devel] [PATCH] KVM: emulate lapic tsc deadline timer for guest
@ 2011-10-05 17:18             ` Liu, Jinsong
  0 siblings, 0 replies; 18+ messages in thread
From: Liu, Jinsong @ 2011-10-05 17:18 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Tian, Kevin, Avi Kivity, kvm, qemu-devel

Marcelo Tosatti wrote:
> On Sun, Sep 25, 2011 at 10:47:46PM +0800, Liu, Jinsong wrote:
>> Marcelo Tosatti wrote:
>>> On Fri, Sep 23, 2011 at 04:25:51PM +0800, Liu, Jinsong wrote:
>>>> Marcelo Tosatti wrote:
>>>>> On Thu, Sep 22, 2011 at 04:55:52PM +0800, Liu, Jinsong wrote:
>>>>>>> From 4d5b83aba40ce0d421add9a41a6c591a8590a32e Mon Sep 17
>>>>>>> 00:00:00 2001
>>>>>> From: Liu, Jinsong <jinsong.liu@intel.com>
>>>>>> Date: Thu, 22 Sep 2011 14:00:08 +0800
>>>>>> Subject: [PATCH 2/2] KVM: emulate lapic tsc deadline timer for
>>>>>> guest 
>>>>>> 
>>>>>> This patch emulate lapic tsc deadline timer for guest:
>>>>>> Enumerate tsc deadline timer capability by CPUID;
>>>>>> Enable tsc deadline timer mode by lapic MMIO;
>>>>>> Start tsc deadline timer by WRMSR;
>>>>>> 
>>>>>> Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com> ---
>>>>>>  arch/x86/include/asm/kvm_host.h |    2 +
>>>>>>  arch/x86/kvm/kvm_timer.h        |    2 +
>>>>>>  arch/x86/kvm/lapic.c            |  123
>>>>>>  ++++++++++++++++++++++++++++++++------- arch/x86/kvm/lapic.h
>>>>>>  |    3 + arch/x86/kvm/x86.c              |   16 +++++-
>>>>>>  5 files changed, 123 insertions(+), 23 deletions(-)
>>>>> 
>>>>> Looks good, please rebase against branch master of
>>>>> 
>>>>> git://github.com/avikivity/kvm.git
>>>> 
>>>> Rebased as attached.
>>>> 
>>>> Thanks,
>>>> Jinsong
>>> 
>>> Please write a simple test case to arm a lapic timer via wrmsr (see
>>> https://github.com/avikivity/kvm-unit-tests).
>>> 
>>> Kernel patches have been applied, thanks.
>> 
>> Marcelo,
>> 
>> I'm not quite clear the purpose and usage of test case of the
>> kvm-unit-tests. Can you give me some hint?
> 
> The purpose is to add unit tests for new features (such as lapic
> deadline timer). There are examples that make it relatively easy to
> construct new test case (or modify existing ones to accomodate new
> tests).
> 
> Please add a new test case for lapic deadline timer, thanks.


Thanks Marcelo. I will add the test case. Sorry for slow email reply because of holiday.

Regards,
Jinsong

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

end of thread, other threads:[~2011-10-05 17:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-22  8:55 [PATCH] KVM: emulate lapic tsc deadline timer for guest Liu, Jinsong
2011-09-22  8:55 ` [Qemu-devel] " Liu, Jinsong
2011-09-22 14:48 ` Marcelo Tosatti
2011-09-22 14:48   ` [Qemu-devel] " Marcelo Tosatti
2011-09-22 15:22   ` Liu, Jinsong
2011-09-22 15:22     ` [Qemu-devel] " Liu, Jinsong
2011-09-22 21:31     ` Marcelo Tosatti
2011-09-22 21:31       ` [Qemu-devel] " Marcelo Tosatti
2011-09-23  8:25   ` Liu, Jinsong
2011-09-23  8:25     ` [Qemu-devel] " Liu, Jinsong
2011-09-23 13:08     ` Marcelo Tosatti
2011-09-23 13:08       ` [Qemu-devel] " Marcelo Tosatti
2011-09-25 14:47       ` Liu, Jinsong
2011-09-25 14:47         ` [Qemu-devel] " Liu, Jinsong
2011-10-03 16:36         ` Marcelo Tosatti
2011-10-03 16:36           ` [Qemu-devel] " Marcelo Tosatti
2011-10-05 17:18           ` Liu, Jinsong
2011-10-05 17:18             ` [Qemu-devel] " Liu, Jinsong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.