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

   - Large set of fixes for vector handling, especially in the
     interactions between host and guest state.

     This fixes a number of bugs affecting actual deployments, and
     greatly simplifies the FP/SIMD/SVE handling. Thanks to Mark Rutland
     for dealing with this thankless task.

   - Fix an ugly race between vcpu and vgic creation/init, resulting in
     unexpected behaviours

   - Fix use of kernel VAs at EL2 when emulating timers with nVHE

   - Small set of pKVM improvements and cleanups

  x86:

   - Fix broken SNP support with KVM module built-in, ensuring the PSP
     module is initialized before KVM even when the module
     infrastructure cannot be used to order initcalls

   - Reject Hyper-V SEND_IPI hypercalls if the local APIC isn't being
     emulated by KVM to fix a NULL pointer dereference

   - Enter guest mode (L2) from KVM's perspective before initializing
     the vCPU's nested NPT MMU so that the MMU is properly tagged for
     L2, not L1

   - Load the guest's DR6 outside of the innermost .vcpu_run() loop, as
     the guest's value may be stale if a VM-Exit is handled in the
     fastpath"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (25 commits)
  x86/sev: Fix broken SNP support with KVM module built-in
  KVM: SVM: Ensure PSP module is initialized if KVM module is built-in
  crypto: ccp: Add external API interface for PSP module initialization
  KVM: arm64: vgic: Hoist SGI/PPI alloc from vgic_init() to kvm_create_vgic()
  KVM: arm64: timer: Drop warning on failed interrupt signalling
  KVM: arm64: Fix alignment of kvm_hyp_memcache allocations
  KVM: arm64: Convert timer offset VA when accessed in HYP code
  KVM: arm64: Simplify warning in kvm_arch_vcpu_load_fp()
  KVM: arm64: Eagerly switch ZCR_EL{1,2}
  KVM: arm64: Mark some header functions as inline
  KVM: arm64: Refactor exit handlers
  KVM: arm64: Refactor CPTR trap deactivation
  KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN
  KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN
  KVM: arm64: Remove host FPSIMD saving for non-protected KVM
  KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state
  KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop
  KVM: nSVM: Enter guest mode before initializing nested NPT MMU
  KVM: selftests: Add CPUID tests for Hyper-V features that need in-kernel APIC
  KVM: selftests: Manage CPUID array in Hyper-V CPUID test's core helper
  ...
parents b878a1c0 d3d0b8df
Loading
Loading
Loading
Loading
+0 −42
Original line number Diff line number Diff line
@@ -605,48 +605,6 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
					 __cpacr_to_cptr_set(clr, set));\
	} while (0)

static __always_inline void kvm_write_cptr_el2(u64 val)
{
	if (has_vhe() || has_hvhe())
		write_sysreg(val, cpacr_el1);
	else
		write_sysreg(val, cptr_el2);
}

/* Resets the value of cptr_el2 when returning to the host. */
static __always_inline void __kvm_reset_cptr_el2(struct kvm *kvm)
{
	u64 val;

	if (has_vhe()) {
		val = (CPACR_EL1_FPEN | CPACR_EL1_ZEN_EL1EN);
		if (cpus_have_final_cap(ARM64_SME))
			val |= CPACR_EL1_SMEN_EL1EN;
	} else if (has_hvhe()) {
		val = CPACR_EL1_FPEN;

		if (!kvm_has_sve(kvm) || !guest_owns_fp_regs())
			val |= CPACR_EL1_ZEN;
		if (cpus_have_final_cap(ARM64_SME))
			val |= CPACR_EL1_SMEN;
	} else {
		val = CPTR_NVHE_EL2_RES1;

		if (kvm_has_sve(kvm) && guest_owns_fp_regs())
			val |= CPTR_EL2_TZ;
		if (!cpus_have_final_cap(ARM64_SME))
			val |= CPTR_EL2_TSM;
	}

	kvm_write_cptr_el2(val);
}

#ifdef __KVM_NVHE_HYPERVISOR__
#define kvm_reset_cptr_el2(v)	__kvm_reset_cptr_el2(kern_hyp_va((v)->kvm))
#else
#define kvm_reset_cptr_el2(v)	__kvm_reset_cptr_el2((v)->kvm)
#endif

/*
 * Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE
 * format if E2H isn't set.
+6 −18
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
static inline void *pop_hyp_memcache(struct kvm_hyp_memcache *mc,
				     void *(*to_va)(phys_addr_t phys))
{
	phys_addr_t *p = to_va(mc->head);
	phys_addr_t *p = to_va(mc->head & PAGE_MASK);

	if (!mc->nr_pages)
		return NULL;
@@ -615,8 +615,6 @@ struct cpu_sve_state {
struct kvm_host_data {
#define KVM_HOST_DATA_FLAG_HAS_SPE			0
#define KVM_HOST_DATA_FLAG_HAS_TRBE			1
#define KVM_HOST_DATA_FLAG_HOST_SVE_ENABLED		2
#define KVM_HOST_DATA_FLAG_HOST_SME_ENABLED		3
#define KVM_HOST_DATA_FLAG_TRBE_ENABLED			4
#define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED	5
	unsigned long flags;
@@ -624,23 +622,13 @@ struct kvm_host_data {
	struct kvm_cpu_context host_ctxt;

	/*
	 * All pointers in this union are hyp VA.
	 * Hyp VA.
	 * sve_state is only used in pKVM and if system_supports_sve().
	 */
	union {
		struct user_fpsimd_state *fpsimd_state;
	struct cpu_sve_state *sve_state;
	};

	union {
		/* HYP VA pointer to the host storage for FPMR */
		u64	*fpmr_ptr;
		/*
		 * Used by pKVM only, as it needs to provide storage
		 * for the host
		 */
	/* Used by pKVM only. */
	u64	fpmr;
	};

	/* Ownership of the FP regs */
	enum {
+0 −25
Original line number Diff line number Diff line
@@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void)
		sve_to_fpsimd(current);
}

/*
 * Called by KVM when entering the guest.
 */
void fpsimd_kvm_prepare(void)
{
	if (!system_supports_sve())
		return;

	/*
	 * KVM does not save host SVE state since we can only enter
	 * the guest from a syscall so the ABI means that only the
	 * non-saved SVE state needs to be saved.  If we have left
	 * SVE enabled for performance reasons then update the task
	 * state to be FPSIMD only.
	 */
	get_cpu_fpsimd_context();

	if (test_and_clear_thread_flag(TIF_SVE)) {
		sve_to_fpsimd(current);
		current->thread.fp_type = FP_STATE_FPSIMD;
	}

	put_cpu_fpsimd_context();
}

/*
 * Associate current's FPSIMD context with this cpu
 * The caller must have ownership of the cpu FPSIMD context before calling
+7 −9
Original line number Diff line number Diff line
@@ -447,21 +447,19 @@ static void kvm_timer_update_status(struct arch_timer_context *ctx, bool level)
static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
				 struct arch_timer_context *timer_ctx)
{
	int ret;

	kvm_timer_update_status(timer_ctx, new_level);

	timer_ctx->irq.level = new_level;
	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_irq(timer_ctx),
				   timer_ctx->irq.level);

	if (!userspace_irqchip(vcpu->kvm)) {
		ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu,
	if (userspace_irqchip(vcpu->kvm))
		return;

	kvm_vgic_inject_irq(vcpu->kvm, vcpu,
			    timer_irq(timer_ctx),
			    timer_ctx->irq.level,
			    timer_ctx);
		WARN_ON(ret);
	}
}

/* Only called for a fully emulated timer */
+0 −8
Original line number Diff line number Diff line
@@ -2481,14 +2481,6 @@ static void finalize_init_hyp_mode(void)
			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state =
				kern_hyp_va(sve_state);
		}
	} else {
		for_each_possible_cpu(cpu) {
			struct user_fpsimd_state *fpsimd_state;

			fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs;
			per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state =
				kern_hyp_va(fpsimd_state);
		}
	}
}

Loading