Commit 091258a0 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

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



* kvm-arm64/fpmr:
  : .
  : Add FP8 support to the KVM/arm64 floating point handling.
  :
  : This includes new ID registers (ID_AA64PFR2_EL1 ID_AA64FPFR0_EL1)
  : being made visible to guests, as well as a new confrol register
  : (FPMR) which gets context-switched.
  : .
  KVM: arm64: Expose ID_AA64PFR2_EL1 to userspace and guests
  KVM: arm64: Enable FP8 support when available and configured
  KVM: arm64: Expose ID_AA64FPFR0_EL1 as a writable ID reg
  KVM: arm64: Honor trap routing for FPMR
  KVM: arm64: Add save/restore support for FPMR
  KVM: arm64: Move FPMR into the sysreg array
  KVM: arm64: Add predicate for FPMR support in a VM
  KVM: arm64: Move SVCR into the sysreg array

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 8884fd12 13c7a51e
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -446,6 +446,10 @@ enum vcpu_sysreg {
	GCR_EL1,	/* Tag Control Register */
	TFSRE0_EL1,	/* Tag Fault Status Register (EL0) */

	/* FP/SIMD/SVE */
	SVCR,
	FPMR,

	/* 32bit specific registers. */
	DACR32_EL2,	/* Domain Access Control Register */
	IFSR32_EL2,	/* Instruction Fault Status Register */
@@ -595,6 +599,16 @@ struct kvm_host_data {
		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
		 */
		u64	fpmr;
	};

	/* Ownership of the FP regs */
	enum {
		FP_STATE_FREE,
@@ -664,8 +678,6 @@ struct kvm_vcpu_arch {
	void *sve_state;
	enum fp_type fp_type;
	unsigned int sve_max_vl;
	u64 svcr;
	u64 fpmr;

	/* Stage 2 paging state used by the hardware on next switch */
	struct kvm_s2_mmu *hw_mmu;
@@ -1473,4 +1485,8 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
		(pa + pi + pa3) == 1;					\
	})

#define kvm_has_fpmr(k)					\
	(system_supports_fpmr() &&			\
	 kvm_has_feat((k), ID_AA64PFR2_EL1, FPMR, IMP))

#endif /* __ARM64_KVM_HOST_H__ */
+8 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ enum cgt_group_id {
	CGT_CPTR_TAM,
	CGT_CPTR_TCPAC,

	CGT_HCRX_EnFPM,
	CGT_HCRX_TCR2En,

	/*
@@ -372,6 +373,12 @@ static const struct trap_bits coarse_trap_bits[] = {
		.mask		= CPTR_EL2_TCPAC,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_HCRX_EnFPM] = {
		.index		= HCRX_EL2,
		.value 		= 0,
		.mask		= HCRX_EL2_EnFPM,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_HCRX_TCR2En] = {
		.index		= HCRX_EL2,
		.value 		= 0,
@@ -1108,6 +1115,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
	SR_TRAP(SYS_CNTP_CTL_EL0,	CGT_CNTHCTL_EL1PTEN),
	SR_TRAP(SYS_CNTPCT_EL0,		CGT_CNTHCTL_EL1PCTEN),
	SR_TRAP(SYS_CNTPCTSS_EL0,	CGT_CNTHCTL_EL1PCTEN),
	SR_TRAP(SYS_FPMR,		CGT_HCRX_EnFPM),
};

static DEFINE_XARRAY(sr_forward_xa);
+3 −2
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
	 */
	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
	*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
	*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);

	vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
	if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -134,8 +135,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
		fp_state.sve_state = vcpu->arch.sve_state;
		fp_state.sve_vl = vcpu->arch.sve_max_vl;
		fp_state.sme_state = NULL;
		fp_state.svcr = &vcpu->arch.svcr;
		fp_state.fpmr = &vcpu->arch.fpmr;
		fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR);
		fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR);
		fp_state.fp_type = &vcpu->arch.fp_type;

		if (vcpu_has_sve(vcpu))
+3 −0
Original line number Diff line number Diff line
@@ -403,6 +403,9 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
	else
		__fpsimd_restore_state(&vcpu->arch.ctxt.fp_regs);

	if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
		write_sysreg_s(__vcpu_sys_reg(vcpu, FPMR), SYS_FPMR);

	/* Skip restoring fpexc32 for AArch64 guests */
	if (!(read_sysreg(hcr_el2) & HCR_RW))
		write_sysreg(__vcpu_sys_reg(vcpu, FPEXC32_EL2), fpexc32_el2);
+9 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ static void fpsimd_sve_flush(void)

static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
{
	bool has_fpmr;

	if (!guest_owns_fp_regs())
		return;

@@ -73,11 +75,18 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
	else
		__fpsimd_save_state(&vcpu->arch.ctxt.fp_regs);

	has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm));
	if (has_fpmr)
		__vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR);

	if (system_supports_sve())
		__hyp_sve_restore_host();
	else
		__fpsimd_restore_state(*host_data_ptr(fpsimd_state));

	if (has_fpmr)
		write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);

	*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
}

Loading