Fixed time processing.
- arm64: Get TSC corresponding to boot time from IHK. - x86_64: Calculate the current time using vdso. Refs: #1186 Fujitsu: POSTK_DEBUG_ARCH_DEP_52 Change-Id: I293ba4bbe5390d50dea44b8a5b7471f59237daff
This commit is contained in:
committed by
Masamichi Takagi
parent
07aa96ef95
commit
5bc54a3bbe
@ -2699,4 +2699,40 @@ SYSCALL_DECLARE(time)
|
||||
return time();
|
||||
}
|
||||
|
||||
void calculate_time_from_tsc(struct timespec *ts)
|
||||
{
|
||||
long ver;
|
||||
unsigned long current_tsc;
|
||||
time_t sec_delta;
|
||||
long ns_delta;
|
||||
|
||||
for (;;) {
|
||||
while ((ver = ihk_atomic64_read(&tod_data.version)) & 1) {
|
||||
/* settimeofday() is in progress */
|
||||
cpu_pause();
|
||||
}
|
||||
rmb(); /* fetch version before time */
|
||||
*ts = tod_data.origin;
|
||||
rmb(); /* fetch time before checking version */
|
||||
if (ver == ihk_atomic64_read(&tod_data.version)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* settimeofday() has intervened */
|
||||
cpu_pause();
|
||||
}
|
||||
|
||||
current_tsc = rdtsc();
|
||||
sec_delta = current_tsc / tod_data.clocks_per_sec;
|
||||
ns_delta = NS_PER_SEC * (current_tsc % tod_data.clocks_per_sec)
|
||||
/ tod_data.clocks_per_sec;
|
||||
/* calc. of ns_delta overflows if clocks_per_sec exceeds 18.44 GHz */
|
||||
|
||||
ts->tv_sec += sec_delta;
|
||||
ts->tv_nsec += ns_delta;
|
||||
if (ts->tv_nsec >= NS_PER_SEC) {
|
||||
ts->tv_nsec -= NS_PER_SEC;
|
||||
++ts->tv_sec;
|
||||
}
|
||||
}
|
||||
/*** End of File ***/
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#define DDEBUG_DEFAULT DDEBUG_PRINT
|
||||
#endif
|
||||
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_52
|
||||
#define VDSO_MAXPAGES 1
|
||||
struct vdso {
|
||||
long busy;
|
||||
@ -34,7 +33,6 @@ struct vdso {
|
||||
long lbase;
|
||||
long offset_sigtramp;
|
||||
};
|
||||
#endif /*POSTK_DEBUG_ARCH_DEP_52*/
|
||||
|
||||
extern char vdso_start, vdso_end;
|
||||
static struct vdso vdso;
|
||||
|
||||
@ -64,7 +64,6 @@ uintptr_t debug_constants[] = {
|
||||
-1,
|
||||
};
|
||||
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_52
|
||||
#define VDSO_MAXPAGES 2
|
||||
struct vdso {
|
||||
long busy;
|
||||
@ -80,8 +79,24 @@ struct vdso {
|
||||
long hpet_phys;
|
||||
void *pvti_virt;
|
||||
long pvti_phys;
|
||||
void *vgtod_virt;
|
||||
};
|
||||
|
||||
struct vsyscall_gtod_data {
|
||||
int seq;
|
||||
|
||||
struct {
|
||||
int vclock_mode;
|
||||
unsigned long cycle_last;
|
||||
unsigned long mask;
|
||||
unsigned int mult;
|
||||
unsigned int shift;
|
||||
} clock;
|
||||
|
||||
/* open coded 'struct timespec' */
|
||||
time_t wall_time_sec;
|
||||
unsigned long wall_time_snsec;
|
||||
};
|
||||
#endif /*POSTK_DEBUG_ARCH_DEP_52*/
|
||||
|
||||
static struct vdso vdso;
|
||||
static size_t container_size = 0;
|
||||
@ -2811,4 +2826,37 @@ time_t time(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void calculate_time_from_tsc(struct timespec *ts)
|
||||
{
|
||||
unsigned long seq;
|
||||
unsigned long seq2;
|
||||
unsigned long ns;
|
||||
unsigned long delta;
|
||||
struct vsyscall_gtod_data *gtod = vdso.vgtod_virt;
|
||||
|
||||
do {
|
||||
for (;;) {
|
||||
seq = ACCESS_ONCE(gtod->seq);
|
||||
if (unlikely(seq & 1)) {
|
||||
cpu_pause();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rmb(); /* fetch sequence before time */
|
||||
ts->tv_sec = gtod->wall_time_sec;
|
||||
ns = gtod->wall_time_snsec;
|
||||
delta = rdtsc() - gtod->clock.cycle_last;
|
||||
ns += delta * gtod->clock.mult;
|
||||
ns >>= gtod->clock.shift;
|
||||
seq2 = ACCESS_ONCE(gtod->seq);
|
||||
rmb(); /* fetch time before checking sequence */
|
||||
} while (seq != seq2);
|
||||
ts->tv_nsec = ns;
|
||||
|
||||
if (ts->tv_nsec >= NS_PER_SEC) {
|
||||
ts->tv_nsec -= NS_PER_SEC;
|
||||
++ts->tv_sec;
|
||||
}
|
||||
}
|
||||
/*** End of File ***/
|
||||
|
||||
Reference in New Issue
Block a user