Skip to content

Commit 0e5c9a9

Browse files
author
Marc Zyngier
committed
KVM: arm64: Expose SMC/HVC width to userspace
When returning to userspace to handle a SMCCC call, we consistently set PC to point to the instruction immediately after the HVC/SMC. However, should userspace need to know the exact address of the trapping instruction, it needs to know about the *size* of that instruction. For AArch64, this is pretty easy. For AArch32, this is a bit more funky, as Thumb has 16bit encodings for both HVC and SMC. Expose this to userspace with a new flag that directly derives from ESR_EL2.IL. Also update the documentation to reflect the PC state at the point of exit. Finally, this fixes a small buglet where the hypercall.{args,ret} fields would not be cleared on exit, and could contain some random junk. Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/86pm8iv8tj.wl-maz@kernel.org
1 parent 60e7dad commit 0e5c9a9

3 files changed

Lines changed: 21 additions & 6 deletions

File tree

Documentation/virt/kvm/api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6244,6 +6244,14 @@ Definition of ``flags``:
62446244
conduit to initiate the SMCCC call. If this bit is 0 then the guest
62456245
used the HVC conduit for the SMCCC call.
62466246

6247+
- ``KVM_HYPERCALL_EXIT_16BIT``: Indicates that the guest used a 16bit
6248+
instruction to initiate the SMCCC call. If this bit is 0 then the
6249+
guest used a 32bit instruction. An AArch64 guest always has this
6250+
bit set to 0.
6251+
6252+
At the point of exit, PC points to the instruction immediately following
6253+
the trapping instruction.
6254+
62476255
::
62486256

62496257
/* KVM_EXIT_TPR_ACCESS */

arch/arm64/include/uapi/asm/kvm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,8 @@ struct kvm_smccc_filter {
491491
};
492492

493493
/* arm64-specific KVM_EXIT_HYPERCALL flags */
494-
#define KVM_HYPERCALL_EXIT_SMC (1U << 0)
494+
#define KVM_HYPERCALL_EXIT_SMC (1U << 0)
495+
#define KVM_HYPERCALL_EXIT_16BIT (1U << 1)
495496

496497
#endif
497498

arch/arm64/kvm/hypercalls.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,19 @@ static void kvm_prepare_hypercall_exit(struct kvm_vcpu *vcpu, u32 func_id)
222222
{
223223
u8 ec = ESR_ELx_EC(kvm_vcpu_get_esr(vcpu));
224224
struct kvm_run *run = vcpu->run;
225-
226-
run->exit_reason = KVM_EXIT_HYPERCALL;
227-
run->hypercall.nr = func_id;
228-
run->hypercall.flags = 0;
225+
u64 flags = 0;
229226

230227
if (ec == ESR_ELx_EC_SMC32 || ec == ESR_ELx_EC_SMC64)
231-
run->hypercall.flags |= KVM_HYPERCALL_EXIT_SMC;
228+
flags |= KVM_HYPERCALL_EXIT_SMC;
229+
230+
if (!kvm_vcpu_trap_il_is32bit(vcpu))
231+
flags |= KVM_HYPERCALL_EXIT_16BIT;
232+
233+
run->exit_reason = KVM_EXIT_HYPERCALL;
234+
run->hypercall = (typeof(run->hypercall)) {
235+
.nr = func_id,
236+
.flags = flags,
237+
};
232238
}
233239

234240
int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)

0 commit comments

Comments
 (0)