Commit 15a1ba8d authored by Marc Zyngier's avatar Marc Zyngier
Browse files

KVM: arm64: Add trap routing information for ICH_HCR_EL2



The usual song and dance. Anything that is a trap, any register
it traps. Note that we don't handle the registers added by
FEAT_NMI for now.

Reviewed-by: default avatarOliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20240827152517.3909653-8-maz@kernel.org


Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 9f5deace
Loading
Loading
Loading
Loading
+66 −5
Original line number Diff line number Diff line
@@ -85,12 +85,17 @@ enum cgt_group_id {

	CGT_HCRX_TCR2En,

	CGT_ICH_HCR_TC,
	CGT_ICH_HCR_TALL0,
	CGT_ICH_HCR_TALL1,
	CGT_ICH_HCR_TDIR,

	/*
	 * Anything after this point is a combination of coarse trap
	 * controls, which must all be evaluated to decide what to do.
	 */
	__MULTIPLE_CONTROL_BITS__,
	CGT_HCR_IMO_FMO = __MULTIPLE_CONTROL_BITS__,
	CGT_HCR_IMO_FMO_ICH_HCR_TC = __MULTIPLE_CONTROL_BITS__,
	CGT_HCR_TID2_TID4,
	CGT_HCR_TTLB_TTLBIS,
	CGT_HCR_TTLB_TTLBOS,
@@ -105,6 +110,8 @@ enum cgt_group_id {
	CGT_MDCR_TDE_TDRA,
	CGT_MDCR_TDCC_TDE_TDA,

	CGT_ICH_HCR_TC_TDIR,

	/*
	 * Anything after this point requires a callback evaluating a
	 * complex trap condition. Ugly stuff.
@@ -378,6 +385,30 @@ static const struct trap_bits coarse_trap_bits[] = {
		.mask		= HCRX_EL2_TCR2En,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_ICH_HCR_TC] = {
		.index		= ICH_HCR_EL2,
		.value		= ICH_HCR_TC,
		.mask		= ICH_HCR_TC,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_ICH_HCR_TALL0] = {
		.index		= ICH_HCR_EL2,
		.value		= ICH_HCR_TALL0,
		.mask		= ICH_HCR_TALL0,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_ICH_HCR_TALL1] = {
		.index		= ICH_HCR_EL2,
		.value		= ICH_HCR_TALL1,
		.mask		= ICH_HCR_TALL1,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
	[CGT_ICH_HCR_TDIR] = {
		.index		= ICH_HCR_EL2,
		.value		= ICH_HCR_TDIR,
		.mask		= ICH_HCR_TDIR,
		.behaviour	= BEHAVE_FORWARD_ANY,
	},
};

#define MCB(id, ...)						\
@@ -387,7 +418,6 @@ static const struct trap_bits coarse_trap_bits[] = {
		}

static const enum cgt_group_id *coarse_control_combo[] = {
	MCB(CGT_HCR_IMO_FMO,		CGT_HCR_IMO, CGT_HCR_FMO),
	MCB(CGT_HCR_TID2_TID4,		CGT_HCR_TID2, CGT_HCR_TID4),
	MCB(CGT_HCR_TTLB_TTLBIS,	CGT_HCR_TTLB, CGT_HCR_TTLBIS),
	MCB(CGT_HCR_TTLB_TTLBOS,	CGT_HCR_TTLB, CGT_HCR_TTLBOS),
@@ -402,6 +432,9 @@ static const enum cgt_group_id *coarse_control_combo[] = {
	MCB(CGT_MDCR_TDE_TDOSA,		CGT_MDCR_TDE, CGT_MDCR_TDOSA),
	MCB(CGT_MDCR_TDE_TDRA,		CGT_MDCR_TDE, CGT_MDCR_TDRA),
	MCB(CGT_MDCR_TDCC_TDE_TDA,	CGT_MDCR_TDCC, CGT_MDCR_TDE, CGT_MDCR_TDA),

	MCB(CGT_HCR_IMO_FMO_ICH_HCR_TC,	CGT_HCR_IMO, CGT_HCR_FMO, CGT_ICH_HCR_TC),
	MCB(CGT_ICH_HCR_TC_TDIR,	CGT_ICH_HCR_TC, CGT_ICH_HCR_TDIR),
};

typedef enum trap_behaviour (*complex_condition_check)(struct kvm_vcpu *);
@@ -536,9 +569,9 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
	SR_TRAP(SYS_CSSELR_EL1,		CGT_HCR_TID2_TID4),
	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),
	SR_TRAP(SYS_ICC_ASGI1R_EL1,	CGT_HCR_IMO_FMO),
	SR_TRAP(SYS_ICC_SGI1R_EL1,	CGT_HCR_IMO_FMO),
	SR_TRAP(SYS_ICC_SGI0R_EL1,	CGT_HCR_IMO_FMO_ICH_HCR_TC),
	SR_TRAP(SYS_ICC_ASGI1R_EL1,	CGT_HCR_IMO_FMO_ICH_HCR_TC),
	SR_TRAP(SYS_ICC_SGI1R_EL1,	CGT_HCR_IMO_FMO_ICH_HCR_TC),
	SR_RANGE_TRAP(sys_reg(3, 0, 11, 0, 0),
		      sys_reg(3, 0, 11, 15, 7), CGT_HCR_TIDCP),
	SR_RANGE_TRAP(sys_reg(3, 1, 11, 0, 0),
@@ -1108,6 +1141,34 @@ 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),
	/*
	 * IMPDEF choice:
	 * We treat ICC_SRE_EL2.{SRE,Enable) and ICV_SRE_EL1.SRE as
	 * RAO/WI. We therefore never consider ICC_SRE_EL2.Enable for
	 * ICC_SRE_EL1 access, and always handle it locally.
	 */
	SR_TRAP(SYS_ICC_AP0R0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_AP0R1_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_AP0R2_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_AP0R3_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_AP1R0_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_AP1R1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_AP1R2_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_AP1R3_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_BPR0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_BPR1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_CTLR_EL1,	CGT_ICH_HCR_TC),
	SR_TRAP(SYS_ICC_DIR_EL1,	CGT_ICH_HCR_TC_TDIR),
	SR_TRAP(SYS_ICC_EOIR0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_EOIR1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_HPPIR0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_HPPIR1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_IAR0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_IAR1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_IGRPEN0_EL1,	CGT_ICH_HCR_TALL0),
	SR_TRAP(SYS_ICC_IGRPEN1_EL1,	CGT_ICH_HCR_TALL1),
	SR_TRAP(SYS_ICC_PMR_EL1,	CGT_ICH_HCR_TC),
	SR_TRAP(SYS_ICC_RPR_EL1,	CGT_ICH_HCR_TC),
};

static DEFINE_XARRAY(sr_forward_xa);