- Fix the locking around the i8254. Values for the TSC clock and lapic
delay function were wildly inaccurate due to multiple CPUs competing in DELAY() during calibration, confusing the clock chip. - Use i8254_delay() explictly in a few more places.
This commit is contained in:
parent
05237843cf
commit
83caeda725
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: clock.c,v 1.13 2007/11/14 17:55:00 ad Exp $ */
|
||||
/* $NetBSD: clock.c,v 1.14 2007/12/04 16:05:34 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
|
@ -121,7 +121,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.13 2007/11/14 17:55:00 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.14 2007/12/04 16:05:34 ad Exp $");
|
||||
|
||||
/* #define CLOCKDEBUG */
|
||||
/* #define CLOCK_PARANOIA */
|
||||
|
@ -257,22 +257,21 @@ static int ticks[6];
|
|||
static unsigned int
|
||||
gettick_broken_latch(void)
|
||||
{
|
||||
u_long flags;
|
||||
int v1, v2, v3;
|
||||
int w1, w2, w3;
|
||||
int s;
|
||||
|
||||
/* Don't want someone screwing with the counter while we're here. */
|
||||
flags = x86_read_psl();
|
||||
x86_disable_intr();
|
||||
|
||||
s = splhigh();
|
||||
__cpu_simple_lock(&tmr_lock);
|
||||
v1 = inb(IO_TIMER1+TIMER_CNTR0);
|
||||
v1 |= inb(IO_TIMER1+TIMER_CNTR0) << 8;
|
||||
v2 = inb(IO_TIMER1+TIMER_CNTR0);
|
||||
v2 |= inb(IO_TIMER1+TIMER_CNTR0) << 8;
|
||||
v3 = inb(IO_TIMER1+TIMER_CNTR0);
|
||||
v3 |= inb(IO_TIMER1+TIMER_CNTR0) << 8;
|
||||
|
||||
x86_write_psl(flags);
|
||||
__cpu_simple_unlock(&tmr_lock);
|
||||
splx(s);
|
||||
|
||||
#ifdef CLOCK_PARANOIA
|
||||
if (clock_debug) {
|
||||
|
@ -371,7 +370,7 @@ startrtclock(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* Must be called at splclock().
|
||||
* Must be called at splsched().
|
||||
*/
|
||||
static void
|
||||
tickle_tc(void)
|
||||
|
@ -418,31 +417,25 @@ u_int
|
|||
i8254_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
u_int count;
|
||||
u_char high, low;
|
||||
u_long flags;
|
||||
uint16_t rdval;
|
||||
int s;
|
||||
|
||||
/* Don't want someone screwing with the counter while we're here. */
|
||||
flags = x86_read_psl();
|
||||
x86_disable_intr();
|
||||
s = splhigh();
|
||||
__cpu_simple_lock(&tmr_lock);
|
||||
|
||||
/* Select timer0 and latch counter value. */
|
||||
outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
|
||||
|
||||
low = inb(IO_TIMER1 + TIMER_CNTR0);
|
||||
high = inb(IO_TIMER1 + TIMER_CNTR0);
|
||||
count = rtclock_tval - ((high << 8) | low);
|
||||
|
||||
/* insb to make the read atomic */
|
||||
insb(IO_TIMER1+TIMER_CNTR0, &rdval, 2);
|
||||
count = rtclock_tval - rdval;
|
||||
if (rtclock_tval && (count < i8254_lastcount || !i8254_ticked)) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += rtclock_tval;
|
||||
}
|
||||
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
|
||||
__cpu_simple_unlock(&tmr_lock);
|
||||
x86_write_psl(flags);
|
||||
splx(s);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
@ -450,21 +443,23 @@ i8254_get_timecount(struct timecounter *tc)
|
|||
unsigned int
|
||||
gettick(void)
|
||||
{
|
||||
u_long flags;
|
||||
u_char lo, hi;
|
||||
|
||||
uint16_t rdval;
|
||||
int s;
|
||||
|
||||
if (clock_broken_latch)
|
||||
return (gettick_broken_latch());
|
||||
|
||||
/* Don't want someone screwing with the counter while we're here. */
|
||||
flags = x86_read_psl();
|
||||
x86_disable_intr();
|
||||
s = splhigh();
|
||||
__cpu_simple_lock(&tmr_lock);
|
||||
/* Select counter 0 and latch it. */
|
||||
outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
|
||||
lo = inb(IO_TIMER1+TIMER_CNTR0);
|
||||
hi = inb(IO_TIMER1+TIMER_CNTR0);
|
||||
x86_write_psl(flags);
|
||||
return ((hi << 8) | lo);
|
||||
/* insb to make the read atomic */
|
||||
insb(IO_TIMER1+TIMER_CNTR0, &rdval, 2);
|
||||
__cpu_simple_unlock(&tmr_lock);
|
||||
splx(s);
|
||||
|
||||
return rdval;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
/* $NetBSD: cpu.c,v 1.10 2007/12/02 20:34:41 ad Exp $ */
|
||||
/* $NetBSD: cpu.c,v 1.11 2007/12/04 16:05:34 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by RedBack Networks Inc.
|
||||
*
|
||||
* Author: Bill Sommerfeld
|
||||
* by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -71,7 +69,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.10 2007/12/02 20:34:41 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.11 2007/12/04 16:05:34 ad Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
|
@ -576,7 +574,7 @@ cpu_start_secondary(ci)
|
|||
* wait for it to become ready
|
||||
*/
|
||||
for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
|
||||
delay(10);
|
||||
i8254_delay(10);
|
||||
}
|
||||
if ((ci->ci_flags & CPUF_PRESENT) == 0) {
|
||||
aprint_error("%s: failed to become ready\n",
|
||||
|
@ -598,7 +596,7 @@ cpu_boot_secondary(ci)
|
|||
|
||||
atomic_or_32(&ci->ci_flags, CPUF_GO);
|
||||
for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {
|
||||
DELAY(10);
|
||||
i8254_delay(10);
|
||||
}
|
||||
if ((ci->ci_flags & CPUF_RUNNING) == 0) {
|
||||
aprint_error("%s: failed to start\n", ci->ci_dev->dv_xname);
|
||||
|
@ -829,7 +827,7 @@ mp_cpu_start(struct cpu_info *ci)
|
|||
if ((error = x86_ipi_init(ci->ci_apicid)) != 0)
|
||||
return error;
|
||||
|
||||
delay(10000);
|
||||
i8254_delay(10000);
|
||||
|
||||
if (cpu_feature & CPUID_APIC) {
|
||||
|
||||
|
@ -837,13 +835,13 @@ mp_cpu_start(struct cpu_info *ci)
|
|||
ci->ci_apicid,
|
||||
LAPIC_DLMODE_STARTUP)) != 0)
|
||||
return error;
|
||||
delay(200);
|
||||
i8254_delay(200);
|
||||
|
||||
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
|
||||
ci->ci_apicid,
|
||||
LAPIC_DLMODE_STARTUP)) != 0)
|
||||
return error;
|
||||
delay(200);
|
||||
i8254_delay(200);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue