aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/isa/clock.c60
1 files changed, 32 insertions, 28 deletions
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index a2f3e2f9127a..f1f3e94236cd 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -102,6 +102,8 @@ u_int timer_freq = TIMER_FREQ;
int timer0_max_count;
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
struct mtx clock_lock;
+#define RTC_LOCK mtx_lock_spin(&clock_lock)
+#define RTC_UNLOCK mtx_unlock_spin(&clock_lock)
static int beeping = 0;
static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
@@ -113,7 +115,7 @@ static int (*i8254_pending)(struct intsrc *);
static int i8254_ticked;
static int using_lapic_timer;
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
-static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR;
+static u_char rtc_statusb = RTCSB_24HR;
/* Values for timerX_state: */
#define RELEASED 0
@@ -401,30 +403,28 @@ int
rtcin(reg)
int reg;
{
- int s;
u_char val;
- s = splhigh();
+ RTC_LOCK;
outb(IO_RTC, reg);
inb(0x84);
val = inb(IO_RTC + 1);
inb(0x84);
- splx(s);
+ RTC_UNLOCK;
return (val);
}
static __inline void
writertc(u_char reg, u_char val)
{
- int s;
- s = splhigh();
+ RTC_LOCK;
inb(0x84);
outb(IO_RTC, reg);
inb(0x84);
outb(IO_RTC + 1, val);
inb(0x84); /* XXX work around wrong order in rtcin() */
- splx(s);
+ RTC_UNLOCK;
}
static __inline int
@@ -725,37 +725,41 @@ cpu_initclocks()
int diag;
using_lapic_timer = lapic_setup_clock();
- if (statclock_disable || using_lapic_timer) {
- /*
- * The stat interrupt mask is different without the
- * statistics clock. Also, don't set the interrupt
- * flag which would normally cause the RTC to generate
- * interrupts.
- */
- rtc_statusb = RTCSB_24HR;
- } else {
- /* Setting stathz to nonzero early helps avoid races. */
- stathz = RTC_NOPROFRATE;
- profhz = RTC_PROFRATE;
- }
-
- /* Finish initializing 8254 timer 0. */
- intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
- INTR_TYPE_CLK | INTR_FAST, NULL);
- i8254_intsrc = intr_lookup_source(0);
- if (i8254_intsrc != NULL)
- i8254_pending = i8254_intsrc->is_pic->pic_source_pending;
+ /*
+ * If we aren't using the local APIC timer to drive the kernel
+ * clocks, setup the interrupt handler for the 8254 timer 0 so
+ * that it can drive hardclock().
+ */
+ if (!using_lapic_timer) {
+ intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
+ INTR_TYPE_CLK | INTR_FAST, NULL);
+ i8254_intsrc = intr_lookup_source(0);
+ if (i8254_intsrc != NULL)
+ i8254_pending =
+ i8254_intsrc->is_pic->pic_source_pending;
+ }
/* Initialize RTC. */
writertc(RTC_STATUSA, rtc_statusa);
writertc(RTC_STATUSB, RTCSB_24HR);
- /* Don't bother enabling the statistics clock. */
+ /*
+ * If the separate statistics clock hasn't been explicility disabled
+ * and we aren't already using the local APIC timer to drive the
+ * kernel clocks, then setup the RTC to periodically interrupt to
+ * drive statclock() and profclock().
+ */
if (!statclock_disable && !using_lapic_timer) {
diag = rtcin(RTC_DIAG);
if (diag != 0)
printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
+ /* Setting stathz to nonzero early helps avoid races. */
+ stathz = RTC_NOPROFRATE;
+ profhz = RTC_PROFRATE;
+
+ /* Enable periodic interrupts from the RTC. */
+ rtc_statusb |= RTCSB_PINTR;
intr_add_handler("rtc", 8, (driver_intr_t *)rtcintr, NULL,
INTR_TYPE_CLK | INTR_FAST, NULL);