Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/x86/local_apic.c
Show All 39 Lines | |||||
#include "opt_hwpmc_hooks.h" | #include "opt_hwpmc_hooks.h" | ||||
#include "opt_ddb.h" | #include "opt_ddb.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/asan.h> | #include <sys/asan.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/clockcalib.h> | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/msan.h> | #include <sys/msan.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/pcpu.h> | #include <sys/pcpu.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/timeet.h> | #include <sys/timeet.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <x86/apicreg.h> | #include <x86/apicreg.h> | ||||
#include <machine/clock.h> | #include <machine/clock.h> | ||||
#include <machine/cpufunc.h> | #include <machine/cpufunc.h> | ||||
#include <machine/cputypes.h> | #include <machine/cputypes.h> | ||||
#include <machine/fpu.h> | |||||
#include <machine/frame.h> | #include <machine/frame.h> | ||||
#include <machine/intr_machdep.h> | #include <machine/intr_machdep.h> | ||||
#include <x86/apicvar.h> | #include <x86/apicvar.h> | ||||
#include <x86/mca.h> | #include <x86/mca.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/smp.h> | #include <machine/smp.h> | ||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#include <x86/init.h> | #include <x86/init.h> | ||||
▲ Show 20 Lines • Show All 920 Lines • ▼ Show 20 Lines | |||||
#ifdef SMP | #ifdef SMP | ||||
/* The APs should always be started when hwpmc is unloaded. */ | /* The APs should always be started when hwpmc is unloaded. */ | ||||
KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early")); | KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early")); | ||||
#endif | #endif | ||||
smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL); | smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL); | ||||
#endif | #endif | ||||
} | } | ||||
static uint64_t | |||||
cb_lapic_getcount(void) | |||||
{ | |||||
jhb: New functions don't have to have the gratuitous blank line here, but if you are matching the… | |||||
return (APIC_TIMER_MAX_COUNT - lapic_read32(LAPIC_CCR_TIMER)); | |||||
} | |||||
static void | static void | ||||
lapic_calibrate_initcount(struct lapic *la) | lapic_calibrate_initcount(struct lapic *la) | ||||
{ | { | ||||
u_long value; | uint64_t freq; | ||||
/* Start off with a divisor of 2 (power on reset default). */ | /* Calibrate the APIC timer frequency. */ | ||||
lapic_timer_set_divisor(2); | |||||
lapic_timer_oneshot_nointr(la, APIC_TIMER_MAX_COUNT); | |||||
fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); | |||||
freq = clockcalib(cb_lapic_getcount, "lapic"); | |||||
fpu_kern_leave(curthread, NULL); | |||||
/* Pick a different divisor if necessary. */ | |||||
lapic_timer_divisor = 2; | lapic_timer_divisor = 2; | ||||
/* Try to calibrate the local APIC timer. */ | |||||
do { | do { | ||||
lapic_timer_set_divisor(lapic_timer_divisor); | if (freq * 2 / lapic_timer_divisor < APIC_TIMER_MAX_COUNT) | ||||
lapic_timer_oneshot_nointr(la, APIC_TIMER_MAX_COUNT); | |||||
DELAY(1000000); | |||||
value = APIC_TIMER_MAX_COUNT - lapic_read32(LAPIC_CCR_TIMER); | |||||
if (value != APIC_TIMER_MAX_COUNT) | |||||
break; | break; | ||||
lapic_timer_divisor <<= 1; | lapic_timer_divisor <<= 1; | ||||
} while (lapic_timer_divisor <= 128); | } while (lapic_timer_divisor <= 128); | ||||
if (lapic_timer_divisor > 128) | if (lapic_timer_divisor > 128) | ||||
panic("lapic: Divisor too big"); | panic("lapic: Divisor too big"); | ||||
count_freq = freq * 2 / lapic_timer_divisor; | |||||
if (bootverbose) { | if (bootverbose) { | ||||
printf("lapic: Divisor %lu, Frequency %lu Hz\n", | printf("lapic: Divisor %lu, Frequency %lu Hz\n", | ||||
lapic_timer_divisor, value); | lapic_timer_divisor, count_freq); | ||||
} | } | ||||
count_freq = value; | |||||
} | } | ||||
static void | static void | ||||
lapic_change_mode(struct eventtimer *et, struct lapic *la, | lapic_change_mode(struct eventtimer *et, struct lapic *la, | ||||
enum lat_timer_mode newmode) | enum lat_timer_mode newmode) | ||||
{ | { | ||||
if (la->la_timer_mode == newmode) | if (la->la_timer_mode == newmode) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 1,174 Lines • Show Last 20 Lines |
New functions don't have to have the gratuitous blank line here, but if you are matching the style of existing functions in this file, it is ok to stay.