From: Marc Zyngier <maz@kernel.org>
To: Andre Przywara <andre.przywara@arm.com>
Cc: Julien Thierry <julien.thierry.kdev@gmail.com>,
Will Deacon <will@kernel.org>,
kvm@vger.kernel.org, kvmarm@lists.linux.dev,
Alexandru Elisei <alexandru.elisei@arm.com>,
Sascha Bischoff <sascha.bischoff@arm.com>
Subject: Re: [PATCH kvmtool v5 7/7] arm64: Handle virtio endianness reset when running nested
Date: Fri, 23 Jan 2026 16:03:05 +0000 [thread overview]
Message-ID: <86jyx8b9l2.wl-maz@kernel.org> (raw)
In-Reply-To: <20260123142729.604737-8-andre.przywara@arm.com>
On Fri, 23 Jan 2026 14:27:29 +0000,
Andre Przywara <andre.przywara@arm.com> wrote:
>
> From: Marc Zyngier <maz@kernel.org>
>
> When running an EL2 guest, we need to make sure we don't sample
> SCTLR_EL1 to work out the virtio endianness, as this is likely
> to be a bit random.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> arm64/include/kvm/kvm-cpu-arch.h | 5 ++--
> arm64/kvm-cpu.c | 47 +++++++++++++++++++++++++-------
> 2 files changed, 40 insertions(+), 12 deletions(-)
>
> diff --git a/arm64/include/kvm/kvm-cpu-arch.h b/arm64/include/kvm/kvm-cpu-arch.h
> index 1af394aa..85646ad4 100644
> --- a/arm64/include/kvm/kvm-cpu-arch.h
> +++ b/arm64/include/kvm/kvm-cpu-arch.h
> @@ -10,8 +10,9 @@
> #define ARM_MPIDR_HWID_BITMASK 0xFF00FFFFFFUL
> #define ARM_CPU_ID 3, 0, 0, 0
> #define ARM_CPU_ID_MPIDR 5
> -#define ARM_CPU_CTRL 3, 0, 1, 0
> -#define ARM_CPU_CTRL_SCTLR_EL1 0
> +#define SYS_SCTLR_EL1 3, 4, 1, 0, 0
> +#define SYS_SCTLR_EL2 3, 4, 1, 0, 0
> +#define SYS_HCR_EL2 3, 4, 1, 1, 0
>
> struct kvm_cpu {
> pthread_t thread;
> diff --git a/arm64/kvm-cpu.c b/arm64/kvm-cpu.c
> index 5e4f3a7d..35e1c639 100644
> --- a/arm64/kvm-cpu.c
> +++ b/arm64/kvm-cpu.c
> @@ -12,6 +12,7 @@
>
> #define SCTLR_EL1_E0E_MASK (1 << 24)
> #define SCTLR_EL1_EE_MASK (1 << 25)
> +#define HCR_EL2_TGE (1 << 27)
>
> static int debug_fd;
>
> @@ -408,7 +409,8 @@ int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
> {
> struct kvm_one_reg reg;
> u64 psr;
> - u64 sctlr;
> + u64 sctlr, bit;
> + u64 hcr = 0;
>
> /*
> * Quoting the definition given by Peter Maydell:
> @@ -419,8 +421,9 @@ int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
> * We first check for an AArch32 guest: its endianness can
> * change when using SETEND, which affects the CPSR.E bit.
> *
> - * If we're AArch64, use SCTLR_EL1.E0E if access comes from
> - * EL0, and SCTLR_EL1.EE if access comes from EL1.
> + * If we're AArch64, determine which SCTLR register to use,
> + * depending on NV being used or not. Then use either the E0E
> + * bit for EL0, or the EE bit for EL1/EL2.
> */
> reg.id = ARM64_CORE_REG(regs.pstate);
> reg.addr = (u64)&psr;
> @@ -430,16 +433,40 @@ int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
> if (psr & PSR_MODE32_BIT)
> return (psr & COMPAT_PSR_E_BIT) ? VIRTIO_ENDIAN_BE : VIRTIO_ENDIAN_LE;
>
> - reg.id = ARM64_SYS_REG(ARM_CPU_CTRL, ARM_CPU_CTRL_SCTLR_EL1);
> + if (vcpu->kvm->cfg.arch.nested_virt) {
> + reg.id = ARM64_SYS_REG(SYS_HCR_EL2);
> + reg.addr = (u64)&hcr;
> + if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0)
> + die("KVM_GET_ONE_REG failed (HCR_EL2)");
> + }
> +
> + switch (psr & PSR_MODE_MASK) {
> + case PSR_MODE_EL0t:
> + if (hcr & HCR_EL2_TGE)
> + reg.id = ARM64_SYS_REG(SYS_SCTLR_EL2);
> + else
> + reg.id = ARM64_SYS_REG(SYS_SCTLR_EL1);
> + bit = SCTLR_EL1_E0E_MASK;
> + break;
A discussion with Sascha outlined a small bug here: when using the EL2
translation regime (E2H==0), we sample the wrong bit (SCTLR_EL2.E0E
does not exist in this case).
A potential fix is as follows, though I don't think anyone will care...
M.
diff --git a/arm64/kvm-cpu.c b/arm64/kvm-cpu.c
index 35e1c639..7b012e7a 100644
--- a/arm64/kvm-cpu.c
+++ b/arm64/kvm-cpu.c
@@ -12,7 +12,8 @@
#define SCTLR_EL1_E0E_MASK (1 << 24)
#define SCTLR_EL1_EE_MASK (1 << 25)
-#define HCR_EL2_TGE (1 << 27)
+#define HCR_EL2_TGE (1UL << 27)
+#define HCR_EL2_E2H (1UL << 34)
static int debug_fd;
@@ -442,11 +443,21 @@ int kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
switch (psr & PSR_MODE_MASK) {
case PSR_MODE_EL0t:
- if (hcr & HCR_EL2_TGE)
+ switch (hcr & (HCR_EL2_E2H | HCR_EL2_TGE)) {
+ case HCR_EL2_E2H | HCR_EL2_TGE: /* EL2&0 */
reg.id = ARM64_SYS_REG(SYS_SCTLR_EL2);
- else
+ bit = SCTLR_EL1_E0E_MASK;
+ break;
+ case HCR_EL2_TGE: /* EL2 */
+ reg.id = ARM64_SYS_REG(SYS_SCTLR_EL2);
+ bit = SCTLR_EL1_EE_MASK;
+ break;
+ case HCR_EL2_E2H: /* EL1&0 (VHE) */
+ default: /* EL1&0 (!VHE) */
reg.id = ARM64_SYS_REG(SYS_SCTLR_EL1);
- bit = SCTLR_EL1_E0E_MASK;
+ bit = SCTLR_EL1_E0E_MASK;
+ break;
+ }
break;
case PSR_MODE_EL1t:
case PSR_MODE_EL1h:
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2026-01-23 16:03 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-23 14:27 [PATCH kvmtool v5 0/7] arm64: Nested virtualization support Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 1/7] Sync kernel UAPI headers with v6.19-rc6 Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 2/7] arm64: Initial nested virt support Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 3/7] arm64: nested: Add support for setting maintenance IRQ Andre Przywara
2026-01-26 18:03 ` Marc Zyngier
2026-01-27 12:07 ` Andre Przywara
2026-01-27 13:23 ` Sascha Bischoff
2026-01-29 17:08 ` Andre Przywara
2026-01-30 9:29 ` Sascha Bischoff
2026-02-02 8:54 ` Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 4/7] arm64: Add counter offset control Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 5/7] arm64: Add FEAT_E2H0 support Andre Przywara
2026-01-30 9:29 ` Sascha Bischoff
2026-01-23 14:27 ` [PATCH kvmtool v5 6/7] arm64: Generate HYP timer interrupt specifiers Andre Przywara
2026-01-23 14:27 ` [PATCH kvmtool v5 7/7] arm64: Handle virtio endianness reset when running nested Andre Przywara
2026-01-23 16:03 ` Marc Zyngier [this message]
2026-01-27 10:15 ` Sascha Bischoff
2026-02-09 2:21 ` [PATCH kvmtool v5 0/7] arm64: Nested virtualization support Itaru Kitayama
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=86jyx8b9l2.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=alexandru.elisei@arm.com \
--cc=andre.przywara@arm.com \
--cc=julien.thierry.kdev@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=sascha.bischoff@arm.com \
--cc=will@kernel.org \
/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 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.