kvm/x86: Hyper-V HV_X64_MSR_VP_RUNTIME support
authorAndrey Smetanin <asmetanin@virtuozzo.com>
Wed, 16 Sep 2015 09:29:50 +0000 (12:29 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 1 Oct 2015 13:06:33 +0000 (15:06 +0200)
HV_X64_MSR_VP_RUNTIME msr used by guest to get
"the time the virtual processor consumes running guest code,
and the time the associated logical processor spends running
hypervisor code on behalf of that guest."

Calculation of this time is performed by task_cputime_adjusted()
for vcpu task.

Necessary to support loading of winhv.sys in guest, which in turn is
required to support Windows VMBus.

Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Gleb Natapov <gleb@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/include/uapi/asm/hyperv.h
arch/x86/kvm/hyperv.c
arch/x86/kvm/x86.c
kernel/sched/cputime.c

index 76a5b30979b31e8d5a90a811ddfa543734e6b8a3..d064cb2e19e8f6c3e743a1d3f0020142d72a6fce 100644 (file)
@@ -374,6 +374,7 @@ struct kvm_mtrr {
 /* Hyper-V per vcpu emulation context */
 struct kvm_vcpu_hv {
        u64 hv_vapic;
+       s64 runtime_offset;
 };
 
 struct kvm_vcpu_arch {
index dab584bf7ddf11acb811a8fd148588a1ccf6ec63..2677a0aac2ccbcddd1f59770424ab32ba4a44587 100644 (file)
 /* MSR used to reset the guest OS. */
 #define HV_X64_MSR_RESET                       0x40000003
 
+/* MSR used to provide vcpu runtime in 100ns units */
+#define HV_X64_MSR_VP_RUNTIME                  0x40000010
+
 /* MSR used to read the per-partition time reference counter */
 #define HV_X64_MSR_TIME_REF_COUNT              0x40000020
 
index 0ad11a2324749ce44563da44bae9f72b0daee9a0..62cf8c915e95df1577d1d226bae9dc04f51b52e3 100644 (file)
@@ -178,7 +178,16 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
        return 0;
 }
 
-static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+/* Calculate cpu time spent by current task in 100ns units */
+static u64 current_task_runtime_100ns(void)
+{
+       cputime_t utime, stime;
+
+       task_cputime_adjusted(current, &utime, &stime);
+       return div_u64(cputime_to_nsecs(utime + stime), 100);
+}
+
+static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
 {
        struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
 
@@ -212,6 +221,11 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
        case HV_X64_MSR_TPR:
                return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
+       case HV_X64_MSR_VP_RUNTIME:
+               if (!host)
+                       return 1;
+               hv->runtime_offset = data - current_task_runtime_100ns();
+               break;
        default:
                vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n",
                            msr, data);
@@ -287,6 +301,9 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case HV_X64_MSR_APIC_ASSIST_PAGE:
                data = hv->hv_vapic;
                break;
+       case HV_X64_MSR_VP_RUNTIME:
+               data = current_task_runtime_100ns() + hv->runtime_offset;
+               break;
        default:
                vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
                return 1;
@@ -305,7 +322,7 @@ int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
                mutex_unlock(&vcpu->kvm->lock);
                return r;
        } else
-               return kvm_hv_set_msr(vcpu, msr, data);
+               return kvm_hv_set_msr(vcpu, msr, data, host);
 }
 
 int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
index 716b4610791c58781eee49ae1048497c9f0d912d..185fc1619c99e0e46ae14f824ff94c8b600290c1 100644 (file)
@@ -954,6 +954,7 @@ static u32 emulated_msrs[] = {
        HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL,
        HV_X64_MSR_RESET,
        HV_X64_MSR_VP_INDEX,
+       HV_X64_MSR_VP_RUNTIME,
        HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
        MSR_KVM_PV_EOI_EN,
 
index 8cbc3db671df5290f93b136175da42fdb5522bbb..26a54461bf59ca46ce7f68d7a926b03840ca8711 100644 (file)
@@ -444,6 +444,7 @@ void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
        *ut = p->utime;
        *st = p->stime;
 }
+EXPORT_SYMBOL_GPL(task_cputime_adjusted);
 
 void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
 {
@@ -652,6 +653,7 @@ void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
        task_cputime(p, &cputime.utime, &cputime.stime);
        cputime_adjust(&cputime, &p->prev_cputime, ut, st);
 }
+EXPORT_SYMBOL_GPL(task_cputime_adjusted);
 
 void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st)
 {