Re: [PATCH v3 1/4] KVM: arm64: Apply the fine-grained UNDEFs without FEAT_FGT

From: Wei-Lin Chang

Date: Tue Sep 29 2026 - 10:59:51 EST


On Tue, Sep 29, 2026 at 10:00:28AM +0100, Fuad Tabba wrote:
> triage_sysreg_trap() applies the FGU bits through the encoding's FGT
> entry in the trap xarray, and populate_nv_trap_config() only adds those
> entries on a CPU with FEAT_FGT. Without it, a hidden feature that still
> traps reaches its handler instead: a TLBI OS trapped through
> HCR_EL2.TTLBOS lands in handle_tlbi_el1(), which expects an EL1 TLBI
> only from vEL2 and WARNs before the guest gets its UNDEF. A VMM can
> trigger the WARN by hiding TLBI OS and having the guest execute one.
>
> kvm_calculate_traps() computes the FGU bits with or without FEAT_FGT,
> and the entries map an encoding to its FGT bit whatever the CPU
> implements. Add them unconditionally, so that a hidden feature that
> traps is UNDEFINED on any CPU.

This reads a bit mechanical to me, can I suggest:

```
FGUs don't actually require hardware support, so don't gate fgt trap
config insertion on FGT. This is the only action required to allow FGUs
always, as kvm_calculate_traps() already computes the FGU bits with or
without FEAT_FGT.

This also fixes a spurious WARN when a TLBI OS is run on a guest in vEL1
without FEAT_TLBIOS on non FEAT_FGT hardware. In this configuration the
course-grained HCR_EL2.TTLBOS trap reaches the handler handle_tlbi_el1(),
which expects an EL1 TLBI only from vEL2. With FGUs enabled the UNDEF
will be injected without needing the specific handler.
```

Other than that, this is very nice! Sorry for missing this. It's way
better to have FGU regardless of FGT and handle unexposed TLBIOS with
FGU always. Thanks Oliver for suggesting this instead, and thanks Fuad
for digging in.

Reviewed-by: Wei-Lin Chang <weilin.chang@xxxxxxx>

Thanks,
Wei-Lin Chang

>
> Fixes: f5a5a406b4b8b ("KVM: arm64: Propagate and handle Fine-Grained UNDEF bits")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>

> ---
>
> Notes:
> For a nested guest on a CPU without FGT, check_fgt_bit() now runs too,
> but it forwards nothing: a guest without FEAT_FGT has its FGT registers
> RES0.
>
> f5a5a406b4b8b added the FGU check to triage_sysreg_trap() behind an
> ARM64_HAS_FGT gate that populate_nv_trap_config() already had, so the
> check never fired without FGT.
>
> arch/arm64/kvm/emulate-nested.c | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> index 625604019fb32..b8529532b6e78 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -2386,9 +2386,6 @@ int __init populate_nv_trap_config(void)
> 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);
>
> --
> 2.39.5
>