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

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

KVM VMX changes for 6.12:

 - Set FINAL/PAGE in the page fault error code for EPT Violations if and only
   if the GVA is valid.  If the GVA is NOT valid, there is no guest-side page
   table walk and so stuffing paging related metadata is nonsensical.

 - Fix a bug where KVM would incorrectly synthesize a nested VM-Exit instead of
   emulating posted interrupt delivery to L2.

 - Add a lockdep assertion to detect unsafe accesses of vmcs12 structures.

 - Harden eVMCS loading against an impossible NULL pointer deref (really truly
   should be impossible).

 - Minor SGX fix and a cleanup.
parents 55e6f8f2 f3009482
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -4214,7 +4214,9 @@ whether or not KVM_CAP_X86_USER_SPACE_MSR's KVM_MSR_EXIT_REASON_FILTER is
enabled.  If KVM_MSR_EXIT_REASON_FILTER is enabled, KVM will exit to userspace
on denied accesses, i.e. userspace effectively intercepts the MSR access.  If
KVM_MSR_EXIT_REASON_FILTER is not enabled, KVM will inject a #GP into the guest
on denied accesses.
on denied accesses.  Note, if an MSR access is denied during emulation of MSR
load/stores during VMX transitions, KVM ignores KVM_MSR_EXIT_REASON_FILTER.
See the below warning for full details.

If an MSR access is allowed by userspace, KVM will emulate and/or virtualize
the access in accordance with the vCPU model.  Note, KVM may still ultimately
@@ -4229,9 +4231,22 @@ filtering. In that mode, ``KVM_MSR_FILTER_DEFAULT_DENY`` is invalid and causes
an error.

.. warning::
   MSR accesses as part of nested VM-Enter/VM-Exit are not filtered.
   This includes both writes to individual VMCS fields and reads/writes
   through the MSR lists pointed to by the VMCS.
   MSR accesses that are side effects of instruction execution (emulated or
   native) are not filtered as hardware does not honor MSR bitmaps outside of
   RDMSR and WRMSR, and KVM mimics that behavior when emulating instructions
   to avoid pointless divergence from hardware.  E.g. RDPID reads MSR_TSC_AUX,
   SYSENTER reads the SYSENTER MSRs, etc.

   MSRs that are loaded/stored via dedicated VMCS fields are not filtered as
   part of VM-Enter/VM-Exit emulation.

   MSRs that are loaded/store via VMX's load/store lists _are_ filtered as part
   of VM-Enter/VM-Exit emulation.  If an MSR access is denied on VM-Enter, KVM
   synthesizes a consistency check VM-Exit(EXIT_REASON_MSR_LOAD_FAIL).  If an
   MSR access is denied on VM-Exit, KVM synthesizes a VM-Abort.  In short, KVM
   extends Intel's architectural list of MSRs that cannot be loaded/saved via
   the VM-Enter/VM-Exit MSR list.  It is platform owner's responsibility to
   to communicate any such restrictions to their end users.

   x2APIC MSR accesses cannot be filtered (KVM silently ignores filters that
   cover any x2APIC MSRs).
+3 −0
Original line number Diff line number Diff line
@@ -2062,6 +2062,8 @@ void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu);

void kvm_enable_efer_bits(u64);
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data);
int kvm_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 data);
int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, bool host_initiated);
int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data);
int kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data);
@@ -2264,6 +2266,7 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
int kvm_cpu_has_extint(struct kvm_vcpu *v);
int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
int kvm_cpu_get_extint(struct kvm_vcpu *v);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);

+7 −3
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
 * Read pending interrupt(from non-APIC source)
 * vector and intack.
 */
static int kvm_cpu_get_extint(struct kvm_vcpu *v)
int kvm_cpu_get_extint(struct kvm_vcpu *v)
{
	if (!kvm_cpu_has_extint(v)) {
		WARN_ON(!lapic_in_kernel(v));
@@ -131,6 +131,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
	} else
		return kvm_pic_read_irq(v->kvm); /* PIC */
}
EXPORT_SYMBOL_GPL(kvm_cpu_get_extint);

/*
 * Read pending interrupt vector and intack.
@@ -141,9 +142,12 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
	if (vector != -1)
		return vector;			/* PIC */

	return kvm_get_apic_interrupt(v);	/* APIC */
	vector = kvm_apic_has_interrupt(v);	/* APIC */
	if (vector != -1)
		kvm_apic_ack_interrupt(v, vector);

	return vector;
}
EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);

void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
{
+4 −5
Original line number Diff line number Diff line
@@ -2959,14 +2959,13 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
	}
}

int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector)
{
	int vector = kvm_apic_has_interrupt(vcpu);
	struct kvm_lapic *apic = vcpu->arch.apic;
	u32 ppr;

	if (vector == -1)
		return -1;
	if (WARN_ON_ONCE(vector < 0 || !apic))
		return;

	/*
	 * We get here even with APIC virtualization enabled, if doing
@@ -2994,8 +2993,8 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
		__apic_update_ppr(apic, &ppr);
	}

	return vector;
}
EXPORT_SYMBOL_GPL(kvm_apic_ack_interrupt);

static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
		struct kvm_lapic_state *s, bool set)
+1 −1
Original line number Diff line number Diff line
@@ -88,8 +88,8 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu);
void kvm_free_lapic(struct kvm_vcpu *vcpu);

int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu);
void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector);
int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu);
int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu);
int kvm_apic_accept_events(struct kvm_vcpu *vcpu);
void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
Loading