Commit 7f3225fe authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch kvm-arm64/nv-nv into kvmarm-master/next



* kvm-arm64/nv-nv:
  : .
  : Flick the switch on the NV support by adding the missing piece
  : in the form of the VNCR page management. From the cover letter:
  :
  : "This is probably the most interesting bit of the whole NV adventure.
  : So far, everything else has been a walk in the park, but this one is
  : where the real fun takes place.
  :
  : With FEAT_NV2, most of the NV support revolves around tricking a guest
  : into accessing memory while it tries to access system registers. The
  : hypervisor's job is to handle the context switch of the actual
  : registers with the state in memory as needed."
  : .
  KVM: arm64: nv: Release faulted-in VNCR page from mmu_lock critical section
  KVM: arm64: nv: Handle TLBI S1E2 for VNCR invalidation with mmu_lock held
  KVM: arm64: nv: Hold mmu_lock when invalidating VNCR SW-TLB before translating
  KVM: arm64: Document NV caps and vcpu flags
  KVM: arm64: Allow userspace to request KVM_ARM_VCPU_EL2*
  KVM: arm64: nv: Remove dead code from ERET handling
  KVM: arm64: nv: Plumb TLBI S1E2 into system instruction dispatch
  KVM: arm64: nv: Add S1 TLB invalidation primitive for VNCR_EL2
  KVM: arm64: nv: Program host's VNCR_EL2 to the fixmap address
  KVM: arm64: nv: Handle VNCR_EL2 invalidation from MMU notifiers
  KVM: arm64: nv: Handle mapping of VNCR_EL2 at EL2
  KVM: arm64: nv: Handle VNCR_EL2-triggered faults
  KVM: arm64: nv: Add userspace and guest handling of VNCR_EL2
  KVM: arm64: nv: Add pseudo-TLB backing VNCR_EL2
  KVM: arm64: nv: Don't adjust PSTATE.M when L2 is nesting
  KVM: arm64: nv: Move TLBI range decoding to a helper
  KVM: arm64: nv: Snapshot S1 ASID tagging information during walk
  KVM: arm64: nv: Extract translation helper from the AT code
  KVM: arm64: nv: Allocate VNCR page when required
  arm64: sysreg: Add layout for VNCR_EL2

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 35e4d7fe 538fbac7
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -3460,7 +3460,8 @@ The initial values are defined as:
	- FPSIMD/NEON registers: set to 0
	- SVE registers: set to 0
	- System registers: Reset to their architecturally defined
	  values as for a warm reset to EL1 (resp. SVC)
	  values as for a warm reset to EL1 (resp. SVC) or EL2 (in the
	  case of EL2 being enabled).

Note that because some registers reflect machine topology, all vcpus
should be created before this ioctl is invoked.
@@ -3527,6 +3528,17 @@ Possible features:
	      - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
	        no longer be written using KVM_SET_ONE_REG.

	- KVM_ARM_VCPU_HAS_EL2: Enable Nested Virtualisation support,
	  booting the guest from EL2 instead of EL1.
	  Depends on KVM_CAP_ARM_EL2.
	  The VM is running with HCR_EL2.E2H being RES1 (VHE) unless
	  KVM_ARM_VCPU_HAS_EL2_E2H0 is also set.

	- KVM_ARM_VCPU_HAS_EL2_E2H0: Restrict Nested Virtualisation
	  support to HCR_EL2.E2H being RES0 (non-VHE).
	  Depends on KVM_CAP_ARM_EL2_E2H0.
	  KVM_ARM_VCPU_HAS_EL2 must also be set.

4.83 KVM_ARM_PREFERRED_TARGET
-----------------------------

+2 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@
#define ESR_ELx_AET_CE		(UL(6) << ESR_ELx_AET_SHIFT)

/* Shared ISS field definitions for Data/Instruction aborts */
#define ESR_ELx_VNCR_SHIFT	(13)
#define ESR_ELx_VNCR		(UL(1) << ESR_ELx_VNCR_SHIFT)
#define ESR_ELx_SET_SHIFT	(11)
#define ESR_ELx_SET_MASK	(UL(3) << ESR_ELx_SET_SHIFT)
#define ESR_ELx_FnV_SHIFT	(10)
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,12 @@ enum fixed_addresses {
	FIX_EARLYCON_MEM_BASE,
	FIX_TEXT_POKE0,

#ifdef CONFIG_KVM
	/* One slot per CPU, mapping the guest's VNCR page at EL2. */
	FIX_VNCR_END,
	FIX_VNCR = FIX_VNCR_END + NR_CPUS,
#endif

#ifdef CONFIG_ACPI_APEI_GHES
	/* Used for GHES mapping from assorted contexts */
	FIX_APEI_GHES_IRQ,
+14 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@

#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS

#define KVM_VCPU_MAX_FEATURES 7
#define KVM_VCPU_MAX_FEATURES 9
#define KVM_VCPU_VALID_FEATURES	(BIT(KVM_VCPU_MAX_FEATURES) - 1)

#define KVM_REQ_SLEEP \
@@ -53,6 +53,7 @@
#define KVM_REQ_RESYNC_PMU_EL0		KVM_ARCH_REQ(7)
#define KVM_REQ_NESTED_S2_UNMAP		KVM_ARCH_REQ(8)
#define KVM_REQ_GUEST_HYP_IRQ_PENDING	KVM_ARCH_REQ(9)
#define KVM_REQ_MAP_L1_VNCR_EL2		KVM_ARCH_REQ(10)

#define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
				     KVM_DIRTY_LOG_INITIALLY_SET)
@@ -395,6 +396,9 @@ struct kvm_arch {
	/* Masks for VNCR-backed and general EL2 sysregs */
	struct kvm_sysreg_masks	*sysreg_masks;

	/* Count the number of VNCR_EL2 currently mapped */
	atomic_t vncr_map_count;

	/*
	 * For an untrusted host VM, 'pkvm.handle' is used to lookup
	 * the associated pKVM instance in the hypervisor.
@@ -573,6 +577,8 @@ enum vcpu_sysreg {
	VNCR(HDFGRTR2_EL2),
	VNCR(HDFGWTR2_EL2),

	VNCR(VNCR_EL2),

	VNCR(CNTVOFF_EL2),
	VNCR(CNTV_CVAL_EL0),
	VNCR(CNTV_CTL_EL0),
@@ -696,6 +702,8 @@ struct kvm_host_data {
#define KVM_HOST_DATA_FLAG_HAS_TRBE			1
#define KVM_HOST_DATA_FLAG_TRBE_ENABLED			4
#define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED	5
#define KVM_HOST_DATA_FLAG_VCPU_IN_HYP_CONTEXT		6
#define KVM_HOST_DATA_FLAG_L1_VNCR_MAPPED		7
	unsigned long flags;

	struct kvm_cpu_context host_ctxt;
@@ -772,6 +780,8 @@ struct vcpu_reset_state {
	bool		reset;
};

struct vncr_tlb;

struct kvm_vcpu_arch {
	struct kvm_cpu_context ctxt;

@@ -866,6 +876,9 @@ struct kvm_vcpu_arch {

	/* Per-vcpu CCSIDR override or NULL */
	u32 *ccsidr;

	/* Per-vcpu TLB for VNCR_EL2 -- NULL when !NV */
	struct vncr_tlb	*vncr_tlb;
};

/*
+100 −0
Original line number Diff line number Diff line
@@ -231,6 +231,38 @@ static inline u64 kvm_encode_nested_level(struct kvm_s2_trans *trans)
		shift;							\
	})

static inline u64 decode_range_tlbi(u64 val, u64 *range, u16 *asid)
{
	u64 base, tg, num, scale;
	int shift;

	tg	= FIELD_GET(GENMASK(47, 46), val);

	switch(tg) {
	case 1:
		shift = 12;
		break;
	case 2:
		shift = 14;
		break;
	case 3:
	default:		/* IMPDEF: handle tg==0 as 64k */
		shift = 16;
		break;
	}

	base	= (val & GENMASK(36, 0)) << shift;

	if (asid)
		*asid = FIELD_GET(TLBIR_ASID_MASK, val);

	scale	= FIELD_GET(GENMASK(45, 44), val);
	num	= FIELD_GET(GENMASK(43, 39), val);
	*range	= __TLBI_RANGE_PAGES(num, scale) << shift;

	return base;
}

static inline unsigned int ps_to_output_size(unsigned int ps)
{
	switch (ps) {
@@ -245,4 +277,72 @@ static inline unsigned int ps_to_output_size(unsigned int ps)
	}
}

enum trans_regime {
	TR_EL10,
	TR_EL20,
	TR_EL2,
};

struct s1_walk_info {
	u64	     		baddr;
	enum trans_regime	regime;
	unsigned int		max_oa_bits;
	unsigned int		pgshift;
	unsigned int		txsz;
	int 	     		sl;
	bool			as_el0;
	bool	     		hpd;
	bool			e0poe;
	bool			poe;
	bool			pan;
	bool	     		be;
	bool	     		s2;
};

struct s1_walk_result {
	union {
		struct {
			u64	desc;
			u64	pa;
			s8	level;
			u8	APTable;
			bool	nG;
			u16	asid;
			bool	UXNTable;
			bool	PXNTable;
			bool	uwxn;
			bool	uov;
			bool	ur;
			bool	uw;
			bool	ux;
			bool	pwxn;
			bool	pov;
			bool	pr;
			bool	pw;
			bool	px;
		};
		struct {
			u8	fst;
			bool	ptw;
			bool	s2;
		};
	};
	bool	failed;
};

int __kvm_translate_va(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
		       struct s1_walk_result *wr, u64 va);

/* VNCR management */
int kvm_vcpu_allocate_vncr_tlb(struct kvm_vcpu *vcpu);
int kvm_handle_vncr_abort(struct kvm_vcpu *vcpu);
void kvm_handle_s1e2_tlbi(struct kvm_vcpu *vcpu, u32 inst, u64 val);

#define vncr_fixmap(c)						\
	({							\
		u32 __c = (c);					\
		BUG_ON(__c >= NR_CPUS);				\
		(FIX_VNCR - __c);				\
	})

#endif /* __ARM64_KVM_NESTED_H */
Loading