summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/local_apic.c28
-rw-r--r--sys/amd64/include/apicvar.h2
-rw-r--r--sys/i386/i386/local_apic.c36
-rw-r--r--sys/i386/include/apicvar.h2
-rw-r--r--sys/x86/isa/clock.c25
5 files changed, 52 insertions, 41 deletions
diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c
index 0d04bbd..c274631 100644
--- a/sys/amd64/amd64/local_apic.c
+++ b/sys/amd64/amd64/local_apic.c
@@ -149,6 +149,7 @@ extern inthand_t IDTVEC(rsvd);
volatile lapic_t *lapic;
vm_paddr_t lapic_paddr;
static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
+static enum lapic_clock clockcoverage;
static void lapic_enable(void);
static void lapic_resume(struct pic *pic);
@@ -160,9 +161,6 @@ static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
struct pic lapic_pic = { .pic_resume = lapic_resume };
-static int lapic_allclocks;
-TUNABLE_INT("machdep.lapic_allclocks", &lapic_allclocks);
-
static uint32_t
lvt_mode(struct lapic *la, u_int pin, uint32_t value)
{
@@ -423,17 +421,20 @@ lapic_disable_pmc(void)
* local APIC only for the hardclock and 0 if none of them can be handled.
*/
enum lapic_clock
-lapic_setup_clock(void)
+lapic_setup_clock(enum lapic_clock srcsdes)
{
u_long value;
int i;
- /* Can't drive the timer without a local APIC. */
- if (lapic == NULL)
- return (LAPIC_CLOCK_NONE);
+ /* lapic_setup_clock() should not be called with LAPIC_CLOCK_NONE. */
+ MPASS(srcsdes != LAPIC_CLOCK_NONE);
- if (resource_int_value("apic", 0, "clock", &i) == 0 && i == 0)
- return (LAPIC_CLOCK_NONE);
+ /* Can't drive the timer without a local APIC. */
+ if (lapic == NULL ||
+ (resource_int_value("apic", 0, "clock", &i) == 0 && i == 0)) {
+ clockcoverage = LAPIC_CLOCK_NONE;
+ return (clockcoverage);
+ }
/* Start off with a divisor of 2 (power on reset default). */
lapic_timer_divisor = 2;
@@ -469,7 +470,7 @@ lapic_setup_clock(void)
* Please note that stathz and profhz are set only if all the
* clocks are handled through the local APIC.
*/
- if (lapic_allclocks != 0) {
+ if (srcsdes == LAPIC_CLOCK_ALL) {
if (hz >= 1500)
lapic_timer_hz = hz;
else if (hz >= 750)
@@ -479,7 +480,7 @@ lapic_setup_clock(void)
} else
lapic_timer_hz = hz;
lapic_timer_period = value / lapic_timer_hz;
- if (lapic_allclocks != 0) {
+ if (srcsdes == LAPIC_CLOCK_ALL) {
if (lapic_timer_hz < 128)
stathz = lapic_timer_hz;
else
@@ -493,7 +494,8 @@ lapic_setup_clock(void)
*/
lapic_timer_periodic(lapic_timer_period);
lapic_timer_enable_intr();
- return (lapic_allclocks == 0 ? LAPIC_CLOCK_HARDCLOCK : LAPIC_CLOCK_ALL);
+ clockcoverage = srcsdes;
+ return (srcsdes);
}
void
@@ -796,7 +798,7 @@ lapic_handle_timer(struct trapframe *frame)
else
hardclock_cpu(TRAPF_USERMODE(frame));
}
- if (lapic_allclocks != 0) {
+ if (clockcoverage == LAPIC_CLOCK_ALL) {
/* Fire statclock at stathz. */
la->la_stat_ticks += stathz;
diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h
index 8f15d84..110ce81 100644
--- a/sys/amd64/include/apicvar.h
+++ b/sys/amd64/include/apicvar.h
@@ -230,7 +230,7 @@ int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
void lapic_setup(int boot);
-enum lapic_clock lapic_setup_clock(void);
+enum lapic_clock lapic_setup_clock(enum lapic_clock srcsdes);
#endif /* !LOCORE */
#endif /* _MACHINE_APICVAR_H_ */
diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c
index e0049c8..6c62200 100644
--- a/sys/i386/i386/local_apic.c
+++ b/sys/i386/i386/local_apic.c
@@ -150,6 +150,7 @@ extern inthand_t IDTVEC(rsvd);
volatile lapic_t *lapic;
vm_paddr_t lapic_paddr;
static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
+static enum lapic_clock clockcoverage;
static void lapic_enable(void);
static void lapic_resume(struct pic *pic);
@@ -161,17 +162,6 @@ static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
struct pic lapic_pic = { .pic_resume = lapic_resume };
-/*
- * The atrtc device is compiled in only if atpic is present.
- * If it is not, force lapic to take care of all the clocks.
- */
-#ifdef DEV_ATPIC
-static int lapic_allclocks;
-TUNABLE_INT("machdep.lapic_allclocks", &lapic_allclocks);
-#else
-static int lapic_allclocks = 1;
-#endif
-
static uint32_t
lvt_mode(struct lapic *la, u_int pin, uint32_t value)
{
@@ -431,17 +421,20 @@ lapic_disable_pmc(void)
* that it can drive hardclock, statclock, and profclock.
*/
enum lapic_clock
-lapic_setup_clock(void)
+lapic_setup_clock(enum lapic_clock srcsdes)
{
u_long value;
int i;
- /* Can't drive the timer without a local APIC. */
- if (lapic == NULL)
- return (LAPIC_CLOCK_NONE);
+ /* lapic_setup_clock() should not be called with LAPIC_CLOCK_NONE. */
+ MPASS(srcsdes != LAPIC_CLOCK_NONE);
- if (resource_int_value("apic", 0, "clock", &i) == 0 && i == 0)
- return (LAPIC_CLOCK_NONE);
+ /* Can't drive the timer without a local APIC. */
+ if (lapic == NULL ||
+ (resource_int_value("apic", 0, "clock", &i) == 0 && i == 0)) {
+ clockcoverage = LAPIC_CLOCK_NONE;
+ return (clockcoverage);
+ }
/* Start off with a divisor of 2 (power on reset default). */
lapic_timer_divisor = 2;
@@ -477,7 +470,7 @@ lapic_setup_clock(void)
* Please note that stathz and profhz are set only if all the
* clocks are handled through the local APIC.
*/
- if (lapic_allclocks != 0) {
+ if (srcsdes == LAPIC_CLOCK_ALL) {
if (hz >= 1500)
lapic_timer_hz = hz;
else if (hz >= 750)
@@ -487,7 +480,7 @@ lapic_setup_clock(void)
} else
lapic_timer_hz = hz;
lapic_timer_period = value / lapic_timer_hz;
- if (lapic_allclocks != 0) {
+ if (srcsdes == LAPIC_CLOCK_ALL) {
if (lapic_timer_hz < 128)
stathz = lapic_timer_hz;
else
@@ -501,7 +494,8 @@ lapic_setup_clock(void)
*/
lapic_timer_periodic(lapic_timer_period);
lapic_timer_enable_intr();
- return (lapic_allclocks == 0 ? LAPIC_CLOCK_HARDCLOCK : LAPIC_CLOCK_ALL);
+ clockcoverage = srcsdes;
+ return (srcsdes);
}
void
@@ -804,7 +798,7 @@ lapic_handle_timer(struct trapframe *frame)
else
hardclock_cpu(TRAPF_USERMODE(frame));
}
- if (lapic_allclocks != 0) {
+ if (clockcoverage == LAPIC_CLOCK_ALL) {
/* Fire statclock at stathz. */
la->la_stat_ticks += stathz;
diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h
index 2f8e716..208ffb5 100644
--- a/sys/i386/include/apicvar.h
+++ b/sys/i386/include/apicvar.h
@@ -259,7 +259,7 @@ int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
void lapic_setup(int boot);
-enum lapic_clock lapic_setup_clock(void);
+enum lapic_clock lapic_setup_clock(enum lapic_clock srcsdes);
#endif /* !LOCORE */
#endif /* _MACHINE_APICVAR_H_ */
diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c
index 6ced537..4a20709 100644
--- a/sys/x86/isa/clock.c
+++ b/sys/x86/isa/clock.c
@@ -97,6 +97,9 @@ TUNABLE_INT("hw.i8254.freq", &i8254_freq);
int i8254_max_count;
static int i8254_real_max_count;
+static int lapic_allclocks;
+TUNABLE_INT("machdep.lapic_allclocks", &lapic_allclocks);
+
struct mtx clock_lock;
static struct intsrc *i8254_intsrc;
static u_int32_t i8254_lastcount;
@@ -526,9 +529,24 @@ startrtclock()
void
cpu_initclocks()
{
+#if defined(__amd64__) || defined(DEV_APIC)
+ enum lapic_clock tlsca;
+#endif
+ int tasc;
+
+ /* Initialize RTC. */
+ atrtc_start();
+ tasc = atrtc_setup_clock();
+ /*
+ * If the atrtc successfully initialized and the users didn't force
+ * otherwise use the LAPIC in order to cater hardclock only, otherwise
+ * take in charge all the clock sources.
+ */
#if defined(__amd64__) || defined(DEV_APIC)
- using_lapic_timer = lapic_setup_clock();
+ tlsca = (lapic_allclocks == 0 && tasc != 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
@@ -550,9 +568,6 @@ cpu_initclocks()
set_i8254_freq(i8254_freq, hz);
}
- /* Initialize RTC. */
- atrtc_start();
-
/*
* If the separate statistics clock hasn't been explicility disabled
* and we aren't already using the local APIC timer to drive the
@@ -560,7 +575,7 @@ cpu_initclocks()
* drive statclock() and profclock().
*/
if (using_lapic_timer != LAPIC_CLOCK_ALL) {
- using_atrtc_timer = atrtc_setup_clock();
+ using_atrtc_timer = tasc;
if (using_atrtc_timer) {
/* Enable periodic interrupts from the RTC. */
intr_add_handler("rtc", 8,
OpenPOWER on IntegriCloud