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:
parent
435bece4c5
commit
d317106ce2
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user