]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: x86/xen: register steal clock
authorJoao Martins <joao.m.martins@oracle.com>
Tue, 24 Jul 2018 16:47:14 +0000 (12:47 -0400)
committerJoao Martins <joao.m.martins@oracle.com>
Wed, 20 Feb 2019 17:30:52 +0000 (12:30 -0500)
Allow emulator to register vcpu runstates which allow Xen guests
to use that for steal clock. The 'preempted' state of KVM steal clock
equates to 'runnable' state, 'running' has similar meanings for both and
'offline' is used when system admin needs to bring vcpu offline or
hotplug.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/x86.c
arch/x86/kvm/xen.c
arch/x86/kvm/xen.h
include/uapi/linux/kvm.h

index f39d50dd8f40066a3f0a6f505289769e9a4db88b..9d388ba0a05cb0e3a8c1128a3eb036d959fad5a3 100644 (file)
@@ -541,6 +541,8 @@ struct kvm_vcpu_xen {
        struct vcpu_info *vcpu_info;
        gpa_t pv_time_addr;
        struct pvclock_vcpu_time_info *pv_time;
+       gpa_t steal_time_addr;
+       struct vcpu_runstate_info *steal_time;
 };
 
 struct kvm_vcpu_arch {
index 3ce97860e6eeab8234b74fb1bbb5bcfe18740710..888598fdf5435d55a38eefff3705096ea379ff1a 100644 (file)
@@ -2389,6 +2389,11 @@ static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
 
 static void record_steal_time(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->arch.xen.steal_time_addr) {
+               kvm_xen_setup_runstate_page(vcpu);
+               return;
+       }
+
        if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
                return;
 
@@ -3251,6 +3256,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->arch.xen.steal_time_addr) {
+               kvm_xen_runstate_set_preempted(vcpu);
+               return;
+       }
+
        if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
                return;
 
index 77d1153386bc02ef759a9722aabec6d80433afb1..4fdc4c71245a6c3ff6d312944f0329f4a494adf4 100644 (file)
@@ -9,9 +9,11 @@
 #include "xen.h"
 
 #include <linux/kvm_host.h>
+#include <linux/sched/stat.h>
 
 #include <trace/events/kvm.h>
 #include <xen/interface/xen.h>
+#include <xen/interface/vcpu.h>
 
 #include "trace.h"
 
@@ -30,6 +32,11 @@ static void set_vcpu_attr(struct kvm_vcpu *v, u16 type, gpa_t gpa, void *addr)
                vcpu_xen->pv_time = addr;
                kvm_xen_setup_pvclock_page(v);
                break;
+       case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE:
+               vcpu_xen->steal_time_addr = gpa;
+               vcpu_xen->steal_time = addr;
+               kvm_xen_setup_runstate_page(v);
+               break;
        default:
                break;
        }
@@ -44,6 +51,8 @@ static gpa_t get_vcpu_attr(struct kvm_vcpu *v, u16 type)
                return vcpu_xen->vcpu_info_addr;
        case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
                return vcpu_xen->pv_time_addr;
+       case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE:
+               return vcpu_xen->steal_time_addr;
        default:
                return 0;
        }
@@ -124,6 +133,41 @@ static void kvm_xen_update_vcpu_time(struct kvm_vcpu *v,
        guest_hv_clock->version = vcpu->hv_clock.version;
 }
 
+void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu);
+       int state = RUNSTATE_runnable;
+
+       vcpu->arch.st.steal.preempted = KVM_VCPU_PREEMPTED;
+
+       vcpu_xen->steal_time->state = state;
+}
+
+void kvm_xen_setup_runstate_page(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(vcpu);
+       struct vcpu_runstate_info runstate;
+
+       runstate = *vcpu_xen->steal_time;
+
+       runstate.state_entry_time += 1;
+       runstate.state_entry_time |= XEN_RUNSTATE_UPDATE;
+       vcpu_xen->steal_time->state_entry_time = runstate.state_entry_time;
+       smp_wmb();
+
+       vcpu->arch.st.steal.steal += current->sched_info.run_delay -
+               vcpu->arch.st.last_steal;
+       vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+       runstate.state = RUNSTATE_running;
+       runstate.time[RUNSTATE_runnable] = vcpu->arch.st.steal.steal;
+       *vcpu_xen->steal_time = runstate;
+
+       runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE;
+       vcpu_xen->steal_time->state_entry_time = runstate.state_entry_time;
+       smp_wmb();
+}
+
 void kvm_xen_setup_pvclock_page(struct kvm_vcpu *v)
 {
        struct kvm_vcpu_xen *vcpu_xen = vcpu_to_xen_vcpu(v);
@@ -155,6 +199,10 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
                r = kvm_xen_shared_info_init(kvm, gfn);
                break;
        }
+       case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE:
+               if (unlikely(!sched_info_on()))
+                       return -ENOTSUPP;
+       /* fallthrough */
        case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
        case KVM_XEN_ATTR_TYPE_VCPU_INFO: {
                gpa_t gpa = data->u.vcpu_attr.gpa;
@@ -191,6 +239,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
                data->u.shared_info.gfn = kvm->arch.xen.shinfo_addr;
                break;
        }
+       case KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE:
        case KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO:
        case KVM_XEN_ATTR_TYPE_VCPU_INFO: {
                struct kvm_vcpu *v;
@@ -282,6 +331,8 @@ void kvm_xen_vcpu_uninit(struct kvm_vcpu *vcpu)
                put_page(virt_to_page(vcpu_xen->vcpu_info));
        if (vcpu_xen->pv_time)
                put_page(virt_to_page(vcpu_xen->pv_time));
+       if (vcpu_xen->steal_time)
+               put_page(virt_to_page(vcpu_xen->steal_time));
 }
 
 void kvm_xen_destroy_vm(struct kvm *kvm)
index 10ebd0b7a25ed533757055633e1aff21405b73ca..2feef68ee80f96dd305edadd70ccb25cce7b6465 100644 (file)
@@ -17,6 +17,8 @@ static inline struct kvm_vcpu *xen_vcpu_to_vcpu(struct kvm_vcpu_xen *xen_vcpu)
 }
 
 void kvm_xen_setup_pvclock_page(struct kvm_vcpu *vcpu);
+void kvm_xen_setup_runstate_page(struct kvm_vcpu *vcpu);
+void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu);
 int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
 int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
 bool kvm_xen_hypercall_enabled(struct kvm *kvm);
index 8296c3a2434f663ce1232db9530ea5abf90c5bfc..b91e57d9e6d3d05558c7ea2fa525b13f28b05892 100644 (file)
@@ -1475,6 +1475,7 @@ struct kvm_xen_hvm_attr {
 #define KVM_XEN_ATTR_TYPE_SHARED_INFO       0x0
 #define KVM_XEN_ATTR_TYPE_VCPU_INFO         0x1
 #define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO    0x2
+#define KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE     0x3
 
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {