Commit cb6cd8a8 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

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



* kvm-arm64/feat_idst:
  : .
  : Add support for FEAT_IDST, allowing ID registers that are not implemented
  : to be reported as a normal trap rather than as an UNDEF exception.
  : .
  KVM: arm64: selftests: Add a test for FEAT_IDST
  KVM: arm64: pkvm: Report optional ID register traps with a 0x18 syndrome
  KVM: arm64: pkvm: Add a generic synchronous exception injection primitive
  KVM: arm64: Force trap of GMID_EL1 when the guest doesn't have MTE
  KVM: arm64: Handle CSSIDR2_EL1 and SMIDR_EL1 in a generic way
  KVM: arm64: Handle FEAT_IDST for sysregs without specific handlers
  KVM: arm64: Add a generic synchronous exception injection primitive
  KVM: arm64: Add trap routing for GMID_EL1
  arm64: Repaint ID_AA64MMFR2_EL1.IDS description

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 7c652c0d b638a9d0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu);

void kvm_inject_undefined(struct kvm_vcpu *vcpu);
void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
+21 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ enum cgt_group_id {
	CGT_HCR_ENSCXT,
	CGT_HCR_TTLBIS,
	CGT_HCR_TTLBOS,
	CGT_HCR_TID5,

	CGT_MDCR_TPMCR,
	CGT_MDCR_TPM,
@@ -308,6 +309,12 @@ static const struct trap_bits coarse_trap_bits[] = {
		.mask		= HCR_TTLBOS,
		.behaviour	= BEHAVE_FORWARD_RW,
	},
	[CGT_HCR_TID5] = {
		.index		= HCR_EL2,
		.value		= HCR_TID5,
		.mask		= HCR_TID5,
		.behaviour	= BEHAVE_FORWARD_RW,
	},
	[CGT_MDCR_TPMCR] = {
		.index		= MDCR_EL2,
		.value		= MDCR_EL2_TPMCR,
@@ -665,6 +672,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
	SR_TRAP(SYS_CCSIDR2_EL1,	CGT_HCR_TID2_TID4),
	SR_TRAP(SYS_CLIDR_EL1,		CGT_HCR_TID2_TID4),
	SR_TRAP(SYS_CSSELR_EL1,		CGT_HCR_TID2_TID4),
	SR_TRAP(SYS_GMID_EL1,		CGT_HCR_TID5),
	SR_RANGE_TRAP(SYS_ID_PFR0_EL1,
		      sys_reg(3, 0, 0, 7, 7), CGT_HCR_TID3),
	SR_TRAP(SYS_ICC_SGI0R_EL1,	CGT_HCR_IMO_FMO_ICH_HCR_TC),
@@ -2587,6 +2595,19 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)

		params = esr_sys64_to_params(esr);

		/*
		 * This implements the pseudocode UnimplementedIDRegister()
		 * helper for the purpose of dealing with FEAT_IDST.
		 */
		if (in_feat_id_space(&params)) {
			if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, IMP))
				kvm_inject_sync(vcpu, kvm_vcpu_get_esr(vcpu));
			else
				kvm_inject_undefined(vcpu);

			return true;
		}

		/*
		 * Check for the IMPDEF range, as per DDI0487 J.a,
		 * D18.3.2 Reserved encodings for IMPLEMENTATION
+31 −8
Original line number Diff line number Diff line
@@ -134,7 +134,7 @@ static const struct pvm_ftr_bits pvmid_aa64mmfr2[] = {
	MAX_FEAT(ID_AA64MMFR2_EL1, UAO, IMP),
	MAX_FEAT(ID_AA64MMFR2_EL1, IESB, IMP),
	MAX_FEAT(ID_AA64MMFR2_EL1, AT, IMP),
	MAX_FEAT_ENUM(ID_AA64MMFR2_EL1, IDS, 0x18),
	MAX_FEAT(ID_AA64MMFR2_EL1, IDS, IMP),
	MAX_FEAT(ID_AA64MMFR2_EL1, TTL, IMP),
	MAX_FEAT(ID_AA64MMFR2_EL1, BBM, 2),
	MAX_FEAT(ID_AA64MMFR2_EL1, E0PD, IMP),
@@ -243,16 +243,15 @@ static u64 pvm_calc_id_reg(const struct kvm_vcpu *vcpu, u32 id)
	}
}

/*
 * Inject an unknown/undefined exception to an AArch64 guest while most of its
 * sysregs are live.
 */
static void inject_undef64(struct kvm_vcpu *vcpu)
static void inject_sync64(struct kvm_vcpu *vcpu, u64 esr)
{
	u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);

	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
	*vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);

	/*
	 * Make sure we have the latest update to VBAR_EL1, as pKVM
	 * handles traps very early, before sysregs are resync'ed
	 */
	__vcpu_assign_sys_reg(vcpu, VBAR_EL1, read_sysreg_el1(SYS_VBAR));

	kvm_pend_exception(vcpu, EXCEPT_AA64_EL1_SYNC);
@@ -265,6 +264,15 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
	write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
}

/*
 * Inject an unknown/undefined exception to an AArch64 guest while most of its
 * sysregs are live.
 */
static void inject_undef64(struct kvm_vcpu *vcpu)
{
	inject_sync64(vcpu, (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT));
}

static u64 read_id_reg(const struct kvm_vcpu *vcpu,
		       struct sys_reg_desc const *r)
{
@@ -339,6 +347,18 @@ static bool pvm_gic_read_sre(struct kvm_vcpu *vcpu,
	return true;
}

static bool pvm_idst_access(struct kvm_vcpu *vcpu,
			    struct sys_reg_params *p,
			    const struct sys_reg_desc *r)
{
	if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, IMP))
		inject_sync64(vcpu, kvm_vcpu_get_esr(vcpu));
	else
		inject_undef64(vcpu);

	return false;
}

/* Mark the specified system register as an AArch32 feature id register. */
#define AARCH32(REG) { SYS_DESC(REG), .access = pvm_access_id_aarch32 }

@@ -469,6 +489,9 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {

	HOST_HANDLED(SYS_CCSIDR_EL1),
	HOST_HANDLED(SYS_CLIDR_EL1),
	{ SYS_DESC(SYS_CCSIDR2_EL1), .access = pvm_idst_access },
	{ SYS_DESC(SYS_GMID_EL1), .access = pvm_idst_access },
	{ SYS_DESC(SYS_SMIDR_EL1), .access = pvm_idst_access },
	HOST_HANDLED(SYS_AIDR_EL1),
	HOST_HANDLED(SYS_CSSELR_EL1),
	HOST_HANDLED(SYS_CTR_EL0),
+7 −3
Original line number Diff line number Diff line
@@ -162,12 +162,16 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
}

void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr)
{
	pend_sync_exception(vcpu);
	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
}

static void inject_undef64(struct kvm_vcpu *vcpu)
{
	u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);

	pend_sync_exception(vcpu);

	/*
	 * Build an unknown exception, depending on the instruction
	 * set.
@@ -175,7 +179,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
	if (kvm_vcpu_trap_il_is32bit(vcpu))
		esr |= ESR_ELx_IL;

	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
	kvm_inject_sync(vcpu, esr);
}

#define DFSR_FSC_EXTABT_LPAE	0x10
+2 −2
Original line number Diff line number Diff line
@@ -3414,8 +3414,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
	{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
	{ SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
	  .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
	{ SYS_DESC(SYS_CCSIDR2_EL1), undef_access },
	{ SYS_DESC(SYS_SMIDR_EL1), undef_access },
	IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)),
	{ SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
	ID_FILTERED(CTR_EL0, ctr_el0,
@@ -5581,6 +5579,8 @@ static void vcpu_set_hcr(struct kvm_vcpu *vcpu)

	if (kvm_has_mte(vcpu->kvm))
		vcpu->arch.hcr_el2 |= HCR_ATA;
	else
		vcpu->arch.hcr_el2 |= HCR_TID5;

	/*
	 * In the absence of FGT, we cannot independently trap TLBI
Loading