History

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Paolo Bonzini: - Doc fixes - selftests fixes - Add runstate information to the new Xen support - Allow compiling out the Xen interface - 32-bit PAE without EPT bugfix - NULL pointer dereference bugfix * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: SVM: Clear the CR4 register on reset KVM: x86/xen: Add support for vCPU runstate information KVM: x86/xen: Fix return code when clearing vcpu_info and vcpu_time_info selftests: kvm: Mmap the entire vcpu mmap area KVM: Documentation: Fix index for KVM_CAP_PPC_DAWR1 KVM: x86: allow compiling out the Xen hypercall interface KVM: xen: flush deferred static key before checking it KVM: x86/mmu: Set SPTE_AD_WRPROT_ONLY_MASK if and only if PML is enabled KVM: x86: hyper-v: Fix Hyper-V context null-ptr-deref KVM: x86: remove misplaced comment on active_mmu_pages KVM: Documentation: rectify rst markup in kvm_run->flags Documentation: kvm: fix messy conversion from .txt to .rst

Linus Torvalds committed 5 years ago

Commit cee407c2 parents c5a58f8 9e46f6c13 files · +633 −76Browse files

Unified · Split

13 files
  1. Documentation/virt/kvm/api.rst +60 −55
  2. arch/x86/include/asm/kvm_host.h +6 −3
  3. arch/x86/kvm/Kconfig +9 −0
  4. arch/x86/kvm/Makefile +2 −1
  5. arch/x86/kvm/hyperv.c +1 −1
  6. arch/x86/kvm/mmu/mmu_internal.h +8 −8
  7. arch/x86/kvm/svm/svm.c +1 −0
  8. arch/x86/kvm/x86.c +21 −1
  9. arch/x86/kvm/xen.c +290 −0
  10. arch/x86/kvm/xen.h +62 −2
  11. include/uapi/linux/kvm.h +13 −0
  12. tools/testing/selftests/kvm/lib/kvm_util.c +4 −2
  13. tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c +156 −3
Documentation/virt/kvm/api.rst+60−55
@@ -3856,49 +3856,20 @@ base 2 of the page size in the bottom 6 bits. · 3855 unmodified lines
38563856 -EFAULT if struct kvm_reinject_control cannot be read,
38573857 -EINVAL if the supplied shift or flags are invalid,
38583858 -ENOMEM if unable to allocate the new HPT,
3859− -ENOSPC if there was a hash collision
3860−
3861−::
3862−
3863− struct kvm_ppc_rmmu_info {
3864− struct kvm_ppc_radix_geom {
3865− __u8 page_shift;
3866− __u8 level_bits[4];
3867− __u8 pad[3];
3868− } geometries[8];
3869− __u32 ap_encodings[8];
3870− };
3871−
3872−The geometries[] field gives up to 8 supported geometries for the
3873−radix page table, in terms of the log base 2 of the smallest page
3874−size, and the number of bits indexed at each level of the tree, from
3875−the PTE level up to the PGD level in that order. Any unused entries
3876−will have 0 in the page_shift field.
3877−
3878−The ap_encodings gives the supported page sizes and their AP field
3879−encodings, encoded with the AP value in the top 3 bits and the log
3880−base 2 of the page size in the bottom 6 bits.
3881−
3882−4.102 KVM_PPC_RESIZE_HPT_PREPARE
3883−--------------------------------
3884−
3885−:Capability: KVM_CAP_SPAPR_RESIZE_HPT
3886−:Architectures: powerpc
3887−:Type: vm ioctl
3888−:Parameters: struct kvm_ppc_resize_hpt (in)
3889−:Returns: 0 on successful completion,
3890− >0 if a new HPT is being prepared, the value is an estimated
3891− number of milliseconds until preparation is complete,
3892− -EFAULT if struct kvm_reinject_control cannot be read,
3893− -EINVAL if the supplied shift or flags are invalid,when moving existing
3894− HPT entries to the new HPT,
3895− -EIO on other error conditions
38963859
38973860 Used to implement the PAPR extension for runtime resizing of a guest's
38983861 Hashed Page Table (HPT). Specifically this starts, stops or monitors
38993862 the preparation of a new potential HPT for the guest, essentially
39003863 implementing the H_RESIZE_HPT_PREPARE hypercall.
39013864
3865+::
3866+
3867+ struct kvm_ppc_resize_hpt {
3868+ __u64 flags;
3869+ __u32 shift;
3870+ __u32 pad;
3871+ };
3872+
39023873 If called with shift > 0 when there is no pending HPT for the guest,
39033874 this begins preparation of a new pending HPT of size 2^(shift) bytes.
39043875 It then returns a positive integer with the estimated number of
@@ -3926,14 +3897,6 @@ Normally this will be called repeatedly with the same parameters until · 21 unmodified lines
39263897 it returns <= 0. The first call will initiate preparation, subsequent
39273898 ones will monitor preparation until it completes or fails.
39283899
3929−::
3930−
3931− struct kvm_ppc_resize_hpt {
3932− __u64 flags;
3933− __u32 shift;
3934− __u32 pad;
3935− };
3936−
39373900 4.103 KVM_PPC_RESIZE_HPT_COMMIT
39383901 -------------------------------
39393902
@@ -3956,6 +3919,14 @@ Hashed Page Table (HPT). Specifically this requests that the guest be · 16 unmodified lines
39563919 transferred to working with the new HPT, essentially implementing the
39573920 H_RESIZE_HPT_COMMIT hypercall.
39583921
3922+::
3923+
3924+ struct kvm_ppc_resize_hpt {
3925+ __u64 flags;
3926+ __u32 shift;
3927+ __u32 pad;
3928+ };
3929+
39593930 This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has
39603931 returned 0 with the same parameters. In other cases
39613932 KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or
@@ -3971,14 +3942,6 @@ HPT and the previous HPT will be discarded. · 9 unmodified lines
39713942
39723943 On failure, the guest will still be operating on its previous HPT.
39733944
3974−::
3975−
3976− struct kvm_ppc_resize_hpt {
3977− __u64 flags;
3978− __u32 shift;
3979− __u32 pad;
3980− };
3981−
39823945 4.104 KVM_X86_GET_MCE_CAP_SUPPORTED
39833946 -----------------------------------
39843947
@@ -4915,6 +4878,14 @@ see KVM_XEN_HVM_SET_ATTR above. · 930 unmodified lines
49154878 union {
49164879 __u64 gpa;
49174880 __u64 pad[4];
4881+ struct {
4882+ __u64 state;
4883+ __u64 state_entry_time;
4884+ __u64 time_running;
4885+ __u64 time_runnable;
4886+ __u64 time_blocked;
4887+ __u64 time_offline;
4888+ } runstate;
49184889 } u;
49194890 };
49204891
@@ -4927,6 +4898,31 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO · 6 unmodified lines
49274898 Sets the guest physical address of an additional pvclock structure
49284899 for a given vCPU. This is typically used for guest vsyscall support.
49294900
4901+KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR
4902+ Sets the guest physical address of the vcpu_runstate_info for a given
4903+ vCPU. This is how a Xen guest tracks CPU state such as steal time.
4904+
4905+KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT
4906+ Sets the runstate (RUNSTATE_running/_runnable/_blocked/_offline) of
4907+ the given vCPU from the .u.runstate.state member of the structure.
4908+ KVM automatically accounts running and runnable time but blocked
4909+ and offline states are only entered explicitly.
4910+
4911+KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA
4912+ Sets all fields of the vCPU runstate data from the .u.runstate member
4913+ of the structure, including the current runstate. The state_entry_time
4914+ must equal the sum of the other four times.
4915+
4916+KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST
4917+ This *adds* the contents of the .u.runstate members of the structure
4918+ to the corresponding members of the given vCPU's runstate data, thus
4919+ permitting atomic adjustments to the runstate times. The adjustment
4920+ to the state_entry_time must equal the sum of the adjustments to the
4921+ other four times. The state field must be set to -1, or to a valid
4922+ runstate value (RUNSTATE_running, RUNSTATE_runnable, RUNSTATE_blocked
4923+ or RUNSTATE_offline) to set the current accounted state as of the
4924+ adjusted state_entry_time.
4925+
49304926 4.130 KVM_XEN_VCPU_GET_ATTR
49314927 ---------------------------
49324928
@@ -4939,6 +4935,9 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO · 6 unmodified lines
49394935 Allows Xen vCPU attributes to be read. For the structure and types,
49404936 see KVM_XEN_VCPU_SET_ATTR above.
49414937
4938+The KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST type may not be used
4939+with the KVM_XEN_VCPU_GET_ATTR ioctl.
4940+
49424941 5. The kvm_run structure
49434942 ========================
49444943
@@ -5000,7 +4999,8 @@ local APIC is not used. · 55 unmodified lines
50004999 __u16 flags;
50015000
50025001 More architecture-specific flags detailing state of the VCPU that may
5003−affect the device's behavior. Current defined flags:
5002+affect the device's behavior. Current defined flags::
5003+
50045004 /* x86, set if the VCPU is in system management mode */
50055005 #define KVM_RUN_X86_SMM (1 << 0)
50065006 /* x86, set if bus lock detected in VM */
@@ -6217,7 +6217,7 @@ the bus lock vm exit can be preempted by a higher priority VM exit, the exit · 1210 unmodified lines
62176217 notifications to userspace can be KVM_EXIT_BUS_LOCK or other reasons.
62186218 KVM_RUN_BUS_LOCK flag is used to distinguish between them.
62196219
6220−7.22 KVM_CAP_PPC_DAWR1
6220+7.23 KVM_CAP_PPC_DAWR1
62216221 ----------------------
62226222
62236223 :Architectures: ppc
@@ -6702,6 +6702,7 @@ PVHVM guests. Valid flags are:: · 478 unmodified lines
67026702 #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0)
67036703 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
67046704 #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
6705+ #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 2)
67056706
67066707 The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG
67076708 ioctl is available, for the guest to set its hypercall page.
@@ -6716,3 +6717,7 @@ KVM_XEN_HVM_SET_ATTR, KVM_XEN_HVM_GET_ATTR, KVM_XEN_VCPU_SET_ATTR and · 8 unmodified lines
67166717 KVM_XEN_VCPU_GET_ATTR ioctls, as well as the delivery of exception vectors
67176718 for event channel upcalls when the evtchn_upcall_pending field of a vcpu's
67186719 vcpu_info is set.
6720+
6721+The KVM_XEN_HVM_CONFIG_RUNSTATE flag indicates that the runstate-related
6722+features KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR/_CURRENT/_DATA/_ADJUST are
6723+supported by the KVM_XEN_VCPU_SET_ATTR/KVM_XEN_VCPU_GET_ATTR ioctls.
arch/x86/include/asm/kvm_host.h+6−3
@@ -535,10 +535,16 @@ struct kvm_vcpu_hv { · 534 unmodified lines
535535 /* Xen HVM per vcpu emulation context */
536536 struct kvm_vcpu_xen {
537537 u64 hypercall_rip;
538+ u32 current_runstate;
538539 bool vcpu_info_set;
539540 bool vcpu_time_info_set;
541+ bool runstate_set;
540542 struct gfn_to_hva_cache vcpu_info_cache;
541543 struct gfn_to_hva_cache vcpu_time_info_cache;
544+ struct gfn_to_hva_cache runstate_cache;
545+ u64 last_steal;
546+ u64 runstate_entry_time;
547+ u64 runstate_times[4];
542548 };
543549
544550 struct kvm_vcpu_arch {
@@ -939,9 +945,6 @@ struct kvm_arch { · 394 unmodified lines
939945 unsigned int indirect_shadow_pages;
940946 u8 mmu_valid_gen;
941947 struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
942− /*
943− * Hash table of struct kvm_mmu_page.
944− */
945948 struct list_head active_mmu_pages;
946949 struct list_head zapped_obsolete_pages;
947950 struct list_head lpage_disallowed_mmu_pages;
arch/x86/kvm/Kconfig+9−0
@@ -103,6 +103,15 @@ config KVM_AMD_SEV · 102 unmodified lines
103103 Provides support for launching Encrypted VMs (SEV) and Encrypted VMs
104104 with Encrypted State (SEV-ES) on AMD processors.
105105
106+config KVM_XEN
107+ bool "Support for Xen hypercall interface"
108+ depends on KVM
109+ help
110+ Provides KVM support for the hosting Xen HVM guests and
111+ passing Xen hypercalls to userspace.
112+
113+ If in doubt, say "N".
114+
106115 config KVM_MMU_AUDIT
107116 bool "Audit KVM MMU"
108117 depends on KVM && TRACEPOINTS
arch/x86/kvm/Makefile+2−1
@@ -14,11 +14,12 @@ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ · 13 unmodified lines
1414 $(KVM)/dirty_ring.o
1515 kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
1616
17−kvm-y += x86.o emulate.o i8259.o irq.o lapic.o xen.o \
17+kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
1818 i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
1919 hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \
2020 mmu/spte.o
2121 kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o
22+kvm-$(CONFIG_KVM_XEN) += xen.o
2223
2324 kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
2425 vmx/evmcs.o vmx/nested.o vmx/posted_intr.o
arch/x86/kvm/hyperv.c+1−1
@@ -159,7 +159,7 @@ static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vpidx) · 158 unmodified lines
159159 struct kvm_vcpu_hv_synic *synic;
160160
161161 vcpu = get_vcpu_by_vpidx(kvm, vpidx);
162− if (!vcpu)
162+ if (!vcpu || !to_hv_vcpu(vcpu))
163163 return NULL;
164164 synic = to_hv_synic(vcpu);
165165 return (synic->active) ? synic : NULL;
arch/x86/kvm/mmu/mmu_internal.h+8−8
@@ -81,15 +81,15 @@ static inline struct kvm_mmu_page *sptep_to_sp(u64 *sptep) · 80 unmodified lines
8181 static inline bool kvm_vcpu_ad_need_write_protect(struct kvm_vcpu *vcpu)
8282 {
8383 /*
84− * When using the EPT page-modification log, the GPAs in the log
85− * would come from L2 rather than L1. Therefore, we need to rely
86− * on write protection to record dirty pages. This also bypasses
87− * PML, since writes now result in a vmexit. Note, this helper will
88− * tag SPTEs as needing write-protection even if PML is disabled or
89− * unsupported, but that's ok because the tag is consumed if and only
90− * if PML is enabled. Omit the PML check to save a few uops.
84+ * When using the EPT page-modification log, the GPAs in the CPU dirty
85+ * log would come from L2 rather than L1. Therefore, we need to rely
86+ * on write protection to record dirty pages, which bypasses PML, since
87+ * writes now result in a vmexit. Note, the check on CPU dirty logging
88+ * being enabled is mandatory as the bits used to denote WP-only SPTEs
89+ * are reserved for NPT w/ PAE (32-bit KVM).
9190 */
92− return vcpu->arch.mmu == &vcpu->arch.guest_mmu;
91+ return vcpu->arch.mmu == &vcpu->arch.guest_mmu &&
92+ kvm_x86_ops.cpu_dirty_log_size;
9393 }
9494
9595 bool is_nx_huge_page_enabled(void);
arch/x86/kvm/svm/svm.c+1−0
@@ -1200,6 +1200,7 @@ static void init_vmcb(struct vcpu_svm *svm) · 1199 unmodified lines
12001200 init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
12011201 init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
12021202
1203+ svm_set_cr4(&svm->vcpu, 0);
12031204 svm_set_efer(&svm->vcpu, 0);
12041205 save->dr6 = 0xffff0ff0;
12051206 kvm_set_rflags(&svm->vcpu, X86_EFLAGS_FIXED);
arch/x86/kvm/x86.c+21−1
@@ -2957,6 +2957,11 @@ static void record_steal_time(struct kvm_vcpu *vcpu) · 2956 unmodified lines
29572957 struct kvm_host_map map;
29582958 struct kvm_steal_time *st;
29592959
2960+ if (kvm_xen_msr_enabled(vcpu->kvm)) {
2961+ kvm_xen_runstate_set_running(vcpu);
2962+ return;
2963+ }
2964+
29602965 if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
29612966 return;
29622967
@@ -3756,11 +3761,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 793 unmodified lines
37563761 case KVM_CAP_ENFORCE_PV_FEATURE_CPUID:
37573762 r = 1;
37583763 break;
3764+#ifdef CONFIG_KVM_XEN
37593765 case KVM_CAP_XEN_HVM:
37603766 r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
37613767 KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL |
37623768 KVM_XEN_HVM_CONFIG_SHARED_INFO;
3769+ if (sched_info_on())
3770+ r |= KVM_XEN_HVM_CONFIG_RUNSTATE;
37633771 break;
3772+#endif
37643773 case KVM_CAP_SYNC_REGS:
37653774 r = KVM_SYNC_X86_VALID_FIELDS;
37663775 break;
@@ -4038,7 +4047,11 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) · 271 unmodified lines
40384047 if (vcpu->preempted && !vcpu->arch.guest_state_protected)
40394048 vcpu->arch.preempted_in_kernel = !static_call(kvm_x86_get_cpl)(vcpu);
40404049
4041− kvm_steal_time_set_preempted(vcpu);
4050+ if (kvm_xen_msr_enabled(vcpu->kvm))
4051+ kvm_xen_runstate_set_preempted(vcpu);
4052+ else
4053+ kvm_steal_time_set_preempted(vcpu);
4054+
40424055 static_call(kvm_x86_vcpu_put)(vcpu);
40434056 vcpu->arch.last_host_tsc = rdtsc();
40444057 /*
@@ -5013,6 +5026,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 968 unmodified lines
50135026 case KVM_GET_SUPPORTED_HV_CPUID:
50145027 r = kvm_ioctl_get_supported_hv_cpuid(vcpu, argp);
50155028 break;
5029+#ifdef CONFIG_KVM_XEN
50165030 case KVM_XEN_VCPU_GET_ATTR: {
50175031 struct kvm_xen_vcpu_attr xva;
50185032
@@ -5033,6 +5047,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 14 unmodified lines
50335047 r = kvm_xen_vcpu_set_attr(vcpu, &xva);
50345048 break;
50355049 }
5050+#endif
50365051 default:
50375052 r = -EINVAL;
50385053 }
@@ -5654,6 +5669,7 @@ set_pit2_out: · 615 unmodified lines
56545669 kvm->arch.bsp_vcpu_id = arg;
56555670 mutex_unlock(&kvm->lock);
56565671 break;
5672+#ifdef CONFIG_KVM_XEN
56575673 case KVM_XEN_HVM_CONFIG: {
56585674 struct kvm_xen_hvm_config xhc;
56595675 r = -EFAULT;
@@ -5682,6 +5698,7 @@ set_pit2_out: · 22 unmodified lines
56825698 r = kvm_xen_hvm_set_attr(kvm, &xha);
56835699 break;
56845700 }
5701+#endif
56855702 case KVM_SET_CLOCK: {
56865703 struct kvm_clock_data user_ns;
56875704 u64 now_ns;
@@ -8040,7 +8057,10 @@ void kvm_arch_exit(void) · 2352 unmodified lines
80408057 kvm_mmu_module_exit();
80418058 free_percpu(user_return_msrs);
80428059 kmem_cache_destroy(x86_fpu_cache);
8060+#ifdef CONFIG_KVM_XEN
8061+ static_key_deferred_flush(&kvm_xen_enabled);
80438062 WARN_ON(static_branch_unlikely(&kvm_xen_enabled.key));
8063+#endif
80448064 }
80458065
80468066 static int __kvm_vcpu_halt(struct kvm_vcpu *vcpu, int state, int reason)
arch/x86/kvm/xen.c+290−0
@@ -11,9 +11,11 @@ · 10 unmodified lines
1111 #include "hyperv.h"
1212
1313 #include <linux/kvm_host.h>
14+#include <linux/sched/stat.h>
1415
1516 #include <trace/events/kvm.h>
1617 #include <xen/interface/xen.h>
18+#include <xen/interface/vcpu.h>
1719
1820 #include "trace.h"
1921
@@ -61,6 +63,132 @@ out: · 41 unmodified lines
6163 return ret;
6264 }
6365
66+static void kvm_xen_update_runstate(struct kvm_vcpu *v, int state)
67+{
68+ struct kvm_vcpu_xen *vx = &v->arch.xen;
69+ u64 now = get_kvmclock_ns(v->kvm);
70+ u64 delta_ns = now - vx->runstate_entry_time;
71+ u64 run_delay = current->sched_info.run_delay;
72+
73+ if (unlikely(!vx->runstate_entry_time))
74+ vx->current_runstate = RUNSTATE_offline;
75+
76+ /*
77+ * Time waiting for the scheduler isn't "stolen" if the
78+ * vCPU wasn't running anyway.
79+ */
80+ if (vx->current_runstate == RUNSTATE_running) {
81+ u64 steal_ns = run_delay - vx->last_steal;
82+
83+ delta_ns -= steal_ns;
84+
85+ vx->runstate_times[RUNSTATE_runnable] += steal_ns;
86+ }
87+ vx->last_steal = run_delay;
88+
89+ vx->runstate_times[vx->current_runstate] += delta_ns;
90+ vx->current_runstate = state;
91+ vx->runstate_entry_time = now;
92+}
93+
94+void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
95+{
96+ struct kvm_vcpu_xen *vx = &v->arch.xen;
97+ uint64_t state_entry_time;
98+ unsigned int offset;
99+
100+ kvm_xen_update_runstate(v, state);
101+
102+ if (!vx->runstate_set)
103+ return;
104+
105+ BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c);
106+
107+ offset = offsetof(struct compat_vcpu_runstate_info, state_entry_time);
108+#ifdef CONFIG_X86_64
109+ /*
110+ * The only difference is alignment of uint64_t in 32-bit.
111+ * So the first field 'state' is accessed directly using
112+ * offsetof() (where its offset happens to be zero), while the
113+ * remaining fields which are all uint64_t, start at 'offset'
114+ * which we tweak here by adding 4.
115+ */
116+ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) !=
117+ offsetof(struct compat_vcpu_runstate_info, state_entry_time) + 4);
118+ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, time) !=
119+ offsetof(struct compat_vcpu_runstate_info, time) + 4);
120+
121+ if (v->kvm->arch.xen.long_mode)
122+ offset = offsetof(struct vcpu_runstate_info, state_entry_time);
123+#endif
124+ /*
125+ * First write the updated state_entry_time at the appropriate
126+ * location determined by 'offset'.
127+ */
128+ state_entry_time = vx->runstate_entry_time;
129+ state_entry_time |= XEN_RUNSTATE_UPDATE;
130+
131+ BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state_entry_time) !=
132+ sizeof(state_entry_time));
133+ BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state_entry_time) !=
134+ sizeof(state_entry_time));
135+
136+ if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
137+ &state_entry_time, offset,
138+ sizeof(state_entry_time)))
139+ return;
140+ smp_wmb();
141+
142+ /*
143+ * Next, write the new runstate. This is in the *same* place
144+ * for 32-bit and 64-bit guests, asserted here for paranoia.
145+ */
146+ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) !=
147+ offsetof(struct compat_vcpu_runstate_info, state));
148+ BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state) !=
149+ sizeof(vx->current_runstate));
150+ BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state) !=
151+ sizeof(vx->current_runstate));
152+
153+ if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
154+ &vx->current_runstate,
155+ offsetof(struct vcpu_runstate_info, state),
156+ sizeof(vx->current_runstate)))
157+ return;
158+
159+ /*
160+ * Write the actual runstate times immediately after the
161+ * runstate_entry_time.
162+ */
163+ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) !=
164+ offsetof(struct vcpu_runstate_info, time) - sizeof(u64));
165+ BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state_entry_time) !=
166+ offsetof(struct compat_vcpu_runstate_info, time) - sizeof(u64));
167+ BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
168+ sizeof(((struct compat_vcpu_runstate_info *)0)->time));
169+ BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
170+ sizeof(vx->runstate_times));
171+
172+ if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
173+ &vx->runstate_times[0],
174+ offset + sizeof(u64),
175+ sizeof(vx->runstate_times)))
176+ return;
177+
178+ smp_wmb();
179+
180+ /*
181+ * Finally, clear the XEN_RUNSTATE_UPDATE bit in the guest's
182+ * runstate_entry_time field.
183+ */
184+
185+ state_entry_time &= ~XEN_RUNSTATE_UPDATE;
186+ if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
187+ &state_entry_time, offset,
188+ sizeof(state_entry_time)))
189+ return;
190+}
191+
64192 int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
65193 {
66194 u8 rc = 0;
@@ -187,9 +315,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 120 unmodified lines
187315 /* No compat necessary here. */
188316 BUILD_BUG_ON(sizeof(struct vcpu_info) !=
189317 sizeof(struct compat_vcpu_info));
318+ BUILD_BUG_ON(offsetof(struct vcpu_info, time) !=
319+ offsetof(struct compat_vcpu_info, time));
190320
191321 if (data->u.gpa == GPA_INVALID) {
192322 vcpu->arch.xen.vcpu_info_set = false;
323+ r = 0;
193324 break;
194325 }
195326
@@ -206,6 +337,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 10 unmodified lines
206337 case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
207338 if (data->u.gpa == GPA_INVALID) {
208339 vcpu->arch.xen.vcpu_time_info_set = false;
340+ r = 0;
209341 break;
210342 }
211343
@@ -219,6 +351,121 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 7 unmodified lines
219351 }
220352 break;
221353
354+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR:
355+ if (!sched_info_on()) {
356+ r = -EOPNOTSUPP;
357+ break;
358+ }
359+ if (data->u.gpa == GPA_INVALID) {
360+ vcpu->arch.xen.runstate_set = false;
361+ r = 0;
362+ break;
363+ }
364+
365+ r = kvm_gfn_to_hva_cache_init(vcpu->kvm,
366+ &vcpu->arch.xen.runstate_cache,
367+ data->u.gpa,
368+ sizeof(struct vcpu_runstate_info));
369+ if (!r) {
370+ vcpu->arch.xen.runstate_set = true;
371+ }
372+ break;
373+
374+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT:
375+ if (!sched_info_on()) {
376+ r = -EOPNOTSUPP;
377+ break;
378+ }
379+ if (data->u.runstate.state > RUNSTATE_offline) {
380+ r = -EINVAL;
381+ break;
382+ }
383+
384+ kvm_xen_update_runstate(vcpu, data->u.runstate.state);
385+ r = 0;
386+ break;
387+
388+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA:
389+ if (!sched_info_on()) {
390+ r = -EOPNOTSUPP;
391+ break;
392+ }
393+ if (data->u.runstate.state > RUNSTATE_offline) {
394+ r = -EINVAL;
395+ break;
396+ }
397+ if (data->u.runstate.state_entry_time !=
398+ (data->u.runstate.time_running +
399+ data->u.runstate.time_runnable +
400+ data->u.runstate.time_blocked +
401+ data->u.runstate.time_offline)) {
402+ r = -EINVAL;
403+ break;
404+ }
405+ if (get_kvmclock_ns(vcpu->kvm) <
406+ data->u.runstate.state_entry_time) {
407+ r = -EINVAL;
408+ break;
409+ }
410+
411+ vcpu->arch.xen.current_runstate = data->u.runstate.state;
412+ vcpu->arch.xen.runstate_entry_time =
413+ data->u.runstate.state_entry_time;
414+ vcpu->arch.xen.runstate_times[RUNSTATE_running] =
415+ data->u.runstate.time_running;
416+ vcpu->arch.xen.runstate_times[RUNSTATE_runnable] =
417+ data->u.runstate.time_runnable;
418+ vcpu->arch.xen.runstate_times[RUNSTATE_blocked] =
419+ data->u.runstate.time_blocked;
420+ vcpu->arch.xen.runstate_times[RUNSTATE_offline] =
421+ data->u.runstate.time_offline;
422+ vcpu->arch.xen.last_steal = current->sched_info.run_delay;
423+ r = 0;
424+ break;
425+
426+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST:
427+ if (!sched_info_on()) {
428+ r = -EOPNOTSUPP;
429+ break;
430+ }
431+ if (data->u.runstate.state > RUNSTATE_offline &&
432+ data->u.runstate.state != (u64)-1) {
433+ r = -EINVAL;
434+ break;
435+ }
436+ /* The adjustment must add up */
437+ if (data->u.runstate.state_entry_time !=
438+ (data->u.runstate.time_running +
439+ data->u.runstate.time_runnable +
440+ data->u.runstate.time_blocked +
441+ data->u.runstate.time_offline)) {
442+ r = -EINVAL;
443+ break;
444+ }
445+
446+ if (get_kvmclock_ns(vcpu->kvm) <
447+ (vcpu->arch.xen.runstate_entry_time +
448+ data->u.runstate.state_entry_time)) {
449+ r = -EINVAL;
450+ break;
451+ }
452+
453+ vcpu->arch.xen.runstate_entry_time +=
454+ data->u.runstate.state_entry_time;
455+ vcpu->arch.xen.runstate_times[RUNSTATE_running] +=
456+ data->u.runstate.time_running;
457+ vcpu->arch.xen.runstate_times[RUNSTATE_runnable] +=
458+ data->u.runstate.time_runnable;
459+ vcpu->arch.xen.runstate_times[RUNSTATE_blocked] +=
460+ data->u.runstate.time_blocked;
461+ vcpu->arch.xen.runstate_times[RUNSTATE_offline] +=
462+ data->u.runstate.time_offline;
463+
464+ if (data->u.runstate.state <= RUNSTATE_offline)
465+ kvm_xen_update_runstate(vcpu, data->u.runstate.state);
466+ r = 0;
467+ break;
468+
222469 default:
223470 break;
224471 }
@@ -251,6 +498,49 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 26 unmodified lines
251498 r = 0;
252499 break;
253500
501+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR:
502+ if (!sched_info_on()) {
503+ r = -EOPNOTSUPP;
504+ break;
505+ }
506+ if (vcpu->arch.xen.runstate_set) {
507+ data->u.gpa = vcpu->arch.xen.runstate_cache.gpa;
508+ r = 0;
509+ }
510+ break;
511+
512+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT:
513+ if (!sched_info_on()) {
514+ r = -EOPNOTSUPP;
515+ break;
516+ }
517+ data->u.runstate.state = vcpu->arch.xen.current_runstate;
518+ r = 0;
519+ break;
520+
521+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA:
522+ if (!sched_info_on()) {
523+ r = -EOPNOTSUPP;
524+ break;
525+ }
526+ data->u.runstate.state = vcpu->arch.xen.current_runstate;
527+ data->u.runstate.state_entry_time =
528+ vcpu->arch.xen.runstate_entry_time;
529+ data->u.runstate.time_running =
530+ vcpu->arch.xen.runstate_times[RUNSTATE_running];
531+ data->u.runstate.time_runnable =
532+ vcpu->arch.xen.runstate_times[RUNSTATE_runnable];
533+ data->u.runstate.time_blocked =
534+ vcpu->arch.xen.runstate_times[RUNSTATE_blocked];
535+ data->u.runstate.time_offline =
536+ vcpu->arch.xen.runstate_times[RUNSTATE_offline];
537+ r = 0;
538+ break;
539+
540+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST:
541+ r = -EINVAL;
542+ break;
543+
254544 default:
255545 break;
256546 }
arch/x86/kvm/xen.h+62−2
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #ifndef __ARCH_X86_KVM_XEN_H__
1010 #define __ARCH_X86_KVM_XEN_H__
1111
12+#ifdef CONFIG_KVM_XEN
1213 #include <linux/jump_label_ratelimit.h>
1314
1415 extern struct static_key_false_deferred kvm_xen_enabled;
@@ -18,11 +19,16 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 3 unmodified lines
1819 int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data);
1920 int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
2021 int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
21−int kvm_xen_hypercall(struct kvm_vcpu *vcpu);
2222 int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data);
2323 int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc);
2424 void kvm_xen_destroy_vm(struct kvm *kvm);
2525
26+static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
27+{
28+ return static_branch_unlikely(&kvm_xen_enabled.key) &&
29+ kvm->arch.xen_hvm_config.msr;
30+}
31+
2632 static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm)
2733 {
2834 return static_branch_unlikely(&kvm_xen_enabled.key) &&
@@ -38,11 +44,59 @@ static inline int kvm_xen_has_interrupt(struct kvm_vcpu *vcpu) · 9 unmodified lines
3844
3945 return 0;
4046 }
47+#else
48+static inline int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
49+{
50+ return 1;
51+}
52+
53+static inline void kvm_xen_destroy_vm(struct kvm *kvm)
54+{
55+}
56+
57+static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
58+{
59+ return false;
60+}
61+
62+static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm)
63+{
64+ return false;
65+}
66+
67+static inline int kvm_xen_has_interrupt(struct kvm_vcpu *vcpu)
68+{
69+ return 0;
70+}
71+#endif
72+
73+int kvm_xen_hypercall(struct kvm_vcpu *vcpu);
4174
42−/* 32-bit compatibility definitions, also used natively in 32-bit build */
4375 #include <asm/pvclock-abi.h>
4476 #include <asm/xen/interface.h>
77+#include <xen/interface/vcpu.h>
78+
79+void kvm_xen_update_runstate_guest(struct kvm_vcpu *vcpu, int state);
4580
81+static inline void kvm_xen_runstate_set_running(struct kvm_vcpu *vcpu)
82+{
83+ kvm_xen_update_runstate_guest(vcpu, RUNSTATE_running);
84+}
85+
86+static inline void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu)
87+{
88+ /*
89+ * If the vCPU wasn't preempted but took a normal exit for
90+ * some reason (hypercalls, I/O, etc.), that is accounted as
91+ * still RUNSTATE_running, as the VMM is still operating on
92+ * behalf of the vCPU. Only if the VMM does actually block
93+ * does it need to enter RUNSTATE_blocked.
94+ */
95+ if (vcpu->preempted)
96+ kvm_xen_update_runstate_guest(vcpu, RUNSTATE_runnable);
97+}
98+
99+/* 32-bit compatibility definitions, also used natively in 32-bit build */
46100 struct compat_arch_vcpu_info {
47101 unsigned int cr2;
48102 unsigned int pad[5];
@@ -75,4 +129,10 @@ struct compat_shared_info { · 26 unmodified lines
75129 struct compat_arch_shared_info arch;
76130 };
77131
132+struct compat_vcpu_runstate_info {
133+ int state;
134+ uint64_t state_entry_time;
135+ uint64_t time[4];
136+} __attribute__((packed));
137+
78138 #endif /* __ARCH_X86_KVM_XEN_H__ */
include/uapi/linux/kvm.h+13−0
@@ -1154,6 +1154,7 @@ struct kvm_x86_mce { · 1153 unmodified lines
11541154 #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0)
11551155 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
11561156 #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
1157+#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3)
11571158
11581159 struct kvm_xen_hvm_config {
11591160 __u32 flags;
@@ -1621,12 +1622,24 @@ struct kvm_xen_vcpu_attr { · 461 unmodified lines
16211622 union {
16221623 __u64 gpa;
16231624 __u64 pad[8];
1625+ struct {
1626+ __u64 state;
1627+ __u64 state_entry_time;
1628+ __u64 time_running;
1629+ __u64 time_runnable;
1630+ __u64 time_blocked;
1631+ __u64 time_offline;
1632+ } runstate;
16241633 } u;
16251634 };
16261635
16271636 /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
16281637 #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0
16291638 #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1
1639+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR 0x2
1640+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3
1641+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4
1642+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
16301643
16311644 /* Secure Encrypted Virtualization command */
16321645 enum sev_cmd_id {
tools/testing/selftests/kvm/lib/kvm_util.c+4−2
@@ -21,6 +21,8 @@ · 20 unmodified lines
2121 #define KVM_UTIL_PGS_PER_HUGEPG 512
2222 #define KVM_UTIL_MIN_PFN 2
2323
24+static int vcpu_mmap_sz(void);
25+
2426 /* Aligns x up to the next multiple of size. Size must be a power of 2. */
2527 static void *align(void *x, size_t size)
2628 {
@@ -509,7 +511,7 @@ static void vm_vcpu_rm(struct kvm_vm *vm, struct vcpu *vcpu) · 482 unmodified lines
509511 vcpu->dirty_gfns = NULL;
510512 }
511513
512− ret = munmap(vcpu->state, sizeof(*vcpu->state));
514+ ret = munmap(vcpu->state, vcpu_mmap_sz());
513515 TEST_ASSERT(ret == 0, "munmap of VCPU fd failed, rc: %i "
514516 "errno: %i", ret, errno);
515517 close(vcpu->fd);
@@ -978,7 +980,7 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid) · 462 unmodified lines
978980 TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->state), "vcpu mmap size "
979981 "smaller than expected, vcpu_mmap_sz: %i expected_min: %zi",
980982 vcpu_mmap_sz(), sizeof(*vcpu->state));
981− vcpu->state = (struct kvm_run *) mmap(NULL, sizeof(*vcpu->state),
983+ vcpu->state = (struct kvm_run *) mmap(NULL, vcpu_mmap_sz(),
982984 PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0);
983985 TEST_ASSERT(vcpu->state != MAP_FAILED, "mmap vcpu_state failed, "
984986 "vcpu id: %u errno: %i", vcpuid, errno);
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c+156−3
@@ -13,19 +13,27 @@ · 12 unmodified lines
1313
1414 #include <stdint.h>
1515 #include <time.h>
16+#include <sched.h>
17+#include <sys/syscall.h>
1618
1719 #define VCPU_ID 5
1820
21+#define SHINFO_REGION_GVA 0xc0000000ULL
1922 #define SHINFO_REGION_GPA 0xc0000000ULL
2023 #define SHINFO_REGION_SLOT 10
2124 #define PAGE_SIZE 4096
2225
2326 #define PVTIME_ADDR (SHINFO_REGION_GPA + PAGE_SIZE)
27+#define RUNSTATE_ADDR (SHINFO_REGION_GPA + PAGE_SIZE + 0x20)
28+
29+#define RUNSTATE_VADDR (SHINFO_REGION_GVA + PAGE_SIZE + 0x20)
2430
2531 static struct kvm_vm *vm;
2632
2733 #define XEN_HYPERCALL_MSR 0x40000000
2834
35+#define MIN_STEAL_TIME 50000
36+
2937 struct pvclock_vcpu_time_info {
3038 u32 version;
3139 u32 pad0;
@@ -43,11 +51,67 @@ struct pvclock_wall_clock { · 11 unmodified lines
4351 u32 nsec;
4452 } __attribute__((__packed__));
4553
54+struct vcpu_runstate_info {
55+ uint32_t state;
56+ uint64_t state_entry_time;
57+ uint64_t time[4];
58+};
59+
60+#define RUNSTATE_running 0
61+#define RUNSTATE_runnable 1
62+#define RUNSTATE_blocked 2
63+#define RUNSTATE_offline 3
64+
4665 static void guest_code(void)
4766 {
67+ struct vcpu_runstate_info *rs = (void *)RUNSTATE_VADDR;
68+
69+ /* Test having the host set runstates manually */
70+ GUEST_SYNC(RUNSTATE_runnable);
71+ GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0);
72+ GUEST_ASSERT(rs->state == 0);
73+
74+ GUEST_SYNC(RUNSTATE_blocked);
75+ GUEST_ASSERT(rs->time[RUNSTATE_blocked] != 0);
76+ GUEST_ASSERT(rs->state == 0);
77+
78+ GUEST_SYNC(RUNSTATE_offline);
79+ GUEST_ASSERT(rs->time[RUNSTATE_offline] != 0);
80+ GUEST_ASSERT(rs->state == 0);
81+
82+ /* Test runstate time adjust */
83+ GUEST_SYNC(4);
84+ GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x5a);
85+ GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x6b6b);
86+
87+ /* Test runstate time set */
88+ GUEST_SYNC(5);
89+ GUEST_ASSERT(rs->state_entry_time >= 0x8000);
90+ GUEST_ASSERT(rs->time[RUNSTATE_runnable] == 0);
91+ GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x6b6b);
92+ GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x5a);
93+
94+ /* sched_yield() should result in some 'runnable' time */
95+ GUEST_SYNC(6);
96+ GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME);
97+
4898 GUEST_DONE();
4999 }
50100
101+static long get_run_delay(void)
102+{
103+ char path[64];
104+ long val[2];
105+ FILE *fp;
106+
107+ sprintf(path, "/proc/%ld/schedstat", syscall(SYS_gettid));
108+ fp = fopen(path, "r");
109+ fscanf(fp, "%ld %ld ", &val[0], &val[1]);
110+ fclose(fp);
111+
112+ return val[1];
113+}
114+
51115 static int cmp_timespec(struct timespec *a, struct timespec *b)
52116 {
53117 if (a->tv_sec > b->tv_sec)
@@ -66,12 +130,14 @@ int main(int argc, char *argv[]) · 12 unmodified lines
66130 {
67131 struct timespec min_ts, max_ts, vm_ts;
68132
69− if (!(kvm_check_cap(KVM_CAP_XEN_HVM) &
70− KVM_XEN_HVM_CONFIG_SHARED_INFO) ) {
133+ int xen_caps = kvm_check_cap(KVM_CAP_XEN_HVM);
134+ if (!(xen_caps & KVM_XEN_HVM_CONFIG_SHARED_INFO) ) {
71135 print_skip("KVM_XEN_HVM_CONFIG_SHARED_INFO not available");
72136 exit(KSFT_SKIP);
73137 }
74138
139+ bool do_runstate_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_RUNSTATE);
140+
75141 clock_gettime(CLOCK_REALTIME, &min_ts);
76142
77143 vm = vm_create_default(VCPU_ID, 0, (void *) guest_code);
@@ -80,6 +146,7 @@ int main(int argc, char *argv[]) · 2 unmodified lines
80146 /* Map a region for the shared_info page */
81147 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
82148 SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0);
149+ virt_map(vm, SHINFO_REGION_GVA, SHINFO_REGION_GPA, 2, 0);
83150
84151 struct kvm_xen_hvm_config hvmc = {
85152 .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
@@ -111,6 +178,17 @@ int main(int argc, char *argv[]) · 25 unmodified lines
111178 };
112179 vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &pvclock);
113180
181+ if (do_runstate_tests) {
182+ struct kvm_xen_vcpu_attr st = {
183+ .type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR,
184+ .u.gpa = RUNSTATE_ADDR,
185+ };
186+ vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &st);
187+ }
188+
189+ struct vcpu_runstate_info *rs = addr_gpa2hva(vm, RUNSTATE_ADDR);;
190+ rs->state = 0x5a;
191+
114192 for (;;) {
115193 volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
116194 struct ucall uc;
@@ -126,8 +204,56 @@ int main(int argc, char *argv[]) · 9 unmodified lines
126204 case UCALL_ABORT:
127205 TEST_FAIL("%s", (const char *)uc.args[0]);
128206 /* NOT REACHED */
129− case UCALL_SYNC:
207+ case UCALL_SYNC: {
208+ struct kvm_xen_vcpu_attr rst;
209+ long rundelay;
210+
211+ /* If no runstate support, bail out early */
212+ if (!do_runstate_tests)
213+ goto done;
214+
215+ TEST_ASSERT(rs->state_entry_time == rs->time[0] +
216+ rs->time[1] + rs->time[2] + rs->time[3],
217+ "runstate times don't add up");
218+
219+ switch (uc.args[1]) {
220+ case RUNSTATE_running...RUNSTATE_offline:
221+ rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT;
222+ rst.u.runstate.state = uc.args[1];
223+ vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &rst);
224+ break;
225+ case 4:
226+ rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST;
227+ memset(&rst.u, 0, sizeof(rst.u));
228+ rst.u.runstate.state = (uint64_t)-1;
229+ rst.u.runstate.time_blocked =
230+ 0x5a - rs->time[RUNSTATE_blocked];
231+ rst.u.runstate.time_offline =
232+ 0x6b6b - rs->time[RUNSTATE_offline];
233+ rst.u.runstate.time_runnable = -rst.u.runstate.time_blocked -
234+ rst.u.runstate.time_offline;
235+ vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &rst);
236+ break;
237+
238+ case 5:
239+ rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA;
240+ memset(&rst.u, 0, sizeof(rst.u));
241+ rst.u.runstate.state = RUNSTATE_running;
242+ rst.u.runstate.state_entry_time = 0x6b6b + 0x5a;
243+ rst.u.runstate.time_blocked = 0x6b6b;
244+ rst.u.runstate.time_offline = 0x5a;
245+ vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &rst);
246+ break;
247+ case 6:
248+ /* Yield until scheduler delay exceeds target */
249+ rundelay = get_run_delay() + MIN_STEAL_TIME;
250+ do {
251+ sched_yield();
252+ } while (get_run_delay() < rundelay);
253+ break;
254+ }
130255 break;
256+ }
131257 case UCALL_DONE:
132258 goto done;
133259 default:
@@ -162,6 +288,33 @@ int main(int argc, char *argv[]) · 28 unmodified lines
162288 TEST_ASSERT(ti2->version && !(ti2->version & 1),
163289 "Bad time_info version %x", ti->version);
164290
291+ if (do_runstate_tests) {
292+ /*
293+ * Fetch runstate and check sanity. Strictly speaking in the
294+ * general case we might not expect the numbers to be identical
295+ * but in this case we know we aren't running the vCPU any more.
296+ */
297+ struct kvm_xen_vcpu_attr rst = {
298+ .type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA,
299+ };
300+ vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_GET_ATTR, &rst);
301+
302+ TEST_ASSERT(rs->state == rst.u.runstate.state, "Runstate mismatch");
303+ TEST_ASSERT(rs->state_entry_time == rst.u.runstate.state_entry_time,
304+ "State entry time mismatch");
305+ TEST_ASSERT(rs->time[RUNSTATE_running] == rst.u.runstate.time_running,
306+ "Running time mismatch");
307+ TEST_ASSERT(rs->time[RUNSTATE_runnable] == rst.u.runstate.time_runnable,
308+ "Runnable time mismatch");
309+ TEST_ASSERT(rs->time[RUNSTATE_blocked] == rst.u.runstate.time_blocked,
310+ "Blocked time mismatch");
311+ TEST_ASSERT(rs->time[RUNSTATE_offline] == rst.u.runstate.time_offline,
312+ "Offline time mismatch");
313+
314+ TEST_ASSERT(rs->state_entry_time == rs->time[0] +
315+ rs->time[1] + rs->time[2] + rs->time[3],
316+ "runstate times don't add up");
317+ }
165318 kvm_vm_free(vm);
166319 return 0;
167320 }