Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Marc Zyngier and committed by
Will Deacon
f174a9ff 018a231b

+28 -2
+26 -1
arch/arm64/kvm/mmio.c
··· 159 159 bool is_write; 160 160 int len; 161 161 u8 data_buf[8]; 162 + u64 esr; 163 + 164 + esr = kvm_vcpu_get_esr(vcpu); 162 165 163 166 /* 164 167 * No valid syndrome? Ask userspace for help if it has ··· 171 168 * though, so directly deliver an exception to the guest. 172 169 */ 173 170 if (!kvm_vcpu_dabt_isvalid(vcpu)) { 174 - trace_kvm_mmio_nisv(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu), 171 + trace_kvm_mmio_nisv(*vcpu_pc(vcpu), esr, 175 172 kvm_vcpu_get_hfar(vcpu), fault_ipa); 176 173 177 174 if (vcpu_is_protected(vcpu)) ··· 186 183 } 187 184 188 185 return -ENOSYS; 186 + } 187 + 188 + /* 189 + * When (DFSC == 0b00xxxx || DFSC == 0b10101x) && DFSC != 0b0000xx 190 + * ESR_EL2[12:11] describe the Load/Store Type. This allows us to 191 + * punt the LD64B/ST64B/ST64BV/ST64BV0 instructions to userspace, 192 + * which will have to provide a full emulation of these 4 193 + * instructions. No, we don't expect this do be fast. 194 + * 195 + * We rely on traps being set if the corresponding features are not 196 + * enabled, so if we get here, userspace has promised us to handle 197 + * it already. 198 + */ 199 + switch (kvm_vcpu_trap_get_fault(vcpu)) { 200 + case 0b000100 ... 0b001111: 201 + case 0b101010 ... 0b101011: 202 + if (FIELD_GET(GENMASK(12, 11), esr)) { 203 + run->exit_reason = KVM_EXIT_ARM_LDST64B; 204 + run->arm_nisv.esr_iss = esr & ~(u64)ESR_ELx_FSC; 205 + run->arm_nisv.fault_ipa = fault_ipa; 206 + return 0; 207 + } 189 208 } 190 209 191 210 /*
+2 -1
include/uapi/linux/kvm.h
··· 180 180 #define KVM_EXIT_MEMORY_FAULT 39 181 181 #define KVM_EXIT_TDX 40 182 182 #define KVM_EXIT_ARM_SEA 41 183 + #define KVM_EXIT_ARM_LDST64B 42 183 184 184 185 /* For KVM_EXIT_INTERNAL_ERROR */ 185 186 /* Emulate instruction failed. */ ··· 403 402 } eoi; 404 403 /* KVM_EXIT_HYPERV */ 405 404 struct kvm_hyperv_exit hyperv; 406 - /* KVM_EXIT_ARM_NISV */ 405 + /* KVM_EXIT_ARM_NISV / KVM_EXIT_ARM_LDST64B */ 407 406 struct { 408 407 __u64 esr_iss; 409 408 __u64 fault_ipa;