Improving the clocks auto-tunning by firstly checking if the atrtc may be
correctly initialized and just then assign to softclock/profclock. Right now, some atrtc seems reporting strange diagnostic error* making the current pattern bogus. In order to do that cleanly, lapic_setup_clock(), on both ia32 and amd64, now accepts as arguments the desired sources to handle, and returns the actual ones (LAPIC_CLOCK_NONE is forbidden because otherwise there is no meaning in calling such function). This allows to bring out into commont x86 code the handling part for machdep.lapic_allclocks tunable, which is retained. Sponsored by: Sandvine Incorporated Tested by: yongari, Richard Todd <rmtodd at ichotolot dot servalan dot com> MFC: 3 weeks X-MFC: r202387, 204309
This commit is contained in:
parent
2598954edc
commit
306c0c6ea0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=204641
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
using_lapic_timer = lapic_setup_clock();
|
||||
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)
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user