svn commit: r333638 - head/sys/x86/x86

Andriy Gapon avg at FreeBSD.org
Tue May 15 16:56:31 UTC 2018


Author: avg
Date: Tue May 15 16:56:30 2018
New Revision: 333638
URL: https://svnweb.freebsd.org/changeset/base/333638

Log:
  calibrate lapic timer in native_lapic_setup
  
  The idea is to calibrate the LAPIC timer just once and only on boot,
  given that [at present] the timer constants are global and shared
  between all processors.
  
  My primary motivation is to fix a panic that can happen when dynamically
  switching to lapic timer.  The panic is caused by a recursion on
  et_hw_mtx when printing the calibration results to console.  See the
  review for the details of the panic.
  
  Also, the code should become slightly simpler and easier to read.  The
  previous code was racy too.  Multiple processors could start calibrating
  the global constants concurrently, although that seems to have been
  benign.
  
  Reviewed by:	kib, mav, jhb
  MFC after:	3 weeks
  Differential Revision: https://reviews.freebsd.org/D15422

Modified:
  head/sys/x86/x86/local_apic.c

Modified: head/sys/x86/x86/local_apic.c
==============================================================================
--- head/sys/x86/x86/local_apic.c	Tue May 15 16:54:41 2018	(r333637)
+++ head/sys/x86/x86/local_apic.c	Tue May 15 16:56:30 2018	(r333638)
@@ -206,6 +206,9 @@ SYSCTL_INT(_hw_apic, OID_AUTO, eoi_suppression, CTLFLA
 SYSCTL_INT(_hw_apic, OID_AUTO, timer_tsc_deadline, CTLFLAG_RD,
     &lapic_timer_tsc_deadline, 0, "");
 
+static void lapic_calibrate_initcount(struct lapic *la);
+static void lapic_calibrate_deadline(struct lapic *la);
+
 static uint32_t
 lapic_read32(enum LAPIC_REGISTERS reg)
 {
@@ -787,6 +790,13 @@ native_lapic_setup(int boot)
 		intrcnt_add(buf, &la->la_timer_count);
 	}
 
+	/* Calibrate the timer parameters using BSP. */
+	if (boot && IS_BSP()) {
+		lapic_calibrate_initcount(la);
+		if (lapic_timer_tsc_deadline)
+			lapic_calibrate_deadline(la);
+	}
+
 	/* Setup the timer if configured. */
 	if (la->la_timer_mode != LAT_MODE_UNDEF) {
 		KASSERT(la->la_timer_period != 0, ("lapic%u: zero divisor",
@@ -921,7 +931,7 @@ native_lapic_disable_pmc(void)
 }
 
 static void
-lapic_calibrate_initcount(struct eventtimer *et, struct lapic *la)
+lapic_calibrate_initcount(struct lapic *la)
 {
 	u_long value;
 
@@ -947,7 +957,7 @@ lapic_calibrate_initcount(struct eventtimer *et, struc
 }
 
 static void
-lapic_calibrate_deadline(struct eventtimer *et, struct lapic *la __unused)
+lapic_calibrate_deadline(struct lapic *la __unused)
 {
 
 	if (bootverbose) {
@@ -989,11 +999,6 @@ lapic_et_start(struct eventtimer *et, sbintime_t first
 	struct lapic *la;
 
 	la = &lapics[PCPU_GET(apic_id)];
-	if (et->et_frequency == 0) {
-		lapic_calibrate_initcount(et, la);
-		if (lapic_timer_tsc_deadline)
-			lapic_calibrate_deadline(et, la);
-	}
 	if (period != 0) {
 		lapic_change_mode(et, la, LAT_MODE_PERIODIC);
 		la->la_timer_period = ((uint32_t)et->et_frequency * period) >>


More information about the svn-src-all mailing list