mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
KVM: arm64: nv: Handle SMCs taken from virtual EL2
Non-nested guests have used the hvc instruction to initiate SMCCC calls into KVM. This is quite a poor fit for NV as hvc exceptions are always taken to EL2. In other words, KVM needs to unconditionally forward the hvc exception back into vEL2 to uphold the architecture. Instead, treat the smc instruction from vEL2 as we would a guest hypercall, thereby allowing the vEL2 to interact with KVM's hypercall surface. Note that on NV-capable hardware HCR_EL2.TSC causes smc instructions executed in non-secure EL1 to trap to EL2, even if EL3 is not implemented. Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com> Signed-off-by: Jintack Lim <jintack.lim@linaro.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20230209175820.1939006-13-maz@kernel.org [Oliver: redo commit message, only handle smc from vEL2] Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
parent
6898a55ce3
commit
bd36b1a9eb
@ -63,6 +63,8 @@ static int handle_hvc(struct kvm_vcpu *vcpu)
|
||||
|
||||
static int handle_smc(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* "If an SMC instruction executed at Non-secure EL1 is
|
||||
* trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
|
||||
@ -70,10 +72,30 @@ static int handle_smc(struct kvm_vcpu *vcpu)
|
||||
*
|
||||
* We need to advance the PC after the trap, as it would
|
||||
* otherwise return to the same address...
|
||||
*
|
||||
* Only handle SMCs from the virtual EL2 with an immediate of zero and
|
||||
* skip it otherwise.
|
||||
*/
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
if (!vcpu_is_el2(vcpu) || kvm_vcpu_hvc_get_imm(vcpu)) {
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
kvm_incr_pc(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If imm is zero then it is likely an SMCCC call.
|
||||
*
|
||||
* Note that on ARMv8.3, even if EL3 is not implemented, SMC executed
|
||||
* at Non-secure EL1 is trapped to EL2 if HCR_EL2.TSC==1, rather than
|
||||
* being treated as UNDEFINED.
|
||||
*/
|
||||
ret = kvm_hvc_call_handler(vcpu);
|
||||
if (ret < 0)
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
|
||||
kvm_incr_pc(vcpu);
|
||||
return 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user