Skip to content

Commit f174a9f

Browse files
Marc Zyngierwilldeacon
authored andcommitted
KVM: arm64: Add exit to userspace on {LD,ST}64B* outside of memslots
The main use of {LD,ST}64B* is to talk to a device, which is hopefully directly assigned to the guest and requires no additional handling. However, this does not preclude a VMM from exposing a virtual device to the guest, and to allow 64 byte accesses as part of the programming interface. A direct consequence of this is that we need to be able to forward such access to userspace. Given that such a contraption is very unlikely to ever exist, we choose to offer a limited service: userspace gets (as part of a new exit reason) the ESR, the IPA, and that's it. It is fully expected to handle the full semantics of the instructions, deal with ACCDATA, the return values and increment PC. Much fun. A canonical implementation can also simply inject an abort and be done with it. Frankly, don't try to do anything else unless you have time to waste. Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Oliver Upton <oupton@kernel.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com> Signed-off-by: Will Deacon <will@kernel.org>
1 parent 018a231 commit f174a9f

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

arch/arm64/kvm/mmio.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
159159
bool is_write;
160160
int len;
161161
u8 data_buf[8];
162+
u64 esr;
163+
164+
esr = kvm_vcpu_get_esr(vcpu);
162165

163166
/*
164167
* No valid syndrome? Ask userspace for help if it has
@@ -168,7 +171,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
168171
* though, so directly deliver an exception to the guest.
169172
*/
170173
if (!kvm_vcpu_dabt_isvalid(vcpu)) {
171-
trace_kvm_mmio_nisv(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu),
174+
trace_kvm_mmio_nisv(*vcpu_pc(vcpu), esr,
172175
kvm_vcpu_get_hfar(vcpu), fault_ipa);
173176

174177
if (vcpu_is_protected(vcpu))
@@ -185,6 +188,28 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
185188
return -ENOSYS;
186189
}
187190

191+
/*
192+
* When (DFSC == 0b00xxxx || DFSC == 0b10101x) && DFSC != 0b0000xx
193+
* ESR_EL2[12:11] describe the Load/Store Type. This allows us to
194+
* punt the LD64B/ST64B/ST64BV/ST64BV0 instructions to userspace,
195+
* which will have to provide a full emulation of these 4
196+
* instructions. No, we don't expect this do be fast.
197+
*
198+
* We rely on traps being set if the corresponding features are not
199+
* enabled, so if we get here, userspace has promised us to handle
200+
* it already.
201+
*/
202+
switch (kvm_vcpu_trap_get_fault(vcpu)) {
203+
case 0b000100 ... 0b001111:
204+
case 0b101010 ... 0b101011:
205+
if (FIELD_GET(GENMASK(12, 11), esr)) {
206+
run->exit_reason = KVM_EXIT_ARM_LDST64B;
207+
run->arm_nisv.esr_iss = esr & ~(u64)ESR_ELx_FSC;
208+
run->arm_nisv.fault_ipa = fault_ipa;
209+
return 0;
210+
}
211+
}
212+
188213
/*
189214
* Prepare MMIO operation. First decode the syndrome data we get
190215
* from the CPU. Then try if some in-kernel emulation feels

include/uapi/linux/kvm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ struct kvm_xen_exit {
180180
#define KVM_EXIT_MEMORY_FAULT 39
181181
#define KVM_EXIT_TDX 40
182182
#define KVM_EXIT_ARM_SEA 41
183+
#define KVM_EXIT_ARM_LDST64B 42
183184

184185
/* For KVM_EXIT_INTERNAL_ERROR */
185186
/* Emulate instruction failed. */
@@ -402,7 +403,7 @@ struct kvm_run {
402403
} eoi;
403404
/* KVM_EXIT_HYPERV */
404405
struct kvm_hyperv_exit hyperv;
405-
/* KVM_EXIT_ARM_NISV */
406+
/* KVM_EXIT_ARM_NISV / KVM_EXIT_ARM_LDST64B */
406407
struct {
407408
__u64 esr_iss;
408409
__u64 fault_ipa;

0 commit comments

Comments
 (0)