* [PATCH v2 1/7] KVM: arm64: Set ESR_ELx.IL for injected undefined exceptions at EL2
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 2/7] KVM: arm64: Unconditionally set IL for injected undefined exceptions Fuad Tabba
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
inject_undef64() constructs an ESR with EC=0 (Unknown) but does not set
IL. The architecture mandates IL=1 for EC=0 unconditionally (ARM DDI
0487, ESR_ELx.IL description), so the injected syndrome is one that
conforming hardware cannot produce.
Set ESR_ELx_IL in the constructed syndrome.
Fixes: e5d40a5a97c1 ("KVM: arm64: pkvm: Add a generic synchronous exception injection primitive")
Reported-by: sashiko <sashiko@sashiko.dev>
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
index 8c3fbb413a06..9767adf1f73e 100644
--- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
+++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
@@ -278,7 +278,7 @@ static void inject_sync64(struct kvm_vcpu *vcpu, u64 esr)
*/
static void inject_undef64(struct kvm_vcpu *vcpu)
{
- inject_sync64(vcpu, (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT));
+ inject_sync64(vcpu, (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) | ESR_ELx_IL);
}
static u64 read_id_reg(const struct kvm_vcpu *vcpu,
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 2/7] KVM: arm64: Unconditionally set IL for injected undefined exceptions
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 1/7] KVM: arm64: Set ESR_ELx.IL for injected undefined exceptions at EL2 Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 3/7] KVM: arm64: Unconditionally set IL for injected abort exceptions Fuad Tabba
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
inject_undef64() derives IL from the triggering trap's instruction
length (kvm_vcpu_trap_il_is32bit()), but the IL of the injected
exception is fixed by its EC, not by the triggering instruction. The
architecture mandates IL=1 for EC=0 (Unknown) unconditionally, so the
conditional is wrong. The undef-injection paths are not reached from
16-bit instructions, so there is no functional change today, but the
logic should not rely on that.
Set ESR_ELx_IL unconditionally.
Fixes: aa8eff9bfbd5 ("arm64: KVM: fault injection into a guest")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/inject_fault.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 89982bd3345f..9dfae1bcdf99 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -170,14 +170,7 @@ void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr)
static void inject_undef64(struct kvm_vcpu *vcpu)
{
- u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
-
- /*
- * Build an unknown exception, depending on the instruction
- * set.
- */
- if (kvm_vcpu_trap_il_is32bit(vcpu))
- esr |= ESR_ELx_IL;
+ u64 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) | ESR_ELx_IL;
kvm_inject_sync(vcpu, esr);
}
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 3/7] KVM: arm64: Unconditionally set IL for injected abort exceptions
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 1/7] KVM: arm64: Set ESR_ELx.IL for injected undefined exceptions at EL2 Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 2/7] KVM: arm64: Unconditionally set IL for injected undefined exceptions Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 4/7] KVM: arm64: Set IL for injected FPAC exceptions during ERET emulation Fuad Tabba
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
inject_abt64() derives IL from the triggering trap's instruction length
(kvm_vcpu_trap_il_is32bit()), but the IL of the injected abort is fixed
by its EC, not by the triggering instruction. The architecture mandates
IL=1 for Instruction Aborts unconditionally and for Data Aborts with
ISV=0, and this function never sets ISV (the FSC is always EXTABT or
SEA_TTW). For a 16-bit T32 trap (a 32-bit EL0 task under an AArch64 EL1
guest) the trap has IL=0, so the abort is injected with the wrong IL.
Set ESR_ELx_IL unconditionally.
Fixes: aa8eff9bfbd5 ("arm64: KVM: fault injection into a guest")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/inject_fault.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 9dfae1bcdf99..444d219b0217 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -138,11 +138,10 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
pend_sync_exception(vcpu);
/*
- * Build an {i,d}abort, depending on the level and the
- * instruction set. Report an external synchronous abort.
+ * Build an {i,d}abort, depending on the level.
+ * Report an external synchronous abort.
*/
- if (kvm_vcpu_trap_il_is32bit(vcpu))
- esr |= ESR_ELx_IL;
+ esr |= ESR_ELx_IL;
/*
* Here, the guest runs in AArch64 mode when in EL1. If we get
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 4/7] KVM: arm64: Set IL for injected FPAC exceptions during ERET emulation
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
` (2 preceding siblings ...)
2026-06-18 12:16 ` [PATCH v2 3/7] KVM: arm64: Unconditionally set IL for injected abort exceptions Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 5/7] KVM: arm64: Set IL for emulated SError injection Fuad Tabba
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
The FPAC syndrome constructed during nested ERET emulation does not set
IL. For FPAC (EC=0x1C), IL reflects the instruction length. ERET and
its authenticated variants are always A64 32-bit instructions, so IL
must be 1.
Fixes: 213b3d1ea161 ("KVM: arm64: nv: Handle ERETA[AB] instructions")
Suggested-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/emulate-nested.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index dba7ced74ca5..b74369e9ad7f 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2776,7 +2776,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
* ERET handling, and the guest will have a little surprise.
*/
if (kvm_has_pauth(vcpu->kvm, FPACCOMBINE) && !(spsr & PSR_IL_BIT)) {
- esr &= ESR_ELx_ERET_ISS_ERETA;
+ esr &= (ESR_ELx_ERET_ISS_ERETA | ESR_ELx_IL);
esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_FPAC);
kvm_inject_nested_sync(vcpu, esr);
return;
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 5/7] KVM: arm64: Set IL for emulated SError injection
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
` (3 preceding siblings ...)
2026-06-18 12:16 ` [PATCH v2 4/7] KVM: arm64: Set IL for injected FPAC exceptions during ERET emulation Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 6/7] KVM: arm64: Set IL for nested " Fuad Tabba
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
kvm_inject_serror_esr() constructs an SError syndrome without IL. The
architecture mandates IL=1 for SError unconditionally.
Fixes: f6e2262dfa1a ("KVM: arm64: Populate ESR_ELx.EC for emulated SError injection")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/inject_fault.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 444d219b0217..d6c4fc16f879 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -381,7 +381,7 @@ int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr)
*/
if (!serror_is_masked(vcpu)) {
pend_serror_exception(vcpu);
- esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR);
+ esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR) | ESR_ELx_IL;
vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
return 1;
}
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 6/7] KVM: arm64: Set IL for nested SError injection
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
` (4 preceding siblings ...)
2026-06-18 12:16 ` [PATCH v2 5/7] KVM: arm64: Set IL for emulated SError injection Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 12:16 ` [PATCH v2 7/7] KVM: arm64: Set IL in fake ESR for pKVM memory sharing exit Fuad Tabba
2026-06-18 15:47 ` [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
kvm_inject_nested_serror() constructs an SError syndrome without IL.
The architecture mandates IL=1 for SError unconditionally.
Fixes: 77ee70a07357 ("KVM: arm64: nv: Honor SError exception routing / masking")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/emulate-nested.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index b74369e9ad7f..6f12496cae81 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -2938,6 +2938,6 @@ int kvm_inject_nested_serror(struct kvm_vcpu *vcpu, u64 esr)
* vSError injection. Manually populate EC for an emulated SError
* exception.
*/
- esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR);
+ esr |= FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SERROR) | ESR_ELx_IL;
return kvm_inject_nested(vcpu, esr, except_type_serror);
}
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 7/7] KVM: arm64: Set IL in fake ESR for pKVM memory sharing exit
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
` (5 preceding siblings ...)
2026-06-18 12:16 ` [PATCH v2 6/7] KVM: arm64: Set IL for nested " Fuad Tabba
@ 2026-06-18 12:16 ` Fuad Tabba
2026-06-18 15:47 ` [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 12:16 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff, tabba
__pkvm_memshare_page_req() constructs a fake DABT ESR_EL2 to exit to
the host without setting IL. The ESR has ISV=0, so IL must be 1 per the
architecture. The host does not read IL on this path, but the
constructed syndrome should still be architecturally valid.
Set ESR_ELx_IL.
Fixes: 03313efed5e2 ("KVM: arm64: Implement the MEM_SHARE hypercall for protected VMs")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
arch/arm64/kvm/hyp/nvhe/pkvm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index eb1c10120f9f..c982a3a04c37 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -1054,7 +1054,8 @@ static u64 __pkvm_memshare_page_req(struct kvm_vcpu *vcpu, u64 ipa)
/* Fake up a data abort (level 3 translation fault on write) */
vcpu->arch.fault.esr_el2 = (ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT) |
- ESR_ELx_WNR | ESR_ELx_FSC_FAULT |
+ ESR_ELx_IL | ESR_ELx_WNR |
+ ESR_ELx_FSC_FAULT |
FIELD_PREP(ESR_ELx_FSC_LEVEL, 3);
/* Shuffle the IPA around into the HPFAR */
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection
2026-06-18 12:16 [PATCH v2 0/7] KVM: arm64: Fix missing ESR_ELx.IL in syndrome injection Fuad Tabba
` (6 preceding siblings ...)
2026-06-18 12:16 ` [PATCH v2 7/7] KVM: arm64: Set IL in fake ESR for pKVM memory sharing exit Fuad Tabba
@ 2026-06-18 15:47 ` Fuad Tabba
7 siblings, 0 replies; 9+ messages in thread
From: Fuad Tabba @ 2026-06-18 15:47 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon, kvmarm,
linux-arm-kernel, linux-kernel
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Vincent Donnefort, Sascha Bischoff
On Thu, 18 Jun 2026 at 13:16, Fuad Tabba <tabba@google.com> wrote:
>
> Hi folks,
>
> After sashiko caught the missing IL bug [1], I did an audit of all ESR
> syndrome construction sites in KVM/arm64 as Marc suggested. This series
> is the result of that audit.
FWIW, went through all the issues Sashiko raised [1]; the only real
bug it found is the one we already fixed [2].
Cheers,
/fuad
[1] https://sashiko.dev/#/patchset/20260618121643.4105064-1-tabba@google.com
[2] https://lore.kernel.org/all/20260615131116.390977-1-tabba@google.com/
>
> The ARM architecture mandates ESR_ELx.IL=1 for several exception
> classes regardless of instruction length: EC=Unknown, Instruction
> Aborts, Data Aborts with ISV=0, and SError. For FPAC (EC=0x1C), IL
> reflects instruction length, but FPAC can only be generated by A64
> instructions, so IL must also be 1.
>
> Patch 1 is the bug sashiko found: inject_undef64() in the pKVM hyp (EL2)
> path never set IL. Patch 2 makes the same fix to inject_undef64() in the
> normal host path, where IL was derived from the triggering trap's
> instruction length. No instruction that reaches undef injection has a
> 16-bit encoding, so patch 2 has no functional change today.
> Patch 3 makes the matching fix to inject_abt64(). Unlike undef
> injection, abort injection is reachable from a 16-bit T32 instruction (a
> 32-bit EL0 task under an AArch64 EL1 guest), so the old code there
> injects an abort with IL=0.
> Patch 4 fixes the FPAC syndrome constructed during nested ERET
> emulation, which did not set IL.
> Patches 5-6 fix SError injection in the emulated and nested paths,
> neither of which set IL.
> Patch 7 fixes a fake ESR used to exit to the host. The host does not
> read IL there, so it is not guest-visible.
>
> Changes since v1 [2]:
> - Patch 4: keep IL by masking it through from the trapped ERET's ESR
> instead of OR-ing the bit in. The ERET trap (EC=0x1A) always reports
> IL=1, so this preserves the source syndrome rather than adding the
> bit unconditionally (Marc).
> - Rebased on v7.1.
>
> Cheers,
> /fuad
>
> [1] https://lore.kernel.org/all/87pl1t8q24.wl-maz@kernel.org/
> [2] https://lore.kernel.org/all/20260614163336.3490925-1-tabba@google.com/
>
> Signed-off-by: Fuad Tabba <tabba@google.com>
>
> Fuad Tabba (7):
> KVM: arm64: Set ESR_ELx.IL for injected undefined exceptions at EL2
> KVM: arm64: Unconditionally set IL for injected undefined exceptions
> KVM: arm64: Unconditionally set IL for injected abort exceptions
> KVM: arm64: Set IL for injected FPAC exceptions during ERET emulation
> KVM: arm64: Set IL for emulated SError injection
> KVM: arm64: Set IL for nested SError injection
> KVM: arm64: Set IL in fake ESR for pKVM memory sharing exit
>
> arch/arm64/kvm/emulate-nested.c | 4 ++--
> arch/arm64/kvm/hyp/nvhe/pkvm.c | 3 ++-
> arch/arm64/kvm/hyp/nvhe/sys_regs.c | 2 +-
> arch/arm64/kvm/inject_fault.c | 18 +++++-------------
> 4 files changed, 10 insertions(+), 17 deletions(-)
>
> --
> 2.54.0.1189.g8c84645362-goog
>
^ permalink raw reply [flat|nested] 9+ messages in thread