1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-17 10:26:15 +00:00

Initialize DTrace hrtimer frequency during SI_SUB_CPU on i386 and amd64.

This allows the hrtimer to be used earlier during boot. This is required
for boot-time DTrace: anonymous enablings are created during
SI_SUB_DTRACE_ANON, which runs before APs are started. In particular,
the DTrace deadman timer requires that the hrtimer be functional.

MFC after:	2 weeks
This commit is contained in:
Mark Johnston 2016-04-10 01:23:39 +00:00
parent 5cf581e264
commit e1e33ff912
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297770
2 changed files with 72 additions and 48 deletions

View File

@ -246,24 +246,14 @@ static uint64_t nsec_scale;
/* See below for the explanation of this macro. */
#define SCALE_SHIFT 28
/*
* Get the frequency and scale factor as early as possible so that they can be
* used for boot-time tracing.
*/
static void
dtrace_gethrtime_init_cpu(void *arg)
dtrace_gethrtime_init_early(void *arg)
{
uintptr_t cpu = (uintptr_t) arg;
if (cpu == curcpu)
tgt_cpu_tsc = rdtsc();
else
hst_cpu_tsc = rdtsc();
}
static void
dtrace_gethrtime_init(void *arg)
{
struct pcpu *pc;
uint64_t tsc_f;
cpuset_t map;
int i;
/*
* Get TSC frequency known at this moment.
@ -279,7 +269,8 @@ dtrace_gethrtime_init(void *arg)
* another 32-bit integer without overflowing 64-bit.
* Thus minimum supported TSC frequency is 62.5MHz.
*/
KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), ("TSC frequency is too low"));
KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)),
("TSC frequency is too low"));
/*
* We scale up NANOSEC/tsc_f ratio to preserve as much precision
@ -291,6 +282,27 @@ dtrace_gethrtime_init(void *arg)
* (terahertz) values;
*/
nsec_scale = ((uint64_t)NANOSEC << SCALE_SHIFT) / tsc_f;
}
SYSINIT(dtrace_gethrtime_init_early, SI_SUB_CPU, SI_ORDER_ANY,
dtrace_gethrtime_init_early, NULL);
static void
dtrace_gethrtime_init_cpu(void *arg)
{
uintptr_t cpu = (uintptr_t) arg;
if (cpu == curcpu)
tgt_cpu_tsc = rdtsc();
else
hst_cpu_tsc = rdtsc();
}
static void
dtrace_gethrtime_init(void *arg)
{
struct pcpu *pc;
cpuset_t map;
int i;
/* The current CPU is the reference one. */
sched_pin();
@ -311,8 +323,8 @@ dtrace_gethrtime_init(void *arg)
}
sched_unpin();
}
SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, NULL);
SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init,
NULL);
/*
* DTrace needs a high resolution time function which can

View File

@ -248,6 +248,46 @@ static uint64_t nsec_scale;
/* See below for the explanation of this macro. */
#define SCALE_SHIFT 28
/*
* Get the frequency and scale factor as early as possible so that they can be
* used for boot-time tracing.
*/
static void
dtrace_gethrtime_init_early(void *arg)
{
uint64_t tsc_f;
/*
* Get TSC frequency known at this moment.
* This should be constant if TSC is invariant.
* Otherwise tick->time conversion will be inaccurate, but
* will preserve monotonic property of TSC.
*/
tsc_f = atomic_load_acq_64(&tsc_freq);
/*
* The following line checks that nsec_scale calculated below
* doesn't overflow 32-bit unsigned integer, so that it can multiply
* another 32-bit integer without overflowing 64-bit.
* Thus minimum supported TSC frequency is 62.5MHz.
*/
KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)),
("TSC frequency is too low"));
/*
* We scale up NANOSEC/tsc_f ratio to preserve as much precision
* as possible.
* 2^28 factor was chosen quite arbitrarily from practical
* considerations:
* - it supports TSC frequencies as low as 62.5MHz (see above);
* - it provides quite good precision (e < 0.01%) up to THz
* (terahertz) values;
*/
nsec_scale = ((uint64_t)NANOSEC << SCALE_SHIFT) / tsc_f;
}
SYSINIT(dtrace_gethrtime_init_early, SI_SUB_CPU, SI_ORDER_ANY,
dtrace_gethrtime_init_early, NULL);
static void
dtrace_gethrtime_init_cpu(void *arg)
{
@ -264,36 +304,8 @@ dtrace_gethrtime_init(void *arg)
{
cpuset_t map;
struct pcpu *pc;
uint64_t tsc_f;
int i;
/*
* Get TSC frequency known at this moment.
* This should be constant if TSC is invariant.
* Otherwise tick->time conversion will be inaccurate, but
* will preserve monotonic property of TSC.
*/
tsc_f = atomic_load_acq_64(&tsc_freq);
/*
* The following line checks that nsec_scale calculated below
* doesn't overflow 32-bit unsigned integer, so that it can multiply
* another 32-bit integer without overflowing 64-bit.
* Thus minimum supported TSC frequency is 62.5MHz.
*/
KASSERT(tsc_f > (NANOSEC >> (32 - SCALE_SHIFT)), ("TSC frequency is too low"));
/*
* We scale up NANOSEC/tsc_f ratio to preserve as much precision
* as possible.
* 2^28 factor was chosen quite arbitrarily from practical
* considerations:
* - it supports TSC frequencies as low as 62.5MHz (see above);
* - it provides quite good precision (e < 0.01%) up to THz
* (terahertz) values;
*/
nsec_scale = ((uint64_t)NANOSEC << SCALE_SHIFT) / tsc_f;
/* The current CPU is the reference one. */
sched_pin();
tsc_skew[curcpu] = 0;
@ -313,8 +325,8 @@ dtrace_gethrtime_init(void *arg)
}
sched_unpin();
}
SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init, NULL);
SYSINIT(dtrace_gethrtime_init, SI_SUB_SMP, SI_ORDER_ANY, dtrace_gethrtime_init,
NULL);
/*
* DTrace needs a high resolution time function which can