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
Unified · Split
| @@ -3856,49 +3856,20 @@ base 2 of the page size in the bottom 6 bits. · 3855 unmodified lines | |||
| 3856 | -EFAULT if struct kvm_reinject_control cannot be read, | 3856 | -EFAULT if struct kvm_reinject_control cannot be read, |
| 3857 | -EINVAL if the supplied shift or flags are invalid, | 3857 | -EINVAL if the supplied shift or flags are invalid, |
| 3858 | -ENOMEM if unable to allocate the new HPT, | 3858 | -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 | ||
| 3896 | 3859 | ||
| 3897 | Used to implement the PAPR extension for runtime resizing of a guest's | 3860 | Used to implement the PAPR extension for runtime resizing of a guest's |
| 3898 | Hashed Page Table (HPT). Specifically this starts, stops or monitors | 3861 | Hashed Page Table (HPT). Specifically this starts, stops or monitors |
| 3899 | the preparation of a new potential HPT for the guest, essentially | 3862 | the preparation of a new potential HPT for the guest, essentially |
| 3900 | implementing the H_RESIZE_HPT_PREPARE hypercall. | 3863 | implementing the H_RESIZE_HPT_PREPARE hypercall. |
| 3901 | 3864 | ||
| 3865 | :: | ||
| 3866 | |||
| 3867 | struct kvm_ppc_resize_hpt { | ||
| 3868 | __u64 flags; | ||
| 3869 | __u32 shift; | ||
| 3870 | __u32 pad; | ||
| 3871 | }; | ||
| 3872 | |||
| 3902 | If called with shift > 0 when there is no pending HPT for the guest, | 3873 | If called with shift > 0 when there is no pending HPT for the guest, |
| 3903 | this begins preparation of a new pending HPT of size 2^(shift) bytes. | 3874 | this begins preparation of a new pending HPT of size 2^(shift) bytes. |
| 3904 | It then returns a positive integer with the estimated number of | 3875 | 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 | |||
| 3926 | it returns <= 0. The first call will initiate preparation, subsequent | 3897 | it returns <= 0. The first call will initiate preparation, subsequent |
| 3927 | ones will monitor preparation until it completes or fails. | 3898 | ones will monitor preparation until it completes or fails. |
| 3928 | 3899 | ||
| 3929 | :: | ||
| 3930 | |||
| 3931 | struct kvm_ppc_resize_hpt { | ||
| 3932 | __u64 flags; | ||
| 3933 | __u32 shift; | ||
| 3934 | __u32 pad; | ||
| 3935 | }; | ||
| 3936 | |||
| 3937 | 4.103 KVM_PPC_RESIZE_HPT_COMMIT | 3900 | 4.103 KVM_PPC_RESIZE_HPT_COMMIT |
| 3938 | ------------------------------- | 3901 | ------------------------------- |
| 3939 | 3902 | ||
| @@ -3956,6 +3919,14 @@ Hashed Page Table (HPT). Specifically this requests that the guest be · 16 unmodified lines | |||
| 3956 | transferred to working with the new HPT, essentially implementing the | 3919 | transferred to working with the new HPT, essentially implementing the |
| 3957 | H_RESIZE_HPT_COMMIT hypercall. | 3920 | H_RESIZE_HPT_COMMIT hypercall. |
| 3958 | 3921 | ||
| 3922 | :: | ||
| 3923 | |||
| 3924 | struct kvm_ppc_resize_hpt { | ||
| 3925 | __u64 flags; | ||
| 3926 | __u32 shift; | ||
| 3927 | __u32 pad; | ||
| 3928 | }; | ||
| 3929 | |||
| 3959 | This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has | 3930 | This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has |
| 3960 | returned 0 with the same parameters. In other cases | 3931 | returned 0 with the same parameters. In other cases |
| 3961 | KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or | 3932 | 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 | |||
| 3971 | 3942 | ||
| 3972 | On failure, the guest will still be operating on its previous HPT. | 3943 | On failure, the guest will still be operating on its previous HPT. |
| 3973 | 3944 | ||
| 3974 | :: | ||
| 3975 | |||
| 3976 | struct kvm_ppc_resize_hpt { | ||
| 3977 | __u64 flags; | ||
| 3978 | __u32 shift; | ||
| 3979 | __u32 pad; | ||
| 3980 | }; | ||
| 3981 | |||
| 3982 | 4.104 KVM_X86_GET_MCE_CAP_SUPPORTED | 3945 | 4.104 KVM_X86_GET_MCE_CAP_SUPPORTED |
| 3983 | ----------------------------------- | 3946 | ----------------------------------- |
| 3984 | 3947 | ||
| @@ -4915,6 +4878,14 @@ see KVM_XEN_HVM_SET_ATTR above. · 930 unmodified lines | |||
| 4915 | union { | 4878 | union { |
| 4916 | __u64 gpa; | 4879 | __u64 gpa; |
| 4917 | __u64 pad[4]; | 4880 | __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; | ||
| 4918 | } u; | 4889 | } u; |
| 4919 | }; | 4890 | }; |
| 4920 | 4891 | ||
| @@ -4927,6 +4898,31 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO · 6 unmodified lines | |||
| 4927 | Sets the guest physical address of an additional pvclock structure | 4898 | Sets the guest physical address of an additional pvclock structure |
| 4928 | for a given vCPU. This is typically used for guest vsyscall support. | 4899 | for a given vCPU. This is typically used for guest vsyscall support. |
| 4929 | 4900 | ||
| 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 | |||
| 4930 | 4.130 KVM_XEN_VCPU_GET_ATTR | 4926 | 4.130 KVM_XEN_VCPU_GET_ATTR |
| 4931 | --------------------------- | 4927 | --------------------------- |
| 4932 | 4928 | ||
| @@ -4939,6 +4935,9 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO · 6 unmodified lines | |||
| 4939 | Allows Xen vCPU attributes to be read. For the structure and types, | 4935 | Allows Xen vCPU attributes to be read. For the structure and types, |
| 4940 | see KVM_XEN_VCPU_SET_ATTR above. | 4936 | see KVM_XEN_VCPU_SET_ATTR above. |
| 4941 | 4937 | ||
| 4938 | The KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST type may not be used | ||
| 4939 | with the KVM_XEN_VCPU_GET_ATTR ioctl. | ||
| 4940 | |||
| 4942 | 5. The kvm_run structure | 4941 | 5. The kvm_run structure |
| 4943 | ======================== | 4942 | ======================== |
| 4944 | 4943 | ||
| @@ -5000,7 +4999,8 @@ local APIC is not used. · 55 unmodified lines | |||
| 5000 | __u16 flags; | 4999 | __u16 flags; |
| 5001 | 5000 | ||
| 5002 | More architecture-specific flags detailing state of the VCPU that may | 5001 | 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 | |||
| 5004 | /* x86, set if the VCPU is in system management mode */ | 5004 | /* x86, set if the VCPU is in system management mode */ |
| 5005 | #define KVM_RUN_X86_SMM (1 << 0) | 5005 | #define KVM_RUN_X86_SMM (1 << 0) |
| 5006 | /* x86, set if bus lock detected in VM */ | 5006 | /* 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 | |||
| 6217 | notifications to userspace can be KVM_EXIT_BUS_LOCK or other reasons. | 6217 | notifications to userspace can be KVM_EXIT_BUS_LOCK or other reasons. |
| 6218 | KVM_RUN_BUS_LOCK flag is used to distinguish between them. | 6218 | KVM_RUN_BUS_LOCK flag is used to distinguish between them. |
| 6219 | 6219 | ||
| 6220 | 7.22 KVM_CAP_PPC_DAWR1 | 6220 | 7.23 KVM_CAP_PPC_DAWR1 |
| 6221 | ---------------------- | 6221 | ---------------------- |
| 6222 | 6222 | ||
| 6223 | :Architectures: ppc | 6223 | :Architectures: ppc |
| @@ -6702,6 +6702,7 @@ PVHVM guests. Valid flags are:: · 478 unmodified lines | |||
| 6702 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) | 6702 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) |
| 6703 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) | 6703 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) |
| 6704 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) | 6704 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) |
| 6705 | #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 2) | ||
| 6705 | 6706 | ||
| 6706 | The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG | 6707 | The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG |
| 6707 | ioctl is available, for the guest to set its hypercall page. | 6708 | 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 | |||
| 6716 | KVM_XEN_VCPU_GET_ATTR ioctls, as well as the delivery of exception vectors | 6717 | KVM_XEN_VCPU_GET_ATTR ioctls, as well as the delivery of exception vectors |
| 6717 | for event channel upcalls when the evtchn_upcall_pending field of a vcpu's | 6718 | for event channel upcalls when the evtchn_upcall_pending field of a vcpu's |
| 6718 | vcpu_info is set. | 6719 | 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. | ||
| @@ -535,10 +535,16 @@ struct kvm_vcpu_hv { · 534 unmodified lines | |||
| 535 | /* Xen HVM per vcpu emulation context */ | 535 | /* Xen HVM per vcpu emulation context */ |
| 536 | struct kvm_vcpu_xen { | 536 | struct kvm_vcpu_xen { |
| 537 | u64 hypercall_rip; | 537 | u64 hypercall_rip; |
| 538 | u32 current_runstate; | ||
| 538 | bool vcpu_info_set; | 539 | bool vcpu_info_set; |
| 539 | bool vcpu_time_info_set; | 540 | bool vcpu_time_info_set; |
| 541 | bool runstate_set; | ||
| 540 | struct gfn_to_hva_cache vcpu_info_cache; | 542 | struct gfn_to_hva_cache vcpu_info_cache; |
| 541 | struct gfn_to_hva_cache vcpu_time_info_cache; | 543 | 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]; | ||
| 542 | }; | 548 | }; |
| 543 | 549 | ||
| 544 | struct kvm_vcpu_arch { | 550 | struct kvm_vcpu_arch { |
| @@ -939,9 +945,6 @@ struct kvm_arch { · 394 unmodified lines | |||
| 939 | unsigned int indirect_shadow_pages; | 945 | unsigned int indirect_shadow_pages; |
| 940 | u8 mmu_valid_gen; | 946 | u8 mmu_valid_gen; |
| 941 | struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; | 947 | struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; |
| 942 | /* | ||
| 943 | * Hash table of struct kvm_mmu_page. | ||
| 944 | */ | ||
| 945 | struct list_head active_mmu_pages; | 948 | struct list_head active_mmu_pages; |
| 946 | struct list_head zapped_obsolete_pages; | 949 | struct list_head zapped_obsolete_pages; |
| 947 | struct list_head lpage_disallowed_mmu_pages; | 950 | struct list_head lpage_disallowed_mmu_pages; |
| @@ -103,6 +103,15 @@ config KVM_AMD_SEV · 102 unmodified lines | |||
| 103 | Provides support for launching Encrypted VMs (SEV) and Encrypted VMs | 103 | Provides support for launching Encrypted VMs (SEV) and Encrypted VMs |
| 104 | with Encrypted State (SEV-ES) on AMD processors. | 104 | with Encrypted State (SEV-ES) on AMD processors. |
| 105 | 105 | ||
| 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 | |||
| 106 | config KVM_MMU_AUDIT | 115 | config KVM_MMU_AUDIT |
| 107 | bool "Audit KVM MMU" | 116 | bool "Audit KVM MMU" |
| 108 | depends on KVM && TRACEPOINTS | 117 | depends on KVM && TRACEPOINTS |
| @@ -14,11 +14,12 @@ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ · 13 unmodified lines | |||
| 14 | $(KVM)/dirty_ring.o | 14 | $(KVM)/dirty_ring.o |
| 15 | kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o | 15 | kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o |
| 16 | 16 | ||
| 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 \ |
| 18 | i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \ | 18 | i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \ |
| 19 | hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \ | 19 | hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \ |
| 20 | mmu/spte.o | 20 | mmu/spte.o |
| 21 | kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o | 21 | kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o |
| 22 | kvm-$(CONFIG_KVM_XEN) += xen.o | ||
| 22 | 23 | ||
| 23 | kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \ | 24 | kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \ |
| 24 | vmx/evmcs.o vmx/nested.o vmx/posted_intr.o | 25 | vmx/evmcs.o vmx/nested.o vmx/posted_intr.o |
| @@ -159,7 +159,7 @@ static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vpidx) · 158 unmodified lines | |||
| 159 | struct kvm_vcpu_hv_synic *synic; | 159 | struct kvm_vcpu_hv_synic *synic; |
| 160 | 160 | ||
| 161 | vcpu = get_vcpu_by_vpidx(kvm, vpidx); | 161 | vcpu = get_vcpu_by_vpidx(kvm, vpidx); |
| 162 | if (!vcpu) | 162 | if (!vcpu || !to_hv_vcpu(vcpu)) |
| 163 | return NULL; | 163 | return NULL; |
| 164 | synic = to_hv_synic(vcpu); | 164 | synic = to_hv_synic(vcpu); |
| 165 | return (synic->active) ? synic : NULL; | 165 | return (synic->active) ? synic : NULL; |
| @@ -81,15 +81,15 @@ static inline struct kvm_mmu_page *sptep_to_sp(u64 *sptep) · 80 unmodified lines | |||
| 81 | static inline bool kvm_vcpu_ad_need_write_protect(struct kvm_vcpu *vcpu) | 81 | static inline bool kvm_vcpu_ad_need_write_protect(struct kvm_vcpu *vcpu) |
| 82 | { | 82 | { |
| 83 | /* | 83 | /* |
| 84 | * When using the EPT page-modification log, the GPAs in the log | 84 | * When using the EPT page-modification log, the GPAs in the CPU dirty |
| 85 | * would come from L2 rather than L1. Therefore, we need to rely | 85 | * log would come from L2 rather than L1. Therefore, we need to rely |
| 86 | * on write protection to record dirty pages. This also bypasses | 86 | * on write protection to record dirty pages, which bypasses PML, since |
| 87 | * PML, since writes now result in a vmexit. Note, this helper will | 87 | * writes now result in a vmexit. Note, the check on CPU dirty logging |
| 88 | * tag SPTEs as needing write-protection even if PML is disabled or | 88 | * being enabled is mandatory as the bits used to denote WP-only SPTEs |
| 89 | * unsupported, but that's ok because the tag is consumed if and only | 89 | * are reserved for NPT w/ PAE (32-bit KVM). |
| 90 | * if PML is enabled. Omit the PML check to save a few uops. | ||
| 91 | */ | 90 | */ |
| 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; | ||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | bool is_nx_huge_page_enabled(void); | 95 | bool is_nx_huge_page_enabled(void); |
| @@ -1200,6 +1200,7 @@ static void init_vmcb(struct vcpu_svm *svm) · 1199 unmodified lines | |||
| 1200 | init_sys_seg(&save->ldtr, SEG_TYPE_LDT); | 1200 | init_sys_seg(&save->ldtr, SEG_TYPE_LDT); |
| 1201 | init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); | 1201 | init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); |
| 1202 | 1202 | ||
| 1203 | svm_set_cr4(&svm->vcpu, 0); | ||
| 1203 | svm_set_efer(&svm->vcpu, 0); | 1204 | svm_set_efer(&svm->vcpu, 0); |
| 1204 | save->dr6 = 0xffff0ff0; | 1205 | save->dr6 = 0xffff0ff0; |
| 1205 | kvm_set_rflags(&svm->vcpu, X86_EFLAGS_FIXED); | 1206 | kvm_set_rflags(&svm->vcpu, X86_EFLAGS_FIXED); |
| @@ -2957,6 +2957,11 @@ static void record_steal_time(struct kvm_vcpu *vcpu) · 2956 unmodified lines | |||
| 2957 | struct kvm_host_map map; | 2957 | struct kvm_host_map map; |
| 2958 | struct kvm_steal_time *st; | 2958 | struct kvm_steal_time *st; |
| 2959 | 2959 | ||
| 2960 | if (kvm_xen_msr_enabled(vcpu->kvm)) { | ||
| 2961 | kvm_xen_runstate_set_running(vcpu); | ||
| 2962 | return; | ||
| 2963 | } | ||
| 2964 | |||
| 2960 | if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) | 2965 | if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) |
| 2961 | return; | 2966 | return; |
| 2962 | 2967 | ||
| @@ -3756,11 +3761,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 793 unmodified lines | |||
| 3756 | case KVM_CAP_ENFORCE_PV_FEATURE_CPUID: | 3761 | case KVM_CAP_ENFORCE_PV_FEATURE_CPUID: |
| 3757 | r = 1; | 3762 | r = 1; |
| 3758 | break; | 3763 | break; |
| 3764 | #ifdef CONFIG_KVM_XEN | ||
| 3759 | case KVM_CAP_XEN_HVM: | 3765 | case KVM_CAP_XEN_HVM: |
| 3760 | r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | | 3766 | r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | |
| 3761 | KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | | 3767 | KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | |
| 3762 | KVM_XEN_HVM_CONFIG_SHARED_INFO; | 3768 | KVM_XEN_HVM_CONFIG_SHARED_INFO; |
| 3769 | if (sched_info_on()) | ||
| 3770 | r |= KVM_XEN_HVM_CONFIG_RUNSTATE; | ||
| 3763 | break; | 3771 | break; |
| 3772 | #endif | ||
| 3764 | case KVM_CAP_SYNC_REGS: | 3773 | case KVM_CAP_SYNC_REGS: |
| 3765 | r = KVM_SYNC_X86_VALID_FIELDS; | 3774 | r = KVM_SYNC_X86_VALID_FIELDS; |
| 3766 | break; | 3775 | break; |
| @@ -4038,7 +4047,11 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) · 271 unmodified lines | |||
| 4038 | if (vcpu->preempted && !vcpu->arch.guest_state_protected) | 4047 | if (vcpu->preempted && !vcpu->arch.guest_state_protected) |
| 4039 | vcpu->arch.preempted_in_kernel = !static_call(kvm_x86_get_cpl)(vcpu); | 4048 | vcpu->arch.preempted_in_kernel = !static_call(kvm_x86_get_cpl)(vcpu); |
| 4040 | 4049 | ||
| 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 | |||
| 4042 | static_call(kvm_x86_vcpu_put)(vcpu); | 4055 | static_call(kvm_x86_vcpu_put)(vcpu); |
| 4043 | vcpu->arch.last_host_tsc = rdtsc(); | 4056 | vcpu->arch.last_host_tsc = rdtsc(); |
| 4044 | /* | 4057 | /* |
| @@ -5013,6 +5026,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 968 unmodified lines | |||
| 5013 | case KVM_GET_SUPPORTED_HV_CPUID: | 5026 | case KVM_GET_SUPPORTED_HV_CPUID: |
| 5014 | r = kvm_ioctl_get_supported_hv_cpuid(vcpu, argp); | 5027 | r = kvm_ioctl_get_supported_hv_cpuid(vcpu, argp); |
| 5015 | break; | 5028 | break; |
| 5029 | #ifdef CONFIG_KVM_XEN | ||
| 5016 | case KVM_XEN_VCPU_GET_ATTR: { | 5030 | case KVM_XEN_VCPU_GET_ATTR: { |
| 5017 | struct kvm_xen_vcpu_attr xva; | 5031 | struct kvm_xen_vcpu_attr xva; |
| 5018 | 5032 | ||
| @@ -5033,6 +5047,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 14 unmodified lines | |||
| 5033 | r = kvm_xen_vcpu_set_attr(vcpu, &xva); | 5047 | r = kvm_xen_vcpu_set_attr(vcpu, &xva); |
| 5034 | break; | 5048 | break; |
| 5035 | } | 5049 | } |
| 5050 | #endif | ||
| 5036 | default: | 5051 | default: |
| 5037 | r = -EINVAL; | 5052 | r = -EINVAL; |
| 5038 | } | 5053 | } |
| @@ -5654,6 +5669,7 @@ set_pit2_out: · 615 unmodified lines | |||
| 5654 | kvm->arch.bsp_vcpu_id = arg; | 5669 | kvm->arch.bsp_vcpu_id = arg; |
| 5655 | mutex_unlock(&kvm->lock); | 5670 | mutex_unlock(&kvm->lock); |
| 5656 | break; | 5671 | break; |
| 5672 | #ifdef CONFIG_KVM_XEN | ||
| 5657 | case KVM_XEN_HVM_CONFIG: { | 5673 | case KVM_XEN_HVM_CONFIG: { |
| 5658 | struct kvm_xen_hvm_config xhc; | 5674 | struct kvm_xen_hvm_config xhc; |
| 5659 | r = -EFAULT; | 5675 | r = -EFAULT; |
| @@ -5682,6 +5698,7 @@ set_pit2_out: · 22 unmodified lines | |||
| 5682 | r = kvm_xen_hvm_set_attr(kvm, &xha); | 5698 | r = kvm_xen_hvm_set_attr(kvm, &xha); |
| 5683 | break; | 5699 | break; |
| 5684 | } | 5700 | } |
| 5701 | #endif | ||
| 5685 | case KVM_SET_CLOCK: { | 5702 | case KVM_SET_CLOCK: { |
| 5686 | struct kvm_clock_data user_ns; | 5703 | struct kvm_clock_data user_ns; |
| 5687 | u64 now_ns; | 5704 | u64 now_ns; |
| @@ -8040,7 +8057,10 @@ void kvm_arch_exit(void) · 2352 unmodified lines | |||
| 8040 | kvm_mmu_module_exit(); | 8057 | kvm_mmu_module_exit(); |
| 8041 | free_percpu(user_return_msrs); | 8058 | free_percpu(user_return_msrs); |
| 8042 | kmem_cache_destroy(x86_fpu_cache); | 8059 | kmem_cache_destroy(x86_fpu_cache); |
| 8060 | #ifdef CONFIG_KVM_XEN | ||
| 8061 | static_key_deferred_flush(&kvm_xen_enabled); | ||
| 8043 | WARN_ON(static_branch_unlikely(&kvm_xen_enabled.key)); | 8062 | WARN_ON(static_branch_unlikely(&kvm_xen_enabled.key)); |
| 8063 | #endif | ||
| 8044 | } | 8064 | } |
| 8045 | 8065 | ||
| 8046 | static int __kvm_vcpu_halt(struct kvm_vcpu *vcpu, int state, int reason) | 8066 | static int __kvm_vcpu_halt(struct kvm_vcpu *vcpu, int state, int reason) |
| @@ -11,9 +11,11 @@ · 10 unmodified lines | |||
| 11 | #include "hyperv.h" | 11 | #include "hyperv.h" |
| 12 | 12 | ||
| 13 | #include <linux/kvm_host.h> | 13 | #include <linux/kvm_host.h> |
| 14 | #include <linux/sched/stat.h> | ||
| 14 | 15 | ||
| 15 | #include <trace/events/kvm.h> | 16 | #include <trace/events/kvm.h> |
| 16 | #include <xen/interface/xen.h> | 17 | #include <xen/interface/xen.h> |
| 18 | #include <xen/interface/vcpu.h> | ||
| 17 | 19 | ||
| 18 | #include "trace.h" | 20 | #include "trace.h" |
| 19 | 21 | ||
| @@ -61,6 +63,132 @@ out: · 41 unmodified lines | |||
| 61 | return ret; | 63 | return ret; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 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 | |||
| 64 | int __kvm_xen_has_interrupt(struct kvm_vcpu *v) | 192 | int __kvm_xen_has_interrupt(struct kvm_vcpu *v) |
| 65 | { | 193 | { |
| 66 | u8 rc = 0; | 194 | 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 | |||
| 187 | /* No compat necessary here. */ | 315 | /* No compat necessary here. */ |
| 188 | BUILD_BUG_ON(sizeof(struct vcpu_info) != | 316 | BUILD_BUG_ON(sizeof(struct vcpu_info) != |
| 189 | sizeof(struct compat_vcpu_info)); | 317 | sizeof(struct compat_vcpu_info)); |
| 318 | BUILD_BUG_ON(offsetof(struct vcpu_info, time) != | ||
| 319 | offsetof(struct compat_vcpu_info, time)); | ||
| 190 | 320 | ||
| 191 | if (data->u.gpa == GPA_INVALID) { | 321 | if (data->u.gpa == GPA_INVALID) { |
| 192 | vcpu->arch.xen.vcpu_info_set = false; | 322 | vcpu->arch.xen.vcpu_info_set = false; |
| 323 | r = 0; | ||
| 193 | break; | 324 | break; |
| 194 | } | 325 | } |
| 195 | 326 | ||
| @@ -206,6 +337,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 10 unmodified lines | |||
| 206 | case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO: | 337 | case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO: |
| 207 | if (data->u.gpa == GPA_INVALID) { | 338 | if (data->u.gpa == GPA_INVALID) { |
| 208 | vcpu->arch.xen.vcpu_time_info_set = false; | 339 | vcpu->arch.xen.vcpu_time_info_set = false; |
| 340 | r = 0; | ||
| 209 | break; | 341 | break; |
| 210 | } | 342 | } |
| 211 | 343 | ||
| @@ -219,6 +351,121 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 7 unmodified lines | |||
| 219 | } | 351 | } |
| 220 | break; | 352 | break; |
| 221 | 353 | ||
| 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 | |||
| 222 | default: | 469 | default: |
| 223 | break; | 470 | break; |
| 224 | } | 471 | } |
| @@ -251,6 +498,49 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) · 26 unmodified lines | |||
| 251 | r = 0; | 498 | r = 0; |
| 252 | break; | 499 | break; |
| 253 | 500 | ||
| 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 | |||
| 254 | default: | 544 | default: |
| 255 | break; | 545 | break; |
| 256 | } | 546 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #ifndef __ARCH_X86_KVM_XEN_H__ | 9 | #ifndef __ARCH_X86_KVM_XEN_H__ |
| 10 | #define __ARCH_X86_KVM_XEN_H__ | 10 | #define __ARCH_X86_KVM_XEN_H__ |
| 11 | 11 | ||
| 12 | #ifdef CONFIG_KVM_XEN | ||
| 12 | #include <linux/jump_label_ratelimit.h> | 13 | #include <linux/jump_label_ratelimit.h> |
| 13 | 14 | ||
| 14 | extern struct static_key_false_deferred kvm_xen_enabled; | 15 | 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 | |||
| 18 | int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data); | 19 | int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data); |
| 19 | int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); | 20 | int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); |
| 20 | int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); | 21 | int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); |
| 21 | int kvm_xen_hypercall(struct kvm_vcpu *vcpu); | ||
| 22 | int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data); | 22 | int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data); |
| 23 | int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc); | 23 | int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc); |
| 24 | void kvm_xen_destroy_vm(struct kvm *kvm); | 24 | void kvm_xen_destroy_vm(struct kvm *kvm); |
| 25 | 25 | ||
| 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 | |||
| 26 | static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) | 32 | static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) |
| 27 | { | 33 | { |
| 28 | return static_branch_unlikely(&kvm_xen_enabled.key) && | 34 | 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 | |||
| 38 | 44 | ||
| 39 | return 0; | 45 | return 0; |
| 40 | } | 46 | } |
| 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); | ||
| 41 | 74 | ||
| 42 | /* 32-bit compatibility definitions, also used natively in 32-bit build */ | ||
| 43 | #include <asm/pvclock-abi.h> | 75 | #include <asm/pvclock-abi.h> |
| 44 | #include <asm/xen/interface.h> | 76 | #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); | ||
| 45 | 80 | ||
| 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 */ | ||
| 46 | struct compat_arch_vcpu_info { | 100 | struct compat_arch_vcpu_info { |
| 47 | unsigned int cr2; | 101 | unsigned int cr2; |
| 48 | unsigned int pad[5]; | 102 | unsigned int pad[5]; |
| @@ -75,4 +129,10 @@ struct compat_shared_info { · 26 unmodified lines | |||
| 75 | struct compat_arch_shared_info arch; | 129 | struct compat_arch_shared_info arch; |
| 76 | }; | 130 | }; |
| 77 | 131 | ||
| 132 | struct compat_vcpu_runstate_info { | ||
| 133 | int state; | ||
| 134 | uint64_t state_entry_time; | ||
| 135 | uint64_t time[4]; | ||
| 136 | } __attribute__((packed)); | ||
| 137 | |||
| 78 | #endif /* __ARCH_X86_KVM_XEN_H__ */ | 138 | #endif /* __ARCH_X86_KVM_XEN_H__ */ |
| @@ -1154,6 +1154,7 @@ struct kvm_x86_mce { · 1153 unmodified lines | |||
| 1154 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) | 1154 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) |
| 1155 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) | 1155 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) |
| 1156 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) | 1156 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) |
| 1157 | #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) | ||
| 1157 | 1158 | ||
| 1158 | struct kvm_xen_hvm_config { | 1159 | struct kvm_xen_hvm_config { |
| 1159 | __u32 flags; | 1160 | __u32 flags; |
| @@ -1621,12 +1622,24 @@ struct kvm_xen_vcpu_attr { · 461 unmodified lines | |||
| 1621 | union { | 1622 | union { |
| 1622 | __u64 gpa; | 1623 | __u64 gpa; |
| 1623 | __u64 pad[8]; | 1624 | __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; | ||
| 1624 | } u; | 1633 | } u; |
| 1625 | }; | 1634 | }; |
| 1626 | 1635 | ||
| 1627 | /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ | 1636 | /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ |
| 1628 | #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 | 1637 | #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 |
| 1629 | #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1 | 1638 | #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 | ||
| 1630 | 1643 | ||
| 1631 | /* Secure Encrypted Virtualization command */ | 1644 | /* Secure Encrypted Virtualization command */ |
| 1632 | enum sev_cmd_id { | 1645 | enum sev_cmd_id { |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | |||
| 21 | #define KVM_UTIL_PGS_PER_HUGEPG 512 | 21 | #define KVM_UTIL_PGS_PER_HUGEPG 512 |
| 22 | #define KVM_UTIL_MIN_PFN 2 | 22 | #define KVM_UTIL_MIN_PFN 2 |
| 23 | 23 | ||
| 24 | static int vcpu_mmap_sz(void); | ||
| 25 | |||
| 24 | /* Aligns x up to the next multiple of size. Size must be a power of 2. */ | 26 | /* Aligns x up to the next multiple of size. Size must be a power of 2. */ |
| 25 | static void *align(void *x, size_t size) | 27 | static void *align(void *x, size_t size) |
| 26 | { | 28 | { |
| @@ -509,7 +511,7 @@ static void vm_vcpu_rm(struct kvm_vm *vm, struct vcpu *vcpu) · 482 unmodified lines | |||
| 509 | vcpu->dirty_gfns = NULL; | 511 | vcpu->dirty_gfns = NULL; |
| 510 | } | 512 | } |
| 511 | 513 | ||
| 512 | ret = munmap(vcpu->state, sizeof(*vcpu->state)); | 514 | ret = munmap(vcpu->state, vcpu_mmap_sz()); |
| 513 | TEST_ASSERT(ret == 0, "munmap of VCPU fd failed, rc: %i " | 515 | TEST_ASSERT(ret == 0, "munmap of VCPU fd failed, rc: %i " |
| 514 | "errno: %i", ret, errno); | 516 | "errno: %i", ret, errno); |
| 515 | close(vcpu->fd); | 517 | close(vcpu->fd); |
| @@ -978,7 +980,7 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid) · 462 unmodified lines | |||
| 978 | TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->state), "vcpu mmap size " | 980 | TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->state), "vcpu mmap size " |
| 979 | "smaller than expected, vcpu_mmap_sz: %i expected_min: %zi", | 981 | "smaller than expected, vcpu_mmap_sz: %i expected_min: %zi", |
| 980 | vcpu_mmap_sz(), sizeof(*vcpu->state)); | 982 | 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(), |
| 982 | PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0); | 984 | PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0); |
| 983 | TEST_ASSERT(vcpu->state != MAP_FAILED, "mmap vcpu_state failed, " | 985 | TEST_ASSERT(vcpu->state != MAP_FAILED, "mmap vcpu_state failed, " |
| 984 | "vcpu id: %u errno: %i", vcpuid, errno); | 986 | "vcpu id: %u errno: %i", vcpuid, errno); |
| @@ -13,19 +13,27 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #include <stdint.h> | 14 | #include <stdint.h> |
| 15 | #include <time.h> | 15 | #include <time.h> |
| 16 | #include <sched.h> | ||
| 17 | #include <sys/syscall.h> | ||
| 16 | 18 | ||
| 17 | #define VCPU_ID 5 | 19 | #define VCPU_ID 5 |
| 18 | 20 | ||
| 21 | #define SHINFO_REGION_GVA 0xc0000000ULL | ||
| 19 | #define SHINFO_REGION_GPA 0xc0000000ULL | 22 | #define SHINFO_REGION_GPA 0xc0000000ULL |
| 20 | #define SHINFO_REGION_SLOT 10 | 23 | #define SHINFO_REGION_SLOT 10 |
| 21 | #define PAGE_SIZE 4096 | 24 | #define PAGE_SIZE 4096 |
| 22 | 25 | ||
| 23 | #define PVTIME_ADDR (SHINFO_REGION_GPA + PAGE_SIZE) | 26 | #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) | ||
| 24 | 30 | ||
| 25 | static struct kvm_vm *vm; | 31 | static struct kvm_vm *vm; |
| 26 | 32 | ||
| 27 | #define XEN_HYPERCALL_MSR 0x40000000 | 33 | #define XEN_HYPERCALL_MSR 0x40000000 |
| 28 | 34 | ||
| 35 | #define MIN_STEAL_TIME 50000 | ||
| 36 | |||
| 29 | struct pvclock_vcpu_time_info { | 37 | struct pvclock_vcpu_time_info { |
| 30 | u32 version; | 38 | u32 version; |
| 31 | u32 pad0; | 39 | u32 pad0; |
| @@ -43,11 +51,67 @@ struct pvclock_wall_clock { · 11 unmodified lines | |||
| 43 | u32 nsec; | 51 | u32 nsec; |
| 44 | } __attribute__((__packed__)); | 52 | } __attribute__((__packed__)); |
| 45 | 53 | ||
| 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 | |||
| 46 | static void guest_code(void) | 65 | static void guest_code(void) |
| 47 | { | 66 | { |
| 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 | |||
| 48 | GUEST_DONE(); | 98 | GUEST_DONE(); |
| 49 | } | 99 | } |
| 50 | 100 | ||
| 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 | |||
| 51 | static int cmp_timespec(struct timespec *a, struct timespec *b) | 115 | static int cmp_timespec(struct timespec *a, struct timespec *b) |
| 52 | { | 116 | { |
| 53 | if (a->tv_sec > b->tv_sec) | 117 | if (a->tv_sec > b->tv_sec) |
| @@ -66,12 +130,14 @@ int main(int argc, char *argv[]) · 12 unmodified lines | |||
| 66 | { | 130 | { |
| 67 | struct timespec min_ts, max_ts, vm_ts; | 131 | struct timespec min_ts, max_ts, vm_ts; |
| 68 | 132 | ||
| 69 | if (!(kvm_check_cap(KVM_CAP_XEN_HVM) & | 133 | int xen_caps = kvm_check_cap(KVM_CAP_XEN_HVM); |
| 70 | KVM_XEN_HVM_CONFIG_SHARED_INFO) ) { | 134 | if (!(xen_caps & KVM_XEN_HVM_CONFIG_SHARED_INFO) ) { |
| 71 | print_skip("KVM_XEN_HVM_CONFIG_SHARED_INFO not available"); | 135 | print_skip("KVM_XEN_HVM_CONFIG_SHARED_INFO not available"); |
| 72 | exit(KSFT_SKIP); | 136 | exit(KSFT_SKIP); |
| 73 | } | 137 | } |
| 74 | 138 | ||
| 139 | bool do_runstate_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_RUNSTATE); | ||
| 140 | |||
| 75 | clock_gettime(CLOCK_REALTIME, &min_ts); | 141 | clock_gettime(CLOCK_REALTIME, &min_ts); |
| 76 | 142 | ||
| 77 | vm = vm_create_default(VCPU_ID, 0, (void *) guest_code); | 143 | vm = vm_create_default(VCPU_ID, 0, (void *) guest_code); |
| @@ -80,6 +146,7 @@ int main(int argc, char *argv[]) · 2 unmodified lines | |||
| 80 | /* Map a region for the shared_info page */ | 146 | /* Map a region for the shared_info page */ |
| 81 | vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, | 147 | vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, |
| 82 | SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0); | 148 | SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0); |
| 149 | virt_map(vm, SHINFO_REGION_GVA, SHINFO_REGION_GPA, 2, 0); | ||
| 83 | 150 | ||
| 84 | struct kvm_xen_hvm_config hvmc = { | 151 | struct kvm_xen_hvm_config hvmc = { |
| 85 | .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL, | 152 | .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL, |
| @@ -111,6 +178,17 @@ int main(int argc, char *argv[]) · 25 unmodified lines | |||
| 111 | }; | 178 | }; |
| 112 | vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &pvclock); | 179 | vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &pvclock); |
| 113 | 180 | ||
| 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 | |||
| 114 | for (;;) { | 192 | for (;;) { |
| 115 | volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); | 193 | volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); |
| 116 | struct ucall uc; | 194 | struct ucall uc; |
| @@ -126,8 +204,56 @@ int main(int argc, char *argv[]) · 9 unmodified lines | |||
| 126 | case UCALL_ABORT: | 204 | case UCALL_ABORT: |
| 127 | TEST_FAIL("%s", (const char *)uc.args[0]); | 205 | TEST_FAIL("%s", (const char *)uc.args[0]); |
| 128 | /* NOT REACHED */ | 206 | /* 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 | } | ||
| 130 | break; | 255 | break; |
| 256 | } | ||
| 131 | case UCALL_DONE: | 257 | case UCALL_DONE: |
| 132 | goto done; | 258 | goto done; |
| 133 | default: | 259 | default: |
| @@ -162,6 +288,33 @@ int main(int argc, char *argv[]) · 28 unmodified lines | |||
| 162 | TEST_ASSERT(ti2->version && !(ti2->version & 1), | 288 | TEST_ASSERT(ti2->version && !(ti2->version & 1), |
| 163 | "Bad time_info version %x", ti->version); | 289 | "Bad time_info version %x", ti->version); |
| 164 | 290 | ||
| 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 | } | ||
| 165 | kvm_vm_free(vm); | 318 | kvm_vm_free(vm); |
| 166 | return 0; | 319 | return 0; |
| 167 | } | 320 | } |