[PATCH v4 09/66] KVM: arm64: nv: Support virtual EL2 exceptions
Zenghui Yu
yuzenghui at huawei.com
Thu May 20 05:55:48 PDT 2021
On 2021/5/11 0:58, 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>
> ---
> arch/arm64/include/asm/kvm_arm.h | 17 +++
> arch/arm64/include/asm/kvm_emulate.h | 10 ++
> arch/arm64/kvm/Makefile | 2 +-
> arch/arm64/kvm/emulate-nested.c | 176 +++++++++++++++++++++++++++
> arch/arm64/kvm/hyp/exception.c | 45 +++++--
> arch/arm64/kvm/inject_fault.c | 63 ++++++++--
> arch/arm64/kvm/trace_arm.h | 59 +++++++++
> 7 files changed, 354 insertions(+), 18 deletions(-)
> create mode 100644 arch/arm64/kvm/emulate-nested.c
[...]
> static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
> {
> unsigned long cpsr = *vcpu_cpsr(vcpu);
> bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
> u32 esr = 0;
>
> - vcpu->arch.flags |= (KVM_ARM64_EXCEPT_AA64_EL1 |
> - KVM_ARM64_EXCEPT_AA64_ELx_SYNC |
> - KVM_ARM64_PENDING_EXCEPTION);
> -
> - vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
> + pend_sync_exception(vcpu);
>
> /*
> * Build an {i,d}abort, depending on the level and the
> @@ -45,16 +79,22 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
> if (!is_iabt)
> esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
>
> - vcpu_write_sys_reg(vcpu, esr | ESR_ELx_FSC_EXTABT, ESR_EL1);
> + esr |= ESR_ELx_FSC_EXTABT;
> +
> + if (vcpu->arch.flags & KVM_ARM64_EXCEPT_AA64_EL1) {
This isn't the right way to pick between EL1 and EL2 since
KVM_ARM64_EXCEPT_AA64_EL1 is (0 << 11), we will not be able
to inject abort to EL1 that way.
> + vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
> + vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
> + } else {
> + vcpu_write_sys_reg(vcpu, addr, FAR_EL2);
> + vcpu_write_sys_reg(vcpu, esr, ESR_EL2);
> + }
> }
>
> static void inject_undef64(struct kvm_vcpu *vcpu)
> {
> u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
>
> - vcpu->arch.flags |= (KVM_ARM64_EXCEPT_AA64_EL1 |
> - KVM_ARM64_EXCEPT_AA64_ELx_SYNC |
> - KVM_ARM64_PENDING_EXCEPTION);
> + pend_sync_exception(vcpu);
>
> /*
> * Build an unknown exception, depending on the instruction
> @@ -63,7 +103,10 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
> if (kvm_vcpu_trap_il_is32bit(vcpu))
> esr |= ESR_ELx_IL;
>
> - vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
> + if (vcpu->arch.flags & KVM_ARM64_EXCEPT_AA64_EL1)
> + vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
> + else
> + vcpu_write_sys_reg(vcpu, esr, ESR_EL2);
Same here.
Thanks,
Zenghui
More information about the linux-arm-kernel
mailing list