Add a fallback mechanism to the in-kernel instruction emulator that allows userspace the opportunity to process an instruction the emulator was unable to. When the in-kernel instruction emulator fails to process an instruction it will either inject a #UD into the guest or exit to userspace with exit reason KVM_INTERNAL_ERROR. This is because it does not know how to proceed in an appropriate manner. This feature lets userspace get involved to see if it can figure out a better path forward.
Showing the changes to include/uapi (1 of 4 files). Show all
Unified · Split
| @@ -280,6 +280,9 @@ struct kvm_xen_exit { · 279 unmodified lines | ||
| 280 | 280 | /* Encounter unexpected vm-exit reason */ |
| 281 | 281 | #define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4 |
| 282 | 282 | |
| 283 | +/* Flags that describe what fields in emulation_failure hold valid data. */ | |
| 284 | +#define KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES (1ULL << 0) | |
| 285 | + | |
| 283 | 286 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ |
| 284 | 287 | struct kvm_run { |
| 285 | 288 | /* in */ |
| @@ -383,6 +386,25 @@ struct kvm_run { · 97 unmodified lines | ||
| 383 | 386 | __u32 ndata; |
| 384 | 387 | __u64 data[16]; |
| 385 | 388 | } internal; |
| 389 | + /* | |
| 390 | + * KVM_INTERNAL_ERROR_EMULATION | |
| 391 | + * | |
| 392 | + * "struct emulation_failure" is an overlay of "struct internal" | |
| 393 | + * that is used for the KVM_INTERNAL_ERROR_EMULATION sub-type of | |
| 394 | + * KVM_EXIT_INTERNAL_ERROR. Note, unlike other internal error | |
| 395 | + * sub-types, this struct is ABI! It also needs to be backwards | |
| 396 | + * compatible with "struct internal". Take special care that | |
| 397 | + * "ndata" is correct, that new fields are enumerated in "flags", | |
| 398 | + * and that each flag enumerates fields that are 64-bit aligned | |
| 399 | + * and sized (so that ndata+internal.data[] is valid/accurate). | |
| 400 | + */ | |
| 401 | + struct { | |
| 402 | + __u32 suberror; | |
| 403 | + __u32 ndata; | |
| 404 | + __u64 flags; | |
| 405 | + __u8 insn_size; | |
| 406 | + __u8 insn_bytes[15]; | |
| 407 | + } emulation_failure; | |
| 386 | 408 | /* KVM_EXIT_OSI */ |
| 387 | 409 | struct { |
| 388 | 410 | __u64 gprs[32]; |
| @@ -1088,6 +1110,7 @@ struct kvm_ppc_resize_hpt { · 699 unmodified lines | ||
| 1088 | 1110 | #define KVM_CAP_EXIT_HYPERCALL 201 |
| 1089 | 1111 | #define KVM_CAP_PPC_RPT_INVALIDATE 202 |
| 1090 | 1112 | #define KVM_CAP_BINARY_STATS_FD 203 |
| 1113 | +#define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 | |
| 1091 | 1114 | |
| 1092 | 1115 | #ifdef KVM_CAP_IRQ_ROUTING |
| 1093 | 1116 | |