[PATCH v5 14/69] KVM: arm64: nv: Support virtual EL2 exceptions
Alexandru Elisei
alexandru.elisei at arm.com
Thu Jan 20 05:58:02 PST 2022
Hi Marc,
On Mon, Nov 29, 2021 at 08:00:55PM +0000, Marc Zyngier wrote:
> From: Jintack Lim <jintack.lim at linaro.org>
>
> Support injecting exceptions and performing exception returns to and
> from virtual EL2. This must be done entirely in software except when
> taking an exception from vEL0 to vEL2 when the virtual HCR_EL2.{E2H,TGE}
> == {1,1} (a VHE guest hypervisor).
>
> Signed-off-by: Jintack Lim <jintack.lim at linaro.org>
> Signed-off-by: Christoffer Dall <christoffer.dall at arm.com>
> [maz: switch to common exception injection framework]
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>
> [..]
>
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> new file mode 100644
> index 000000000000..339e8272b01e
> --- /dev/null
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright (C) 2016 - Linaro and Columbia University
> + * Author: Jintack Lim <jintack.lim at linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include <asm/kvm_emulate.h>
> +#include <asm/kvm_nested.h>
> +
> +#include "hyp/include/hyp/adjust_pc.h"
> +
> +#include "trace.h"
> +
> +void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
> +{
> + u64 spsr, elr, mode;
> + bool direct_eret;
> +
> + /*
> + * Going through the whole put/load motions is a waste of time
> + * if this is a VHE guest hypervisor returning to its own
> + * userspace, or the hypervisor performing a local exception
> + * return. No need to save/restore registers, no need to
> + * switch S2 MMU. Just do the canonical ERET.
> + */
> + spsr = vcpu_read_sys_reg(vcpu, SPSR_EL2);
> + mode = spsr & (PSR_MODE_MASK | PSR_MODE32_BIT);
> +
> + direct_eret = (mode == PSR_MODE_EL0t &&
> + vcpu_el2_e2h_is_set(vcpu) &&
> + vcpu_el2_tge_is_set(vcpu));
> + direct_eret |= (mode == PSR_MODE_EL2h || mode == PSR_MODE_EL2t);
> +
> + if (direct_eret) {
> + *vcpu_pc(vcpu) = vcpu_read_sys_reg(vcpu, ELR_EL2);
> + *vcpu_cpsr(vcpu) = spsr;
> + trace_kvm_nested_eret(vcpu, *vcpu_pc(vcpu), spsr);
> + return;
> + }
> +
> + preempt_disable();
> + kvm_arch_vcpu_put(vcpu);
> +
> + elr = __vcpu_sys_reg(vcpu, ELR_EL2);
> +
> + trace_kvm_nested_eret(vcpu, elr, spsr);
> +
> + /*
> + * Note that the current exception level is always the virtual EL2,
> + * since we set HCR_EL2.NV bit only when entering the virtual EL2.
> + */
> + *vcpu_pc(vcpu) = elr;
> + *vcpu_cpsr(vcpu) = spsr;
> +
> + kvm_arch_vcpu_load(vcpu, smp_processor_id());
> + preempt_enable();
According to ARM DDI 0487G.a, page D13-3289, ERET'ing to EL1 when HCR_EL2.TGE is
set is an illegal exception return. I don't see this case treated here.
Thanks,
Alex
More information about the linux-arm-kernel
mailing list