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 | 3856 | -EFAULT if struct kvm_reinject_control cannot be read, |
| 3857 | 3857 | -EINVAL if the supplied shift or flags are invalid, |
| 3858 | 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 | 3860 | Used to implement the PAPR extension for runtime resizing of a guest's |
| 3898 | 3861 | Hashed Page Table (HPT). Specifically this starts, stops or monitors |
| 3899 | 3862 | the preparation of a new potential HPT for the guest, essentially |
| 3900 | 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 | 3873 | If called with shift > 0 when there is no pending HPT for the guest, |
| 3903 | 3874 | this begins preparation of a new pending HPT of size 2^(shift) bytes. |
| 3904 | 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 | 3897 | it returns <= 0. The first call will initiate preparation, subsequent |
| 3927 | 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 | 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 | 3919 | transferred to working with the new HPT, essentially implementing the |
| 3957 | 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 | 3930 | This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has |
| 3960 | 3931 | returned 0 with the same parameters. In other cases |
| 3961 | 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 | 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 | 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 | 4878 | union { |
| 4916 | 4879 | __u64 gpa; |
| 4917 | 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 | 4889 | } u; |
| 4919 | 4890 | }; |
| 4920 | 4891 | |
| @@ -4927,6 +4898,31 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO · 6 unmodified lines | ||
| 4927 | 4898 | Sets the guest physical address of an additional pvclock structure |
| 4928 | 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 | 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 | 4935 | Allows Xen vCPU attributes to be read. For the structure and types, |
| 4940 | 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 | 4941 | 5. The kvm_run structure |
| 4943 | 4942 | ======================== |
| 4944 | 4943 | |
| @@ -5000,7 +4999,8 @@ local APIC is not used. · 55 unmodified lines | ||
| 5000 | 4999 | __u16 flags; |
| 5001 | 5000 | |
| 5002 | 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 | 5004 | /* x86, set if the VCPU is in system management mode */ |
| 5005 | 5005 | #define KVM_RUN_X86_SMM (1 << 0) |
| 5006 | 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 | 6217 | notifications to userspace can be KVM_EXIT_BUS_LOCK or other reasons. |
| 6218 | 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 | 6223 | :Architectures: ppc |
| @@ -6702,6 +6702,7 @@ PVHVM guests. Valid flags are:: · 478 unmodified lines | ||
| 6702 | 6702 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) |
| 6703 | 6703 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) |
| 6704 | 6704 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) |
| 6705 | + #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 2) | |
| 6705 | 6706 | |
| 6706 | 6707 | The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG |
| 6707 | 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 | 6717 | KVM_XEN_VCPU_GET_ATTR ioctls, as well as the delivery of exception vectors |
| 6717 | 6718 | for event channel upcalls when the evtchn_upcall_pending field of a vcpu's |
| 6718 | 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 | 535 | /* Xen HVM per vcpu emulation context */ |
| 536 | 536 | struct kvm_vcpu_xen { |
| 537 | 537 | u64 hypercall_rip; |
| 538 | + u32 current_runstate; | |
| 538 | 539 | bool vcpu_info_set; |
| 539 | 540 | bool vcpu_time_info_set; |
| 541 | + bool runstate_set; | |
| 540 | 542 | struct gfn_to_hva_cache vcpu_info_cache; |
| 541 | 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 | 550 | struct kvm_vcpu_arch { |
| @@ -939,9 +945,6 @@ struct kvm_arch { · 394 unmodified lines | ||
| 939 | 945 | unsigned int indirect_shadow_pages; |
| 940 | 946 | u8 mmu_valid_gen; |
| 941 | 947 | struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES]; |
| 942 | − /* | |
| 943 | − * Hash table of struct kvm_mmu_page. | |
| 944 | − */ | |
| 945 | 948 | struct list_head active_mmu_pages; |
| 946 | 949 | struct list_head zapped_obsolete_pages; |
| 947 | 950 | struct list_head lpage_disallowed_mmu_pages; |
| @@ -103,6 +103,15 @@ config KVM_AMD_SEV · 102 unmodified lines | ||
| 103 | 103 | Provides support for launching Encrypted VMs (SEV) and Encrypted VMs |
| 104 | 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 | 115 | config KVM_MMU_AUDIT |
| 107 | 116 | bool "Audit KVM MMU" |
| 108 | 117 | depends on KVM && TRACEPOINTS |
| @@ -14,11 +14,12 @@ kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ · 13 unmodified lines | ||
| 14 | 14 | $(KVM)/dirty_ring.o |
| 15 | 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 | 18 | i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \ |
| 19 | 19 | hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \ |
| 20 | 20 | mmu/spte.o |
| 21 | 21 | kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o |
| 22 | +kvm-$(CONFIG_KVM_XEN) += xen.o | |
| 22 | 23 | |
| 23 | 24 | kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \ |
| 24 | 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 | 159 | struct kvm_vcpu_hv_synic *synic; |
| 160 | 160 | |
| 161 | 161 | vcpu = get_vcpu_by_vpidx(kvm, vpidx); |
| 162 | − if (!vcpu) | |
| 162 | + if (!vcpu || !to_hv_vcpu(vcpu)) | |
| 163 | 163 | return NULL; |
| 164 | 164 | synic = to_hv_synic(vcpu); |
| 165 | 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 | 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 | |
| 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). | |
| 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 | 95 | bool is_nx_huge_page_enabled(void); |
| @@ -1200,6 +1200,7 @@ static void init_vmcb(struct vcpu_svm *svm) · 1199 unmodified lines | ||
| 1200 | 1200 | init_sys_seg(&save->ldtr, SEG_TYPE_LDT); |
| 1201 | 1201 | init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16); |
| 1202 | 1202 | |
| 1203 | + svm_set_cr4(&svm->vcpu, 0); | |
| 1203 | 1204 | svm_set_efer(&svm->vcpu, 0); |
| 1204 | 1205 | save->dr6 = 0xffff0ff0; |
| 1205 | 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 | 2957 | struct kvm_host_map map; |
| 2958 | 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 | 2965 | if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) |
| 2961 | 2966 | return; |
| 2962 | 2967 | |
| @@ -3756,11 +3761,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 793 unmodified lines | ||
| 3756 | 3761 | case KVM_CAP_ENFORCE_PV_FEATURE_CPUID: |
| 3757 | 3762 | r = 1; |
| 3758 | 3763 | break; |
| 3764 | +#ifdef CONFIG_KVM_XEN | |
| 3759 | 3765 | case KVM_CAP_XEN_HVM: |
| 3760 | 3766 | r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR | |
| 3761 | 3767 | KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL | |
| 3762 | 3768 | KVM_XEN_HVM_CONFIG_SHARED_INFO; |
| 3769 | + if (sched_info_on()) | |
| 3770 | + r |= KVM_XEN_HVM_CONFIG_RUNSTATE; | |
| 3763 | 3771 | break; |
| 3772 | +#endif | |
| 3764 | 3773 | case KVM_CAP_SYNC_REGS: |
| 3765 | 3774 | r = KVM_SYNC_X86_VALID_FIELDS; |
| 3766 | 3775 | break; |
| @@ -4038,7 +4047,11 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) · 271 unmodified lines | ||
| 4038 | 4047 | if (vcpu->preempted && !vcpu->arch.guest_state_protected) |
| 4039 | 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 | 4055 | static_call(kvm_x86_vcpu_put)(vcpu); |
| 4043 | 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 | 5026 | case KVM_GET_SUPPORTED_HV_CPUID: |
| 5014 | 5027 | r = kvm_ioctl_get_supported_hv_cpuid(vcpu, argp); |
| 5015 | 5028 | break; |
| 5029 | +#ifdef CONFIG_KVM_XEN | |
| 5016 | 5030 | case KVM_XEN_VCPU_GET_ATTR: { |
| 5017 | 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 | 5047 | r = kvm_xen_vcpu_set_attr(vcpu, &xva); |
| 5034 | 5048 | break; |
| 5035 | 5049 | } |
| 5050 | +#endif | |
| 5036 | 5051 | default: |
| 5037 | 5052 | r = -EINVAL; |
| 5038 | 5053 | } |
| @@ -5654,6 +5669,7 @@ set_pit2_out: · 615 unmodified lines | ||
| 5654 | 5669 | kvm->arch.bsp_vcpu_id = arg; |
| 5655 | 5670 | mutex_unlock(&kvm->lock); |
| 5656 | 5671 | break; |
| 5672 | +#ifdef CONFIG_KVM_XEN | |
| 5657 | 5673 | case KVM_XEN_HVM_CONFIG: { |
| 5658 | 5674 | struct kvm_xen_hvm_config xhc; |
| 5659 | 5675 | r = -EFAULT; |
| @@ -5682,6 +5698,7 @@ set_pit2_out: · 22 unmodified lines | ||
| 5682 | 5698 | r = kvm_xen_hvm_set_attr(kvm, &xha); |
| 5683 | 5699 | break; |
| 5684 | 5700 | } |
| 5701 | +#endif | |
| 5685 | 5702 | case KVM_SET_CLOCK: { |
| 5686 | 5703 | struct kvm_clock_data user_ns; |
| 5687 | 5704 | u64 now_ns; |
| @@ -8040,7 +8057,10 @@ void kvm_arch_exit(void) · 2352 unmodified lines | ||
| 8040 | 8057 | kvm_mmu_module_exit(); |
| 8041 | 8058 | free_percpu(user_return_msrs); |
| 8042 | 8059 | kmem_cache_destroy(x86_fpu_cache); |
| 8060 | +#ifdef CONFIG_KVM_XEN | |
| 8061 | + static_key_deferred_flush(&kvm_xen_enabled); | |
| 8043 | 8062 | WARN_ON(static_branch_unlikely(&kvm_xen_enabled.key)); |
| 8063 | +#endif | |
| 8044 | 8064 | } |
| 8045 | 8065 | |
| 8046 | 8066 | static int __kvm_vcpu_halt(struct kvm_vcpu *vcpu, int state, int reason) |
| @@ -11,9 +11,11 @@ · 10 unmodified lines | ||
| 11 | 11 | #include "hyperv.h" |
| 12 | 12 | |
| 13 | 13 | #include <linux/kvm_host.h> |
| 14 | +#include <linux/sched/stat.h> | |
| 14 | 15 | |
| 15 | 16 | #include <trace/events/kvm.h> |
| 16 | 17 | #include <xen/interface/xen.h> |
| 18 | +#include <xen/interface/vcpu.h> | |
| 17 | 19 | |
| 18 | 20 | #include "trace.h" |
| 19 | 21 | |
| @@ -61,6 +63,132 @@ out: · 41 unmodified lines | ||
| 61 | 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 | 192 | int __kvm_xen_has_interrupt(struct kvm_vcpu *v) |
| 65 | 193 | { |
| 66 | 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 | 315 | /* No compat necessary here. */ |
| 188 | 316 | BUILD_BUG_ON(sizeof(struct vcpu_info) != |
| 189 | 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 | 321 | if (data->u.gpa == GPA_INVALID) { |
| 192 | 322 | vcpu->arch.xen.vcpu_info_set = false; |
| 323 | + r = 0; | |
| 193 | 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 | 337 | case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO: |
| 207 | 338 | if (data->u.gpa == GPA_INVALID) { |
| 208 | 339 | vcpu->arch.xen.vcpu_time_info_set = false; |
| 340 | + r = 0; | |
| 209 | 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 | 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 | 469 | default: |
| 223 | 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 | 498 | r = 0; |
| 252 | 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 | 544 | default: |
| 255 | 545 | break; |
| 256 | 546 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #ifndef __ARCH_X86_KVM_XEN_H__ |
| 10 | 10 | #define __ARCH_X86_KVM_XEN_H__ |
| 11 | 11 | |
| 12 | +#ifdef CONFIG_KVM_XEN | |
| 12 | 13 | #include <linux/jump_label_ratelimit.h> |
| 13 | 14 | |
| 14 | 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 | 19 | int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data); |
| 19 | 20 | int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data); |
| 20 | 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 | 22 | int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data); |
| 23 | 23 | int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc); |
| 24 | 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 | 32 | static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm) |
| 27 | 33 | { |
| 28 | 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 | 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 | 75 | #include <asm/pvclock-abi.h> |
| 44 | 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 | 100 | struct compat_arch_vcpu_info { |
| 47 | 101 | unsigned int cr2; |
| 48 | 102 | unsigned int pad[5]; |
| @@ -75,4 +129,10 @@ struct compat_shared_info { · 26 unmodified lines | ||
| 75 | 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 | 138 | #endif /* __ARCH_X86_KVM_XEN_H__ */ |
| @@ -1154,6 +1154,7 @@ struct kvm_x86_mce { · 1153 unmodified lines | ||
| 1154 | 1154 | #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) |
| 1155 | 1155 | #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) |
| 1156 | 1156 | #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) |
| 1157 | +#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) | |
| 1157 | 1158 | |
| 1158 | 1159 | struct kvm_xen_hvm_config { |
| 1159 | 1160 | __u32 flags; |
| @@ -1621,12 +1622,24 @@ struct kvm_xen_vcpu_attr { · 461 unmodified lines | ||
| 1621 | 1622 | union { |
| 1622 | 1623 | __u64 gpa; |
| 1623 | 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 | 1633 | } u; |
| 1625 | 1634 | }; |
| 1626 | 1635 | |
| 1627 | 1636 | /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ |
| 1628 | 1637 | #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 |
| 1629 | 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 | 1644 | /* Secure Encrypted Virtualization command */ |
| 1632 | 1645 | enum sev_cmd_id { |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #define KVM_UTIL_PGS_PER_HUGEPG 512 |
| 22 | 22 | #define KVM_UTIL_MIN_PFN 2 |
| 23 | 23 | |
| 24 | +static int vcpu_mmap_sz(void); | |
| 25 | + | |
| 24 | 26 | /* Aligns x up to the next multiple of size. Size must be a power of 2. */ |
| 25 | 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 | 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 | 515 | TEST_ASSERT(ret == 0, "munmap of VCPU fd failed, rc: %i " |
| 514 | 516 | "errno: %i", ret, errno); |
| 515 | 517 | close(vcpu->fd); |
| @@ -978,7 +980,7 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid) · 462 unmodified lines | ||
| 978 | 980 | TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->state), "vcpu mmap size " |
| 979 | 981 | "smaller than expected, vcpu_mmap_sz: %i expected_min: %zi", |
| 980 | 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 | 984 | PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0); |
| 983 | 985 | TEST_ASSERT(vcpu->state != MAP_FAILED, "mmap vcpu_state failed, " |
| 984 | 986 | "vcpu id: %u errno: %i", vcpuid, errno); |
| @@ -13,19 +13,27 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include <stdint.h> |
| 15 | 15 | #include <time.h> |
| 16 | +#include <sched.h> | |
| 17 | +#include <sys/syscall.h> | |
| 16 | 18 | |
| 17 | 19 | #define VCPU_ID 5 |
| 18 | 20 | |
| 21 | +#define SHINFO_REGION_GVA 0xc0000000ULL | |
| 19 | 22 | #define SHINFO_REGION_GPA 0xc0000000ULL |
| 20 | 23 | #define SHINFO_REGION_SLOT 10 |
| 21 | 24 | #define PAGE_SIZE 4096 |
| 22 | 25 | |
| 23 | 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 | 31 | static struct kvm_vm *vm; |
| 26 | 32 | |
| 27 | 33 | #define XEN_HYPERCALL_MSR 0x40000000 |
| 28 | 34 | |
| 35 | +#define MIN_STEAL_TIME 50000 | |
| 36 | + | |
| 29 | 37 | struct pvclock_vcpu_time_info { |
| 30 | 38 | u32 version; |
| 31 | 39 | u32 pad0; |
| @@ -43,11 +51,67 @@ struct pvclock_wall_clock { · 11 unmodified lines | ||
| 43 | 51 | u32 nsec; |
| 44 | 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 | 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 | 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 | 115 | static int cmp_timespec(struct timespec *a, struct timespec *b) |
| 52 | 116 | { |
| 53 | 117 | if (a->tv_sec > b->tv_sec) |
| @@ -66,12 +130,14 @@ int main(int argc, char *argv[]) · 12 unmodified lines | ||
| 66 | 130 | { |
| 67 | 131 | struct timespec min_ts, max_ts, vm_ts; |
| 68 | 132 | |
| 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) ) { | |
| 71 | 135 | print_skip("KVM_XEN_HVM_CONFIG_SHARED_INFO not available"); |
| 72 | 136 | exit(KSFT_SKIP); |
| 73 | 137 | } |
| 74 | 138 | |
| 139 | + bool do_runstate_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_RUNSTATE); | |
| 140 | + | |
| 75 | 141 | clock_gettime(CLOCK_REALTIME, &min_ts); |
| 76 | 142 | |
| 77 | 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 | 146 | /* Map a region for the shared_info page */ |
| 81 | 147 | vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, |
| 82 | 148 | SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0); |
| 149 | + virt_map(vm, SHINFO_REGION_GVA, SHINFO_REGION_GPA, 2, 0); | |
| 83 | 150 | |
| 84 | 151 | struct kvm_xen_hvm_config hvmc = { |
| 85 | 152 | .flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL, |
| @@ -111,6 +178,17 @@ int main(int argc, char *argv[]) · 25 unmodified lines | ||
| 111 | 178 | }; |
| 112 | 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 | 192 | for (;;) { |
| 115 | 193 | volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID); |
| 116 | 194 | struct ucall uc; |
| @@ -126,8 +204,56 @@ int main(int argc, char *argv[]) · 9 unmodified lines | ||
| 126 | 204 | case UCALL_ABORT: |
| 127 | 205 | TEST_FAIL("%s", (const char *)uc.args[0]); |
| 128 | 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 | 255 | break; |
| 256 | + } | |
| 131 | 257 | case UCALL_DONE: |
| 132 | 258 | goto done; |
| 133 | 259 | default: |
| @@ -162,6 +288,33 @@ int main(int argc, char *argv[]) · 28 unmodified lines | ||
| 162 | 288 | TEST_ASSERT(ti2->version && !(ti2->version & 1), |
| 163 | 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 | 318 | kvm_vm_free(vm); |
| 166 | 319 | return 0; |
| 167 | 320 | } |