diff options
-rw-r--r-- | sys/amd64/amd64/local_apic.c | 28 | ||||
-rw-r--r-- | sys/amd64/include/apicvar.h | 2 | ||||
-rw-r--r-- | sys/i386/i386/local_apic.c | 36 | ||||
-rw-r--r-- | sys/i386/include/apicvar.h | 2 | ||||
-rw-r--r-- | sys/x86/isa/clock.c | 25 |
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, |