Commit b6b26489 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull kvm fixes from Paolo Bonzini:
 "ARM:

   - Take care of faults occuring between the PARange and IPA range by
     injecting an exception

   - Fix S2 faults taken from a host EL0 in protected mode

   - Work around Oops caused by a PMU access from a 32bit guest when PMU
     has been created. This is a temporary bodge until we fix it for
     good.

  x86:

   - Fix potential races when walking host page table

   - Fix shadow page table leak when KVM runs nested

   - Work around bug in userspace when KVM synthesizes leaf 0x80000021
     on older (pre-EPYC) or Intel processors

  Generic (but affects only RISC-V):

   - Fix bad user ABI for KVM_EXIT_SYSTEM_EVENT"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: x86: work around QEMU issue with synthetic CPUID leaves
  Revert "x86/mm: Introduce lookup_address_in_mm()"
  KVM: x86/mmu: fix potential races when walking host page table
  KVM: fix bad user ABI for KVM_EXIT_SYSTEM_EVENT
  KVM: x86/mmu: Do not create SPTEs for GFNs that exceed host.MAXPHYADDR
  KVM: arm64: Inject exception on out-of-IPA-range translation fault
  KVM/arm64: Don't emulate a PMU for 32-bit guests if feature not set
  KVM: arm64: Handle host stage-2 faults from 32-bit EL0
parents b2da7df5 f751d8ea
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -5986,16 +5986,16 @@ should put the acknowledged interrupt vector into the 'epr' field.
  #define KVM_SYSTEM_EVENT_RESET          2
  #define KVM_SYSTEM_EVENT_CRASH          3
			__u32 type;
			__u64 flags;
                        __u32 ndata;
                        __u64 data[16];
		} system_event;

If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
a system-level event using some architecture specific mechanism (hypercall
or some special instruction). In case of ARM64, this is triggered using
HVC instruction based PSCI call from the vcpu. The 'type' field describes
the system-level event type. The 'flags' field describes architecture
specific flags for the system-level event.
HVC instruction based PSCI call from the vcpu.

The 'type' field describes the system-level event type.
Valid values for 'type' are:

 - KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
@@ -6010,10 +6010,20 @@ Valid values for 'type' are:
   to ignore the request, or to gather VM memory core dump and/or
   reset/shutdown of the VM.

Valid flags are:
If KVM_CAP_SYSTEM_EVENT_DATA is present, the 'data' field can contain
architecture specific information for the system-level event.  Only
the first `ndata` items (possibly zero) of the data array are valid.

 - for arm64, data[0] is set to KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 if
   the guest issued a SYSTEM_RESET2 call according to v1.1 of the PSCI
   specification.

 - for RISC-V, data[0] is set to the value of the second argument of the
   ``sbi_system_reset`` call.

 - KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (arm64 only) -- the guest issued
   a SYSTEM_RESET2 call according to v1.1 of the PSCI specification.
Previous versions of Linux defined a `flags` member in this struct.  The
field is now aliased to `data[0]`.  Userspace can assume that it is only
written if ndata is greater than 0.

::

+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
void kvm_inject_vabt(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_size_fault(struct kvm_vcpu *vcpu);

void kvm_vcpu_wfi(struct kvm_vcpu *vcpu);

+9 −9
Original line number Diff line number Diff line
@@ -198,15 +198,15 @@ SYM_CODE_START(__kvm_hyp_host_vector)
	invalid_host_el2_vect			// FIQ EL2h
	invalid_host_el2_vect			// Error EL2h

	host_el1_sync_vect			// Synchronous 64-bit EL1
	invalid_host_el1_vect			// IRQ 64-bit EL1
	invalid_host_el1_vect			// FIQ 64-bit EL1
	invalid_host_el1_vect			// Error 64-bit EL1

	invalid_host_el1_vect			// Synchronous 32-bit EL1
	invalid_host_el1_vect			// IRQ 32-bit EL1
	invalid_host_el1_vect			// FIQ 32-bit EL1
	invalid_host_el1_vect			// Error 32-bit EL1
	host_el1_sync_vect			// Synchronous 64-bit EL1/EL0
	invalid_host_el1_vect			// IRQ 64-bit EL1/EL0
	invalid_host_el1_vect			// FIQ 64-bit EL1/EL0
	invalid_host_el1_vect			// Error 64-bit EL1/EL0

	host_el1_sync_vect			// Synchronous 32-bit EL1/EL0
	invalid_host_el1_vect			// IRQ 32-bit EL1/EL0
	invalid_host_el1_vect			// FIQ 32-bit EL1/EL0
	invalid_host_el1_vect			// Error 32-bit EL1/EL0
SYM_CODE_END(__kvm_hyp_host_vector)

/*
+28 −0
Original line number Diff line number Diff line
@@ -145,6 +145,34 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
		inject_abt64(vcpu, true, addr);
}

void kvm_inject_size_fault(struct kvm_vcpu *vcpu)
{
	unsigned long addr, esr;

	addr  = kvm_vcpu_get_fault_ipa(vcpu);
	addr |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);

	if (kvm_vcpu_trap_is_iabt(vcpu))
		kvm_inject_pabt(vcpu, addr);
	else
		kvm_inject_dabt(vcpu, addr);

	/*
	 * If AArch64 or LPAE, set FSC to 0 to indicate an Address
	 * Size Fault at level 0, as if exceeding PARange.
	 *
	 * Non-LPAE guests will only get the external abort, as there
	 * is no way to to describe the ASF.
	 */
	if (vcpu_el1_is_32bit(vcpu) &&
	    !(vcpu_read_sys_reg(vcpu, TCR_EL1) & TTBCR_EAE))
		return;

	esr = vcpu_read_sys_reg(vcpu, ESR_EL1);
	esr &= ~GENMASK_ULL(5, 0);
	vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
}

/**
 * kvm_inject_undefined - inject an undefined instruction into the guest
 * @vcpu: The vCPU in which to inject the exception
+19 −0
Original line number Diff line number Diff line
@@ -1337,6 +1337,25 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
	fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);

	if (fault_status == FSC_FAULT) {
		/* Beyond sanitised PARange (which is the IPA limit) */
		if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
			kvm_inject_size_fault(vcpu);
			return 1;
		}

		/* Falls between the IPA range and the PARange? */
		if (fault_ipa >= BIT_ULL(vcpu->arch.hw_mmu->pgt->ia_bits)) {
			fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);

			if (is_iabt)
				kvm_inject_pabt(vcpu, fault_ipa);
			else
				kvm_inject_dabt(vcpu, fault_ipa);
			return 1;
		}
	}

	/* Synchronous External Abort? */
	if (kvm_vcpu_abt_issea(vcpu)) {
		/*
Loading