[PATCH v2 11/13] KVM: arm64: nv: Add emulation for ERETAx instructions
Marc Zyngier
maz at kernel.org
Fri Mar 8 09:54:20 PST 2024
On Fri, 08 Mar 2024 17:20:59 +0000,
Joey Gouly <joey.gouly at arm.com> wrote:
>
> Phew..
[...]
> Each function in this file is quite small, but there's certainly a lot of
> complexity and background knowledge required to understand them!
>
> I spent quite some time on each part to see if it matches what I understood
> from the Arm ARM.
>
> Reviewed-by: Joey Gouly <joey.gouly at arm.com>
Thanks a lot for putting up with it, much appreciated.
> A side note / thing I considered. KVM doesn't currently handle ERET exceptions
> from EL1.
EL1 is ambiguous here. Is that EL1 from the PoV of the guest?
>
> 1. If an ERETA{A,B} were executed from a nested EL1 guest, that would be
> trapped up to Host KVM at EL2.
There are two possibilities for that (assuming EL1 from the PoV of a
L1 guest):
(1) this EL1 guest is itself a guest hypervisor (i.e. we are running
an L1 guest which itself is using NV and running an L2 which
itself is a hypervisor). In that case, ERET* would have to be
trapped to EL2 and re-injected. Note that we do not support NV
under NV. Yet...
(2) the L2 guest is not a hypervisor (no recursive NV), but the L1
hypervisor has set HFGITR_EL2.ERET==1. We'd have to re-inject the
exception into L1, just like in the precedent case.
If neither HCR_EL2.NV nor HFGITR_EL2.ERET are set, then no ERET* gets
trapped at all. Crucially, when running an L2 guest that doesn't isn't
itself a hypervisor (no nested NV), we do not trap ERET* at all.
In a way, the NV overhead is mostly when running L1. Once you run L2,
the overhead "vanishes", to some extent (as long as you don't exit,
because that's where the cost is).
> 2. kvm_hyp_handle_eret() returns false since it's not from vEL2. Inside
> kvm_handle_eret(), is_hyp_ctxt() is false so the exception is injected into
> vEL2 (via kvm_inject_nested_sync()).
>
> 3. vEL2 gets the exception, kvm_hyp_handle_eret() returns false as before.
> Inside kvm_handle_eret(), is_hyp_ctxt() is also false, so
> kvm_inject_nested_sync() is called but now errors out since vcpu_has_nv() is
> false.
>
> Is that flow right? Am I missing something?
I'm not sure. The cases where ERET gets trapped are really limited to
the above two cases.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
More information about the linux-arm-kernel
mailing list