forked from Qortal/Brooklyn
* 0day explit mitigation * Memory corruption prevention * Privilege escalation prevention * Buffer over flow prevention * File System corruption defense * Thread escape prevention This may very well be the most intensive inclusion to BrooklynR. This will not be part of an x86 suite nor it will be released as tool kit. The security core toolkit will remain part of kernel base.
113 lines
3.0 KiB
C
113 lines
3.0 KiB
C
/*
|
|
* linux/kernel/time/timecounter.c
|
|
*
|
|
* based on code that migrated away from
|
|
* linux/kernel/time/clocksource.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/export.h>
|
|
#include <linux/timecounter.h>
|
|
|
|
void timecounter_init(struct timecounter *tc,
|
|
const struct cyclecounter *cc,
|
|
u64 start_tstamp)
|
|
{
|
|
tc->cc = cc;
|
|
tc->cycle_last = cc->read(cc);
|
|
tc->nsec = start_tstamp;
|
|
tc->mask = (1ULL << cc->shift) - 1;
|
|
tc->frac = 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(timecounter_init);
|
|
|
|
/**
|
|
* timecounter_read_delta - get nanoseconds since last call of this function
|
|
* @tc: Pointer to time counter
|
|
*
|
|
* When the underlying cycle counter runs over, this will be handled
|
|
* correctly as long as it does not run over more than once between
|
|
* calls.
|
|
*
|
|
* The first call to this function for a new time counter initializes
|
|
* the time tracking and returns an undefined result.
|
|
*/
|
|
static u64 timecounter_read_delta(struct timecounter *tc)
|
|
{
|
|
cycle_t cycle_now, cycle_delta;
|
|
u64 ns_offset;
|
|
|
|
/* read cycle counter: */
|
|
cycle_now = tc->cc->read(tc->cc);
|
|
|
|
/* calculate the delta since the last timecounter_read_delta(): */
|
|
cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
|
|
|
|
/* convert to nanoseconds: */
|
|
ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
|
|
tc->mask, &tc->frac);
|
|
|
|
/* update time stamp of timecounter_read_delta() call: */
|
|
tc->cycle_last = cycle_now;
|
|
|
|
return ns_offset;
|
|
}
|
|
|
|
u64 timecounter_read(struct timecounter *tc)
|
|
{
|
|
u64 nsec;
|
|
|
|
/* increment time by nanoseconds since last call */
|
|
nsec = timecounter_read_delta(tc);
|
|
nsec += tc->nsec;
|
|
tc->nsec = nsec;
|
|
|
|
return nsec;
|
|
}
|
|
EXPORT_SYMBOL_GPL(timecounter_read);
|
|
|
|
/*
|
|
* This is like cyclecounter_cyc2ns(), but it is used for computing a
|
|
* time previous to the time stored in the cycle counter.
|
|
*/
|
|
static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
|
|
cycle_t cycles, u64 mask, u64 frac)
|
|
{
|
|
u64 ns = (u64) cycles;
|
|
|
|
ns = ((ns * cc->mult) - frac) >> cc->shift;
|
|
|
|
return ns;
|
|
}
|
|
|
|
u64 timecounter_cyc2time(struct timecounter *tc,
|
|
cycle_t cycle_tstamp)
|
|
{
|
|
u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
|
|
u64 nsec = tc->nsec, frac = tc->frac;
|
|
|
|
/*
|
|
* Instead of always treating cycle_tstamp as more recent
|
|
* than tc->cycle_last, detect when it is too far in the
|
|
* future and treat it as old time stamp instead.
|
|
*/
|
|
if (delta > tc->cc->mask / 2) {
|
|
delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
|
|
nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
|
|
} else {
|
|
nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
|
|
}
|
|
|
|
return nsec;
|
|
}
|
|
EXPORT_SYMBOL_GPL(timecounter_cyc2time);
|