svn commit: r241766 - in projects/bhyve/sys/amd64/vmm: . io

Neel Natu neel at FreeBSD.org
Sat Oct 20 08:23:05 UTC 2012


Author: neel
Date: Sat Oct 20 08:23:05 2012
New Revision: 241766
URL: http://svn.freebsd.org/changeset/base/241766

Log:
  Calculate the number of host ticks until the next guest timer interrupt.
  
  This information will be used in conjunction with guest "HLT exiting" to
  yield the thread hosting the virtual cpu.
  
  Obtained from:	NetApp

Modified:
  projects/bhyve/sys/amd64/vmm/io/vlapic.c
  projects/bhyve/sys/amd64/vmm/io/vlapic.h
  projects/bhyve/sys/amd64/vmm/vmm_lapic.c
  projects/bhyve/sys/amd64/vmm/vmm_lapic.h

Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/io/vlapic.c	Sat Oct 20 08:06:31 2012	(r241765)
+++ projects/bhyve/sys/amd64/vmm/io/vlapic.c	Sat Oct 20 08:23:05 2012	(r241766)
@@ -121,6 +121,31 @@ struct vlapic {
 	enum boot_state		boot_state;
 };
 
+#define VLAPIC_BUS_FREQ	tsc_freq
+
+static int
+vlapic_timer_divisor(uint32_t dcr)
+{
+	switch (dcr & 0xB) {
+	case APIC_TDCR_2:
+		return (2);
+	case APIC_TDCR_4:
+		return (4);
+	case APIC_TDCR_8:
+		return (8);
+	case APIC_TDCR_16:
+		return (16);
+	case APIC_TDCR_32:
+		return (32);
+	case APIC_TDCR_64:
+		return (64);
+	case APIC_TDCR_128:
+		return (128);
+	default:
+		panic("vlapic_timer_divisor: invalid dcr 0x%08x", dcr);
+	}
+}
+
 static void
 vlapic_mask_lvts(uint32_t *lvts, int num_lvt)
 {
@@ -175,6 +200,7 @@ vlapic_op_reset(void* dev)
 	memset(lapic, 0, sizeof(*lapic));
 	lapic->apr = vlapic->vcpuid;
 	vlapic_init_ipi(vlapic);
+	vlapic->divisor = vlapic_timer_divisor(lapic->dcr_timer);
 
 	if (vlapic->vcpuid == 0)
 		vlapic->boot_state = BS_RUNNING;	/* BSP */
@@ -218,32 +244,6 @@ vlapic_set_intr_ready(struct vlapic *vla
 	VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
 }
 
-#define VLAPIC_BUS_FREQ	tsc_freq
-#define VLAPIC_DCR(x)	((x->dcr_timer & 0x8) >> 1)|(x->dcr_timer & 0x3)
-
-static int
-vlapic_timer_divisor(uint32_t dcr)
-{
-	switch (dcr & 0xB) {
-	case APIC_TDCR_2:
-		return (2);
-	case APIC_TDCR_4:
-		return (4);
-	case APIC_TDCR_8:
-		return (8);
-	case APIC_TDCR_16:
-		return (16);
-	case APIC_TDCR_32:
-		return (32);
-	case APIC_TDCR_64:
-		return (64);
-	case APIC_TDCR_128:
-		return (128);
-	default:
-		panic("vlapic_timer_divisor: invalid dcr 0x%08x", dcr);
-	}
-}
-
 static void
 vlapic_start_timer(struct vlapic *vlapic, uint32_t elapsed)
 {
@@ -755,59 +755,68 @@ vlapic_op_mem_write(void* dev, uint64_t 
 	return (retval);
 }
 
-void
+int
 vlapic_timer_tick(struct vlapic *vlapic)
 {
-	int curticks, delta, periodic;
+	int curticks, delta, periodic, fired;
 	uint32_t ccr;
-	uint32_t decrement, remainder;
+	uint32_t decrement, leftover;
 
+restart:
 	curticks = ticks;
-
-	/* Common case */
 	delta = curticks - vlapic->ccr_ticks;
-	if (delta == 0)
-		return;
 
 	/* Local APIC timer is disabled */
 	if (vlapic->apic.icr_timer == 0)
-		return;
+		return (-1);
 
 	/* One-shot mode and timer has already counted down to zero */
 	periodic = vlapic_periodic_timer(vlapic);
 	if (!periodic && vlapic->apic.ccr_timer == 0)
-		return;
+		return (-1);
 	/*
 	 * The 'curticks' and 'ccr_ticks' are out of sync by more than
 	 * 2^31 ticks. We deal with this by restarting the timer.
 	 */
 	if (delta < 0) {
 		vlapic_start_timer(vlapic, 0);
-		return;
+		goto restart;
 	}
 
-	ccr = vlapic->apic.ccr_timer;
+	fired = 0;
 	decrement = (VLAPIC_BUS_FREQ / vlapic->divisor) / hz;
+
+	vlapic->ccr_ticks = curticks;
+	ccr = vlapic->apic.ccr_timer;
+
 	while (delta-- > 0) {
-		if (ccr <= decrement) {
-			remainder = decrement - ccr;
-			vlapic_fire_timer(vlapic);
-			if (periodic) {
-				vlapic_start_timer(vlapic, remainder);
-				ccr = vlapic->apic.ccr_timer;
-			} else {
-				/*
-				 * One-shot timer has counted down to zero.
-				 */
-				ccr = 0;
-				break;
-			}
-		} else 
+		if (ccr > decrement) {
 			ccr -= decrement;
+			continue;
+		}
+
+		/* Trigger the local apic timer interrupt */
+		vlapic_fire_timer(vlapic);
+		if (periodic) {
+			leftover = decrement - ccr;
+			vlapic_start_timer(vlapic, leftover);
+			ccr = vlapic->apic.ccr_timer;
+		} else {
+			/*
+			 * One-shot timer has counted down to zero.
+			 */
+			ccr = 0;
+		}
+		fired = 1;
+		break;
 	}
 
-	vlapic->ccr_ticks = curticks;
 	vlapic->apic.ccr_timer = ccr;
+
+	if (!fired)
+		return ((ccr / decrement) + 1);
+	else
+		return (0);
 }
 
 struct vdev_ops vlapic_dev_ops = {

Modified: projects/bhyve/sys/amd64/vmm/io/vlapic.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/io/vlapic.h	Sat Oct 20 08:06:31 2012	(r241765)
+++ projects/bhyve/sys/amd64/vmm/io/vlapic.h	Sat Oct 20 08:23:05 2012	(r241766)
@@ -102,7 +102,7 @@ int vlapic_op_mem_read(void* dev, uint64
 int vlapic_pending_intr(struct vlapic *vlapic);
 void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
 void vlapic_set_intr_ready(struct vlapic *vlapic, int vector);
-void vlapic_timer_tick(struct vlapic *vlapic);
+int vlapic_timer_tick(struct vlapic *vlapic);
 
 uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
 void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val);

Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_lapic.c	Sat Oct 20 08:06:31 2012	(r241765)
+++ projects/bhyve/sys/amd64/vmm/vmm_lapic.c	Sat Oct 20 08:23:05 2012	(r241766)
@@ -106,14 +106,14 @@ lapic_set_intr(struct vm *vm, int cpu, i
 	return (0);
 }
 
-void
+int
 lapic_timer_tick(struct vm *vm, int cpu)
 {
 	struct vlapic *vlapic;
 
 	vlapic = vm_lapic(vm, cpu);
 
-	vlapic_timer_tick(vlapic);
+	return (vlapic_timer_tick(vlapic));
 }
 
 static boolean_t

Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_lapic.h	Sat Oct 20 08:06:31 2012	(r241765)
+++ projects/bhyve/sys/amd64/vmm/vmm_lapic.h	Sat Oct 20 08:23:05 2012	(r241766)
@@ -38,7 +38,7 @@ int	lapic_wrmsr(struct vm *vm, int cpu, 
 
 int	lapic_mmio(struct vm *vm, int cpu, u_int offset, int rd, struct vie *);
 
-void	lapic_timer_tick(struct vm *vm, int cpu);
+int	lapic_timer_tick(struct vm *vm, int cpu);
 
 /*
  * Returns a vector between 32 and 255 if an interrupt is pending in the


More information about the svn-src-projects mailing list