[PATCH v3 16/36] KVM: arm64: Factor out pKVM host exception injection logic
Fuad Tabba
tabba at google.com
Wed Mar 11 03:12:31 PDT 2026
On Thu, 5 Mar 2026 at 14:45, Will Deacon <will at kernel.org> wrote:
>
> inject_undef64() open-codes the logic to inject an exception into the
> pKVM host. In preparation for reusing this logic to inject a data abort
> on an unhandled stage-2 fault from the host, factor out the meat and
> potatoes of the function into a new inject_host_exception() function
> which takes the ESR as a parameter.
>
> Cc: Fuad Tabba <tabba at google.com>
Reviewed-by: Fuad Tabba <tabba at google.com>
Cheers,
/fuad
> Signed-off-by: Will Deacon <will at kernel.org>
> ---
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 49 ++++++++++++++----------------
> 1 file changed, 23 insertions(+), 26 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 7294c94f9296..adfc0bc15398 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -705,43 +705,40 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
> kvm_skip_host_instr();
> }
>
> -/*
> - * Inject an Undefined Instruction exception into the host.
> - *
> - * This is open-coded to allow control over PSTATE construction without
> - * complicating the generic exception entry helpers.
> - */
> -static void inject_undef64(void)
> +static void inject_host_exception(u64 esr)
> {
> - u64 spsr_mask, vbar, sctlr, old_spsr, new_spsr, esr, offset;
> + u64 sctlr, spsr_el1, spsr_el2, exc_offset = except_type_sync;
> + const u64 spsr_mask = PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT |
> + PSR_V_BIT | PSR_DIT_BIT | PSR_PAN_BIT;
>
> - spsr_mask = PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT | PSR_DIT_BIT | PSR_PAN_BIT;
> + exc_offset += CURRENT_EL_SP_ELx_VECTOR;
> +
> + spsr_el1 = spsr_el2 = read_sysreg_el2(SYS_SPSR);
> + spsr_el2 &= spsr_mask;
> + spsr_el2 |= PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT |
> + PSR_MODE_EL1h;
>
> - vbar = read_sysreg_el1(SYS_VBAR);
> sctlr = read_sysreg_el1(SYS_SCTLR);
> - old_spsr = read_sysreg_el2(SYS_SPSR);
> -
> - new_spsr = old_spsr & spsr_mask;
> - new_spsr |= PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT;
> - new_spsr |= PSR_MODE_EL1h;
> -
> if (!(sctlr & SCTLR_EL1_SPAN))
> - new_spsr |= PSR_PAN_BIT;
> + spsr_el2 |= PSR_PAN_BIT;
>
> if (sctlr & SCTLR_ELx_DSSBS)
> - new_spsr |= PSR_SSBS_BIT;
> + spsr_el2 |= PSR_SSBS_BIT;
>
> if (system_supports_mte())
> - new_spsr |= PSR_TCO_BIT;
> -
> - esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) | ESR_ELx_IL;
> - offset = CURRENT_EL_SP_ELx_VECTOR + except_type_sync;
> + spsr_el2 |= PSR_TCO_BIT;
>
> write_sysreg_el1(esr, SYS_ESR);
> write_sysreg_el1(read_sysreg_el2(SYS_ELR), SYS_ELR);
> - write_sysreg_el1(old_spsr, SYS_SPSR);
> - write_sysreg_el2(vbar + offset, SYS_ELR);
> - write_sysreg_el2(new_spsr, SYS_SPSR);
> + write_sysreg_el1(spsr_el1, SYS_SPSR);
> + write_sysreg_el2(read_sysreg_el1(SYS_VBAR) + exc_offset, SYS_ELR);
> + write_sysreg_el2(spsr_el2, SYS_SPSR);
> +}
> +
> +static void inject_host_undef64(void)
> +{
> + inject_host_exception((ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT) |
> + ESR_ELx_IL);
> }
>
> static bool handle_host_mte(u64 esr)
> @@ -764,7 +761,7 @@ static bool handle_host_mte(u64 esr)
> return false;
> }
>
> - inject_undef64();
> + inject_host_undef64();
> return true;
> }
>
> --
> 2.53.0.473.g4a7958ca14-goog
>
More information about the linux-arm-kernel
mailing list