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

Konstantin Belousov kib at FreeBSD.org
Tue Mar 29 19:54:14 UTC 2016


Author: kib
Date: Tue Mar 29 19:54:13 2016
New Revision: 297398
URL: https://svnweb.freebsd.org/changeset/base/297398

Log:
  Fix several bugs in r297374:
  - fix UP build [1]
  - do not obliterate initial reading of rdtsc by the loop counter [2]
  - restore the meaning of the argument -1 to native_lapic_ipi_wait()
    as wait until LAPIC acknowledge without timeout
  - correct formula for calculating loop iteration count for 1us, it was
    inverted, and ensure that even on unlikely slow CPUs at least one
    check for ack is performed.
  
  Reported by:	Michael Butler <imb at protected-networks.net> [1], rpokala[2],
  	jhb[3]
  Tested by:	Michael Butler
  Pointy hat to:	kib
  Sponsored by:	The FreeBSD Foundation

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

Modified: head/sys/x86/x86/local_apic.c
==============================================================================
--- head/sys/x86/x86/local_apic.c	Tue Mar 29 19:23:00 2016	(r297397)
+++ head/sys/x86/x86/local_apic.c	Tue Mar 29 19:54:13 2016	(r297398)
@@ -172,7 +172,9 @@ int lapic_eoi_suppression;
 static int lapic_timer_tsc_deadline;
 static u_long lapic_timer_divisor;
 static struct eventtimer lapic_et;
+#ifdef SMP
 static uint64_t lapic_ipi_wait_mult;
+#endif
 
 SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD, 0, "APIC options");
 SYSCTL_INT(_hw_apic, OID_AUTO, x2apic_mode, CTLFLAG_RD, &x2apic_mode, 0, "");
@@ -404,7 +406,9 @@ lvt_mode(struct lapic *la, u_int pin, ui
 static void
 native_lapic_init(vm_paddr_t addr)
 {
-	uint64_t r;
+#ifdef SMP
+	uint64_t r, r1, r2, rx;
+#endif
 	uint32_t ver;
 	u_int regs[4];
 	int i, arat;
@@ -506,6 +510,7 @@ native_lapic_init(vm_paddr_t addr)
 		    &lapic_eoi_suppression);
 	}
 
+#ifdef SMP
 #define LOOPS 1000000
 	/*
 	 * Calibrate the busy loop waiting for IPI ack in xAPIC mode.
@@ -521,18 +526,21 @@ native_lapic_init(vm_paddr_t addr)
 	KASSERT((cpu_feature & CPUID_TSC) != 0 && tsc_freq != 0,
 	    ("TSC not initialized"));
 	r = rdtsc();
-	for (r = 0; r < LOOPS; r++) {
+	for (rx = 0; rx < LOOPS; rx++) {
 		(void)lapic_read_icr_lo();
 		ia32_pause();
 	}
 	r = rdtsc() - r;
-	lapic_ipi_wait_mult = (r * 1000000) / tsc_freq / LOOPS;
+	r1 = tsc_freq * LOOPS;
+	r2 = r * 1000000;
+	lapic_ipi_wait_mult = r1 >= r2 ? r1 / r2 : 1;
 	if (bootverbose) {
 		printf("LAPIC: ipi_wait() us multiplier %jd (r %jd tsc %jd)\n",
 		    (uintmax_t)lapic_ipi_wait_mult, (uintmax_t)r,
 		    (uintmax_t)tsc_freq);
 	}
 #undef LOOPS
+#endif /* SMP */
 }
 
 /*
@@ -1757,11 +1765,11 @@ native_lapic_ipi_wait(int delay)
 	uint64_t i, counter;
 
 	/* LAPIC_ICR.APIC_DELSTAT_MASK is undefined in x2APIC mode */
-	if (x2apic_mode || delay == -1)
+	if (x2apic_mode)
 		return (1);
 
 	counter = lapic_ipi_wait_mult * delay;
-	for (i = 0; i < counter; i++) {
+	for (i = 0; delay == -1 || i < counter; i++) {
 		if ((lapic_read_icr_lo() & APIC_DELSTAT_MASK) ==
 		    APIC_DELSTAT_IDLE)
 			return (1);


More information about the svn-src-all mailing list