git: a4f0e93c5142 - main - arm64/vmm: Set and use the fine-grained traps

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 03 Feb 2026 17:27:50 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=a4f0e93c514280bfd0ff3897e5171ec7bbe4796b

commit a4f0e93c514280bfd0ff3897e5171ec7bbe4796b
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2026-02-03 17:14:44 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-02-03 17:14:44 +0000

    arm64/vmm: Set and use the fine-grained traps
    
    Set the Fine-grained trap registers to trap any features we don't
    support. These are expected to be more useful when we support nested
    virtualisation, so for now just the base features and GICv3 are not
    trapped.
    
    As nested virtualisation will require VHE we only set the fine-grained
    trap registers when VHE is used.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D54687
---
 sys/arm64/vmm/arm64.h     |  16 ++
 sys/arm64/vmm/vmm_hyp.c   |  22 +++
 sys/arm64/vmm/vmm_reset.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 443 insertions(+)

diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h
index 1b8762545925..6062d1c07ae4 100644
--- a/sys/arm64/vmm/arm64.h
+++ b/sys/arm64/vmm/arm64.h
@@ -100,6 +100,22 @@ struct hypctx {
 	uint64_t	mdcr_el2;	/* Monitor Debug Configuration Register */
 	uint64_t	vpidr_el2;	/* Virtualization Processor ID Register */
 	uint64_t	vmpidr_el2;	/* Virtualization Multiprocessor ID Register */
+
+	/* FEAT_FGT registers */
+	/*uint64_t	hafgrtr_el2; *//* For FEAT_AMUv1 (not supported) */
+	uint64_t	hdfgrtr_el2;
+	uint64_t	hdfgwtr_el2;
+	uint64_t	hfgitr_el2;
+	uint64_t	hfgrtr_el2;
+	uint64_t	hfgwtr_el2;
+
+	/* FEAT_FGT2 registers */
+	uint64_t	hdfgrtr2_el2;
+	uint64_t	hdfgwtr2_el2;
+	uint64_t	hfgitr2_el2;
+	uint64_t	hfgrtr2_el2;
+	uint64_t	hfgwtr2_el2;
+
 	uint64_t	el2_addr;	/* The address of this in el2 space */
 	struct hyp	*hyp;
 	struct vcpu	*vcpu;
diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c
index 0ad7930e9a87..75c15f06dd08 100644
--- a/sys/arm64/vmm/vmm_hyp.c
+++ b/sys/arm64/vmm/vmm_hyp.c
@@ -293,6 +293,28 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	}
 	isb();
 
+#ifdef VMM_VHE
+	if (guest) {
+		/* Fine-grained trap controls */
+		if ((hyp->feats & HYP_FEAT_FGT) != 0) {
+			WRITE_SPECIALREG(HDFGWTR_EL2_REG, hypctx->hdfgwtr_el2);
+			WRITE_SPECIALREG(HFGITR_EL2_REG, hypctx->hfgitr_el2);
+			WRITE_SPECIALREG(HFGRTR_EL2_REG, hypctx->hfgrtr_el2);
+			WRITE_SPECIALREG(HFGWTR_EL2_REG, hypctx->hfgwtr_el2);
+		}
+
+		if ((hyp->feats & HYP_FEAT_FGT2) != 0) {
+			WRITE_SPECIALREG(HDFGRTR2_EL2_REG,
+			    hypctx->hdfgrtr2_el2);
+			WRITE_SPECIALREG(HDFGWTR2_EL2_REG,
+			    hypctx->hdfgwtr2_el2);
+			WRITE_SPECIALREG(HFGITR2_EL2_REG, hypctx->hfgitr2_el2);
+			WRITE_SPECIALREG(HFGRTR2_EL2_REG, hypctx->hfgrtr2_el2);
+			WRITE_SPECIALREG(HFGWTR2_EL2_REG, hypctx->hfgwtr2_el2);
+		}
+	}
+#endif
+
 	WRITE_SPECIALREG(sp_el0, hypctx->sp_el0);
 	WRITE_SPECIALREG(tpidr_el0, hypctx->tpidr_el0);
 	WRITE_SPECIALREG(tpidrro_el0, hypctx->tpidrro_el0);
diff --git a/sys/arm64/vmm/vmm_reset.c b/sys/arm64/vmm/vmm_reset.c
index 06ac6dec5af8..fd3414ecd066 100644
--- a/sys/arm64/vmm/vmm_reset.c
+++ b/sys/arm64/vmm/vmm_reset.c
@@ -187,4 +187,409 @@ reset_vm_el2_regs(void *vcpu)
 	el2ctx->tf.tf_spsr = PSR_D | PSR_A | PSR_I | PSR_F;
 	/* Use the EL1 stack when taking exceptions to EL1 */
 	el2ctx->tf.tf_spsr |= PSR_M_EL1h;
+
+	/* FEAT_FGT traps */
+	if ((el2ctx->hyp->feats & HYP_FEAT_FGT) != 0) {
+#define	HFGT_TRAP_FIELDS(read, write, read_pfx, write_pfx, name, trap)	\
+do {									\
+	el2ctx->read |= read_pfx ## _EL2_ ## name ## _ ## trap;		\
+	el2ctx->write |= write_pfx ## _EL2_ ## name ## _ ## trap;	\
+} while (0)
+
+
+		/*
+		 * Traps for special registers
+		 */
+
+		/* Debug registers */
+		el2ctx->hdfgrtr_el2 = 0;
+		el2ctx->hdfgwtr_el2 = 0;
+
+		/* FEAT_BRBE */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    nBRBDATA, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    nBRBCTL, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_nBRBIDR_TRAP;
+
+		/* FEAT_TRBE */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBTRG_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBSR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBPTR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBMAR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBLIMITR_EL1, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_TRBIDR_EL1_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRBBASER_EL1, TRAP);
+
+		/* FEAT_TRF */
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_TRFCR_EL1_TRAP;
+
+		/* FEAT_ETE */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCVICTLR, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_TRCSTATR_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCSSCSRn, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCSEQSTR, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCPRGCTLR, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_TRCOSLSR_TRAP;
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_TRCOSLAR_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCIMSPECn, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_TRCID_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCCNTVRn, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCCLAIM, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRCAUXCTLR, TRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_TRCAUTHSTATUS_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    TRC, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSLATFR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSIRR_EL1, TRAP);
+
+		/* FEAT_SPE */
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_PMBIDR_EL1_TRAP;
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_PMSIDR_EL1_TRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSICR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSFCR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSEVFR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSCR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMBSR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMBPTR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMBLIMITR_EL1, TRAP);
+
+		/* FEAT_SPE_FnE */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    nPMSNEVFR_EL1, TRAP);
+
+		/* FEAT_PMUv3 */
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_PMCEIDn_EL0_NOTRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMUSERENR_EL0, NOTRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_PMMIR_EL1_NOTRAP;
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_PMCR_EL0_NOTRAP;
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_PMSWINC_EL0_NOTRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMSELR_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMOVS, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMINTEN, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMCNTEN, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMCCNTR_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMCCFILTR_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMEVTYPERn_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    PMEVCNTRn_EL0, NOTRAP);
+
+		/* FEAT_DoubleLock */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    OSDLR_EL1, TRAP);
+
+		/* Base architecture */
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    OSECCR_EL1, NOTRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_OSLSR_EL1_NOTRAP;
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_OSLAR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    DBGPRCR_EL1, NOTRAP);
+		el2ctx->hdfgrtr_el2 |= HDFGRTR_EL2_DBGAUTHSTATUS_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    DBGCLAIM, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    MDSCR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    DBGWVRn_EL1, NOTRAP);
+		el2ctx->hdfgwtr_el2 |= HDFGWTR_EL2_DBGWCRn_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    DBGBVRn_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hdfgrtr_el2, hdfgwtr_el2, HDFGRTR, HDFGWTR,
+		    DBGBCRn_EL1, NOTRAP);
+
+
+		/* Non-debug special registers */
+		el2ctx->hfgrtr_el2 = 0;
+		el2ctx->hfgwtr_el2 = 0;
+
+		/* FEAT_AIE */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nAMAIR2_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nMAIR2_EL1, TRAP);
+
+		/* FEAT_S2POE */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nS2POR_EL1, TRAP);
+
+		/* FEAT_S1POE */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nPOR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nPOR_EL0, TRAP);
+
+		/* FEAT_S1PIE */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nPIR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nPIRE0_EL1, TRAP);
+
+		/* FEAT_THE */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nRCWMASK_EL1, TRAP);
+
+		/* FEAT_SME */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nTPIDR2_EL0, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nSMPRI_EL1, TRAP);
+
+		/* FEAT_GCS */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nGCS_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nGCS_EL0, TRAP);
+
+		/* FEAT_LS64_ACCDATA */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    nACCDATA_EL1, TRAP);
+
+		/* FEAT_RASv1p1 */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXPFGCDN_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXPFGCTL_EL1, TRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_ERXPFGF_EL1_TRAP;
+
+		/* FEAT_RAS */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXADDR_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXMISCn_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXSTATUS_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERXCTLR_EL1, TRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_ERXFR_EL1_TRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ERRSELR_EL1, TRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_ERRIDR_EL1_TRAP;
+
+		/* GICv3 */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ICC_IGRPENn_EL1, NOTRAP);
+
+		/* FEAT_LOR */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    LORSA_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    LORN_EL1, TRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_LORID_EL1_TRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    LOREA_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    LORC_EL1, TRAP);
+
+		/* FEAT_PAuth */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    APIBKey, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    APIAKey, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    APGAKey, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    APDBKey, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    APDAKey, TRAP);
+
+		/* Base architecture */
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    VBAR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TTBR1_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TTBR0_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TPIDR_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TPIDRRO_EL0, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TPIDR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    TCR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    SCXTNUM_EL0, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    SCXTNUM_EL1, TRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    SCTLR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_REVIDR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    PAR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_MPIDR_EL1_NOTRAP;
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_MIDR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    MAIR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_ISR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    FAR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    ESR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_DCZID_EL0_NOTRAP;
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_CTR_EL0_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    CSSELR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    CPACR_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    CONTEXTIDR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_CLIDR_EL1_NOTRAP;
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_CCSIDR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    AMAIR_EL1, NOTRAP);
+		el2ctx->hfgrtr_el2 |= HFGRTR_EL2_AIDR_EL1_NOTRAP;
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    AFSR1_EL1, NOTRAP);
+		HFGT_TRAP_FIELDS(hfgrtr_el2, hfgwtr_el2, HFGRTR, HFGWTR,
+		    AFSR0_EL1, NOTRAP);
+
+		/*
+		 * Traps for instructions
+		 */
+
+		/* Enable all TLBI, cache and AT variants */
+		el2ctx->hfgitr_el2 = 0;
+
+		/* FEAT_ATS1A */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_ATS1E1A_TRAP;
+
+		/* FEAT_SPECRES2 */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_COSPRCTX_TRAP;
+
+		/* FEAT_GCS */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_nGCSEPP_TRAP |
+		    HFGITR_EL2_nGCSSTR_EL1_TRAP |
+		    HFGITR_EL2_nGCSPUSHM_EL1_TRAP;
+
+		/* FEAT_BRBE */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_nBRBIALL_TRAP |
+		    HFGITR_EL2_nBRBINJ_TRAP;
+
+		/* FEAT_SPECRES */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_CPPRCTX_TRAP |
+		    HFGITR_EL2_DVPRCTX_TRAP |
+		    HFGITR_EL2_CFPRCTX_TRAP;
+
+		/* FEAT_TLBIRANGE */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_TLBIRVAALE1_TRAP |
+		    HFGITR_EL2_TLBIRVALE1_TRAP |
+		    HFGITR_EL2_TLBIRVAAE1_TRAP |
+		    HFGITR_EL2_TLBIRVAE1_TRAP |
+		    HFGITR_EL2_TLBIRVAALE1IS_TRAP |
+		    HFGITR_EL2_TLBIRVALE1IS_TRAP |
+		    HFGITR_EL2_TLBIRVAAE1IS_TRAP |
+		    HFGITR_EL2_TLBIRVAE1IS_TRAP;
+
+		/* FEAT_TLBIRANGE && FEAT_TLBIOS */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_TLBIRVAALE1OS_TRAP |
+		    HFGITR_EL2_TLBIRVALE1OS_TRAP |
+		    HFGITR_EL2_TLBIRVAAE1OS_TRAP |
+		    HFGITR_EL2_TLBIRVAE1OS_TRAP;
+
+		/* FEAT_TLBIOS */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_TLBIVAALE1OS_TRAP |
+		    HFGITR_EL2_TLBIVALE1OS_TRAP |
+		    HFGITR_EL2_TLBIVAAE1OS_TRAP |
+		    HFGITR_EL2_TLBIASIDE1OS_TRAP |
+		    HFGITR_EL2_TLBIVAE1OS_TRAP |
+		    HFGITR_EL2_TLBIVMALLE1OS_TRAP;
+
+		/* FEAT_PAN2 */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_ATS1E1WP_TRAP |
+		    HFGITR_EL2_ATS1E1RP_TRAP;
+
+		/* FEAT_DPB2 */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_DCCVADP_TRAP;
+
+		/* Base architecture */
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_DCCVAC_NOTRAP |
+		    HFGITR_EL2_SVC_EL1_NOTRAP |
+		    HFGITR_EL2_SVC_EL0_NOTRAP |
+		    HFGITR_EL2_ERET_NOTRAP;
+
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_TLBIVAALE1_NOTRAP |
+		    HFGITR_EL2_TLBIVALE1_NOTRAP |
+		    HFGITR_EL2_TLBIVAAE1_NOTRAP |
+		    HFGITR_EL2_TLBIASIDE1_NOTRAP |
+		    HFGITR_EL2_TLBIVAE1_NOTRAP |
+		    HFGITR_EL2_TLBIVMALLE1_NOTRAP |
+		    HFGITR_EL2_TLBIVAALE1IS_NOTRAP |
+		    HFGITR_EL2_TLBIVALE1IS_NOTRAP |
+		    HFGITR_EL2_TLBIVAAE1IS_NOTRAP |
+		    HFGITR_EL2_TLBIASIDE1IS_NOTRAP |
+		    HFGITR_EL2_TLBIVAE1IS_NOTRAP |
+		    HFGITR_EL2_TLBIVMALLE1IS_NOTRAP;
+
+		el2ctx->hfgitr_el2 |=
+		    HFGITR_EL2_ATS1E0W_NOTRAP |
+		    HFGITR_EL2_ATS1E0R_NOTRAP |
+		    HFGITR_EL2_ATS1E1W_NOTRAP |
+		    HFGITR_EL2_ATS1E1R_NOTRAP |
+		    HFGITR_EL2_DCZVA_NOTRAP |
+		    HFGITR_EL2_DCCIVAC_NOTRAP |
+		    HFGITR_EL2_DCCVAP_NOTRAP |
+		    HFGITR_EL2_DCCVAU_NOTRAP |
+		    HFGITR_EL2_DCCISW_NOTRAP |
+		    HFGITR_EL2_DCCSW_NOTRAP |
+		    HFGITR_EL2_DCISW_NOTRAP |
+		    HFGITR_EL2_DCIVAC_NOTRAP |
+		    HFGITR_EL2_ICIVAU_NOTRAP |
+		    HFGITR_EL2_ICIALLU_NOTRAP |
+		    HFGITR_EL2_ICIALLUIS_NOTRAP;
+
+	}
+
+	/* FEAT_FGT2 traps */
+	if ((el2ctx->hyp->feats & HYP_FEAT_FGT2) != 0) {
+		/* Trap everything here until we support the feature */
+		el2ctx->hdfgrtr2_el2 = 0;
+		el2ctx->hdfgwtr2_el2 = 0;
+		el2ctx->hfgitr2_el2 = 0;
+		el2ctx->hfgrtr2_el2 = 0;
+		el2ctx->hfgwtr2_el2 = 0;
+	}
 }