summaryrefslogtreecommitdiffstats
path: root/sys/pc98/cbus
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-06-20 21:33:29 +0000
committermav <mav@FreeBSD.org>2010-06-20 21:33:29 +0000
commitd1175426d7bcb8aeacdb7416e281e63e668da297 (patch)
tree0950027f8a4d7f49ad3b3ae792b390e08763c5c5 /sys/pc98/cbus
parent75f3660605fcdf678edb8498311bba6ec652af82 (diff)
downloadFreeBSD-src-d1175426d7bcb8aeacdb7416e281e63e668da297.zip
FreeBSD-src-d1175426d7bcb8aeacdb7416e281e63e668da297.tar.gz
Implement new event timers infrastructure. It provides unified APIs for
writing event timer drivers, for choosing best possible drivers by machine independent code and for operating them to supply kernel with hardclock(), statclock() and profclock() events in unified fashion on various hardware. Infrastructure provides support for both per-CPU (independent for every CPU core) and global timers in periodic and one-shot modes. MI management code at this moment uses only periodic mode, but one-shot mode use planned for later, as part of tickless kernel project. For this moment infrastructure used on i386 and amd64 architectures. Other archs are welcome to follow, while their current operation should not be affected. This patch updates existing drivers (i8254, RTC and LAPIC) for the new order, and adds event timers support into the HPET driver. These drivers have different capabilities: LAPIC - per-CPU timer, supports periodic and one-shot operation, may freeze in C3 state, calibrated on first use, so may be not exactly precise. HPET - depending on hardware can work as per-CPU or global, supports periodic and one-shot operation, usually provides several event timers. i8254 - global, limited to periodic mode, because same hardware used also as time counter. RTC - global, supports only periodic mode, set of frequencies in Hz limited by powers of 2. Depending on hardware capabilities, drivers preferred in following orders, either LAPIC, HPETs, i8254, RTC or HPETs, LAPIC, i8254, RTC. User may explicitly specify wanted timers via loader tunables or sysctls: kern.eventtimer.timer1 and kern.eventtimer.timer2. If requested driver is unavailable or unoperational, system will try to replace it. If no more timers available or "NONE" specified for second, system will operate using only one timer, multiplying it's frequency by few times and uing respective dividers to honor hz, stathz and profhz values, set during initial setup.
Diffstat (limited to 'sys/pc98/cbus')
-rw-r--r--sys/pc98/cbus/clock.c61
1 files changed, 22 insertions, 39 deletions
diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c
index 2f2c08c..2596571 100644
--- a/sys/pc98/cbus/clock.c
+++ b/sys/pc98/cbus/clock.c
@@ -93,16 +93,12 @@ TUNABLE_INT("hw.i8254.freq", &i8254_freq);
int i8254_max_count;
static int i8254_real_max_count;
-static int lapic_allclocks = 1;
-TUNABLE_INT("machdep.lapic_allclocks", &lapic_allclocks);
-
static struct mtx clock_lock;
static struct intsrc *i8254_intsrc;
static u_int32_t i8254_lastcount;
static u_int32_t i8254_offset;
static int (*i8254_pending)(struct intsrc *);
static int i8254_ticked;
-static enum lapic_clock using_lapic_timer = LAPIC_CLOCK_NONE;
/* Values for timerX_state: */
#define RELEASED 0
@@ -113,7 +109,9 @@ static enum lapic_clock using_lapic_timer = LAPIC_CLOCK_NONE;
static u_char timer1_state;
static unsigned i8254_get_timecount(struct timecounter *tc);
+#if 0
static unsigned i8254_simple_get_timecount(struct timecounter *tc);
+#endif
static void set_i8254_freq(u_int freq, int intr_freq);
static struct timecounter i8254_timecounter = {
@@ -155,8 +153,6 @@ clkintr(struct trapframe *frame)
clkintr_pending = 0;
mtx_unlock_spin(&clock_lock);
}
- KASSERT(using_lapic_timer == LAPIC_CLOCK_NONE,
- ("clk interrupt enabled with lapic timer"));
#ifdef KDTRACE_HOOKS
/*
@@ -352,7 +348,7 @@ set_i8254_freq(u_int freq, int intr_freq)
i8254_timecounter.tc_frequency = freq;
mtx_lock_spin(&clock_lock);
i8254_freq = freq;
- if (using_lapic_timer != LAPIC_CLOCK_NONE)
+ if (intr_freq == 0)
new_i8254_real_max_count = 0x10000;
else
new_i8254_real_max_count = TIMER_DIV(intr_freq);
@@ -425,45 +421,30 @@ startrtclock()
void
cpu_initclocks()
{
-#if defined(DEV_APIC)
- enum lapic_clock tlsca;
- tlsca = lapic_allclocks == 0 ? LAPIC_CLOCK_HARDCLOCK : LAPIC_CLOCK_ALL;
- using_lapic_timer = lapic_setup_clock(tlsca);
-#endif
- /*
- * 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(). Otherwise, change the 8254
- * timecounter to user a simpler algorithm.
- */
- if (using_lapic_timer == LAPIC_CLOCK_NONE) {
- timer1hz = hz;
- intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
- NULL, INTR_TYPE_CLK, NULL);
- i8254_intsrc = intr_lookup_source(0);
- if (i8254_intsrc != NULL)
- i8254_pending =
- i8254_intsrc->is_pic->pic_source_pending;
- } else {
- i8254_timecounter.tc_get_timecount =
- i8254_simple_get_timecount;
- i8254_timecounter.tc_counter_mask = 0xffff;
- set_i8254_freq(i8254_freq, hz);
- }
- if (using_lapic_timer != LAPIC_CLOCK_ALL) {
- profhz = hz;
- if (hz < 128)
- stathz = hz;
- else
- stathz = hz / (hz / 128);
- }
+ timer1hz = hz;
+ intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
+ NULL, INTR_TYPE_CLK, NULL);
+ i8254_intsrc = intr_lookup_source(0);
+ if (i8254_intsrc != NULL)
+ i8254_pending =
+ i8254_intsrc->is_pic->pic_source_pending;
+ profhz = hz;
+ if (hz < 128)
+ stathz = hz;
+ else
+ stathz = hz / (hz / 128);
timer2hz = 0;
init_TSC_tc();
}
void
+cpu_initclocks_ap(void)
+{
+}
+
+void
cpu_startprofclock(void)
{
}
@@ -493,12 +474,14 @@ sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
+#if 0
static unsigned
i8254_simple_get_timecount(struct timecounter *tc)
{
return (i8254_max_count - getit());
}
+#endif
static unsigned
i8254_get_timecount(struct timecounter *tc)
OpenPOWER on IntegriCloud