same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
 specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
 is used in the hypercall for future use.
+
+
+6. KVM_HC_CLOCK_PAIRING
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to synchronize host and guest clocks.
+Usage:
+
+a0: guest physical address where host copies
+"struct kvm_clock_offset" structure.
+
+a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
+is supported (corresponding to the host's CLOCK_REALTIME clock).
+
+               struct kvm_clock_pairing {
+                       __s64 sec;
+                       __s64 nsec;
+                       __u64 tsc;
+                       __u32 flags;
+                       __u32 pad[9];
+               };
+
+       Where:
+               * sec: seconds from clock_type clock.
+               * nsec: nanoseconds from clock_type clock.
+               * tsc: guest TSC value used to calculate sec/nsec pair
+               * flags: flags, unused (0) at the moment.
+
+The hypercall lets a guest compute a precise timestamp across
+host and guest.  The guest can use the returned TSC value to
+compute the CLOCK_REALTIME for its clock, at the same instant.
+
+Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
+or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
 
 
        u64             boot_ns;
        u64             nsec_base;
+       u64             wall_time_sec;
 };
 
 static struct pvclock_gtod_data pvclock_gtod_data;
        vdata->boot_ns                  = boot_ns;
        vdata->nsec_base                = tk->tkr_mono.xtime_nsec;
 
+       vdata->wall_time_sec            = tk->xtime_sec;
+
        write_seqcount_end(&vdata->seq);
 }
 #endif
        return mode;
 }
 
+static int do_realtime(struct timespec *ts, u64 *cycle_now)
+{
+       struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+       unsigned long seq;
+       int mode;
+       u64 ns;
+
+       do {
+               seq = read_seqcount_begin(>od->seq);
+               mode = gtod->clock.vclock_mode;
+               ts->tv_sec = gtod->wall_time_sec;
+               ns = gtod->nsec_base;
+               ns += vgettsc(cycle_now);
+               ns >>= gtod->clock.shift;
+       } while (unlikely(read_seqcount_retry(>od->seq, seq)));
+
+       ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+       ts->tv_nsec = ns;
+
+       return mode;
+}
+
 /* returns true if host is using tsc clocksource */
 static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now)
 {
 
        return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
 }
+
+/* returns true if host is using tsc clocksource */
+static bool kvm_get_walltime_and_clockread(struct timespec *ts,
+                                          u64 *cycle_now)
+{
+       /* checked again under seqlock below */
+       if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
+               return false;
+
+       return do_realtime(ts, cycle_now) == VCLOCK_TSC;
+}
 #endif
 
 /*
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
+static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
+                               unsigned long clock_type)
+{
+       struct kvm_clock_pairing clock_pairing;
+       struct timespec ts;
+       cycle_t cycle;
+       int ret;
+
+       if (clock_type != KVM_CLOCK_PAIRING_WALLCLOCK)
+               return -KVM_EOPNOTSUPP;
+
+       if (kvm_get_walltime_and_clockread(&ts, &cycle) == false)
+               return -KVM_EOPNOTSUPP;
+
+       clock_pairing.sec = ts.tv_sec;
+       clock_pairing.nsec = ts.tv_nsec;
+       clock_pairing.tsc = kvm_read_l1_tsc(vcpu, cycle);
+       clock_pairing.flags = 0;
+
+       ret = 0;
+       if (kvm_write_guest(vcpu->kvm, paddr, &clock_pairing,
+                           sizeof(struct kvm_clock_pairing)))
+               ret = -KVM_EFAULT;
+
+       return ret;
+}
+
 /*
  * kvm_pv_kick_cpu_op:  Kick a vcpu.
  *
                kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
                ret = 0;
                break;
+       case KVM_HC_CLOCK_PAIRING:
+               ret = kvm_pv_clock_pairing(vcpu, a0, a1);
+               break;
        default:
                ret = -KVM_ENOSYS;
                break;