From d551cbfe02dadee2f5067bcd6e8f67f4d7193f37 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 14 Aug 2013 22:41:59 +0800 Subject: [PATCH] cputimer: Allow MP synchronized TSC to become cputimer on i386 See also 8d23b56caf513f5c15f56fb053479cc00fe2eaf4 --- sys/platform/pc32/isa/clock.c | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/sys/platform/pc32/isa/clock.c b/sys/platform/pc32/isa/clock.c index 5fe8ac611b..c42538732c 100644 --- a/sys/platform/pc32/isa/clock.c +++ b/sys/platform/pc32/isa/clock.c @@ -147,6 +147,23 @@ static struct cputimer i8254_cputimer = { 0, 0, 0 }; +static sysclock_t tsc_cputimer_count(void); +static void tsc_cputimer_construct(struct cputimer *, sysclock_t); + +static struct cputimer tsc_cputimer = { + SLIST_ENTRY_INITIALIZER, + "TSC", + CPUTIMER_PRI_TSC, + CPUTIMER_TSC, + tsc_cputimer_count, + cputimer_default_fromhz, + cputimer_default_fromus, + tsc_cputimer_construct, + cputimer_default_destruct, + 0, + 0, 0, 0 +}; + static void i8254_intr_reload(struct cputimer_intr *, sysclock_t); static void i8254_intr_config(struct cputimer_intr *, const struct cputimer *); static void i8254_intr_initclock(struct cputimer_intr *, boolean_t); @@ -1249,6 +1266,57 @@ tsc_mpsync_test(void) } SYSINIT(tsc_mpsync, SI_BOOT2_FINISH_SMP, SI_ORDER_ANY, tsc_mpsync_test, NULL); +#define TSC_CPUTIMER_FREQMAX 128000000 /* 128Mhz */ + +static int tsc_cputimer_shift; + +static void +tsc_cputimer_construct(struct cputimer *timer, sysclock_t oldclock) +{ + timer->base = 0; + timer->base = oldclock - tsc_cputimer_count(); +} + +static sysclock_t +tsc_cputimer_count(void) +{ + uint64_t tsc; + + tsc = rdtsc(); + tsc >>= tsc_cputimer_shift; + + return (tsc + tsc_cputimer.base); +} + +static void +tsc_cputimer_register(void) +{ + uint64_t freq; + int enable = 1; + + if (!tsc_mpsync) + return; + + TUNABLE_INT_FETCH("hw.tsc_cputimer_enable", &enable); + if (!enable) + return; + + freq = tsc_frequency; + while (freq > TSC_CPUTIMER_FREQMAX) { + freq >>= 1; + ++tsc_cputimer_shift; + } + kprintf("TSC: cputimer freq %ju, shift %d\n", + (uintmax_t)freq, tsc_cputimer_shift); + + tsc_cputimer.freq = freq; + + cputimer_register(&tsc_cputimer); + cputimer_select(&tsc_cputimer, 0); +} +SYSINIT(tsc_cputimer_reg, SI_BOOT2_MACHDEP, SI_ORDER_ANY, + tsc_cputimer_register, NULL); + SYSCTL_NODE(_hw, OID_AUTO, i8254, CTLFLAG_RW, 0, "I8254"); SYSCTL_UINT(_hw_i8254, OID_AUTO, freq, CTLFLAG_RD, &i8254_cputimer.freq, 0, "frequency"); -- 2.41.0