Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 May 2009 17:47:21 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r191766 - in head/sys: amd64/include amd64/isa i386/bios i386/include i386/isa i386/xen isa pc98/cbus
Message-ID:  <200905031747.n43HlLHD020054@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun May  3 17:47:21 2009
New Revision: 191766
URL: http://svn.freebsd.org/changeset/base/191766

Log:
  Rename statclock_disable variable to atrtcclock_disable that it actually is,
  and hide it inside of atrtc driver. Add new tunable hint.atrtc.0.clock
  controlling it. Setting it to 0 disables using RTC clock as stat-/
  profclock sources.
  
  Teach i386 and amd64 SMP platforms to emulate stat-/profclocks using i8254
  hardclock, when LAPIC and RTC clocks are disabled.
  
  This allows to reduce global interrupt rate of idle system down to about
  100 interrupts per core, permitting C3 and deeper C-states provide maximum
  CPU power efficiency.

Modified:
  head/sys/amd64/include/clock.h
  head/sys/amd64/isa/clock.c
  head/sys/i386/bios/apm.c
  head/sys/i386/include/clock.h
  head/sys/i386/isa/clock.c
  head/sys/i386/xen/clock.c
  head/sys/isa/atrtc.c
  head/sys/isa/rtc.h
  head/sys/pc98/cbus/clock.c

Modified: head/sys/amd64/include/clock.h
==============================================================================
--- head/sys/amd64/include/clock.h	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/amd64/include/clock.h	Sun May  3 17:47:21 2009	(r191766)
@@ -15,7 +15,6 @@
  * XXX large parts of the driver and its interface are misplaced.
  */
 extern int	clkintr_pending;
-extern int	statclock_disable;
 extern u_int	i8254_freq;
 extern int	i8254_max_count;
 extern uint64_t	tsc_freq;

Modified: head/sys/amd64/isa/clock.c
==============================================================================
--- head/sys/amd64/isa/clock.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/amd64/isa/clock.c	Sun May  3 17:47:21 2009	(r191766)
@@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
 int	clkintr_pending;
 static int pscnt = 1;
 static int psdiv = 1;
-int	statclock_disable;
 #ifndef TIMER_FREQ
 #define TIMER_FREQ   1193182
 #endif
@@ -91,6 +90,7 @@ static	u_int32_t i8254_lastcount;
 static	u_int32_t i8254_offset;
 static	int	(*i8254_pending)(struct intsrc *);
 static	int	i8254_ticked;
+static	int	using_atrtc_timer;
 static	int	using_lapic_timer;
 
 /* Values for timerX_state: */
@@ -122,6 +122,8 @@ hardclockintr(struct trapframe *frame)
 		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
 	else
 		hardclock_cpu(TRAPF_USERMODE(frame));
+	if (!using_atrtc_timer)
+		statclockintr(frame);
 	return (FILTER_HANDLED);
 }
 
@@ -163,10 +165,7 @@ clkintr(struct trapframe *frame)
 	if (smp_started)
 		ipi_all_but_self(IPI_HARDCLOCK);
 #endif
-	if (PCPU_GET(cpuid) == 0)
-		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
-	else
-		hardclock_cpu(TRAPF_USERMODE(frame));
+	hardclockintr(frame);
 	return (FILTER_HANDLED);
 }
 
@@ -461,7 +460,6 @@ startrtclock()
 void
 cpu_initclocks()
 {
-	int diag;
 
 	using_lapic_timer = lapic_setup_clock();
 	/*
@@ -493,21 +491,17 @@ cpu_initclocks()
 	 * kernel clocks, then setup the RTC to periodically interrupt to
 	 * drive statclock() and profclock().
 	 */
-	if (!statclock_disable && !using_lapic_timer) {
-		diag = rtcin(RTC_DIAG);
-		if (diag != 0)
-			printf("RTC BIOS diagnostic error %b\n",
-			    diag, RTCDG_BITS);
-
-	        /* Setting stathz to nonzero early helps avoid races. */
-		stathz = RTC_NOPROFRATE;
-		profhz = RTC_PROFRATE;
-
-		/* Enable periodic interrupts from the RTC. */
-		intr_add_handler("rtc", 8,
-		    (driver_filter_t *)rtcintr, NULL, NULL,
-		    INTR_TYPE_CLK, NULL);
-		atrtc_enable_intr();
+	if (!using_lapic_timer) {
+		using_atrtc_timer = atrtc_setup_clock();
+		if (using_atrtc_timer) {
+			/* Enable periodic interrupts from the RTC. */
+			intr_add_handler("rtc", 8,
+			    (driver_filter_t *)rtcintr, NULL, NULL,
+			    INTR_TYPE_CLK, NULL);
+			atrtc_enable_intr();
+		} else {
+			profhz = stathz = hz;
+		}
 	}
 
 	init_TSC_tc();

Modified: head/sys/i386/bios/apm.c
==============================================================================
--- head/sys/i386/bios/apm.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/i386/bios/apm.c	Sun May  3 17:47:21 2009	(r191766)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_param.h>
 
 #include <i386/bios/apm.h>
+#include <isa/rtc.h>
 
 /* Used by the apm_saver screen saver module */
 int apm_display(int newstate);
@@ -1155,7 +1156,7 @@ apm_attach(device_t dev)
 	cv_init(&sc->cv, "cbb cv");
 
 	if (device_get_flags(dev) & 0x20)
-		statclock_disable = 1;
+		atrtcclock_disable = 1;
 
 	sc->initialized = 0;
 

Modified: head/sys/i386/include/clock.h
==============================================================================
--- head/sys/i386/include/clock.h	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/i386/include/clock.h	Sun May  3 17:47:21 2009	(r191766)
@@ -15,7 +15,6 @@
  * XXX large parts of the driver and its interface are misplaced.
  */
 extern int	clkintr_pending;
-extern int	statclock_disable;
 extern u_int	i8254_freq;
 extern int	i8254_max_count;
 extern uint64_t	tsc_freq;

Modified: head/sys/i386/isa/clock.c
==============================================================================
--- head/sys/i386/isa/clock.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/i386/isa/clock.c	Sun May  3 17:47:21 2009	(r191766)
@@ -91,7 +91,6 @@ __FBSDID("$FreeBSD$");
 int	clkintr_pending;
 static int pscnt = 1;
 static int psdiv = 1;
-int	statclock_disable;
 #ifndef TIMER_FREQ
 #define TIMER_FREQ   1193182
 #endif
@@ -106,6 +105,7 @@ static	u_int32_t i8254_lastcount;
 static	u_int32_t i8254_offset;
 static	int	(*i8254_pending)(struct intsrc *);
 static	int	i8254_ticked;
+static	int	using_atrtc_timer;
 static	int	using_lapic_timer;
 
 /* Values for timerX_state: */
@@ -137,6 +137,8 @@ hardclockintr(struct trapframe *frame)
 		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
 	else
 		hardclock_cpu(TRAPF_USERMODE(frame));
+	if (!using_atrtc_timer)
+		statclockintr(frame);
 	return (FILTER_HANDLED);
 }
 
@@ -190,10 +192,7 @@ clkintr(struct trapframe *frame)
 	if (smp_started)
 		ipi_all_but_self(IPI_HARDCLOCK);
 #endif 
-	if (PCPU_GET(cpuid) == 0)
-		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
-	else
-		hardclock_cpu(TRAPF_USERMODE(frame));
+	hardclockintr(frame);
 #ifdef DEV_MCA
 	/* Reset clock interrupt by asserting bit 7 of port 0x61 */
 	if (MCA_system)
@@ -508,7 +507,6 @@ startrtclock()
 void
 cpu_initclocks()
 {
-	int diag;
 
 #ifdef DEV_APIC
 	using_lapic_timer = lapic_setup_clock();
@@ -542,21 +540,17 @@ cpu_initclocks()
 	 * kernel clocks, then setup the RTC to periodically interrupt to
 	 * drive statclock() and profclock().
 	 */
-	if (!statclock_disable && !using_lapic_timer) {
-		diag = rtcin(RTC_DIAG);
-		if (diag != 0)
-			printf("RTC BIOS diagnostic error %b\n",
-			    diag, RTCDG_BITS);
-
-	        /* Setting stathz to nonzero early helps avoid races. */
-		stathz = RTC_NOPROFRATE;
-		profhz = RTC_PROFRATE;
-
-		/* Enable periodic interrupts from the RTC. */
-		intr_add_handler("rtc", 8,
-		    (driver_filter_t *)rtcintr, NULL, NULL,
-		    INTR_TYPE_CLK, NULL);
-		atrtc_enable_intr();
+	if (!using_lapic_timer) {
+		using_atrtc_timer = atrtc_setup_clock();
+		if (using_atrtc_timer) {
+			/* Enable periodic interrupts from the RTC. */
+			intr_add_handler("rtc", 8,
+			    (driver_filter_t *)rtcintr, NULL, NULL,
+			    INTR_TYPE_CLK, NULL);
+			atrtc_enable_intr();
+		} else {
+			profhz = stathz = hz;
+		}
 	}
 
 	init_TSC_tc();

Modified: head/sys/i386/xen/clock.c
==============================================================================
--- head/sys/i386/xen/clock.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/i386/xen/clock.c	Sun May  3 17:47:21 2009	(r191766)
@@ -120,7 +120,6 @@ int adjkerntz;		/* local offset from GMT
 int clkintr_pending;
 int pscnt = 1;
 int psdiv = 1;
-int statclock_disable;
 int wall_cmos_clock;
 u_int timer_freq = TIMER_FREQ;
 static int independent_wallclock;

Modified: head/sys/isa/atrtc.c
==============================================================================
--- head/sys/isa/atrtc.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/isa/atrtc.c	Sun May  3 17:47:21 2009	(r191766)
@@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$");
 #define	RTC_LOCK	mtx_lock_spin(&clock_lock)
 #define	RTC_UNLOCK	mtx_unlock_spin(&clock_lock)
 
+int	atrtcclock_disable = 0;
+
 static	int	rtc_reg = -1;
 static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
 static	u_char	rtc_statusb = RTCSB_24HR;
@@ -133,6 +135,27 @@ atrtc_restore(void)
 	rtcin(RTC_INTR);
 }
 
+int
+atrtc_setup_clock(void)
+{
+	int diag;
+
+	if (atrtcclock_disable)
+		return (0);
+
+	diag = rtcin(RTC_DIAG);
+	if (diag != 0) {
+		printf("RTC BIOS diagnostic error %b\n",
+		    diag, RTCDG_BITS);
+		return (0);
+	}
+
+	stathz = RTC_NOPROFRATE;
+	profhz = RTC_PROFRATE;
+
+	return (1);
+}
+
 /**********************************************************************
  * RTC driver for subr_rtc
  */
@@ -173,6 +196,7 @@ static int
 atrtc_attach(device_t dev)
 {
 	struct atrtc_softc *sc;
+	int i;
 
 	/*
 	 * Not that we need them or anything, but grab our resources
@@ -187,6 +211,8 @@ atrtc_attach(device_t dev)
 	    &sc->intr_rid, 8, 8, 1, RF_ACTIVE)))
 		device_printf(dev,"Warning: Couldn't map Interrupt.\n");
 	clock_register(dev, 1000000);
+	if (resource_int_value("atrtc", 0, "clock", &i) == 0 && i == 0)
+		atrtcclock_disable = 1;
 	return(0);
 }
 

Modified: head/sys/isa/rtc.h
==============================================================================
--- head/sys/isa/rtc.h	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/isa/rtc.h	Sun May  3 17:47:21 2009	(r191766)
@@ -113,6 +113,8 @@
 
 #ifdef _KERNEL
 extern  struct mtx clock_lock;
+extern	int atrtcclock_disable;
+int	atrtc_setup_clock(void);
 int	rtcin(int reg);
 void	atrtc_start(void);
 void	atrtc_rate(unsigned rate);

Modified: head/sys/pc98/cbus/clock.c
==============================================================================
--- head/sys/pc98/cbus/clock.c	Sun May  3 07:28:16 2009	(r191765)
+++ head/sys/pc98/cbus/clock.c	Sun May  3 17:47:21 2009	(r191766)
@@ -87,7 +87,6 @@ __FBSDID("$FreeBSD$");
 #define	TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
 
 int	clkintr_pending;
-int	statclock_disable;
 #ifndef TIMER_FREQ
 #define TIMER_FREQ   2457600
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905031747.n43HlLHD020054>