@@ -377,6 +377,9 @@ struct kvm_vcpu_arch {
unsigned int hw_tsc_khz;
unsigned int time_offset;
struct page *time_page;
+ gpa_t stime;
+ u64 time_out;
+ u64 this_time_out;
u64 last_host_tsc;
u64 last_guest_tsc;
u64 last_kernel_ns;
@@ -2123,6 +2123,9 @@ static bool need_emulate_wbinvd(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
+ struct kvm_steal_time *st;
+ st = (struct kvm_steal_time *)vcpu->arch.stime;
+
/* Address WBINVD may be executed by guest */
if (need_emulate_wbinvd(vcpu)) {
if (kvm_x86_ops->has_wbinvd_exit())
@@ -2148,6 +2151,14 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_migrate_timers(vcpu);
vcpu->cpu = cpu;
}
+ if (vcpu->arch.this_time_out) {
+ vcpu->arch.time_out +=
+ (get_kernel_ns() - vcpu->arch.this_time_out);
+ kvm_write_guest(vcpu->kvm, (gpa_t)&st->steal,
+ &vcpu->arch.time_out, sizeof(st->steal));
+ /* is it possible to have 2 loads in sequence? */
+ vcpu->arch.this_time_out = 0;
+ }
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -5333,6 +5344,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
kvm_lapic_sync_from_vapic(vcpu);
+ vcpu->arch.this_time_out = get_kernel_ns();
+
r = kvm_x86_ops->handle_exit(vcpu);
out:
return r;