static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
				    struct gfn_to_pfn_cache *gpc,
				    unsigned int offset)
{
	struct kvm_vcpu_arch *vcpu = &v->arch;
	struct pvclock_vcpu_time_info *guest_hv_clock;
	unsigned long flags;

	read_lock_irqsave(&gpc->lock, flags);
	while (!kvm_gfn_to_pfn_cache_check(v->kvm, gpc, gpc->gpa,
					   offset + sizeof(*guest_hv_clock))) {
		read_unlock_irqrestore(&gpc->lock, flags);

		if (kvm_gfn_to_pfn_cache_refresh(v->kvm, gpc, gpc->gpa,
						 offset + sizeof(*guest_hv_clock)))
			return;

		read_lock_irqsave(&gpc->lock, flags);
	}

	guest_hv_clock = (void *)(gpc->khva + offset);

	/*
	 * This VCPU is paused, but it's legal for a guest to read another
	 * VCPU's kvmclock, so we really have to follow the specification where
	 * it says that version is odd if data is being modified, and even after
	 * it is consistent.
	 */

	guest_hv_clock->version = vcpu->hv_clock.version = (guest_hv_clock->version + 1) | 1;
	smp_wmb();

	/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
	vcpu->hv_clock.flags |= (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);

	if (vcpu->pvclock_set_guest_stopped_request) {
		vcpu->hv_clock.flags |= PVCLOCK_GUEST_STOPPED;
		vcpu->pvclock_set_guest_stopped_request = false;
	}

	memcpy(guest_hv_clock, &vcpu->hv_clock, sizeof(*guest_hv_clock));
	smp_wmb();

	guest_hv_clock->version = ++vcpu->hv_clock.version;

	mark_page_dirty_in_slot(v->kvm, gpc->memslot, gpc->gpa >> PAGE_SHIFT);
	read_unlock_irqrestore(&gpc->lock, flags);

	trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
}
static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
				    struct gfn_to_pfn_cache *gpc,
				    unsigned int offset)
{
	struct kvm_vcpu_arch *vcpu = &v->arch;
	struct pvclock_vcpu_time_info *guest_hv_clock;
	unsigned long flags;

	read_lock_irqsave(&gpc->lock, flags);
	while (!kvm_gfn_to_pfn_cache_check(v->kvm, gpc, gpc->gpa,
					   offset + sizeof(*guest_hv_clock))) {
		read_unlock_irqrestore(&gpc->lock, flags);

		if (kvm_gfn_to_pfn_cache_refresh(v->kvm, gpc, gpc->gpa,
						 offset + sizeof(*guest_hv_clock)))
			return;

		read_lock_irqsave(&gpc->lock, flags);
	}

	guest_hv_clock = (void *)(gpc->khva + offset);

	 

	guest_hv_clock->version = vcpu->hv_clock.version = (guest_hv_clock->version + 1) | 1;
	smp_wmb();

	 
	vcpu->hv_clock.flags |= (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);

	if (vcpu->pvclock_set_guest_stopped_request) {
		vcpu->hv_clock.flags |= PVCLOCK_GUEST_STOPPED;
		vcpu->pvclock_set_guest_stopped_request = false;
	}

	memcpy(guest_hv_clock, &vcpu->hv_clock, sizeof(*guest_hv_clock));
	smp_wmb();

	guest_hv_clock->version = ++vcpu->hv_clock.version;

	mark_page_dirty_in_slot(v->kvm, gpc->memslot, gpc->gpa >> PAGE_SHIFT);
	read_unlock_irqrestore(&gpc->lock, flags);

	trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
}