|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 31/62] x86: xen pv clock time source
On 01/12/2018 11:28 AM, Wei Liu wrote:
> It is a variant of TSC clock source.
>
> Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> ---
> Changes since v1:
> - Use the mapped vcpu_info.
> ---
> xen/arch/x86/time.c | 89
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 89 insertions(+)
>
> diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
> index 3b654d7b7d..4cbd068d17 100644
> --- a/xen/arch/x86/time.c
> +++ b/xen/arch/x86/time.c
> @@ -29,6 +29,7 @@
> #include <asm/mpspec.h>
> #include <asm/processor.h>
> #include <asm/fixmap.h>
> +#include <asm/guest.h>
> #include <asm/mc146818rtc.h>
> #include <asm/div64.h>
> #include <asm/acpi.h>
> @@ -525,6 +526,91 @@ static struct platform_timesource __initdata plt_tsc =
> .init = init_tsc,
> };
>
> +#ifdef CONFIG_XEN_GUEST
> +/************************************************************
> + * PLATFORM TIMER 5: XEN PV CLOCK SOURCE
> + *
> + * Xen clock source is a variant of TSC source.
> + */
> +
> +static uint64_t xen_timer_cpu_frequency(void)
> +{
> + struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
> + uint64_t freq;
> +
> + freq = 1000000000ULL << 32;
> + do_div(freq, info->tsc_to_system_mul);
> + if ( info->tsc_shift < 0 )
> + freq <<= -info->tsc_shift;
> + else
> + freq >>= info->tsc_shift;
> +
> + return freq;
> +}
> +
> +static int64_t __init init_xen_timer(struct platform_timesource *pts)
> +{
> + if ( !xen_guest )
> + return 0;
> +
> + pts->frequency = xen_timer_cpu_frequency();
> +
> + return pts->frequency;
> +}
> +
Guests that don't have TSC_RELIABLE set in verify_tsc_reliability() you end up
evaluating this condition to true:
if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
!boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
And that's possibly not necessary to keep sync the TSC in sync with pvclock?
Meaning the default rendezvous function (time_calibration_std_rendezvous) might
be enough.
> +static always_inline uint64_t read_cycle(const struct vcpu_time_info *info,
> + uint64_t tsc)
> +{
> + uint64_t delta = tsc - info->tsc_timestamp;
> + struct time_scale ts = {
> + .shift = info->tsc_shift,
> + .mul_frac = info->tsc_to_system_mul,
> + };
> + uint64_t offset = scale_delta(delta, &ts);
> +
> + return info->system_time + offset;
> +}
> +
> +static uint64_t read_xen_timer(void)
> +{
> + struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
> + uint32_t version;
> + uint64_t ret;
> + uint64_t last;
> + static uint64_t last_value;
> +
> + do {
> + version = info->version & ~1;
> + /* Make sure version is read before the data */
> + smp_rmb();
> +
> + ret = read_cycle(info, rdtsc_ordered());
> + /* Ignore fancy flags for now */
> +
Heh :)
When the dust settles around the security issues, perhaps this patch could help
(I can formally submit it after more proper testing, but should give an
expectation on the changes).
-- >8 --
Subject: x86/time: mark pvclock as stable if supported
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index c90524de9c..3aaa72b6bf 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -65,8 +65,12 @@ struct platform_timesource {
s64 (*init)(struct platform_timesource *);
void (*resume)(struct platform_timesource *);
int counter_bits;
+ unsigned int flags;
};
+/* Clocksource counter monotonically increases across CPUs */
+#define CLOCKSOURCE_F_STABLE (1 << 0)
+
static DEFINE_PER_CPU(struct cpu_time, cpu_time);
/* Calibrate all CPUs to platform timer every EPOCH. */
@@ -533,9 +537,8 @@ static struct platform_timesource __initdata plt_tsc =
* Xen clock source is a variant of TSC source.
*/
-static uint64_t xen_timer_cpu_frequency(void)
+static uint64_t xen_timer_cpu_frequency(struct vcpu_time_info *info)
{
- struct vcpu_time_info *info = &this_cpu(vcpu_info)->time;
uint64_t freq;
freq = 1000000000ULL << 32;
@@ -550,10 +553,20 @@ static uint64_t xen_timer_cpu_frequency(void)
static int64_t __init init_xen_timer(struct platform_timesource *pts)
{
+ struct vcpu_time_info *info;
+
if ( !xen_guest )
return 0;
- pts->frequency = xen_timer_cpu_frequency();
+ info = &this_cpu(vcpu_info)->time;
+
+ pts->frequency = xen_timer_cpu_frequency(info);
+
+ /* Xen pvclock monotonically increases across CPUs */
+ if ( info->flags & XEN_PVCLOCK_TSC_STABLE_BIT ) {
+ pts->flags |= CLOCKSOURCE_F_STABLE;
+ printk("PV CLOCK marked as stable.\n");
+ }
return pts->frequency;
}
@@ -585,12 +598,14 @@ static uint64_t read_xen_timer(void)
smp_rmb();
ret = read_cycle(info, rdtsc_ordered());
- /* Ignore fancy flags for now */
/* Make sure version is reread after the data */
smp_rmb();
} while ( unlikely(version != info->version) );
+ if ( info->flags & XEN_PVCLOCK_TSC_STABLE_BIT )
+ return ret;
+
/* Maintain a monotonic global value */
do {
last = read_atomic(&last_value);
@@ -632,6 +647,8 @@ static u64 plt_stamp64; /* 64-bit platform counter
stamp */
static u64 plt_stamp; /* hardware-width platform counter stamp */
static struct timer plt_overflow_timer;
+static bool clocksource_is_stable(void);
+
static s_time_t __read_platform_stime(u64 platform_time)
{
u64 diff = platform_time - platform_timer_stamp;
@@ -1077,7 +1094,7 @@ static void __update_vcpu_system_time(struct vcpu *v, int
force)
* pvclock read to check whether they can resort solely on this tuple
* or if it further requires monotonicity checks with other vcpus.
*/
- if ( clocksource_is_tsc() )
+ if ( clocksource_is_stable() )
_u.flags |= XEN_PVCLOCK_TSC_STABLE_BIT;
if ( is_hvm_domain(d) )
@@ -1564,7 +1581,7 @@ static void time_calibration(void *unused)
.semaphore = ATOMIC_INIT(0)
};
- if ( clocksource_is_tsc() )
+ if ( clocksource_is_stable() )
{
local_irq_disable();
r.master_stime = read_platform_stime(&r.master_tsc_stamp);
@@ -1740,6 +1757,9 @@ static int __init verify_tsc_reliability(void)
*/
on_selected_cpus(&cpu_online_map, reset_percpu_time, NULL, 1);
+ /* TSC clocksource monotonically increases across CPUs. */
+ plt_tsc.flags |= CLOCKSOURCE_F_STABLE;
+
/*
* We won't do CPU Hotplug and TSC clocksource is being used which
* means we have a reliable TSC, plus we don't sync with any other
@@ -1770,7 +1790,12 @@ static int __init verify_tsc_reliability(void)
*/
if ( boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
!boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )
- time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
+ {
+ if ( clocksource_is_stable() )
+ time_calibration_rendezvous_fn = time_calibration_nop_rendezvous;
+ else if ( plt_src.read_counter != read_xen_timer )
+ time_calibration_rendezvous_fn = time_calibration_tsc_rendezvous;
+ }
return 0;
}
@@ -2057,6 +2082,23 @@ bool clocksource_is_tsc(void)
return plt_src.read_counter == read_tsc;
}
+static bool clocksource_is_stable(void)
+{
+ struct vcpu_time_info *info;
+
+ if ( !(plt_src.flags & CLOCKSOURCE_F_STABLE) )
+ return false;
+
+ if ( plt_src.read_counter == read_tsc )
+ return true;
+
+ info = &this_cpu(vcpu_info)->time;
+ if ( !(info->flags & XEN_PVCLOCK_TSC_STABLE_BIT) )
+ return false;
+
+ return true;
+}
+
int host_tsc_is_safe(void)
{
return boot_cpu_has(X86_FEATURE_TSC_RELIABLE);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |