#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/clockintr.h>
#include <sys/evcount.h>
#include <sys/stdint.h>
#include <sys/timetc.h>
#include <machine/cpufunc.h>
extern uint64_t tb_freq;
uint64_t dec_nsec_cycle_ratio;
uint64_t dec_nsec_max;
struct evcount clock_count;
void dec_rearm(void *, uint64_t);
void dec_trigger(void *);
const struct intrclock dec_intrclock = {
.ic_rearm = dec_rearm,
.ic_trigger = dec_trigger
};
u_int tb_get_timecount(struct timecounter *);
static struct timecounter tb_timecounter = {
.tc_get_timecount = tb_get_timecount,
.tc_counter_mask = 0xffffffff,
.tc_frequency = 0,
.tc_name = "tb",
.tc_quality = 0,
.tc_priv = NULL,
.tc_user = TC_TB,
};
void
dec_rearm(void *unused, uint64_t nsecs)
{
uint32_t cycles;
if (nsecs > dec_nsec_max)
nsecs = dec_nsec_max;
cycles = (nsecs * dec_nsec_cycle_ratio) >> 32;
if (cycles > UINT32_MAX >> 1)
cycles = UINT32_MAX >> 1;
mtdec(cycles);
}
void
dec_trigger(void *unused)
{
u_long s;
s = intr_disable();
mtdec(0);
mtdec(UINT32_MAX);
intr_restore(s);
}
u_int
tb_get_timecount(struct timecounter *tc)
{
return mftb();
}
void
cpu_initclocks(void)
{
tb_timecounter.tc_frequency = tb_freq;
tc_init(&tb_timecounter);
dec_nsec_cycle_ratio = tb_freq * (1ULL << 32) / 1000000000;
dec_nsec_max = UINT64_MAX / dec_nsec_cycle_ratio;
stathz = hz;
profhz = stathz * 10;
statclock_is_randomized = 1;
evcount_attach(&clock_count, "clock", NULL);
}
void
cpu_startclock(void)
{
clockintr_cpu_init(&dec_intrclock);
clockintr_trigger();
intr_enable();
}
void
decr_intr(struct trapframe *frame)
{
struct cpu_info *ci = curcpu();
int s;
clock_count.ec_count++;
mtdec(UINT32_MAX >> 1);
if (ci->ci_cpl >= IPL_CLOCK) {
ci->ci_dec_deferred = 1;
return;
}
ci->ci_dec_deferred = 0;
s = splclock();
intr_enable();
clockintr_dispatch(frame);
intr_disable();
splx(s);
}
void
setstatclockrate(int newhz)
{
}
void
delay(u_int us)
{
uint64_t tb;
tb = mftb();
tb += (us * tb_freq + 999999) / 1000000;
while (tb > mftb())
continue;
}