[PATCH v4 09/66] KVM: arm64: nv: Support virtual EL2 exceptions
Marc Zyngier
maz at kernel.org
Mon May 24 05:35:24 PDT 2021
On Thu, 20 May 2021 13:55:48 +0100,
Zenghui Yu <yuzenghui at huawei.com> wrote:
>
> 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.
Indeed, well observed. I'm squashing the following fix in this patch.
Thanks,
M.
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27397ecf9a23..fe781557e42c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -524,6 +524,7 @@ struct kvm_vcpu_arch {
#define KVM_ARM64_EXCEPT_AA64_ELx_SERR (3 << 9)
#define KVM_ARM64_EXCEPT_AA64_EL1 (0 << 11)
#define KVM_ARM64_EXCEPT_AA64_EL2 (1 << 11)
+#define KVM_ARM64_EXCEPT_AA64_EL_MASK (1 << 11)
/*
* Overlaps with KVM_ARM64_EXCEPT_MASK on purpose so that it can't be
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 06df0bb848ca..5dcf3f8b08b8 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -52,6 +52,11 @@ static void pend_sync_exception(struct kvm_vcpu *vcpu)
}
}
+static bool match_target_el(struct kvm_vcpu *vcpu, unsigned long target)
+{
+ return (vcpu->arch.flags & KVM_ARM64_EXCEPT_AA64_EL_MASK) == target;
+}
+
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
{
unsigned long cpsr = *vcpu_cpsr(vcpu);
@@ -81,7 +86,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
esr |= ESR_ELx_FSC_EXTABT;
- if (vcpu->arch.flags & KVM_ARM64_EXCEPT_AA64_EL1) {
+ if (match_target_el(vcpu, KVM_ARM64_EXCEPT_AA64_EL1)) {
vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
} else {
@@ -103,7 +108,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
if (kvm_vcpu_trap_il_is32bit(vcpu))
esr |= ESR_ELx_IL;
- if (vcpu->arch.flags & KVM_ARM64_EXCEPT_AA64_EL1)
+ if (match_target_el(vcpu, KVM_ARM64_EXCEPT_AA64_EL1))
vcpu_write_sys_reg(vcpu, esr, ESR_EL1);
else
vcpu_write_sys_reg(vcpu, esr, ESR_EL2);
--
Without deviation from the norm, progress is not possible.
More information about the linux-arm-kernel
mailing list