Commit 2d38f439 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

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



* kvm-arm64/nv-eret-pauth:
  : .
  : Add NV support for the ERETAA/ERETAB instructions. From the cover letter:
  :
  : "Although the current upstream NV support has *some* support for
  : correctly emulating ERET, that support is only partial as it doesn't
  : support the ERETAA and ERETAB variants.
  :
  : Supporting these instructions was cast aside for a long time as it
  : involves implementing some form of PAuth emulation, something I wasn't
  : overly keen on. But I have reached a point where enough of the
  : infrastructure is there that it actually makes sense. So here it is!"
  : .
  KVM: arm64: nv: Work around lack of pauth support in old toolchains
  KVM: arm64: Drop trapping of PAuth instructions/keys
  KVM: arm64: nv: Advertise support for PAuth
  KVM: arm64: nv: Handle ERETA[AB] instructions
  KVM: arm64: nv: Add emulation for ERETAx instructions
  KVM: arm64: nv: Add kvm_has_pauth() helper
  KVM: arm64: nv: Reinject PAC exceptions caused by HCR_EL2.API==0
  KVM: arm64: nv: Handle HCR_EL2.{API,APK} independently
  KVM: arm64: nv: Honor HFGITR_EL2.ERET being set
  KVM: arm64: nv: Fast-track 'InHost' exception returns
  KVM: arm64: nv: Add trap forwarding for ERET and SMC
  KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
  KVM: arm64: nv: Drop VCPU_HYP_CONTEXT flag
  KVM: arm64: Constraint PAuth support to consistent implementations
  KVM: arm64: Add helpers for ESR_ELx_ERET_ISS_ERET*
  KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 34c0d5a6 5513394d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -404,6 +404,18 @@ static inline bool esr_fsc_is_access_flag_fault(unsigned long esr)
	return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_ACCESS;
}

/* Indicate whether ESR.EC==0x1A is for an ERETAx instruction */
static inline bool esr_iss_is_eretax(unsigned long esr)
{
	return esr & ESR_ELx_ERET_ISS_ERET;
}

/* Indicate which key is used for ERETAx (false: A-Key, true: B-Key) */
static inline bool esr_iss_is_eretab(unsigned long esr)
{
	return esr & ESR_ELx_ERET_ISS_ERETA;
}

const char *esr_get_class_string(unsigned long esr);
#endif /* __ASSEMBLY */

+0 −10
Original line number Diff line number Diff line
@@ -125,16 +125,6 @@ static inline void vcpu_set_wfx_traps(struct kvm_vcpu *vcpu)
	vcpu->arch.hcr_el2 |= HCR_TWI;
}

static inline void vcpu_ptrauth_enable(struct kvm_vcpu *vcpu)
{
	vcpu->arch.hcr_el2 |= (HCR_API | HCR_APK);
}

static inline void vcpu_ptrauth_disable(struct kvm_vcpu *vcpu)
{
	vcpu->arch.hcr_el2 &= ~(HCR_API | HCR_APK);
}

static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu)
{
	return vcpu->arch.vsesr_el2;
+23 −3
Original line number Diff line number Diff line
@@ -830,8 +830,6 @@ struct kvm_vcpu_arch {
#define DEBUG_STATE_SAVE_SPE	__vcpu_single_flag(iflags, BIT(5))
/* Save TRBE context if active  */
#define DEBUG_STATE_SAVE_TRBE	__vcpu_single_flag(iflags, BIT(6))
/* vcpu running in HYP context */
#define VCPU_HYP_CONTEXT	__vcpu_single_flag(iflags, BIT(7))

/* SVE enabled for host EL0 */
#define HOST_SVE_ENABLED	__vcpu_single_flag(sflags, BIT(0))
@@ -909,7 +907,7 @@ struct kvm_vcpu_arch {
 * Don't bother with VNCR-based accesses in the nVHE code, it has no
 * business dealing with NV.
 */
static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
static inline u64 *___ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
{
#if !defined (__KVM_NVHE_HYPERVISOR__)
	if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&
@@ -919,6 +917,13 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
	return (u64 *)&ctxt->sys_regs[r];
}

#define __ctxt_sys_reg(c,r)						\
	({								\
		BUILD_BUG_ON(__builtin_constant_p(r) &&			\
			     (r) >= NR_SYS_REGS);			\
		___ctxt_sys_reg(c, r);					\
	})

#define ctxt_sys_reg(c,r)	(*__ctxt_sys_reg(c,r))

u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
@@ -1370,4 +1375,19 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu);
	(get_idreg_field((kvm), id, fld) >= expand_field_sign(id, fld, min) && \
	 get_idreg_field((kvm), id, fld) <= expand_field_sign(id, fld, max))

/* Check for a given level of PAuth support */
#define kvm_has_pauth(k, l)						\
	({								\
		bool pa, pi, pa3;					\
									\
		pa  = kvm_has_feat((k), ID_AA64ISAR1_EL1, APA, l);	\
		pa &= kvm_has_feat((k), ID_AA64ISAR1_EL1, GPA, IMP);	\
		pi  = kvm_has_feat((k), ID_AA64ISAR1_EL1, API, l);	\
		pi &= kvm_has_feat((k), ID_AA64ISAR1_EL1, GPI, IMP);	\
		pa3  = kvm_has_feat((k), ID_AA64ISAR2_EL1, APA3, l);	\
		pa3 &= kvm_has_feat((k), ID_AA64ISAR2_EL1, GPA3, IMP);	\
									\
		(pa + pi + pa3) == 1;					\
	})

#endif /* __ARM64_KVM_HOST_H__ */
+13 −0
Original line number Diff line number Diff line
@@ -60,7 +60,20 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0)
	return ttbr0 & ~GENMASK_ULL(63, 48);
}

extern bool forward_smc_trap(struct kvm_vcpu *vcpu);

int kvm_init_nv_sysregs(struct kvm *kvm);

#ifdef CONFIG_ARM64_PTR_AUTH
bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u64 *elr);
#else
static inline bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u64 *elr)
{
	/* We really should never execute this... */
	WARN_ON_ONCE(1);
	*elr = 0xbad9acc0debadbad;
	return false;
}
#endif

#endif /* __ARM64_KVM_NESTED_H */
+21 −0
Original line number Diff line number Diff line
@@ -99,5 +99,26 @@ alternative_else_nop_endif
.macro ptrauth_switch_to_hyp g_ctxt, h_ctxt, reg1, reg2, reg3
.endm
#endif /* CONFIG_ARM64_PTR_AUTH */

#else  /* !__ASSEMBLY */

#define __ptrauth_save_key(ctxt, key)					\
	do {								\
		u64 __val;                                              \
		__val = read_sysreg_s(SYS_ ## key ## KEYLO_EL1);	\
		ctxt_sys_reg(ctxt, key ## KEYLO_EL1) = __val;		\
		__val = read_sysreg_s(SYS_ ## key ## KEYHI_EL1);	\
		ctxt_sys_reg(ctxt, key ## KEYHI_EL1) = __val;		\
	} while(0)

#define ptrauth_save_keys(ctxt)						\
	do {								\
		__ptrauth_save_key(ctxt, APIA);				\
		__ptrauth_save_key(ctxt, APIB);				\
		__ptrauth_save_key(ctxt, APDA);				\
		__ptrauth_save_key(ctxt, APDB);				\
		__ptrauth_save_key(ctxt, APGA);				\
	} while(0)

#endif /* __ASSEMBLY__ */
#endif /* __ASM_KVM_PTRAUTH_H */
Loading