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:
parent
5cf581e264
commit
e1e33ff912
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297770
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user