Timekeeping in virtual machines: Difference between revisions
[unchecked revision] | [unchecked revision] |
Created page with "{{stub}} {{In Progress}} There are several ways to keep track of time in a VM, but they're either very slow (e.g. HPET) or do not work correctly if the VM is migrated (e.g. T..." |
m s/suck/such |
||
Line 4: | Line 4: | ||
There are several ways to keep track of time in a VM, but they're either very slow (e.g. HPET) or do not work correctly if the VM is migrated (e.g. TSC). |
There are several ways to keep track of time in a VM, but they're either very slow (e.g. HPET) or do not work correctly if the VM is migrated (e.g. TSC). |
||
To work around this, VMs |
To work around this, VMs such as QEMU/KVM provide several ways keep track of time whilst sacrificing little performance. |
||
== KVM_HC_CLOCK_PAIRING == |
== KVM_HC_CLOCK_PAIRING == |
Revision as of 19:34, 27 August 2022
There are several ways to keep track of time in a VM, but they're either very slow (e.g. HPET) or do not work correctly if the VM is migrated (e.g. TSC).
To work around this, VMs such as QEMU/KVM provide several ways keep track of time whilst sacrificing little performance.
KVM_HC_CLOCK_PAIRING
This hypercall is used to get the parameters to calculate a host's clock (KVM_CLOCK_PAIRING_WALLCLOCK for CLOCK_REALTIME).
The host copies the following structure to a physical address given by the guest:
struct kvm_clock_pairing {
s64 sec;
s64 nsec;
u64 tsc;
u32 flags;
u32 pad[9];
};
A hypercall is performed with the `vmcall` instruction. On KVM, RBX, RCX, RDX and RSI are used for arguments, RAX as the hypercall number and as the return value. No other registers are clobbered (unless explicitly noted).
For example, calling KVM_HC_CLOCK_PAIRING can be done as follows on x86_64:
; rdi: physical address to copy structure to
; rsi: clock type (KVM_CLOCK_PAIRING_WALLCLOCK = 0)
kvm_hc_clock_pairing:
mov eax, 9 ; KVM_HC_CLOCK_PAIRING
mov rbx, rdi
mov rcx, rsi
vmcall
ret
pvclock
struct pvclock_vcpu_time_info {
u32 version;
u32 pad0;
u64 tsc_timestamp;
u64 system_time;
u32 tsc_to_system_mul;
s8 tsc_shift;
u8 flags;
u8 pad[2];
};
Hyper-V TSC page
struct ms_hyperv_tsc_page {
volatile u32 tsc_sequence;
u32 reserved1;
volatile u64 tsc_scale;
volatile s64 tsc_offset;
u64 reserved2[509];
};