Commit 3ecf162a authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-xen-6.15' of https://github.com/kvm-x86/linux into HEAD

KVM Xen changes for 6.15

 - Don't write to the Xen hypercall page on MSR writes that are initiated by
   the host (userspace or KVM) to fix a class of bugs where KVM can write to
   guest memory at unexpected times, e.g. during vCPU creation if userspace has
   set the Xen hypercall MSR index to collide with an MSR that KVM emulates.

 - Restrict the Xen hypercall MSR indx to the unofficial synthetic range to
   reduce the set of possible collisions with MSRs that are emulated by KVM
   (collisions can still happen as KVM emulates Hyper-V MSRs, which also reside
   in the synthetic range).

 - Clean up and optimize KVM's handling of Xen MSR writes and xen_hvm_config.

 - Update Xen TSC leaves during CPUID emulation instead of modifying the CPUID
   entries when updating PV clocks, as there is no guarantee PV clocks will be
   updated between TSC frequency changes and CPUID emulation, and guest reads
   of Xen TSC should be rare, i.e. are not a hot path.
parents fcce7c1e a2b00f85
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1000,6 +1000,10 @@ blobs in userspace. When the guest writes the MSR, kvm copies one
page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
memory.

The MSR index must be in the range [0x40000000, 0x4fffffff], i.e. must reside
in the range that is unofficially reserved for use by hypervisors.  The min/max
values are enumerated via KVM_XEN_MSR_MIN_INDEX and KVM_XEN_MSR_MAX_INDEX.

::

  struct kvm_xen_hvm_config {
+2 −2
Original line number Diff line number Diff line
@@ -1192,6 +1192,8 @@ struct kvm_xen {
	struct gfn_to_pfn_cache shinfo_cache;
	struct idr evtchn_ports;
	unsigned long poll_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];

	struct kvm_xen_hvm_config hvm_config;
};
#endif

@@ -1412,8 +1414,6 @@ struct kvm_arch {
	struct delayed_work kvmclock_update_work;
	struct delayed_work kvmclock_sync_work;

	struct kvm_xen_hvm_config xen_hvm_config;

	/* reads protected by irq_srcu, writes by irq_lock */
	struct hlist_head mask_notifier_list;

+3 −0
Original line number Diff line number Diff line
@@ -559,6 +559,9 @@ struct kvm_x86_mce {
#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE	(1 << 7)
#define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA	(1 << 8)

#define KVM_XEN_MSR_MIN_INDEX			0x40000000u
#define KVM_XEN_MSR_MAX_INDEX			0x4fffffffu

struct kvm_xen_hvm_config {
	__u32 flags;
	__u32 msr;
+16 −0
Original line number Diff line number Diff line
@@ -2008,6 +2008,22 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
		} else if (function == 0x80000007) {
			if (kvm_hv_invtsc_suppressed(vcpu))
				*edx &= ~feature_bit(CONSTANT_TSC);
		} else if (IS_ENABLED(CONFIG_KVM_XEN) &&
			   kvm_xen_is_tsc_leaf(vcpu, function)) {
			/*
			 * Update guest TSC frequency information if necessary.
			 * Ignore failures, there is no sane value that can be
			 * provided if KVM can't get the TSC frequency.
			 */
			if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu))
				kvm_guest_time_update(vcpu);

			if (index == 1) {
				*ecx = vcpu->arch.pvclock_tsc_mul;
				*edx = vcpu->arch.pvclock_tsc_shift;
			} else if (index == 2) {
				*eax = vcpu->arch.hw_tsc_khz;
			}
		}
	} else {
		*eax = *ebx = *ecx = *edx = 0;
+9 −4
Original line number Diff line number Diff line
@@ -3169,7 +3169,7 @@ static void kvm_setup_guest_pvclock(struct pvclock_vcpu_time_info *ref_hv_clock,
	trace_kvm_pvclock_update(vcpu->vcpu_id, &hv_clock);
}

static int kvm_guest_time_update(struct kvm_vcpu *v)
int kvm_guest_time_update(struct kvm_vcpu *v)
{
	struct pvclock_vcpu_time_info hv_clock = {};
	unsigned long flags, tgt_tsc_khz;
@@ -3242,7 +3242,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
				   &vcpu->pvclock_tsc_shift,
				   &vcpu->pvclock_tsc_mul);
		vcpu->hw_tsc_khz = tgt_tsc_khz;
		kvm_xen_update_tsc_info(v);
	}

	hv_clock.tsc_shift = vcpu->pvclock_tsc_shift;
@@ -3282,7 +3281,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
	 *
	 * Note!  Clear TSC_STABLE only for Xen clocks, i.e. the order matters!
	 */
	if (ka->xen_hvm_config.flags & KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE)
	if (ka->xen.hvm_config.flags & KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE)
		hv_clock.flags &= ~PVCLOCK_TSC_STABLE_BIT;

	if (vcpu->xen.vcpu_info_cache.active)
@@ -3745,7 +3744,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
	u32 msr = msr_info->index;
	u64 data = msr_info->data;

	if (msr && msr == vcpu->kvm->arch.xen_hvm_config.msr)
	/*
	 * Do not allow host-initiated writes to trigger the Xen hypercall
	 * page setup; it could incur locking paths which are not expected
	 * if userspace sets the MSR in an unusual location.
	 */
	if (kvm_xen_is_hypercall_page_msr(vcpu->kvm, msr) &&
	    !msr_info->host_initiated)
		return kvm_xen_write_hypercall_page(vcpu, data);

	switch (msr) {
Loading