:p
atchew
Login
time_offset is currently always added to wc_sec. This means that without the actual value of time_offset, guests have no way of knowing what's the actual host clock. Once the guest clock drifts beyond 1 second, updates to the guest RTC would themselves change time_offset and make it impossible to resync guest time to host time. Since there's no way to add more fields to struct shared_info, the addition has to be done through struct arch_shared_info instead. Add two fields in arch_shared_info representing time_offset's low and high 32-bit halves. Provide a new feature bit XENFEAT_shared_info_time_offset for this functionality. Signed-off-by: Tu Dinh <ngoc-tu.dinh@vates.tech> --- tools/include/xen-foreign/reference.size | 5 ++--- xen/common/kernel.c | 3 ++- xen/common/time.c | 5 +++++ xen/include/public/arch-arm.h | 2 ++ xen/include/public/arch-ppc.h | 3 +++ xen/include/public/arch-riscv.h | 3 ++- xen/include/public/arch-x86/xen.h | 3 +++ xen/include/public/features.h | 5 +++++ 8 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tools/include/xen-foreign/reference.size b/tools/include/xen-foreign/reference.size index XXXXXXX..XXXXXXX 100644 --- a/tools/include/xen-foreign/reference.size +++ b/tools/include/xen-foreign/reference.size @@ -XXX,XX +XXX,XX @@ vcpu_guest_context | 352 352 2800 5168 arch_vcpu_info | 0 0 24 16 vcpu_time_info | 32 32 32 32 vcpu_info | 48 48 64 64 -arch_shared_info | 0 0 28 48 -shared_info | 1088 1088 2344 3136 - +arch_shared_info | 8 8 36 56 +shared_info | 1096 1096 2352 3144 diff --git a/xen/common/kernel.c b/xen/common/kernel.c index XXXXXXX..XXXXXXX 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -XXX,XX +XXX,XX @@ long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) #ifdef CONFIG_X86 (1U << XENFEAT_vcpu_time_phys_area) | #endif - (1U << XENFEAT_runstate_phys_area); + (1U << XENFEAT_runstate_phys_area) | + (1U << XENFEAT_shared_info_time_offset); if ( VM_ASSIST(d, pae_extended_cr3) ) fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb); if ( paging_mode_translate(d) ) diff --git a/xen/common/time.c b/xen/common/time.c index XXXXXXX..XXXXXXX 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -XXX,XX +XXX,XX @@ void update_domain_wallclock_time(struct domain *d) shared_info(d, wc_sec_hi) = sec >> 32; #endif + shared_info(d, arch.time_offset) = + (uint32_t)(uint64_t)d->time_offset.seconds; + shared_info(d, arch.time_offset_hi) = + (uint32_t)((uint64_t)d->time_offset.seconds >> 32); + smp_wmb(); *wc_version = version_update_end(*wc_version); diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -XXX,XX +XXX,XX @@ struct arch_vcpu_info { typedef struct arch_vcpu_info arch_vcpu_info_t; struct arch_shared_info { + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; typedef uint64_t xen_callback_t; diff --git a/xen/include/public/arch-ppc.h b/xen/include/public/arch-ppc.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-ppc.h +++ b/xen/include/public/arch-ppc.h @@ -XXX,XX +XXX,XX @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); struct arch_shared_info { uint64_t boot_timebase; + + uint32_t time_offset; + uint32_t time_offset_hi; }; struct arch_vcpu_info { diff --git a/xen/include/public/arch-riscv.h b/xen/include/public/arch-riscv.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-riscv.h +++ b/xen/include/public/arch-riscv.h @@ -XXX,XX +XXX,XX @@ struct arch_vcpu_info { }; typedef struct arch_vcpu_info arch_vcpu_info_t; -/* TODO: add a placeholder entry if no real ones surface */ struct arch_shared_info { + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-x86/xen.h +++ b/xen/include/public/arch-x86/xen.h @@ -XXX,XX +XXX,XX @@ struct arch_shared_info { /* There's no room for this field in the generic structure. */ uint32_t wc_sec_hi; #endif + + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/features.h b/xen/include/public/features.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/features.h +++ b/xen/include/public/features.h @@ -XXX,XX +XXX,XX @@ */ #define XENFEAT_dm_msix_all_writes 20 +/* + * arch_shared_info provides time_offset and time_offset_hi + */ +#define XENFEAT_shared_info_time_offset 21 + #define XENFEAT_NR_SUBMAPS 1 #endif /* __XEN_PUBLIC_FEATURES_H__ */ -- 2.43.0 -- Ngoc Tu Dinh | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
time_offset is currently always added to wc_sec. This means that without the actual value of time_offset, guests have no way of knowing what's the actual host clock. Once the guest clock drifts beyond 1 second, updates to the guest RTC would themselves change time_offset and make it impossible to resync guest time to host time. Since there's no way to add more fields to struct shared_info, the addition has to be done through struct arch_shared_info instead. Add two fields in arch_shared_info representing time_offset's low and high 32-bit halves. Provide a new feature bit XENFEAT_shared_info_time_offset for this functionality. Signed-off-by: Tu Dinh <ngoc-tu.dinh@vates.tech> --- v2: Remove unnecessary casts. --- tools/include/xen-foreign/reference.size | 5 ++--- xen/common/kernel.c | 3 ++- xen/common/time.c | 5 +++++ xen/include/public/arch-arm.h | 2 ++ xen/include/public/arch-ppc.h | 3 +++ xen/include/public/arch-riscv.h | 3 ++- xen/include/public/arch-x86/xen.h | 3 +++ xen/include/public/features.h | 5 +++++ 8 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tools/include/xen-foreign/reference.size b/tools/include/xen-foreign/reference.size index XXXXXXX..XXXXXXX 100644 --- a/tools/include/xen-foreign/reference.size +++ b/tools/include/xen-foreign/reference.size @@ -XXX,XX +XXX,XX @@ vcpu_guest_context | 352 352 2800 5168 arch_vcpu_info | 0 0 24 16 vcpu_time_info | 32 32 32 32 vcpu_info | 48 48 64 64 -arch_shared_info | 0 0 28 48 -shared_info | 1088 1088 2344 3136 - +arch_shared_info | 8 8 36 56 +shared_info | 1096 1096 2352 3144 diff --git a/xen/common/kernel.c b/xen/common/kernel.c index XXXXXXX..XXXXXXX 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -XXX,XX +XXX,XX @@ long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) #ifdef CONFIG_X86 (1U << XENFEAT_vcpu_time_phys_area) | #endif - (1U << XENFEAT_runstate_phys_area); + (1U << XENFEAT_runstate_phys_area) | + (1U << XENFEAT_shared_info_time_offset); if ( VM_ASSIST(d, pae_extended_cr3) ) fi.submap |= (1U << XENFEAT_pae_pgdir_above_4gb); if ( paging_mode_translate(d) ) diff --git a/xen/common/time.c b/xen/common/time.c index XXXXXXX..XXXXXXX 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -XXX,XX +XXX,XX @@ void update_domain_wallclock_time(struct domain *d) shared_info(d, wc_sec_hi) = sec >> 32; #endif + shared_info(d, arch.time_offset) = + (uint32_t)d->time_offset.seconds; + shared_info(d, arch.time_offset_hi) = + (uint32_t)(d->time_offset.seconds >> 32); + smp_wmb(); *wc_version = version_update_end(*wc_version); diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -XXX,XX +XXX,XX @@ struct arch_vcpu_info { typedef struct arch_vcpu_info arch_vcpu_info_t; struct arch_shared_info { + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; typedef uint64_t xen_callback_t; diff --git a/xen/include/public/arch-ppc.h b/xen/include/public/arch-ppc.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-ppc.h +++ b/xen/include/public/arch-ppc.h @@ -XXX,XX +XXX,XX @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); struct arch_shared_info { uint64_t boot_timebase; + + uint32_t time_offset; + uint32_t time_offset_hi; }; struct arch_vcpu_info { diff --git a/xen/include/public/arch-riscv.h b/xen/include/public/arch-riscv.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-riscv.h +++ b/xen/include/public/arch-riscv.h @@ -XXX,XX +XXX,XX @@ struct arch_vcpu_info { }; typedef struct arch_vcpu_info arch_vcpu_info_t; -/* TODO: add a placeholder entry if no real ones surface */ struct arch_shared_info { + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/arch-x86/xen.h +++ b/xen/include/public/arch-x86/xen.h @@ -XXX,XX +XXX,XX @@ struct arch_shared_info { /* There's no room for this field in the generic structure. */ uint32_t wc_sec_hi; #endif + + uint32_t time_offset; + uint32_t time_offset_hi; }; typedef struct arch_shared_info arch_shared_info_t; diff --git a/xen/include/public/features.h b/xen/include/public/features.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/public/features.h +++ b/xen/include/public/features.h @@ -XXX,XX +XXX,XX @@ */ #define XENFEAT_dm_msix_all_writes 20 +/* + * arch_shared_info provides time_offset and time_offset_hi + */ +#define XENFEAT_shared_info_time_offset 21 + #define XENFEAT_NR_SUBMAPS 1 #endif /* __XEN_PUBLIC_FEATURES_H__ */ -- 2.43.0 -- Ngoc Tu Dinh | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech