* [PATCH v2 0/2] Time-related fixes for migration
@ 2014-04-01 15:53 Boris Ostrovsky
2014-04-01 15:53 ` [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore Boris Ostrovsky
2014-04-01 15:53 ` [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain Boris Ostrovsky
0 siblings, 2 replies; 7+ messages in thread
From: Boris Ostrovsky @ 2014-04-01 15:53 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, keir, ian.campbell, stefano.stabellini, jun.nakajima,
eddie.dong, ian.jackson, jbeulich, suravee.suthikulpanit,
boris.ostrovsky
Version 2:
* Avoid setting parameters from config file twice
* Use out-of-line definition of get_s_time()
* Update rdtscll macro definition to avoid namespace clashes
* Syntax cleanup
Two patches to address issues we discovered during migration testing.
* The first patch loads HVM parameters from configuration file during restore.
To fix the actual problem that we saw only timer_mode needed to be restored but
it seems to me that other parameters are needed as well since at least some of
them are used "at runtime".
The bug can be demonstrated with a Solaris guest but I haven't been able to
trigger it with Linux. Possibly because Solaris's gethrtime() routine is a
fast trap to kernel's hrtimer which does some tricks to account for missed
ticks during interrupts.
* The second patch keeps TSCs synchronized across VPCUs after save/restore.
Currently TSC values diverge after migration because during both save and restore
we calculate them separately for each VCPU and base each calculation on
newly-read host's TSC.
The problem can be easily demonstrated with this program for a 2-VCPU guest
(I am assuming here invariant TSC so, for example, tsc_mode="always_emulate" (*)):
int
main(int argc, char* argv[])
{
unsigned long long h = 0LL;
int proc = 0;
cpu_set_t set;
for(;;) {
unsigned long long n = __native_read_tsc();
if(h && n < h)
printf("prev 0x%llx cur 0x%llx\n", h, n);
CPU_ZERO(&set);
proc = (proc + 1) & 1;
CPU_SET(proc, &set);
if (sched_setaffinity(0, sizeof(cpu_set_t), &set)) {
perror("sched_setaffinity");
exit(1);
}
h = n;
}
}
(*) Which brings up another observation: when we are in default tsc_mode we
start off with vtsc=0 and thus clear TSC_Invariant bit in guest's CPUID.
After migration vtsc is 1 and TSC_Invariant bit is set. So the guest may observe
different values of CPUID. Which technically reflects the fact that TSC became
"safe" but I think potentially may be problematic to some guests.
Boris Ostrovsky (2):
libxl: Set guest parameters from config file during a restore
x86/HVM: Use fixed TSC value when saving or restoring domain
tools/libxl/libxl_dom.c | 49 ++++++++++++++++++++++++-----------------
xen/arch/x86/hvm/hvm.c | 16 ++++++++++----
xen/arch/x86/hvm/save.c | 16 ++++++++++++++
xen/arch/x86/hvm/svm/svm.c | 4 ++--
xen/arch/x86/hvm/vmx/vmx.c | 4 ++--
xen/arch/x86/hvm/vpt.c | 16 +++++++++-----
xen/arch/x86/time.c | 12 ++++++++--
xen/common/hvm/save.c | 5 +++++
xen/include/asm-x86/domain.h | 2 ++
xen/include/asm-x86/hvm/hvm.h | 9 +++++---
xen/include/asm-x86/msr.h | 6 ++---
xen/include/xen/hvm/save.h | 2 ++
xen/include/xen/time.h | 1 +
13 files changed, 100 insertions(+), 42 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore
2014-04-01 15:53 [PATCH v2 0/2] Time-related fixes for migration Boris Ostrovsky
@ 2014-04-01 15:53 ` Boris Ostrovsky
2014-04-07 12:51 ` Ian Campbell
2014-04-01 15:53 ` [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain Boris Ostrovsky
1 sibling, 1 reply; 7+ messages in thread
From: Boris Ostrovsky @ 2014-04-01 15:53 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, keir, ian.campbell, stefano.stabellini, jun.nakajima,
eddie.dong, ian.jackson, jbeulich, suravee.suthikulpanit,
boris.ostrovsky
Guest's configuration parameters (e.g. timer_mode) are used by the hypervisor
during runtime. We should therefore set them during restore.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
tools/libxl/libxl_dom.c | 49 ++++++++++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 55f74b2..d02606d 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -201,6 +201,32 @@ static int numa_place_domain(libxl__gc *gc, uint32_t domid,
return rc;
}
+static unsigned long timer_mode(const libxl_domain_build_info *info)
+{
+ const libxl_timer_mode mode = info->u.hvm.timer_mode;
+ assert(mode >= LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS &&
+ mode <= LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING);
+ return ((unsigned long)mode);
+}
+
+static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
+ libxl_domain_build_info *const info)
+{
+ xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED,
+ libxl_defbool_val(info->u.hvm.pae));
+#if defined(__i386__) || defined(__x86_64__)
+ xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN,
+ libxl_defbool_val(info->u.hvm.viridian));
+ xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED,
+ libxl_defbool_val(info->u.hvm.hpet));
+#endif
+ xc_set_hvm_param(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
+ xc_set_hvm_param(handle, domid, HVM_PARAM_VPT_ALIGN,
+ libxl_defbool_val(info->u.hvm.vpt_align));
+ xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM,
+ libxl_defbool_val(info->u.hvm.nested_hvm));
+}
+
int libxl__build_pre(libxl__gc *gc, uint32_t domid,
libxl_domain_config *d_config, libxl__domain_build_state *state)
{
@@ -255,6 +281,9 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
state->vm_generationid_addr = 0;
+ if (info->type == LIBXL_DOMAIN_TYPE_HVM)
+ hvm_set_conf_params(ctx->xch, domid, info);
+
rc = libxl__arch_domain_create(gc, d_config, domid);
return rc;
@@ -449,13 +478,6 @@ out:
return ret == 0 ? 0 : ERROR_FAIL;
}
-static unsigned long timer_mode(const libxl_domain_build_info *info)
-{
- const libxl_timer_mode mode = info->u.hvm.timer_mode;
- assert(mode >= LIBXL_TIMER_MODE_DELAY_FOR_MISSED_TICKS &&
- mode <= LIBXL_TIMER_MODE_ONE_MISSED_TICK_PENDING);
- return ((unsigned long)mode);
-}
static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
libxl_domain_build_info *info,
int store_evtchn, unsigned long *store_mfn,
@@ -484,19 +506,6 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
xc_get_hvm_param(handle, domid, HVM_PARAM_STORE_PFN, store_mfn);
xc_get_hvm_param(handle, domid, HVM_PARAM_CONSOLE_PFN, console_mfn);
- xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED,
- libxl_defbool_val(info->u.hvm.pae));
-#if defined(__i386__) || defined(__x86_64__)
- xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN,
- libxl_defbool_val(info->u.hvm.viridian));
- xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED,
- libxl_defbool_val(info->u.hvm.hpet));
-#endif
- xc_set_hvm_param(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
- xc_set_hvm_param(handle, domid, HVM_PARAM_VPT_ALIGN,
- libxl_defbool_val(info->u.hvm.vpt_align));
- xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM,
- libxl_defbool_val(info->u.hvm.nested_hvm));
xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain
2014-04-01 15:53 [PATCH v2 0/2] Time-related fixes for migration Boris Ostrovsky
2014-04-01 15:53 ` [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore Boris Ostrovsky
@ 2014-04-01 15:53 ` Boris Ostrovsky
2014-04-04 15:54 ` Boris Ostrovsky
1 sibling, 1 reply; 7+ messages in thread
From: Boris Ostrovsky @ 2014-04-01 15:53 UTC (permalink / raw)
To: xen-devel
Cc: kevin.tian, keir, ian.campbell, stefano.stabellini, jun.nakajima,
eddie.dong, ian.jackson, jbeulich, suravee.suthikulpanit,
boris.ostrovsky
When a domain is saved each VCPU's TSC value needs to be preserved. To get it we
use hvm_get_guest_tsc(). This routine (either itself or via get_s_time() which
it may call) calculates VCPU's TSC based on current host's TSC value (by doing a
rdtscll()). Since this is performed for each VCPU separately we end up with
un-synchronized TSCs.
Similarly, during a restore each VCPU is assigned its TSC based on host's current
tick, causing virtual TSCs to diverge further.
With this, we can easily get into situation where a guest may see time going
backwards.
Instead of reading new TSC value for each VCPU when saving/restoring it we should
use the same value across all VCPUs.
(As part of the patch, update rdtscll's definition so that its variables don't
clash with outer code)
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
---
xen/arch/x86/hvm/hvm.c | 16 ++++++++++++----
xen/arch/x86/hvm/save.c | 16 ++++++++++++++++
xen/arch/x86/hvm/svm/svm.c | 4 ++--
xen/arch/x86/hvm/vmx/vmx.c | 4 ++--
xen/arch/x86/hvm/vpt.c | 16 ++++++++++------
xen/arch/x86/time.c | 12 ++++++++++--
xen/common/hvm/save.c | 5 +++++
xen/include/asm-x86/domain.h | 2 ++
xen/include/asm-x86/hvm/hvm.h | 9 ++++++---
xen/include/asm-x86/msr.h | 6 +++---
xen/include/xen/hvm/save.h | 2 ++
xen/include/xen/time.h | 1 +
12 files changed, 71 insertions(+), 22 deletions(-)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ae24211..edf2824 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -248,16 +248,20 @@ int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat)
return 1;
}
-void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
+void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc)
{
uint64_t tsc;
uint64_t delta_tsc;
if ( v->domain->arch.vtsc )
{
- tsc = hvm_get_guest_time(v);
+ tsc = hvm_get_guest_time_fixed(v, at_tsc);
tsc = gtime_to_gtsc(v->domain, tsc);
}
+ else if ( at_tsc )
+ {
+ tsc = at_tsc;
+ }
else
{
rdtscll(tsc);
@@ -279,16 +283,20 @@ void hvm_set_guest_tsc_adjust(struct vcpu *v, u64 tsc_adjust)
v->arch.hvm_vcpu.msr_tsc_adjust = tsc_adjust;
}
-u64 hvm_get_guest_tsc(struct vcpu *v)
+u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc)
{
uint64_t tsc;
if ( v->domain->arch.vtsc )
{
- tsc = hvm_get_guest_time(v);
+ tsc = hvm_get_guest_time_fixed(v, at_tsc);
tsc = gtime_to_gtsc(v->domain, tsc);
v->domain->arch.vtsc_kerncount++;
}
+ else if ( at_tsc )
+ {
+ tsc = at_tsc;
+ }
else
{
rdtscll(tsc);
diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c
index 066fdb2..309a1fd 100644
--- a/xen/arch/x86/hvm/save.c
+++ b/xen/arch/x86/hvm/save.c
@@ -34,6 +34,14 @@ void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
/* Save guest's preferred TSC. */
hdr->gtsc_khz = d->arch.tsc_khz;
+
+ /* Time when saving started */
+ rdtscll(d->arch.chkpt_tsc);
+}
+
+void arch_hvm_save_done(struct domain *d)
+{
+ d->arch.chkpt_tsc = 0;
}
int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
@@ -67,12 +75,20 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
if ( d->arch.vtsc )
hvm_set_rdtsc_exiting(d, 1);
+ /* Time when restore started */
+ rdtscll(d->arch.chkpt_tsc);
+
/* VGA state is not saved/restored, so we nobble the cache. */
d->arch.hvm_domain.stdvga.cache = 0;
return 0;
}
+void arch_hvm_load_done(struct domain *d)
+{
+ d->arch.chkpt_tsc = 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 4fd5376..7aa55c3 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -318,7 +318,7 @@ static void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_efer = v->arch.hvm_vcpu.guest_efer;
data->msr_flags = -1ULL;
- data->tsc = hvm_get_guest_tsc(v);
+ data->tsc = hvm_get_guest_tsc_fixed(v, v->domain->arch.chkpt_tsc);
}
@@ -334,7 +334,7 @@ static void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
v->arch.hvm_vcpu.guest_efer = data->msr_efer;
svm_update_guest_efer(v);
- hvm_set_guest_tsc(v, data->tsc);
+ hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.chkpt_tsc);
}
static void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 8395e86..f10d34c 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -540,7 +540,7 @@ static void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR];
data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
- data->tsc = hvm_get_guest_tsc(v);
+ data->tsc = hvm_get_guest_tsc_fixed(v, v->domain->arch.chkpt_tsc);
}
static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
@@ -556,7 +556,7 @@ static void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
v->arch.hvm_vmx.cstar = data->msr_cstar;
v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
- hvm_set_guest_tsc(v, data->tsc);
+ hvm_set_guest_tsc_fixed(v, data->tsc, v->domain->arch.chkpt_tsc);
}
diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
index f7af688..38541cf 100644
--- a/xen/arch/x86/hvm/vpt.c
+++ b/xen/arch/x86/hvm/vpt.c
@@ -36,7 +36,7 @@ void hvm_init_guest_time(struct domain *d)
pl->last_guest_time = 0;
}
-u64 hvm_get_guest_time(struct vcpu *v)
+u64 hvm_get_guest_time_fixed(struct vcpu *v, u64 at_tsc)
{
struct pl_time *pl = &v->domain->arch.hvm_domain.pl_time;
u64 now;
@@ -45,11 +45,15 @@ u64 hvm_get_guest_time(struct vcpu *v)
ASSERT(is_hvm_vcpu(v));
spin_lock(&pl->pl_time_lock);
- now = get_s_time() + pl->stime_offset;
- if ( (int64_t)(now - pl->last_guest_time) > 0 )
- pl->last_guest_time = now;
- else
- now = ++pl->last_guest_time;
+ now = get_s_time_fixed(at_tsc) + pl->stime_offset;
+
+ if ( !at_tsc )
+ {
+ if ( (int64_t)(now - pl->last_guest_time) > 0 )
+ pl->last_guest_time = now;
+ else
+ now = ++pl->last_guest_time;
+ }
spin_unlock(&pl->pl_time_lock);
return now + v->arch.hvm_vcpu.stime_offset;
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 000191b..b044717 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -712,19 +712,27 @@ static unsigned long get_cmos_time(void)
* System Time
***************************************************************************/
-s_time_t get_s_time(void)
+s_time_t get_s_time_fixed(u64 at_tsc)
{
struct cpu_time *t = &this_cpu(cpu_time);
u64 tsc, delta;
s_time_t now;
- rdtscll(tsc);
+ if ( at_tsc )
+ tsc = at_tsc;
+ else
+ rdtscll(tsc);
delta = tsc - t->local_tsc_stamp;
now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale);
return now;
}
+s_time_t get_s_time()
+{
+ return get_s_time_fixed(0);
+}
+
uint64_t tsc_ticks2ns(uint64_t ticks)
{
struct cpu_time *t = &this_cpu(cpu_time);
diff --git a/xen/common/hvm/save.c b/xen/common/hvm/save.c
index 6c16399..7db68af 100644
--- a/xen/common/hvm/save.c
+++ b/xen/common/hvm/save.c
@@ -186,6 +186,8 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
}
}
+ arch_hvm_save_done(d);
+
/* Save an end-of-file marker */
if ( hvm_save_entry(END, 0, h, &end) != 0 )
{
@@ -236,7 +238,10 @@ int hvm_load(struct domain *d, hvm_domain_context_t *h)
/* Read the typecode of the next entry and check for the end-marker */
desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
if ( desc->typecode == 0 )
+ {
+ arch_hvm_load_done(d);
return 0;
+ }
/* Find the handler for this entry */
if ( (desc->typecode > HVM_SAVE_CODE_MAX) ||
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 49f7c0c..201f856 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -308,6 +308,8 @@ struct arch_domain
(possibly other cases in the future */
uint64_t vtsc_kerncount; /* for hvm, counts all vtsc */
uint64_t vtsc_usercount; /* not used for hvm */
+ uint64_t chkpt_tsc; /* TSC value that VCPUs use to calculate their
+ tsc_offset value. Used during save/restore */
/* Pseudophysical e820 map (XENMEM_memory_map). */
spinlock_t e820_lock;
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index dcc3483..535b078 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -232,12 +232,15 @@ bool_t hvm_send_assist_req(struct vcpu *v);
void hvm_get_guest_pat(struct vcpu *v, u64 *guest_pat);
int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat);
-void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc);
-u64 hvm_get_guest_tsc(struct vcpu *v);
+void hvm_set_guest_tsc_fixed(struct vcpu *v, u64 guest_tsc, u64 at_tsc);
+#define hvm_set_guest_tsc(v, t) hvm_set_guest_tsc_fixed(v, t, 0)
+u64 hvm_get_guest_tsc_fixed(struct vcpu *v, u64 at_tsc);
+#define hvm_get_guest_tsc(v) hvm_get_guest_tsc_fixed(v, 0)
void hvm_init_guest_time(struct domain *d);
void hvm_set_guest_time(struct vcpu *v, u64 guest_time);
-u64 hvm_get_guest_time(struct vcpu *v);
+u64 hvm_get_guest_time_fixed(struct vcpu *v, u64 at_tsc);
+#define hvm_get_guest_time(v) hvm_get_guest_time_fixed(v, 0)
int vmsi_deliver(
struct domain *d, int vector,
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index 61f579a..52cae4b 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -78,9 +78,9 @@ static inline int wrmsr_safe(unsigned int msr, uint64_t val)
__asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
#define rdtscll(val) do { \
- unsigned int a,d; \
- asm volatile("rdtsc" : "=a" (a), "=d" (d)); \
- (val) = ((unsigned long)a) | (((unsigned long)d)<<32); \
+ unsigned int _eax, _edx; \
+ asm volatile("rdtsc" : "=a" (_eax), "=d" (_edx)); \
+ (val) = ((unsigned long)_eax) | (((unsigned long)_edx)<<32); \
} while(0)
#define __write_tsc(val) wrmsrl(MSR_IA32_TSC, val)
diff --git a/xen/include/xen/hvm/save.h b/xen/include/xen/hvm/save.h
index ae6f0bb..70522a9 100644
--- a/xen/include/xen/hvm/save.h
+++ b/xen/include/xen/hvm/save.h
@@ -133,6 +133,8 @@ int hvm_load(struct domain *d, hvm_domain_context_t *h);
/* Arch-specific definitions. */
struct hvm_save_header;
void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr);
+void arch_hvm_save_done(struct domain *d);
int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr);
+void arch_hvm_load_done(struct domain *d);
#endif /* __XEN_HVM_SAVE_H__ */
diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h
index 95b4b91..d20d356 100644
--- a/xen/include/xen/time.h
+++ b/xen/include/xen/time.h
@@ -32,6 +32,7 @@ struct vcpu;
typedef s64 s_time_t;
#define PRI_stime PRId64
+s_time_t get_s_time_fixed(u64 at_tick);
s_time_t get_s_time(void);
unsigned long get_localtime(struct domain *d);
uint64_t get_localtime_us(struct domain *d);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain
2014-04-01 15:53 ` [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain Boris Ostrovsky
@ 2014-04-04 15:54 ` Boris Ostrovsky
0 siblings, 0 replies; 7+ messages in thread
From: Boris Ostrovsky @ 2014-04-04 15:54 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: kevin.tian, keir, ian.campbell, stefano.stabellini, jun.nakajima,
eddie.dong, ian.jackson, xen-devel, jbeulich,
suravee.suthikulpanit
On 04/01/2014 11:53 AM, Boris Ostrovsky wrote:
> When a domain is saved each VCPU's TSC value needs to be preserved. To get it we
> use hvm_get_guest_tsc(). This routine (either itself or via get_s_time() which
> it may call) calculates VCPU's TSC based on current host's TSC value (by doing a
> rdtscll()). Since this is performed for each VCPU separately we end up with
> un-synchronized TSCs.
>
> Similarly, during a restore each VCPU is assigned its TSC based on host's current
> tick, causing virtual TSCs to diverge further.
>
> With this, we can easily get into situation where a guest may see time going
> backwards.
>
> Instead of reading new TSC value for each VCPU when saving/restoring it we should
> use the same value across all VCPUs.
>
> (As part of the patch, update rdtscll's definition so that its variables don't
> clash with outer code)
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
This patch will need to be updated as it doesn't quite fix the problem
on some AMD processors (they may do one extra rdtsc in
svm_set_tsc_offset()).
-boris
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore
2014-04-01 15:53 ` [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore Boris Ostrovsky
@ 2014-04-07 12:51 ` Ian Campbell
2014-04-08 15:25 ` Ian Campbell
0 siblings, 1 reply; 7+ messages in thread
From: Ian Campbell @ 2014-04-07 12:51 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: kevin.tian, keir, jbeulich, stefano.stabellini, jun.nakajima,
eddie.dong, ian.jackson, xen-devel, suravee.suthikulpanit
On Tue, 2014-04-01 at 11:53 -0400, Boris Ostrovsky wrote:
> Guest's configuration parameters (e.g. timer_mode) are used by the hypervisor
> during runtime. We should therefore set them during restore.
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore
2014-04-07 12:51 ` Ian Campbell
@ 2014-04-08 15:25 ` Ian Campbell
2014-04-08 15:31 ` Boris Ostrovsky
0 siblings, 1 reply; 7+ messages in thread
From: Ian Campbell @ 2014-04-08 15:25 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: kevin.tian, keir, jbeulich, stefano.stabellini, ian.jackson,
eddie.dong, xen-devel, jun.nakajima, suravee.suthikulpanit
On Mon, 2014-04-07 at 13:51 +0100, Ian Campbell wrote:
> On Tue, 2014-04-01 at 11:53 -0400, Boris Ostrovsky wrote:
> > Guest's configuration parameters (e.g. timer_mode) are used by the hypervisor
> > during runtime. We should therefore set them during restore.
> >
> > Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
Applied. I assume someone else will take care of #2.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore
2014-04-08 15:25 ` Ian Campbell
@ 2014-04-08 15:31 ` Boris Ostrovsky
0 siblings, 0 replies; 7+ messages in thread
From: Boris Ostrovsky @ 2014-04-08 15:31 UTC (permalink / raw)
To: Ian Campbell
Cc: kevin.tian, keir, jbeulich, stefano.stabellini, ian.jackson,
eddie.dong, xen-devel, jun.nakajima, suravee.suthikulpanit
On 04/08/2014 11:25 AM, Ian Campbell wrote:
> On Mon, 2014-04-07 at 13:51 +0100, Ian Campbell wrote:
>> On Tue, 2014-04-01 at 11:53 -0400, Boris Ostrovsky wrote:
>>> Guest's configuration parameters (e.g. timer_mode) are used by the hypervisor
>>> during runtime. We should therefore set them during restore.
>>>
>>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> Applied. I assume someone else will take care of #2.
Thanks. #2 needs better AMD support, I'll post in soon.
-boris
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-04-08 15:31 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-01 15:53 [PATCH v2 0/2] Time-related fixes for migration Boris Ostrovsky
2014-04-01 15:53 ` [PATCH v2 1/2] libxl: Set guest parameters from config file during a restore Boris Ostrovsky
2014-04-07 12:51 ` Ian Campbell
2014-04-08 15:25 ` Ian Campbell
2014-04-08 15:31 ` Boris Ostrovsky
2014-04-01 15:53 ` [PATCH v2 2/2] x86/HVM: Use fixed TSC value when saving or restoring domain Boris Ostrovsky
2014-04-04 15:54 ` Boris Ostrovsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).