Thread (26 messages) 26 messages, 7 authors, 2026-01-21

Re: [PATCH v2 4/6] KVM: arm64: Account for RES1 bits in DECLARE_FEAT_MAP() and co

From: Marc Zyngier <maz@kernel.org>
Date: 2026-01-21 10:50:58
Also in: kvm, kvmarm
Subsystem: arm64 port (aarch64 architecture), kernel virtual machine for arm64 (kvm/arm64), the rest · Maintainers: Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton, Linus Torvalds

Hi Nathan,

Thanks for reporting this.

On Tue, 20 Jan 2026 21:15:58 +0000,
Nathan Chancellor [off-list ref] wrote:
Hi Marc,

On Wed, Dec 10, 2025 at 05:30:22PM +0000, Marc Zyngier wrote:
quoted
None of the registers we manage in the feature dependency infrastructure
so far has any RES1 bit. This is about to change, as VTCR_EL2 has
its bit 31 being RES1.

In order to not fail the consistency checks by not describing a bit,
add RES1 bits to the set of immutable bits. This requires some extra
surgery for the FGT handling, as we now need to track RES1 bits there
as well.

There are no RES1 FGT bits *yet*. Watch this space.

Signed-off-by: Marc Zyngier <maz@kernel.org>
After this change in -next as commit c259d763e6b0 ("KVM: arm64: Account
for RES1 bits in DECLARE_FEAT_MAP() and co"), I am seeing several
"undefined behavior" errors on my two arm64 boxes.

  $ journalctl -k -g '(Linux version|kvm)' --no-hostname -o cat
  Linux version 6.19.0-rc4-00014-gc259d763e6b0 (nathan@framework-amd-ryzen-maxplus-395) (aarch64-linux-gcc (GCC) 15.2.0, GNU ld (GNU Binutils) 2.45) #1 SMP PREEMPT_DYNAMIC Tue Jan 20 13:59:52 MST 2026
  kvm [1]: nv: 568 coarse grained trap handlers
  kvm [1]: Undefined hfgrtr_masks behaviour, bits fff7ffffffffffff
  kvm [1]: Undefined hfgwtr_masks behaviour, bits fff7baffe9db39fb
  kvm [1]: Undefined hfgitr_masks behaviour, bits dfffffffffffffff
  kvm [1]: Undefined hdfgrtr_masks behaviour, bits fffdfb3fffcffeff
  kvm [1]: Undefined hdfgwtr_masks behaviour, bits 73f7763bbfbffdbf
  kvm [1]: Undefined hafgrtr_masks behaviour, bits 0003fffffffe001f
  kvm [1]: Undefined hfgrtr2_masks behaviour, bits 0000000000007fff
  kvm [1]: Undefined hfgwtr2_masks behaviour, bits 0000000000007ffd
  kvm [1]: Undefined hfgitr2_masks behaviour, bits 0000000000000003
  kvm [1]: Undefined hdfgrtr2_masks behaviour, bits 0000000001dfffff
  kvm [1]: Undefined hdfgwtr2_masks behaviour, bits 0000000001f9ffbf
  kvm [1]: IPA Size Limit: 44 bits
  kvm [1]: vgic-v2@c0e0000
  kvm [1]: GICv3 sysreg trapping enabled ([C], reduced performance)
  kvm [1]: GIC system register CPU interface enabled
  kvm [1]: vgic interrupt IRQ9
  kvm [1]: Hyp nVHE mode initialized successfully
Let me guess: Cortex-A72 or similarly ancient ARM-designed CPUs, as
hinted by the lack of GICv3 TDIR control? Then these do not have
FEAT_FGT.

The issue stems from the fact that as an optimisation, we skip the
parsing of the FGT trap table on such hardware, which also results in
the FGT masks of known bits not being updated. We then compute the
effective feature map, and discover that the two don't match.

It was harmless so far, as we were only dealing with RES0 bits, and
assuming that anything that wasn't a RES0 bit was a stateful bit. With
the introduction of RES1 handling, we've run out of luck. To be clear,
that's just a warning, not a functional issue.

At this point, I don't think the above "optimisation" is worth having.
This is only done *once*, at boot time, so the gain is extremely
small. I'd like the checks to be effective irrespective of the HW the
kernel runs on, which is consistent with what we do for other tables
describing the architectural state.

Anyway, I came up with the following hack, which performs the checks,
but avoid inserting the FGT information in the sysreg xarray if the HW
doesn't support it, as a memory saving measure. Please let me know if
that helps (it does on my old boxes).

Thanks,

	M.
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 88336336efc9f..fa8fa09de67dc 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2284,9 +2284,6 @@ int __init populate_nv_trap_config(void)
 	kvm_info("nv: %ld coarse grained trap handlers\n",
 		 ARRAY_SIZE(encoding_to_cgt));
 
-	if (!cpus_have_final_cap(ARM64_HAS_FGT))
-		goto check_mcb;
-
 	for (int i = 0; i < ARRAY_SIZE(encoding_to_fgt); i++) {
 		const struct encoding_to_trap_config *fgt = &encoding_to_fgt[i];
 		union trap_config tc;
@@ -2306,6 +2303,15 @@ int __init populate_nv_trap_config(void)
 			}
 
 			tc.val |= fgt->tc.val;
+
+			if (!aggregate_fgt(tc)) {
+				ret = -EINVAL;
+				print_nv_trap_error(fgt, "FGT bit is reserved", ret);
+			}
+
+			if (!cpus_have_final_cap(ARM64_HAS_FGT))
+				continue;
+
 			prev = xa_store(&sr_forward_xa, enc,
 					xa_mk_value(tc.val), GFP_KERNEL);
 
@@ -2313,11 +2319,6 @@ int __init populate_nv_trap_config(void)
 				ret = xa_err(prev);
 				print_nv_trap_error(fgt, "Failed FGT insertion", ret);
 			}
-
-			if (!aggregate_fgt(tc)) {
-				ret = -EINVAL;
-				print_nv_trap_error(fgt, "FGT bit is reserved", ret);
-			}
 		}
 	}
 
@@ -2333,7 +2334,6 @@ int __init populate_nv_trap_config(void)
 	kvm_info("nv: %ld fine grained trap handlers\n",
 		 ARRAY_SIZE(encoding_to_fgt));
 
-check_mcb:
 	for (int id = __MULTIPLE_CONTROL_BITS__; id < __COMPLEX_CONDITIONS__; id++) {
 		const enum cgt_group_id *cgids;
 
-- 
Without deviation from the norm, progress is not possible.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help