Skip to content
Snippets Groups Projects
Commit 2df3c029 authored by Glauber Costa's avatar Glauber Costa Committed by Pekka Enberg
Browse files

pvclock: reuse pvclock's functionality to convert tsc to nano


This patch provides a way to, given a measurement from tsc, acquire a nanosecond
figure. It works only for xen and kvm pvclocks, and I intend to use it for acquiring
early boot figures.

It is possible to measure the tsc frequency and with that figure out how to
convert a tsc read to nanoseconds, but I don't think we should pay that price.
Most of the pvclock drivers already provide that functionality, and we are not
planning that many users of that interface anyway.

Signed-off-by: default avatarGlauber Costa <glommer@cloudius-systems.com>
Signed-off-by: default avatarPekka Enberg <penberg@cloudius-systems.com>
parent 6d5d43c9
No related branches found
No related tags found
No related merge requests found
......@@ -33,17 +33,8 @@ u64 system_time(pvclock_vcpu_time_info *sys)
do {
v1 = sys->version;
barrier();
time = processor::rdtsc() - sys->tsc_timestamp;
if (sys->tsc_shift >= 0) {
time <<= sys->tsc_shift;
} else {
time >>= -sys->tsc_shift;
}
asm("mul %1; shrd $32, %%rdx, %0"
: "+a"(time)
: "rm"(u64(sys->tsc_to_system_mul))
: "rdx");
time += sys->system_time;
time = sys->system_time +
processor_to_nano(sys, processor::rdtsc() - sys->tsc_timestamp);
barrier();
v2 = sys->version;
} while (v1 != v2);
......
......@@ -92,6 +92,13 @@ public:
* different times.
*/
virtual s64 boot_time() = 0;
/*
* convert a processor based timestamp (x86 tsc's for instance) to nanoseconds.
*
* Not all clocks are required to implement it.
*/
virtual u64 processor_to_nano(u64 ticks) { return 0; }
private:
static clock* _c;
};
......
......@@ -22,6 +22,7 @@ public:
virtual s64 time() __attribute__((no_instrument_function));
virtual s64 uptime() override __attribute__((no_instrument_function));
virtual s64 boot_time() override __attribute__((no_instrument_function));
virtual u64 processor_to_nano(u64 ticks) override __attribute__((no_instrument_function));
static bool probe();
private:
u64 wall_clock_boot();
......@@ -122,6 +123,11 @@ u64 kvmclock::system_time()
return r;
}
u64 kvmclock::processor_to_nano(u64 ticks)
{
return pvclock::processor_to_nano(&*_sys, ticks);
}
static __attribute__((constructor(init_prio::clock))) void setup_kvmclock()
{
if (kvmclock::probe()) {
......
......@@ -25,6 +25,7 @@ public:
virtual s64 time() __attribute__((no_instrument_function));
virtual s64 uptime() override __attribute__((no_instrument_function));
virtual s64 boot_time() override __attribute__((no_instrument_function));
virtual u64 processor_to_nano(u64 ticks) override __attribute__((no_instrument_function));
private:
pvclock_wall_clock* _wall;
static void setup_cpu();
......@@ -77,6 +78,15 @@ u64 xenclock::system_time()
}
}
u64 xenclock::processor_to_nano(u64 ticks)
{
WITH_LOCK(preempt_lock) {
auto cpu = sched::cpu::current()->id;
auto sys = &xen::xen_shared_info.vcpu_info[cpu].time;
return pvclock::processor_to_nano(sys, ticks);
}
}
s64 xenclock::uptime()
{
if (_smp_init) {
......
......@@ -27,6 +27,21 @@ struct pvclock_vcpu_time_info {
} __attribute__((__packed__)); /* 32 bytes */
namespace pvclock {
inline u64 processor_to_nano(pvclock_vcpu_time_info *sys, u64 time)
{
if (sys->tsc_shift >= 0) {
time <<= sys->tsc_shift;
} else {
time >>= -sys->tsc_shift;
}
asm("mul %1; shrd $32, %%rdx, %0"
: "+a"(time)
: "rm"(u64(sys->tsc_to_system_mul))
: "rdx");
return time;
}
u64 wall_clock_boot(pvclock_wall_clock *_wall);
u64 system_time(pvclock_vcpu_time_info *sys);
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment