All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV
@ 2026-09-17 21:42 Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1 Wei-Lin Chang
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-17 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland, Jonathan Cameron, Mark Brown, Sascha Bischoff,
	James Clark, Lorenzo Pieralisi, Anshuman Khandual, Thomas Huth,
	Ganapatrao Kulkarni, Wei-Lin Chang

Hi,

This v2 fixes a few naming and styling issues, collects Mark's
Reviewed-by tag, and adds Marc's TCR_EL2 reset patch [1]. Please see
details below.

* Changes from v1 [2]:

  - Renamed tcr_el2_vhe_* to vhe_tcr_el2_*, rename tcr_el2_nvhe_* to
    tcr_el2_* to better align with the TCR_EL2 macros. (Marc)

  - Added Marc's TCR_EL2 reset patch (thanks!).

  - Put each == comparison on one line. (Marc)

  - Added Fixes and Cc: stable tags to patch 1.

  - Collected Reviewed-by tag from Mark (thanks!).

Series based on v7.3-rc3.

Below is the same cover from v1:

Previously for NV FEAT_LPA2 is accidentally exposed to the guest at
stage-1 if hardware supports it. Stage-2 is correctly sanitised out in
ID_AA64MMFR0_EL1 but not stage-1. This is wrong on two fronts:

- There is no FEAT_LPA2 support for NV yet.
- It is non-architectural to advertise different FEAT_LPA2 support in
  stage-1 and stage-2.

This series first removes FEAT_LPA2 from TGRAN4, TGRAN16 for NV, to
present a !FEAT_LPA2 system. Then guest TCR_EL2 sanitisation is added,
to make the DS bit RES0 for NV guests. Note that this sanitisation
can't cover all cases, as we don't trap VHE L1 accesses to the vCPU's
TCR_EL2 via TCR_EL1.

TCR_EL2 sanitisation differs slightly from the AARCHMRS, please see the
commits for details.

For testing I booted a 4K 52-bit nVHE L1 and checked:
1. It is using 48-bit VAs in stage-1.
2. Writing 1 to TCR_EL2.DS and reading it back reads 0.

Thanks!

[1]: https://lore.kernel.org/kvmarm/86pkyk6us5.wl-maz@kernel.org/
[2]: https://lore.kernel.org/kvmarm/20260909222015.3046432-1-weilin.chang@arm.com/

Marc Zyngier (1):
  KVM: arm64: Reset TCR_EL2 according to guest's E2H mode

Wei-Lin Chang (3):
  KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1
  arm64: sysreg: Add TCR_EL2 to sysreg infrastructure
  KVM: arm64: Convert TCR_EL2 to config-driven sanitisation

 arch/arm64/include/asm/kvm_arm.h  |  13 ----
 arch/arm64/include/asm/kvm_host.h |   2 +-
 arch/arm64/include/asm/sysreg.h   |   1 -
 arch/arm64/kvm/config.c           | 113 +++++++++++++++++++++++++++
 arch/arm64/kvm/nested.c           |  15 ++++
 arch/arm64/kvm/sys_regs.c         |  10 ++-
 arch/arm64/tools/sysreg           | 125 ++++++++++++++++++++++++++++++
 7 files changed, 263 insertions(+), 16 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1
  2026-09-17 21:42 [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV Wei-Lin Chang
@ 2026-09-17 21:42 ` Wei-Lin Chang
  2026-09-17 21:51   ` sashiko-bot
  2026-09-17 21:42 ` [PATCH v2 2/4] arm64: sysreg: Add TCR_EL2 to sysreg infrastructure Wei-Lin Chang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-17 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland, Jonathan Cameron, Mark Brown, Sascha Bischoff,
	James Clark, Lorenzo Pieralisi, Anshuman Khandual, Thomas Huth,
	Ganapatrao Kulkarni, Wei-Lin Chang, stable

There is no FEAT_LPA2 support for NV guests as of now, but we missed
limiting it for the non-stage-2 granule size fields (TGRAN4, TGRAN16) in
ID_AA64MMFR0_EL1. Add the sanitisation.

Fixes: 9f75b6d447d7 ("KVM: arm64: nv: Filter out unsupported features from ID regs")
Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
Cc: stable@vger.kernel.org
---
 arch/arm64/kvm/nested.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 3c4fc566eafc..4a860904c1ce 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1731,6 +1731,17 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
 		/* Hide CNTPOFF if present */
 		val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, ECV, IMP);
 
+		/* NV does not support FEAT_LPA2. */
+		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN4, val) == ID_AA64MMFR0_EL1_TGRAN4_52_BIT) {
+			val &= ~ID_AA64MMFR0_EL1_TGRAN4;
+			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4, IMP);
+		}
+
+		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN16, val) == ID_AA64MMFR0_EL1_TGRAN16_52_BIT) {
+			val &= ~ID_AA64MMFR0_EL1_TGRAN16;
+			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16, IMP);
+		}
+
 		/* Disallow unsupported S2 page sizes */
 		switch (PAGE_SIZE) {
 		case SZ_64K:
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/4] arm64: sysreg: Add TCR_EL2 to sysreg infrastructure
  2026-09-17 21:42 [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1 Wei-Lin Chang
@ 2026-09-17 21:42 ` Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 3/4] KVM: arm64: Reset TCR_EL2 according to guest's E2H mode Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation Wei-Lin Chang
  3 siblings, 0 replies; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-17 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland, Jonathan Cameron, Mark Brown, Sascha Bischoff,
	James Clark, Lorenzo Pieralisi, Anshuman Khandual, Thomas Huth,
	Ganapatrao Kulkarni, Wei-Lin Chang

Convert TCR_EL2 to the sysreg infrastructure with data extracted from
Registers.json of the BSD licenced AARCHMRS
(AARCHMRS_OPENSOURCE_A_profile_FAT-2026-06).

There are two formats of TCR_EL2 based on whether the effective value of
HCR_EL2.E2H is 0 or 1. For the E2H == 1 case, prefix the macros with
"VHE_". For the E2H == 0 case, the macros are left unprefixed.

Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
---
 arch/arm64/include/asm/kvm_arm.h |  13 ----
 arch/arm64/include/asm/sysreg.h  |   1 -
 arch/arm64/tools/sysreg          | 125 +++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4bfbd827c5aa..690c13d0b068 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -108,19 +108,6 @@
 #define MPAMHCR_HOST_FLAGS	0
 
 /* TCR_EL2 Registers bits */
-#define TCR_EL2_DS		(1UL << 32)
-#define TCR_EL2_RES1		((1U << 31) | (1 << 23))
-#define TCR_EL2_HPD		(1 << 24)
-#define TCR_EL2_HA		(1 << 21)
-#define TCR_EL2_TBI		(1 << 20)
-#define TCR_EL2_PS_SHIFT	16
-#define TCR_EL2_PS_MASK		(7 << TCR_EL2_PS_SHIFT)
-#define TCR_EL2_PS_40B		(2 << TCR_EL2_PS_SHIFT)
-#define TCR_EL2_TG0_MASK	TCR_TG0_MASK
-#define TCR_EL2_SH0_MASK	TCR_SH0_MASK
-#define TCR_EL2_ORGN0_MASK	TCR_ORGN0_MASK
-#define TCR_EL2_IRGN0_MASK	TCR_IRGN0_MASK
-#define TCR_EL2_T0SZ_MASK	0x3f
 #define TCR_EL2_MASK	(TCR_EL2_TG0_MASK | TCR_EL2_SH0_MASK | \
 			 TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK)
 
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 7aa08d59d494..3499e5fab39e 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -514,7 +514,6 @@
 
 #define SYS_TTBR0_EL2			sys_reg(3, 4, 2, 0, 0)
 #define SYS_TTBR1_EL2			sys_reg(3, 4, 2, 0, 1)
-#define SYS_TCR_EL2			sys_reg(3, 4, 2, 0, 2)
 #define SYS_VTTBR_EL2			sys_reg(3, 4, 2, 1, 0)
 
 #define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index e2d37ee221b8..5093598ac5f7 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -5561,6 +5561,131 @@ Res0    6
 Field   5:0     T0SZ
 EndSysreg
 
+Sysreg	TCR_EL2		3	4	2	0	2
+Prefix	VHE
+Res0	63:62
+Field	61	MTX1
+Field	60	MTX0
+Field	59	DS
+Field	58	TCMA1
+Field	57	TCMA0
+Field	56	E0PD1
+Field	55	E0PD0
+Field	54	NFD1
+Field	53	NFD0
+Field	52	TBID1
+Field	51	TBID0
+Field	50	HWU162
+Field	49	HWU161
+Field	48	HWU160
+Field	47	HWU159
+Field	46	HWU062
+Field	45	HWU061
+Field	44	HWU060
+Field	43	HWU059
+Field	42	HPD1
+Field	41	HPD0
+Field	40	HD
+Field	39	HA
+Field	38	TBI1
+Field	37	TBI0
+Field	36	AS
+Res0	35
+Field	34:32	IPS
+Enum	31:30	TG1
+	0b01	16K
+	0b10	4K
+	0b11	64K
+EndEnum
+Enum	29:28	SH1
+	0b00	NONE
+	0b10	OUTER
+	0b11	INNER
+EndEnum
+Enum	27:26	ORGN1
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Enum	25:24	IRGN1
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Field	23	EPD1
+Field	22	A1
+Field	21:16	T1SZ
+Enum	15:14	TG0
+	0b00	4K
+	0b01	64K
+	0b10	16K
+EndEnum
+Enum	13:12	SH0
+	0b00	NONE
+	0b10	OUTER
+	0b11	INNER
+EndEnum
+Enum	11:10	ORGN0
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Enum	9:8	IRGN0
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Field	7	EPD0
+Res0	6
+Field	5:0	T0SZ
+EndPrefix
+Res0	63:34
+Field	33	MTX
+Field	32	DS
+Res1	31
+Field	30	TCMA
+Field	29	TBID
+Field	28	HWU62
+Field	27	HWU61
+Field	26	HWU60
+Field	25	HWU59
+Field	24	HPD
+Res1	23
+Field	22	HD
+Field	21	HA
+Field	20	TBI
+Res0	19
+Field	18:16	PS
+Enum	15:14	TG0
+	0b00	4K
+	0b01	64K
+	0b10	16K
+EndEnum
+Enum	13:12	SH0
+	0b00	NONE
+	0b10	OUTER
+	0b11	INNER
+EndEnum
+Enum	11:10	ORGN0
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Enum	9:8	IRGN0
+	0b00	NC
+	0b01	WBWA
+	0b10	WT
+	0b11	WBnWA
+EndEnum
+Res0	7:6
+Field	5:0	T0SZ
+EndSysreg
+
 Sysreg	TCR_EL12        3	5	2	0	2
 Mapping	TCR_EL1
 EndSysreg
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/4] KVM: arm64: Reset TCR_EL2 according to guest's E2H mode
  2026-09-17 21:42 [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1 Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 2/4] arm64: sysreg: Add TCR_EL2 to sysreg infrastructure Wei-Lin Chang
@ 2026-09-17 21:42 ` Wei-Lin Chang
  2026-09-17 21:42 ` [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation Wei-Lin Chang
  3 siblings, 0 replies; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-17 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland, Jonathan Cameron, Mark Brown, Sascha Bischoff,
	James Clark, Lorenzo Pieralisi, Anshuman Khandual, Thomas Huth,
	Ganapatrao Kulkarni, Wei-Lin Chang

From: Marc Zyngier <maz@kernel.org>

Previously vCPU TCR_EL2's reset value didn't consider TCR_EL2's
different formats based on the value of HCR_EL2.E2H. It always resets to
the E2H == 0 version.

This didn't cause any problem because the bits set in the E2H == 0
version (TCR_EL2_RES1) all reset to UNKNOWN for E2H == 1 per the
architecture.

Still, it's better to fix it. Choose the correct reset value by checking
KVM_ARM_VCPU_HAS_EL2_E2H0.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
---
 arch/arm64/kvm/sys_regs.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 44aae52c473d..62c059747fbb 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -3275,6 +3275,14 @@ static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 	return vcpu->kvm->arch.nr_pmu_counters;
 }
 
+static u64 reset_tcr_el2(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+	__vcpu_assign_sys_reg(vcpu, r->reg,
+			      vcpu_has_feature(vcpu, KVM_ARM_VCPU_HAS_EL2_E2H0) ?
+			      TCR_EL2_RES1 : VHE_TCR_EL2_RES1);
+	return __vcpu_sys_reg(vcpu, r->reg);
+}
+
 /*
  * Architected system registers.
  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
@@ -3853,7 +3861,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
 	EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
-	EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
+	EL2_REG(TCR_EL2, access_rw, reset_tcr_el2, 0),
 	EL2_REG_FILTERED(TCR2_EL2, access_rw, reset_val, TCR2_EL2_RES1,
 			 tcr2_el2_visibility),
 	EL2_REG_VNCR(VTTBR_EL2, reset_val, 0),
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation
  2026-09-17 21:42 [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV Wei-Lin Chang
                   ` (2 preceding siblings ...)
  2026-09-17 21:42 ` [PATCH v2 3/4] KVM: arm64: Reset TCR_EL2 according to guest's E2H mode Wei-Lin Chang
@ 2026-09-17 21:42 ` Wei-Lin Chang
  2026-09-17 22:00   ` sashiko-bot
  3 siblings, 1 reply; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-17 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel
  Cc: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland, Jonathan Cameron, Mark Brown, Sascha Bischoff,
	James Clark, Lorenzo Pieralisi, Anshuman Khandual, Thomas Huth,
	Ganapatrao Kulkarni, Wei-Lin Chang

Feature dependencies of the fields in TCR_EL2 are extracted from
Registers.json of the BSD licenced AARCHMRS
(AARCHMRS_OPENSOURCE_A_profile_FAT-2026-06).

Places where we slightly deviate from the above:

 - Stick to the ARM ARM M.c requirement for TCR_EL2.TCMA*, which only
   depends on FEAT_MTE2. This avoids updating ID_AA64PFR2_EL1 with new
   VMTE* definitions that we don't know the meaning of, as they aren't
   present in the ARM ARM yet.

 - Ignore TCR_EL2.DS's requirement of needing the effective value of
   TCR2_EL2.D128 be 0. This requires runtime detection of TCR2_EL2.D128
   and we don't have D128 support yet.

 - TCR_EL2.AS is dependent on FEAT_ASID16, this information is missing
   from the json.

Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
---
 arch/arm64/include/asm/kvm_host.h |   2 +-
 arch/arm64/kvm/config.c           | 113 ++++++++++++++++++++++++++++++
 arch/arm64/kvm/nested.c           |   4 ++
 3 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27fe0cd5b2d7..6a5e22ca3430 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -516,7 +516,6 @@ enum vcpu_sysreg {
 	HACR_EL2,	/* Hypervisor Auxiliary Control Register */
 	TTBR0_EL2,	/* Translation Table Base Register 0 (EL2) */
 	TTBR1_EL2,	/* Translation Table Base Register 1 (EL2) */
-	TCR_EL2,	/* Translation Control Register (EL2) */
 	PIRE0_EL2,	/* Permission Indirection Register 0 (EL2) */
 	PIR_EL2,	/* Permission Indirection Register 1 (EL2) */
 	POR_EL2,	/* Permission Overlay Register 2 (EL2) */
@@ -541,6 +540,7 @@ enum vcpu_sysreg {
 	/* Anything from this can be RES0/RES1 sanitised */
 	MARKER(__SANITISED_REG_START__),
 	SCTLR_EL2,	/* System Control Register (EL2) */
+	TCR_EL2,	/* Translation Control Register (EL2) */
 	TCR2_EL2,	/* Extended Translation Control Register (EL2) */
 	SCTLR2_EL2,	/* System Control Register 2 (EL2) */
 	MDCR_EL2,	/* Monitor Debug Configuration Register (EL2) */
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 1053676551af..080b3510b783 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -203,8 +203,11 @@ struct reg_feat_map_desc {
 #define FEAT_CPA2		ID_AA64ISAR3_EL1, CPA, CPA2
 #define FEAT_ASID2		ID_AA64MMFR4_EL1, ASID2, IMP
 #define FEAT_MEC		ID_AA64MMFR3_EL1, MEC, IMP
+#define FEAT_HAF		ID_AA64MMFR1_EL1, HAFDBS, AF
 #define FEAT_HAFT		ID_AA64MMFR1_EL1, HAFDBS, HAFT
+#define FEAT_HAFDBS		ID_AA64MMFR1_EL1, HAFDBS, DBM
 #define FEAT_HDBSS		ID_AA64MMFR1_EL1, HAFDBS, HDBSS
+#define FEAT_HPDS		ID_AA64MMFR1_EL1, HPDS, IMP
 #define FEAT_HPDS2		ID_AA64MMFR1_EL1, HPDS, HPDS2
 #define FEAT_BTI		ID_AA64PFR1_EL1, BT, IMP
 #define FEAT_ExS		ID_AA64MMFR0_EL1, EXS, IMP
@@ -215,6 +218,10 @@ struct reg_feat_map_desc {
 #define FEAT_MixedEndEL0	ID_AA64MMFR0_EL1, BIGENDEL0, IMP
 #define FEAT_MTE_ASYNC		ID_AA64PFR1_EL1, MTE_frac, ASYNC
 #define FEAT_MTE_STORE_ONLY	ID_AA64PFR2_EL1, MTESTOREONLY, IMP
+#define FEAT_MTE_CANONICAL_TAGS	ID_AA64PFR1_EL1, MTEX, MTE4
+#define FEAT_MTE_NO_ADDRESS_TAGS	ID_AA64PFR1_EL1, MTEX, MTE4
+#define FEAT_E0PD		ID_AA64MMFR2_EL1, E0PD, IMP
+#define FEAT_SVE		ID_AA64PFR0_EL1, SVE, IMP
 #define FEAT_PAN		ID_AA64MMFR1_EL1, PAN, IMP
 #define FEAT_PAN3		ID_AA64MMFR1_EL1, PAN, PAN3
 #define FEAT_SSBS		ID_AA64PFR1_EL1, SSBS, IMP
@@ -227,6 +234,19 @@ struct reg_feat_map_desc {
 #define FEAT_GCIE		ID_AA64PFR2_EL1, GCIE, IMP
 #define FEAT_NV3		ID_AA64MMFR4_EL1, NV_frac, NV3
 
+static bool feat_asid16(struct kvm *kvm)
+{
+	return kvm_has_feat_enum(kvm, ID_AA64MMFR0_EL1, ASIDBITS, 16);
+}
+
+static bool feat_mte_no_addr_tags_or_canonical_tags(struct kvm *kvm)
+{
+	bool no_addr_tags = kvm_has_feat(kvm, FEAT_MTE_NO_ADDRESS_TAGS);
+	bool canonical_tags = kvm_has_feat(kvm, FEAT_MTE_CANONICAL_TAGS);
+
+	return no_addr_tags || canonical_tags;
+}
+
 static bool not_feat_aa64el3(struct kvm *kvm)
 {
 	return !kvm_has_feat(kvm, FEAT_AA64EL3);
@@ -1044,6 +1064,91 @@ static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
 static const DECLARE_FEAT_MAP(sctlr2_desc, SCTLR2_EL1,
 			      sctlr2_feat_map, FEAT_SCTLR2);
 
+static const struct reg_bits_to_feat_map vhe_tcr_el2_feat_map[] = {
+	NEEDS_FEAT(VHE_TCR_EL2_MTX1	|
+		   VHE_TCR_EL2_MTX0,
+		   feat_mte_no_addr_tags_or_canonical_tags),
+	NEEDS_FEAT(VHE_TCR_EL2_DS, feat_lpa2),
+	NEEDS_FEAT(VHE_TCR_EL2_TCMA1	|
+		   VHE_TCR_EL2_TCMA0,
+		   FEAT_MTE2),
+	NEEDS_FEAT(VHE_TCR_EL2_E0PD1	|
+		   VHE_TCR_EL2_E0PD0,
+		   FEAT_E0PD),
+	NEEDS_FEAT(VHE_TCR_EL2_NFD1	|
+		   VHE_TCR_EL2_NFD0,
+		   FEAT_SVE),
+	NEEDS_FEAT(VHE_TCR_EL2_TBID1	|
+		   VHE_TCR_EL2_TBID0,
+		   feat_pauth),
+	NEEDS_FEAT(VHE_TCR_EL2_HWU162	|
+		   VHE_TCR_EL2_HWU161	|
+		   VHE_TCR_EL2_HWU160	|
+		   VHE_TCR_EL2_HWU159	|
+		   VHE_TCR_EL2_HWU062	|
+		   VHE_TCR_EL2_HWU061	|
+		   VHE_TCR_EL2_HWU060	|
+		   VHE_TCR_EL2_HWU059,
+		   FEAT_HPDS2),
+	NEEDS_FEAT(VHE_TCR_EL2_HPD1	|
+		   VHE_TCR_EL2_HPD0,
+		   FEAT_HPDS),
+	NEEDS_FEAT(VHE_TCR_EL2_HD, FEAT_HAFDBS),
+	NEEDS_FEAT(VHE_TCR_EL2_HA, FEAT_HAF),
+	NEEDS_FEAT(VHE_TCR_EL2_AS, feat_asid16),
+	NEEDS_FEAT(VHE_TCR_EL2_TBI1		|
+		   VHE_TCR_EL2_TBI0		|
+		   VHE_TCR_EL2_IPS		|
+		   VHE_TCR_EL2_TG1		|
+		   VHE_TCR_EL2_SH1		|
+		   VHE_TCR_EL2_ORGN1		|
+		   VHE_TCR_EL2_IRGN1		|
+		   VHE_TCR_EL2_EPD1		|
+		   VHE_TCR_EL2_A1		|
+		   VHE_TCR_EL2_T1SZ		|
+		   VHE_TCR_EL2_TG0		|
+		   VHE_TCR_EL2_SH0		|
+		   VHE_TCR_EL2_ORGN0		|
+		   VHE_TCR_EL2_IRGN0		|
+		   VHE_TCR_EL2_EPD0		|
+		   VHE_TCR_EL2_T0SZ,
+		   FEAT_AA64EL2),
+	FORCE_RES0(VHE_TCR_EL2_RES0),
+	FORCE_RES1(VHE_TCR_EL2_RES1),
+};
+
+static const DECLARE_FEAT_MAP(vhe_tcr_el2_desc, VHE_TCR_EL2,
+			      vhe_tcr_el2_feat_map, FEAT_AA64EL2);
+
+static const struct reg_bits_to_feat_map tcr_el2_feat_map[] = {
+	NEEDS_FEAT(TCR_EL2_MTX,
+		   feat_mte_no_addr_tags_or_canonical_tags),
+	NEEDS_FEAT(TCR_EL2_DS, feat_lpa2),
+	NEEDS_FEAT(TCR_EL2_TCMA, FEAT_MTE2),
+	NEEDS_FEAT(TCR_EL2_TBID, feat_pauth),
+	NEEDS_FEAT(TCR_EL2_HWU62	|
+		   TCR_EL2_HWU61	|
+		   TCR_EL2_HWU60	|
+		   TCR_EL2_HWU59,
+		   FEAT_HPDS2),
+	NEEDS_FEAT(TCR_EL2_HPD, FEAT_HPDS),
+	NEEDS_FEAT(TCR_EL2_HD, FEAT_HAFDBS),
+	NEEDS_FEAT(TCR_EL2_HA, FEAT_HAF),
+	NEEDS_FEAT(TCR_EL2_TBI		|
+		   TCR_EL2_PS		|
+		   TCR_EL2_TG0		|
+		   TCR_EL2_SH0		|
+		   TCR_EL2_ORGN0	|
+		   TCR_EL2_IRGN0	|
+		   TCR_EL2_T0SZ,
+		   FEAT_AA64EL2),
+	FORCE_RES0(TCR_EL2_RES0),
+	FORCE_RES1(TCR_EL2_RES1),
+};
+
+static const DECLARE_FEAT_MAP(tcr_el2_desc, TCR_EL2,
+			      tcr_el2_feat_map, FEAT_AA64EL2);
+
 static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
 	NEEDS_FEAT_FLAG(TCR2_EL2_FNG1	|
 			TCR2_EL2_FNG0	|
@@ -1398,6 +1503,8 @@ void __init check_feature_map(void)
 	check_reg_desc(&hcr_desc);
 	check_reg_desc(&nvhcr_desc);
 	check_reg_desc(&sctlr2_desc);
+	check_reg_desc(&vhe_tcr_el2_desc);
+	check_reg_desc(&tcr_el2_desc);
 	check_reg_desc(&tcr2_el2_desc);
 	check_reg_desc(&sctlr_el1_desc);
 	check_reg_desc(&sctlr_el2_desc);
@@ -1611,6 +1718,12 @@ struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg)
 	case SCTLR2_EL2:
 		resx = compute_reg_resx_bits(kvm, &sctlr2_desc, 0, 0);
 		break;
+	case TCR_EL2:
+		if (kvm_has_feat(kvm, FEAT_E2H0))
+			resx = compute_reg_resx_bits(kvm, &tcr_el2_desc, 0, 0);
+		else
+			resx = compute_reg_resx_bits(kvm, &vhe_tcr_el2_desc, 0, 0);
+		break;
 	case TCR2_EL2:
 		resx = compute_reg_resx_bits(kvm, &tcr2_el2_desc, 0, 0);
 		break;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 4a860904c1ce..2536ea4297b0 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1957,6 +1957,10 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
 	resx = get_reg_fixed_bits(kvm, HFGITR2_EL2);
 	set_sysreg_masks(kvm, HFGITR2_EL2, resx);
 
+	/* TCR_EL2 */
+	resx = get_reg_fixed_bits(kvm, TCR_EL2);
+	set_sysreg_masks(kvm, TCR_EL2, resx);
+
 	/* TCR2_EL2 */
 	resx = get_reg_fixed_bits(kvm, TCR2_EL2);
 	set_sysreg_masks(kvm, TCR2_EL2, resx);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1
  2026-09-17 21:42 ` [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1 Wei-Lin Chang
@ 2026-09-17 21:51   ` sashiko-bot
  2026-09-28 10:50     ` Wei-Lin Chang
  0 siblings, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-09-17 21:51 UTC (permalink / raw)
  To: Wei-Lin Chang; +Cc: Marc Zyngier, kvmarm, Oliver Upton

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] arm64: kvm: exact equality check for FEAT_LPA2 leaks future CPU features to guest
--

commit 04c3c148ddb66ae2c7e9c401ce8ccd1c725fafd5
Author: Wei-Lin Chang <weilin.chang@arm.com>

KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1

This commit sanitizes ID_AA64MMFR0_EL1 to prevent advertising FEAT_LPA2
to nested guests for non-stage-2 granule size fields (TGRAN4, TGRAN16).
It explicitly clears and resets the fields to IMP when the 52-bit values
are detected.

> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c

[ ... ]

> @@ -1731,6 +1731,17 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
>  		/* Hide CNTPOFF if present */
>  		val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, ECV, IMP);
>  
> +		/* NV does not support FEAT_LPA2. */
> +		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN4, val) == ID_AA64MMFR0_EL1_TGRAN4_52_BIT) {
> +			val &= ~ID_AA64MMFR0_EL1_TGRAN4;
> +			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4, IMP);
> +		}

[Severity: Medium]
Could this exact equality check fail to cap future values of TGRAN4?

If a future hardware extension introduces a CPUID value where TGRAN4 is
greater than ID_AA64MMFR0_EL1_TGRAN4_52_BIT, this condition would be
bypassed. This could expose unsupported capabilities to nested guests on
future hardware, potentially leading to guest crashes or page table
corruption when the guest attempts to use 52-bit translation granules.

> +
> +		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN16, val) == ID_AA64MMFR0_EL1_TGRAN16_52_BIT) {
> +			val &= ~ID_AA64MMFR0_EL1_TGRAN16;
> +			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16, IMP);
> +		}

[Severity: Medium]
Similarly, could this equality check leak future values of TGRAN16 greater
than ID_AA64MMFR0_EL1_TGRAN16_52_BIT?

Would it be safer to handle both of these limits using
ID_REG_LIMIT_FIELD_ENUM instead of exact equality checks to ensure
future monotonic CPUID values remain properly capped?

> +
>  		/* Disallow unsupported S2 page sizes */
>  		switch (PAGE_SIZE) {

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917214215.74135-1-weilin.chang@arm.com?part=1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation
  2026-09-17 21:42 ` [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation Wei-Lin Chang
@ 2026-09-17 22:00   ` sashiko-bot
  2026-09-28 10:56     ` Wei-Lin Chang
  0 siblings, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-09-17 22:00 UTC (permalink / raw)
  To: Wei-Lin Chang; +Cc: Oliver Upton, Marc Zyngier, kvmarm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] kvm: arm64: static TCR_EL2 mask based on FEAT_E2H0 breaks dynamic E2H layouts
--

commit 18ffaaa0986bf7864d7ed4beba6765c60e2a26c1
Author: Wei-Lin Chang <weilin.chang@arm.com>

KVM: arm64: Convert TCR_EL2 to config-driven sanitisation
    
This commit converts the translation control register TCR_EL2 to use the
config-driven sanitisation framework. It extracts feature dependencies
from the BSD-licensed AARCHMRS Registers.json, applying some manual
deviations for dependencies like TCR_EL2.TCMA and FEAT_ASID16.

> diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> index 1053676551aff..080b3510b7831 100644
> --- a/arch/arm64/kvm/config.c
> +++ b/arch/arm64/kvm/config.c
[ ... ]
> @@ -1611,6 +1718,12 @@ struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg)
>  	case SCTLR2_EL2:
>  		resx = compute_reg_resx_bits(kvm, &sctlr2_desc, 0, 0);
>  		break;
> +	case TCR_EL2:
> +		if (kvm_has_feat(kvm, FEAT_E2H0))
> +			resx = compute_reg_resx_bits(kvm, &tcr_el2_desc, 0, 0);
> +		else
> +			resx = compute_reg_resx_bits(kvm, &vhe_tcr_el2_desc, 0, 0);
> +		break;

[Severity: High]
Does this static choice in get_reg_fixed_bits() break dynamic E2H layouts for
nested guests? When FEAT_E2H0 is present on the host, this restricts the sysreg
mask to the E2H=0 layout for all TCR_EL2 accesses, ignoring that guests can
still dynamically enter E2H=1 mode.

If a nested hypervisor runs on a host with FEAT_E2H0, sets HCR_EL2.E2H = 1,
and writes to TCR_EL2 expecting the VHE layout, KVM will intercept the write.
When passed to kvm_vcpu_apply_reg_masks(), the VHE-specific bits (e.g., EPD1,
T1SZ, TG1, IPS) will be cleared because they overlap with RES0 bits in the
static nVHE mask. Could this corrupt translation table configurations and
cause translation aborts?

>  	case TCR2_EL2:
>  		resx = compute_reg_resx_bits(kvm, &tcr2_el2_desc, 0, 0);
>  		break;

> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 7f13f0077c9f4..3e01123d00ca0 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
[ ... ]
> @@ -1957,6 +1957,10 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
>  	resx = get_reg_fixed_bits(kvm, HFGITR2_EL2);
>  	set_sysreg_masks(kvm, HFGITR2_EL2, resx);
>  
> +	/* TCR_EL2 */
> +	resx = get_reg_fixed_bits(kvm, TCR_EL2);
> +	set_sysreg_masks(kvm, TCR_EL2, resx);

[Severity: High]
Does this application in kvm_init_nv_sysregs() cause valid guest writes to be
clobbered?

Since the wrongly computed static mask is applied to the VM's sysreg_masks
array here, it looks like it will break nested virtualization for any nested
guest running in VHE mode.

> +
>  	/* TCR2_EL2 */
>  	resx = get_reg_fixed_bits(kvm, TCR2_EL2);
>  	set_sysreg_masks(kvm, TCR2_EL2, resx);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917214215.74135-1-weilin.chang@arm.com?part=4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1
  2026-09-17 21:51   ` sashiko-bot
@ 2026-09-28 10:50     ` Wei-Lin Chang
  0 siblings, 0 replies; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-28 10:50 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: Marc Zyngier, kvmarm, Oliver Upton

On Thu, Sep 17, 2026 at 09:51:44PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] arm64: kvm: exact equality check for FEAT_LPA2 leaks future CPU features to guest
> --
> 
> commit 04c3c148ddb66ae2c7e9c401ce8ccd1c725fafd5
> Author: Wei-Lin Chang <weilin.chang@arm.com>
> 
> KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1
> 
> This commit sanitizes ID_AA64MMFR0_EL1 to prevent advertising FEAT_LPA2
> to nested guests for non-stage-2 granule size fields (TGRAN4, TGRAN16).
> It explicitly clears and resets the fields to IMP when the 52-bit values
> are detected.
> 
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> 
> [ ... ]
> 
> > @@ -1731,6 +1731,17 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
> >  		/* Hide CNTPOFF if present */
> >  		val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, ECV, IMP);
> >  
> > +		/* NV does not support FEAT_LPA2. */
> > +		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN4, val) == ID_AA64MMFR0_EL1_TGRAN4_52_BIT) {
> > +			val &= ~ID_AA64MMFR0_EL1_TGRAN4;
> > +			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4, IMP);
> > +		}
> 
> [Severity: Medium]
> Could this exact equality check fail to cap future values of TGRAN4?
> 
> If a future hardware extension introduces a CPUID value where TGRAN4 is
> greater than ID_AA64MMFR0_EL1_TGRAN4_52_BIT, this condition would be
> bypassed. This could expose unsupported capabilities to nested guests on
> future hardware, potentially leading to guest crashes or page table
> corruption when the guest attempts to use 52-bit translation granules.

This is the same comment from Sashiko as v1, and it was Nack'd by the
maintainer.

> 
> > +
> > +		if (SYS_FIELD_GET(ID_AA64MMFR0_EL1, TGRAN16, val) == ID_AA64MMFR0_EL1_TGRAN16_52_BIT) {
> > +			val &= ~ID_AA64MMFR0_EL1_TGRAN16;
> > +			val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16, IMP);
> > +		}
> 
> [Severity: Medium]
> Similarly, could this equality check leak future values of TGRAN16 greater
> than ID_AA64MMFR0_EL1_TGRAN16_52_BIT?
> 
> Would it be safer to handle both of these limits using
> ID_REG_LIMIT_FIELD_ENUM instead of exact equality checks to ensure
> future monotonic CPUID values remain properly capped?

Same here.

Thanks,
Wei-Lin Chang

> 
> > +
> >  		/* Disallow unsupported S2 page sizes */
> >  		switch (PAGE_SIZE) {
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260917214215.74135-1-weilin.chang@arm.com?part=1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation
  2026-09-17 22:00   ` sashiko-bot
@ 2026-09-28 10:56     ` Wei-Lin Chang
  0 siblings, 0 replies; 9+ messages in thread
From: Wei-Lin Chang @ 2026-09-28 10:56 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: Oliver Upton, Marc Zyngier, kvmarm

On Thu, Sep 17, 2026 at 10:00:28PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] kvm: arm64: static TCR_EL2 mask based on FEAT_E2H0 breaks dynamic E2H layouts
> --
> 
> commit 18ffaaa0986bf7864d7ed4beba6765c60e2a26c1
> Author: Wei-Lin Chang <weilin.chang@arm.com>
> 
> KVM: arm64: Convert TCR_EL2 to config-driven sanitisation
>     
> This commit converts the translation control register TCR_EL2 to use the
> config-driven sanitisation framework. It extracts feature dependencies
> from the BSD-licensed AARCHMRS Registers.json, applying some manual
> deviations for dependencies like TCR_EL2.TCMA and FEAT_ASID16.
> 
> > diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> > index 1053676551aff..080b3510b7831 100644
> > --- a/arch/arm64/kvm/config.c
> > +++ b/arch/arm64/kvm/config.c
> [ ... ]
> > @@ -1611,6 +1718,12 @@ struct resx get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg)
> >  	case SCTLR2_EL2:
> >  		resx = compute_reg_resx_bits(kvm, &sctlr2_desc, 0, 0);
> >  		break;
> > +	case TCR_EL2:
> > +		if (kvm_has_feat(kvm, FEAT_E2H0))
> > +			resx = compute_reg_resx_bits(kvm, &tcr_el2_desc, 0, 0);
> > +		else
> > +			resx = compute_reg_resx_bits(kvm, &vhe_tcr_el2_desc, 0, 0);
> > +		break;
> 
> [Severity: High]
> Does this static choice in get_reg_fixed_bits() break dynamic E2H layouts for
> nested guests? When FEAT_E2H0 is present on the host, this restricts the sysreg
> mask to the E2H=0 layout for all TCR_EL2 accesses, ignoring that guests can
> still dynamically enter E2H=1 mode.
> 
> If a nested hypervisor runs on a host with FEAT_E2H0, sets HCR_EL2.E2H = 1,
> and writes to TCR_EL2 expecting the VHE layout, KVM will intercept the write.
> When passed to kvm_vcpu_apply_reg_masks(), the VHE-specific bits (e.g., EPD1,
> T1SZ, TG1, IPS) will be cleared because they overlap with RES0 bits in the
> static nVHE mask. Could this corrupt translation table configurations and
> cause translation aborts?

No. VMs can't change their effective HCR_EL2.E2H value.

> 
> >  	case TCR2_EL2:
> >  		resx = compute_reg_resx_bits(kvm, &tcr2_el2_desc, 0, 0);
> >  		break;
> 
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > index 7f13f0077c9f4..3e01123d00ca0 100644
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> [ ... ]
> > @@ -1957,6 +1957,10 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
> >  	resx = get_reg_fixed_bits(kvm, HFGITR2_EL2);
> >  	set_sysreg_masks(kvm, HFGITR2_EL2, resx);
> >  
> > +	/* TCR_EL2 */
> > +	resx = get_reg_fixed_bits(kvm, TCR_EL2);
> > +	set_sysreg_masks(kvm, TCR_EL2, resx);
> 
> [Severity: High]
> Does this application in kvm_init_nv_sysregs() cause valid guest writes to be
> clobbered?
> 
> Since the wrongly computed static mask is applied to the VM's sysreg_masks
> array here, it looks like it will break nested virtualization for any nested
> guest running in VHE mode.

No. VMs can't change their effective HCR_EL2.E2H value.

Thanks,
Wei-Lin Chang

> 
> > +
> >  	/* TCR2_EL2 */
> >  	resx = get_reg_fixed_bits(kvm, TCR2_EL2);
> >  	set_sysreg_masks(kvm, TCR2_EL2, resx);
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260917214215.74135-1-weilin.chang@arm.com?part=4

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-09-28 10:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-17 21:42 [PATCH v2 0/4] KVM: arm64: Properly advertise !FEAT_LPA2 for NV Wei-Lin Chang
2026-09-17 21:42 ` [PATCH v2 1/4] KVM: arm64: nv: Don't advertise FEAT_LPA2 for guest stage-1 Wei-Lin Chang
2026-09-17 21:51   ` sashiko-bot
2026-09-28 10:50     ` Wei-Lin Chang
2026-09-17 21:42 ` [PATCH v2 2/4] arm64: sysreg: Add TCR_EL2 to sysreg infrastructure Wei-Lin Chang
2026-09-17 21:42 ` [PATCH v2 3/4] KVM: arm64: Reset TCR_EL2 according to guest's E2H mode Wei-Lin Chang
2026-09-17 21:42 ` [PATCH v2 4/4] KVM: arm64: Convert TCR_EL2 to config-driven sanitisation Wei-Lin Chang
2026-09-17 22:00   ` sashiko-bot
2026-09-28 10:56     ` Wei-Lin Chang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.