@@ -1529,6 +1529,15 @@ int arch_vcpu_reset(struct vcpu *v)
return 0;
}
+static void cf_check
+time_area_populate(void *map, struct vcpu *v)
+{
+ if ( is_pv_vcpu(v) )
+ v->arch.pv.pending_system_time.version = 0;
+
+ force_update_secondary_system_time(v, map);
+}
+
long do_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
{
long rc = 0;
@@ -1567,6 +1576,25 @@ long do_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
}
+ case VCPUOP_register_vcpu_time_phys_area:
+ {
+ struct vcpu_register_time_memory_area area;
+
+ rc = -EFAULT;
+ if ( copy_from_guest(&area.addr.p, arg, 1) )
+ break;
+
+ rc = map_guest_area(v, area.addr.p,
+ sizeof(vcpu_time_info_t),
+ &v->arch.time_guest_area,
+ time_area_populate);
+ if ( rc == -ERESTART )
+ rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
+ cmd, vcpuid, arg);
+
+ break;
+ }
+
case VCPUOP_get_physid:
{
struct vcpu_get_physid cpu_id;
@@ -692,6 +692,8 @@ void domain_cpu_policy_changed(struct domain *d);
bool update_secondary_system_time(struct vcpu *,
struct vcpu_time_info *);
+void force_update_secondary_system_time(struct vcpu *,
+ struct vcpu_time_info *);
void vcpu_show_registers(const struct vcpu *);
@@ -1628,6 +1628,16 @@ void force_update_vcpu_system_time(struct vcpu *v)
__update_vcpu_system_time(v, 1);
}
+void force_update_secondary_system_time(struct vcpu *v,
+ struct vcpu_time_info *map)
+{
+ struct vcpu_time_info u;
+
+ collect_time_info(v, &u);
+ u.version = -1; /* Compensate for version_update_end(). */
+ write_time_guest_area(map, &u);
+}
+
static void update_domain_rtc(void)
{
struct domain *d;
@@ -115,6 +115,7 @@ compat_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
case VCPUOP_send_nmi:
case VCPUOP_get_physid:
+ case VCPUOP_register_vcpu_time_phys_area:
rc = do_vcpu_op(cmd, vcpuid, arg);
break;
@@ -209,6 +209,9 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
* segment limit). It can then apply the normal algorithm to compute
* system time from the tsc.
*
+ * New code wants to prefer VCPUOP_register_vcpu_time_phys_area, and only
+ * fall back to the operation here for backwards compatibility.
+ *
* @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
*/
#define VCPUOP_register_vcpu_time_memory_area 13
@@ -235,6 +238,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
* VMASST_TYPE_runstate_update_flag engaged by the domain.
*/
#define VCPUOP_register_runstate_phys_area 14
+#define VCPUOP_register_vcpu_time_phys_area 15
#endif /* __XEN_PUBLIC_VCPU_H__ */