Module Name:    src
Committed By:   cherry
Date:           Tue Aug 23 16:19:12 UTC 2011

Modified Files:
        src/sys/arch/xen/xen [cherry-xenmp]: clock.c

Log Message:
MP-fy clock. per-cpu hardclock(). Use the periodic timer, instead of the 
one-shot reload.

idle_loop() does not block the domain anymore. Instead, it yields to the 
hypervisor(). We can thus remove the one-shot "wakeup" timer.


To generate a diff of this commit:
cvs rdiff -u -r1.54.6.2 -r1.54.6.3 src/sys/arch/xen/xen/clock.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/clock.c
diff -u src/sys/arch/xen/xen/clock.c:1.54.6.2 src/sys/arch/xen/xen/clock.c:1.54.6.3
--- src/sys/arch/xen/xen/clock.c:1.54.6.2	Mon Jul 25 17:29:43 2011
+++ src/sys/arch/xen/xen/clock.c	Tue Aug 23 16:19:12 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: clock.c,v 1.54.6.2 2011/07/25 17:29:43 cherry Exp $	*/
+/*	$NetBSD: clock.c,v 1.54.6.3 2011/08/23 16:19:12 cherry Exp $	*/
 
 /*
  *
@@ -29,7 +29,7 @@
 #include "opt_xen.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.54.6.2 2011/07/25 17:29:43 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.54.6.3 2011/08/23 16:19:12 cherry Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -38,12 +38,14 @@
 #include <sys/timetc.h>
 #include <sys/timevar.h>
 #include <sys/kernel.h>
+#include <sys/mutex.h>
 #include <sys/device.h>
 #include <sys/sysctl.h>
 
 #include <xen/xen.h>
 #include <xen/hypervisor.h>
 #include <xen/evtchn.h>
+#include <xen/xen3-public/vcpu.h>
 #include <machine/cpu_counter.h>
 
 #include <dev/clock_subr.h>
@@ -80,6 +82,8 @@
 /* Per CPU shadow time values */
 static volatile struct shadow ci_shadow[MAXCPUS];
 
+static kmutex_t tmutex; /* Protects volatile variables, below */
+
 /* The time when the last hardclock(9) call should have taken place,
  * per cpu.
  */
@@ -90,7 +94,7 @@
  * back to maintain the illusion that hardclock(9) was called when it
  * was supposed to be, not when Xen got around to scheduling us.
  */
-static volatile uint64_t xen_clock_bias[MAXCPUS];
+static volatile uint64_t xen_clock_bias;
 
 #ifdef DOM0OPS
 /* If we're dom0, send our time to Xen every minute or so. */
@@ -245,18 +249,17 @@
 xen_wall_time(struct timespec *wt)
 {
 	uint64_t nsec;
-	int s;
 	struct cpu_info *ci = &cpu_info_primary;
 	volatile struct shadow *shadow = &ci_shadow[ci->ci_cpuid];
 
-	s = splhigh();
+	mutex_enter(&tmutex);
 	get_time_values_from_xen(ci);
 	*wt = shadow->ts;
 	nsec = wt->tv_nsec;
 
 	/* Under Xen3, this is the wall time less system time */
 	nsec += get_system_time();
-	splx(s);
+	mutex_exit(&tmutex);
 	wt->tv_sec += nsec / 1000000000L;
 	wt->tv_nsec = nsec % 1000000000L;
 }
@@ -282,8 +285,6 @@
 #else
 	xen_platform_op_t op;
 #endif
-	int s;
-
 	if (xendomain_is_privileged()) {
  		/* needs to set the RTC chip too */
  		struct clock_ymdhms dt;
@@ -298,9 +299,9 @@
 		/* XXX is rtc_offset handled correctly everywhere? */
 		op.u.settime.secs	 = tvp->tv_sec;
 		op.u.settime.nsecs	 = tvp->tv_usec * 1000;
-		s = splhigh();
+		mutex_enter(&tmutex);
 		op.u.settime.system_time = get_system_time();
-		splx(s);
+		mutex_exit(&tmutex);
 #if __XEN_INTERFACE_VERSION__ < 0x00030204
 		return HYPERVISOR_dom0_op(&op);
 #else
@@ -355,18 +356,17 @@
 		return;
 	} else {
 		uint64_t when;
-		int s;
 		/* for large delays, shadow->system_time is OK */
 		
-		s = splhigh();
+		mutex_enter(&tmutex);
 		get_time_values_from_xen(ci);
 		when = shadow->system_time + n * 1000;
 		while (shadow->system_time < when) {
-			splx(s);
-			s = splhigh();
+			mutex_exit(&tmutex);
+			mutex_enter(&tmutex);
 			get_time_values_from_xen(ci);
 		}
-		splx(s);
+		mutex_exit(&tmutex);
 	}
 }
 
@@ -416,11 +416,10 @@
 xen_get_timecount(struct timecounter *tc)
 {
 	uint64_t ns;
-	int s;
 
-	s = splhigh();
-	ns = get_system_time() - xen_clock_bias[0];
-	splx(s);
+	mutex_enter(&tmutex);
+	ns = get_system_time() - xen_clock_bias;
+	mutex_exit(&tmutex);
 
 	return (u_int)ns;
 }
@@ -437,13 +436,15 @@
 void
 xen_initclocks(void)
 {
-	int evtch;
+	int err, evtch;
 	static bool tcdone = false;
 
+	struct vcpu_set_periodic_timer hardclock_period = { NS_PER_TICK };
+
 	struct cpu_info *ci = curcpu();
 	volatile struct shadow *shadow = &ci_shadow[ci->ci_cpuid];
 
-	xen_clock_bias[ci->ci_cpuid] = 0;
+	xen_clock_bias = 0;
 
 	evcnt_attach_dynamic(&hardclock_called[ci->ci_cpuid],
 			     EVCNT_TYPE_INTR,
@@ -462,10 +463,18 @@
 	get_time_values_from_xen(ci);
 	vcpu_system_time[ci->ci_cpuid] = shadow->system_time;
 	if (!tcdone) { /* Do this only once */
+		mutex_init(&tmutex, MUTEX_DEFAULT, IPL_HIGH);
 		tc_init(&xen_timecounter);
 	}
 	/* The splhigh requirements start here. */
 
+	/* Set hardclock() frequency */
+	err = HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer,
+				 ci->ci_cpuid,
+				 &hardclock_period);
+
+	KASSERT(err == 0);
+
 	event_set_handler(evtch, (int (*)(void *))xen_timer_handler,
 	    ci, IPL_CLOCK, "clock");
 	hypervisor_enable_event(evtch);
@@ -493,43 +502,30 @@
 xen_timer_handler(void *arg, struct intrframe *regs)
 {
 	int64_t delta;
-	int s, ticks_done;
 	struct cpu_info *ci = curcpu();
+	KASSERT(arg == ci);
+	mutex_enter(&tmutex);
 
-	s = splhigh();
-#if 0
-	get_time_values_from_xen(ci);
-#endif
 	delta = (int64_t)(get_vcpu_time(ci) - vcpu_system_time[ci->ci_cpuid]);
 
-	splx(s);
+	mutex_exit(&tmutex);
 
-	ticks_done = 0;
 	/* Several ticks may have passed without our being run; catch up. */
 	while (delta >= (int64_t)NS_PER_TICK) {
-		++ticks_done;
-		s = splhigh();
+		mutex_enter(&tmutex);
 		vcpu_system_time[ci->ci_cpuid] += NS_PER_TICK;
-		xen_clock_bias[ci->ci_cpuid] = (delta -= NS_PER_TICK);
-		splx(s);
+		xen_clock_bias = (delta -= NS_PER_TICK);
+		mutex_exit(&tmutex);
 		hardclock((struct clockframe *)regs);
 		hardclock_called[ci->ci_cpuid].ev_count++;
 	}
 	
-	if (xen_clock_bias[ci->ci_cpuid]) {
-		s = splhigh();
- 		xen_clock_bias[ci->ci_cpuid] = 0;
-		splx(s);
+	if (xen_clock_bias) {
+		mutex_enter(&tmutex);
+		xen_clock_bias = 0;
+		mutex_exit(&tmutex);
 	}
 
-	/*
-	 * Re-arm the timer here, if needed; Xen's auto-ticking while runnable
-	 * is useful only for HZ==100, and even then may be out of phase with
-	 * the vcpu_system_time[ci->ci_cpuid] steps.
-	 */
-	if (ticks_done != 0)
-		HYPERVISOR_set_timer_op(vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
-
 	return 0;
 }
 
@@ -542,7 +538,6 @@
 idle_block(void)
 {
 	int r;
-	struct cpu_info *ci = curcpu();
 
 	/*
 	 * We set the timer to when we expect the next timer
@@ -550,9 +545,11 @@
 	 * easily find out when we will have more work (callouts) to
 	 * process from hardclock.
 	 */
-	r = HYPERVISOR_set_timer_op(vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
-	if (r == 0)
-		HYPERVISOR_block();
+	r = 0; //HYPERVISOR_set_timer_op(vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
+	if (r == 0) {
+		HYPERVISOR_yield();
+		__sti();
+	}
 	else
 		__sti();
 }

Reply via email to