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@protected-networks.net> [1], rpokala[2],
	jhb[3]
Tested by:	Michael Butler
Pointy hat to:	kib
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Konstantin Belousov 2016-03-29 19:54:13 +00:00
parent 435bece4c5
commit d317106ce2

View File

@ -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, uint32_t value)
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);