@@ -57,6 +57,22 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr,
return kvm__emulate_mmio(vcpu, phys_addr, data, len, is_write);
}
+static inline bool kvm_cpu__mmio_not_found(struct kvm_cpu *vcpu, u64 phys_addr)
+{
+ struct kvm_vcpu_events events = {
+ .exception.ext_dabt_pending = 1,
+ };
+ int err;
+
+ if (!kvm__supports_extension(vcpu->kvm, KVM_CAP_ARM_INJECT_EXT_DABT))
+ return false;
+
+ err = ioctl(vcpu->vcpu_fd, KVM_SET_VCPU_EVENTS, &events);
+ if (err)
+ die("failed to inject external abort");
+ return true;
+}
+
unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu);
#endif /* ARM_COMMON__KVM_CPU_ARCH_H */
@@ -142,7 +142,7 @@ bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
if (!arm_addr_in_ioport_region(phys_addr) &&
!kvm__mmio_exists(vcpu, phys_addr))
- die("Guest accessed memory outside RAM and IO ranges");
+ return kvm_cpu__mmio_not_found(vcpu, phys_addr);
/*
* We cannot fetch and decode instructions from a KVM guest,
@@ -40,4 +40,9 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8
return kvm__emulate_mmio(vcpu, phys_addr, data, len, is_write);
}
+static inline bool kvm_cpu__mmio_not_found(struct kvm_cpu *vcpu, u64 phys_addr)
+{
+ return false;
+}
+
#endif /* KVM__KVM_CPU_ARCH_H */
@@ -130,7 +130,8 @@ bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u
if (mmio)
mmio->mmio_fn(vcpu, phys_addr, data, len, is_write, mmio->ptr);
else {
- if (vcpu->kvm->cfg.mmio_debug)
+ if (!kvm_cpu__mmio_not_found(vcpu, phys_addr) &&
+ vcpu->kvm->cfg.mmio_debug)
fprintf(stderr, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
to_direction(is_write),
(unsigned long long)phys_addr, len);
@@ -76,4 +76,9 @@ static inline bool kvm_cpu__emulate_io(struct kvm_cpu *vcpu, u16 port, void *dat
bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+static inline bool kvm_cpu__mmio_not_found(struct kvm_cpu *vcpu, u64 phys_addr)
+{
+ return false;
+}
+
#endif /* KVM__KVM_CPU_ARCH_H */
@@ -47,4 +47,9 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8
return kvm__emulate_mmio(vcpu, phys_addr, data, len, is_write);
}
+static inline bool kvm_cpu__mmio_not_found(struct kvm_cpu *vcpu, u64 phys_addr)
+{
+ return false;
+}
+
#endif /* KVM__KVM_CPU_ARCH_H */
Occasionally guests will attempt to access parts of the guest memory map where there is... nothing at all. Until now, we've handled this by either forcefully killing the guest, or silently (unless a debug option was enabled) ignoring the access. Neither is very helpful to a user, who is most likely running either a broken or misconfigured guest. A more appropriate action is to inject an external abort to the guest. Luckily, with KVM_CAP_ARM_INJECT_EXT_DABT, we can use the set event mechanism and ask KVM to do this for us. So we add an architecture specific hook to handle accesses to MMIO regions which cannot be found, and allow them to return if the invalid access was handled or not. Signed-off-by: Christoffer Dall <christoffer.dall@arm.com> --- arm/include/arm-common/kvm-cpu-arch.h | 16 ++++++++++++++++ arm/kvm-cpu.c | 2 +- mips/include/kvm/kvm-cpu-arch.h | 5 +++++ mmio.c | 3 ++- powerpc/include/kvm/kvm-cpu-arch.h | 5 +++++ x86/include/kvm/kvm-cpu-arch.h | 5 +++++ 6 files changed, 34 insertions(+), 2 deletions(-)