From: Marc Zyngier <maz@kernel.org>
To: Fuad Tabba <tabba@google.com>
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
kvm@vger.kernel.org, Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oupton@kernel.org>,
Zenghui Yu <yuzenghui@huawei.com>, Will Deacon <will@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>
Subject: Re: [PATCH 12/20] KVM: arm64: Add RESx_WHEN_E2Hx constraints as configuration flags
Date: Thu, 29 Jan 2026 10:14:36 +0000 [thread overview]
Message-ID: <86bjicbu9f.wl-maz@kernel.org> (raw)
In-Reply-To: <CA+EHjTzL6bNZ=sZoub3GY=VZ2bJ+4bFr4jkuiMMBCEqXuAkQPA@mail.gmail.com>
Hey Fuad,
On Wed, 28 Jan 2026 17:43:40 +0000,
Fuad Tabba <tabba@google.com> wrote:
>
> Hi Marc,
>
> On Mon, 26 Jan 2026 at 12:17, Marc Zyngier <maz@kernel.org> wrote:
> >
> > "Thanks" to VHE, SCTLR_EL2 radically changes shape depending on the
> > value of HCR_EL2.E2H, as a lot of the bits that didn't have much
> > meaning with E2H=0 start impacting EL0 with E2H=1.
> >
> > This has a direct impact on the RESx behaviour of these bits, and
> > we need a way to express them.
> >
> > For this purpose, introduce a set of 4 new constaints that, when
> > the controlling feature is not present, force the RESx value to
> > be either 0 or 1 depending on the value of E2H.
> >
> > This allows diverging RESx values depending on the value of E2H,
> > something that is required by a bunch of SCTLR_EL2 bits.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/kvm/config.c | 24 +++++++++++++++++++++---
> > 1 file changed, 21 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> > index 1990cebc77c66..7063fffc22799 100644
> > --- a/arch/arm64/kvm/config.c
> > +++ b/arch/arm64/kvm/config.c
> > @@ -26,6 +26,10 @@ struct reg_bits_to_feat_map {
> > #define MASKS_POINTER BIT(3) /* Pointer to fgt_masks struct instead of bits */
> > #define AS_RES1 BIT(4) /* RES1 when not supported */
> > #define REQUIRES_E2H1 BIT(5) /* Add HCR_EL2.E2H RES1 as a pre-condition */
> > +#define RES0_WHEN_E2H0 BIT(6) /* RES0 when E2H=0 and not supported */
> > +#define RES0_WHEN_E2H1 BIT(7) /* RES0 when E2H=1 and not supported */
> > +#define RES1_WHEN_E2H0 BIT(8) /* RES1 when E2H=0 and not supported */
> > +#define RES1_WHEN_E2H1 BIT(9) /* RES1 when E2H=1 and not supported */
> >
> > unsigned long flags;
> >
> > @@ -1298,10 +1302,24 @@ struct resx compute_resx_bits(struct kvm *kvm,
> > match &= !e2h0;
> >
> > if (!match) {
> > + u64 bits = reg_feat_map_bits(&map[i]);
> > +
> > + if (e2h0) {
> > + if (map[i].flags & RES1_WHEN_E2H0)
> > + resx.res1 |= bits;
> > + else if (map[i].flags & RES0_WHEN_E2H0)
> > + resx.res0 |= bits;
> > + } else {
> > + if (map[i].flags & RES1_WHEN_E2H1)
> > + resx.res1 |= bits;
> > + else if (map[i].flags & RES0_WHEN_E2H1)
> > + resx.res0 |= bits;
> > + }
> > +
> > if (map[i].flags & AS_RES1)
> > - resx.res1 |= reg_feat_map_bits(&map[i]);
> > - else
> > - resx.res0 |= reg_feat_map_bits(&map[i]);
> > + resx.res1 |= bits;
> > + else if (!(resx.res1 & bits))
> > + resx.res0 |= bits;
>
> The logic here feels a bit more complex than necessary, specifically
> regarding the interaction between the E2H checks and the fallthrough
> to AS_RES1.
>
> Although AS_RES1 and RES0_WHEN_E2H0 are mutually exclusive in
> practice, the current structure technically permits a scenario where
> both res0 and res1 get set if the flags are mixed (the e2h0 block sets
> res0, and the AS_RES1 block falls through and sets res1). This cannot
> be ruled out by looking at this function alone.
>
> It might be cleaner (and safer) to determine the res1 first, and
> then apply the masks. Something like:
>
> + bool is_res1 = false;
> +
> + if (map[i].flags & AS_RES1)
> + is_res1 = true;
> + else if (e2h0)
> + is_res1 = (map[i].flags & RES1_WHEN_E2H0);
> + else
> + is_res1 = (map[i].flags & RES1_WHEN_E2H1);
> ...
I think you have just put your finger on something that escaped me so
far. You are totally right that the code as written today is ugly, and
the trick to work out that we need to account the bits as RES0 is
awful.
But it additionally outlines something else: since RES0 is an implicit
property (we don't specify a flag for it), RES0_WHEN_E2Hx could also
be implicit properties. I couldn't find an example where anything
would break. This would also avoid the combination with AS_RES1 by
construction.
>
> This also brings up a side point: given the visual similarity of these
> flags, it is quite easy to make a typo and accidentally combine
> incompatible flags (e.g., AS_RES1 | RESx_WHEN_E2Hx, or RES0_WHEN_E2H0
> | RES1_WHEN_E2H0), would it be worth adding a check to warn on
> obviously invalid combinations?
>
> Or maybe even redefining AS_RES1 to be
> (RES1_WHEN_E2H1|RES1_WHEN_E2H0), which is what it is conceptually.
> That could simplify this code even further:
>
> + if (e2h0)
> + is_res1 = (map[i].flags & RES1_WHEN_E2H0);
> + else
> + is_res1 = (map[i].flags & RES1_WHEN_E2H1);
While that would work, I think this is a step too far. Eventually, we
should be able to sanitise things outside of NV, and RES1 should not
depend on E2H at all in this case.
I ended up with the following hack, completely untested (needs
renumbering, and the rest of SCTLR_EL2 repainted). Let me know what
you think.
Thanks,
M.
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 562513a4683e2..204e5aeda4d24 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -26,8 +26,6 @@ struct reg_bits_to_feat_map {
#define MASKS_POINTER BIT(3) /* Pointer to fgt_masks struct instead of bits */
#define AS_RES1 BIT(4) /* RES1 when not supported */
#define REQUIRES_E2H1 BIT(5) /* Add HCR_EL2.E2H RES1 as a pre-condition */
-#define RES0_WHEN_E2H0 BIT(6) /* RES0 when E2H=0 and not supported */
-#define RES0_WHEN_E2H1 BIT(7) /* RES0 when E2H=1 and not supported */
#define RES1_WHEN_E2H0 BIT(8) /* RES1 when E2H=0 and not supported */
#define RES1_WHEN_E2H1 BIT(9) /* RES1 when E2H=1 and not supported */
@@ -1375,22 +1373,15 @@ struct resx compute_resx_bits(struct kvm *kvm,
if (!match) {
u64 bits = reg_feat_map_bits(&map[i]);
+ bool res1;
- if (e2h0) {
- if (map[i].flags & RES1_WHEN_E2H0)
- resx.res1 |= bits;
- else if (map[i].flags & RES0_WHEN_E2H0)
- resx.res0 |= bits;
- } else {
- if (map[i].flags & RES1_WHEN_E2H1)
- resx.res1 |= bits;
- else if (map[i].flags & RES0_WHEN_E2H1)
- resx.res0 |= bits;
- }
-
- if (map[i].flags & AS_RES1)
+ res1 = (map[i].flags & AS_RES1);
+ res1 |= e2h0 && (map[i].flags & RES1_WHEN_E2H0);
+ res1 |= !e2h0 && (map[i].flags & RES1_WHEN_E2H1);
+
+ if (res1)
resx.res1 |= bits;
- else if (!(resx.res1 & bits))
+ else
resx.res0 |= bits;
}
}
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2026-01-29 10:14 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-26 12:16 [PATCH 00/20] KVM: arm64: Generalise RESx handling Marc Zyngier
2026-01-26 12:16 ` [PATCH 01/20] arm64: Convert SCTLR_EL2 to sysreg infrastructure Marc Zyngier
2026-01-26 17:53 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 02/20] KVM: arm64: Remove duplicate configuration for SCTLR_EL1.{EE,E0E} Marc Zyngier
2026-01-26 18:04 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 03/20] KVM: arm64: Introduce standalone FGU computing primitive Marc Zyngier
2026-01-26 18:35 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 04/20] KVM: arm64: Introduce data structure tracking both RES0 and RES1 bits Marc Zyngier
2026-01-26 18:54 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 05/20] KVM: arm64: Extend unified RESx handling to runtime sanitisation Marc Zyngier
2026-01-26 19:15 ` Fuad Tabba
2026-01-27 10:52 ` Marc Zyngier
2026-01-26 12:16 ` [PATCH 06/20] KVM: arm64: Inherit RESx bits from FGT register descriptors Marc Zyngier
2026-01-27 15:21 ` Joey Gouly
2026-01-27 17:58 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 07/20] KVM: arm64: Allow RES1 bits to be inferred from configuration Marc Zyngier
2026-01-27 15:26 ` Joey Gouly
2026-01-27 17:58 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 08/20] KVM: arm64: Correctly handle SCTLR_EL1 RES1 bits for unsupported features Marc Zyngier
2026-01-27 18:06 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 09/20] KVM: arm64: Convert HCR_EL2.RW to AS_RES1 Marc Zyngier
2026-01-27 18:09 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 10/20] KVM: arm64: Simplify FIXED_VALUE handling Marc Zyngier
2026-01-27 18:20 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 11/20] KVM: arm64: Add REQUIRES_E2H1 constraint as configuration flags Marc Zyngier
2026-01-27 18:28 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 12/20] KVM: arm64: Add RESx_WHEN_E2Hx constraints " Marc Zyngier
2026-01-28 17:43 ` Fuad Tabba
2026-01-29 10:14 ` Marc Zyngier [this message]
2026-01-29 10:30 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 13/20] KVM: arm64: Move RESx into individual register descriptors Marc Zyngier
2026-01-29 16:29 ` Fuad Tabba
2026-01-29 17:19 ` Marc Zyngier
2026-01-29 17:39 ` Fuad Tabba
2026-01-29 18:07 ` Marc Zyngier
2026-01-29 18:13 ` Fuad Tabba
2026-01-30 9:06 ` Marc Zyngier
2026-01-26 12:16 ` [PATCH 14/20] KVM: arm64: Simplify handling of HCR_EL2.E2H RESx Marc Zyngier
2026-01-29 16:41 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 15/20] KVM: arm64: Get rid of FIXED_VALUE altogether Marc Zyngier
2026-01-29 16:54 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 16/20] KVM: arm64: Simplify handling of full register invalid constraint Marc Zyngier
2026-01-29 17:34 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 17/20] KVM: arm64: Remove all traces of FEAT_TME Marc Zyngier
2026-01-29 17:43 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 18/20] KVM: arm64: Remove all traces of HCR_EL2.MIOCNCE Marc Zyngier
2026-01-29 17:51 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 19/20] KVM: arm64: Add sanitisation to SCTLR_EL2 Marc Zyngier
2026-01-29 18:11 ` Fuad Tabba
2026-01-26 12:16 ` [PATCH 20/20] KVM: arm64: Add debugfs file dumping computed RESx values Marc Zyngier
2026-02-02 8:59 ` Fuad Tabba
2026-02-02 9:14 ` Marc Zyngier
2026-02-02 9:57 ` Fuad Tabba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86bjicbu9f.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=oupton@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox