mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 11:56:12 +07:00
KVM: x86: add KVM_HC_CLOCK_PAIRING hypercall
Add a hypercall to retrieve the host realtime clock and the TSC value used to calculate that clock read. Used to implement clock synchronization between host and guest. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
6342c50ad1
commit
55dd00a73a
@ -81,3 +81,38 @@ the vcpu to sleep until occurrence of an appropriate event. Another vcpu of the
|
|||||||
same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
|
same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
|
||||||
specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
|
specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
|
||||||
is used in the hypercall for future use.
|
is used in the hypercall for future use.
|
||||||
|
|
||||||
|
|
||||||
|
6. KVM_HC_CLOCK_PAIRING
|
||||||
|
------------------------
|
||||||
|
Architecture: x86
|
||||||
|
Status: active
|
||||||
|
Purpose: Hypercall used to synchronize host and guest clocks.
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
a0: guest physical address where host copies
|
||||||
|
"struct kvm_clock_offset" structure.
|
||||||
|
|
||||||
|
a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
|
||||||
|
is supported (corresponding to the host's CLOCK_REALTIME clock).
|
||||||
|
|
||||||
|
struct kvm_clock_pairing {
|
||||||
|
__s64 sec;
|
||||||
|
__s64 nsec;
|
||||||
|
__u64 tsc;
|
||||||
|
__u32 flags;
|
||||||
|
__u32 pad[9];
|
||||||
|
};
|
||||||
|
|
||||||
|
Where:
|
||||||
|
* sec: seconds from clock_type clock.
|
||||||
|
* nsec: nanoseconds from clock_type clock.
|
||||||
|
* tsc: guest TSC value used to calculate sec/nsec pair
|
||||||
|
* flags: flags, unused (0) at the moment.
|
||||||
|
|
||||||
|
The hypercall lets a guest compute a precise timestamp across
|
||||||
|
host and guest. The guest can use the returned TSC value to
|
||||||
|
compute the CLOCK_REALTIME for its clock, at the same instant.
|
||||||
|
|
||||||
|
Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
|
||||||
|
or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
|
||||||
|
@ -50,6 +50,15 @@ struct kvm_steal_time {
|
|||||||
__u32 pad[11];
|
__u32 pad[11];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define KVM_CLOCK_PAIRING_WALLCLOCK 0
|
||||||
|
struct kvm_clock_pairing {
|
||||||
|
__s64 sec;
|
||||||
|
__s64 nsec;
|
||||||
|
__u64 tsc;
|
||||||
|
__u32 flags;
|
||||||
|
__u32 pad[9];
|
||||||
|
};
|
||||||
|
|
||||||
#define KVM_STEAL_ALIGNMENT_BITS 5
|
#define KVM_STEAL_ALIGNMENT_BITS 5
|
||||||
#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
|
#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
|
||||||
#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
|
#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
|
||||||
|
@ -1142,6 +1142,7 @@ struct pvclock_gtod_data {
|
|||||||
|
|
||||||
u64 boot_ns;
|
u64 boot_ns;
|
||||||
u64 nsec_base;
|
u64 nsec_base;
|
||||||
|
u64 wall_time_sec;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pvclock_gtod_data pvclock_gtod_data;
|
static struct pvclock_gtod_data pvclock_gtod_data;
|
||||||
@ -1165,6 +1166,8 @@ static void update_pvclock_gtod(struct timekeeper *tk)
|
|||||||
vdata->boot_ns = boot_ns;
|
vdata->boot_ns = boot_ns;
|
||||||
vdata->nsec_base = tk->tkr_mono.xtime_nsec;
|
vdata->nsec_base = tk->tkr_mono.xtime_nsec;
|
||||||
|
|
||||||
|
vdata->wall_time_sec = tk->xtime_sec;
|
||||||
|
|
||||||
write_seqcount_end(&vdata->seq);
|
write_seqcount_end(&vdata->seq);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1626,6 +1629,28 @@ static int do_monotonic_boot(s64 *t, u64 *cycle_now)
|
|||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_realtime(struct timespec *ts, u64 *cycle_now)
|
||||||
|
{
|
||||||
|
struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
|
||||||
|
unsigned long seq;
|
||||||
|
int mode;
|
||||||
|
u64 ns;
|
||||||
|
|
||||||
|
do {
|
||||||
|
seq = read_seqcount_begin(>od->seq);
|
||||||
|
mode = gtod->clock.vclock_mode;
|
||||||
|
ts->tv_sec = gtod->wall_time_sec;
|
||||||
|
ns = gtod->nsec_base;
|
||||||
|
ns += vgettsc(cycle_now);
|
||||||
|
ns >>= gtod->clock.shift;
|
||||||
|
} while (unlikely(read_seqcount_retry(>od->seq, seq)));
|
||||||
|
|
||||||
|
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
|
||||||
|
ts->tv_nsec = ns;
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
/* returns true if host is using tsc clocksource */
|
/* returns true if host is using tsc clocksource */
|
||||||
static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now)
|
static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now)
|
||||||
{
|
{
|
||||||
@ -1635,6 +1660,17 @@ static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now)
|
|||||||
|
|
||||||
return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
|
return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns true if host is using tsc clocksource */
|
||||||
|
static bool kvm_get_walltime_and_clockread(struct timespec *ts,
|
||||||
|
u64 *cycle_now)
|
||||||
|
{
|
||||||
|
/* checked again under seqlock below */
|
||||||
|
if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return do_realtime(ts, cycle_now) == VCLOCK_TSC;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6112,6 +6148,33 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvm_emulate_halt);
|
EXPORT_SYMBOL_GPL(kvm_emulate_halt);
|
||||||
|
|
||||||
|
static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
|
||||||
|
unsigned long clock_type)
|
||||||
|
{
|
||||||
|
struct kvm_clock_pairing clock_pairing;
|
||||||
|
struct timespec ts;
|
||||||
|
cycle_t cycle;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (clock_type != KVM_CLOCK_PAIRING_WALLCLOCK)
|
||||||
|
return -KVM_EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (kvm_get_walltime_and_clockread(&ts, &cycle) == false)
|
||||||
|
return -KVM_EOPNOTSUPP;
|
||||||
|
|
||||||
|
clock_pairing.sec = ts.tv_sec;
|
||||||
|
clock_pairing.nsec = ts.tv_nsec;
|
||||||
|
clock_pairing.tsc = kvm_read_l1_tsc(vcpu, cycle);
|
||||||
|
clock_pairing.flags = 0;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (kvm_write_guest(vcpu->kvm, paddr, &clock_pairing,
|
||||||
|
sizeof(struct kvm_clock_pairing)))
|
||||||
|
ret = -KVM_EFAULT;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* kvm_pv_kick_cpu_op: Kick a vcpu.
|
* kvm_pv_kick_cpu_op: Kick a vcpu.
|
||||||
*
|
*
|
||||||
@ -6176,6 +6239,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
|
|||||||
kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
|
kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
case KVM_HC_CLOCK_PAIRING:
|
||||||
|
ret = kvm_pv_clock_pairing(vcpu, a0, a1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -KVM_ENOSYS;
|
ret = -KVM_ENOSYS;
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define KVM_EFAULT EFAULT
|
#define KVM_EFAULT EFAULT
|
||||||
#define KVM_E2BIG E2BIG
|
#define KVM_E2BIG E2BIG
|
||||||
#define KVM_EPERM EPERM
|
#define KVM_EPERM EPERM
|
||||||
|
#define KVM_EOPNOTSUPP 95
|
||||||
|
|
||||||
#define KVM_HC_VAPIC_POLL_IRQ 1
|
#define KVM_HC_VAPIC_POLL_IRQ 1
|
||||||
#define KVM_HC_MMU_OP 2
|
#define KVM_HC_MMU_OP 2
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#define KVM_HC_MIPS_GET_CLOCK_FREQ 6
|
#define KVM_HC_MIPS_GET_CLOCK_FREQ 6
|
||||||
#define KVM_HC_MIPS_EXIT_VM 7
|
#define KVM_HC_MIPS_EXIT_VM 7
|
||||||
#define KVM_HC_MIPS_CONSOLE_OUTPUT 8
|
#define KVM_HC_MIPS_CONSOLE_OUTPUT 8
|
||||||
|
#define KVM_HC_CLOCK_PAIRING 9
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hypercalls use architecture specific
|
* hypercalls use architecture specific
|
||||||
|
Loading…
Reference in New Issue
Block a user