On Sun, Jun 28, 2020 at 04:04:58PM +0100, Beata Michalska wrote: > On ARMv7 & ARMv8 some load/store instructions might trigger a data abort > exception with no valid ISS info to be decoded. The lack of decode info > makes it at least tricky to emulate those instruction which is one of the > (many) reasons why KVM will not even try to do so. > > Add support for handling those by requesting KVM to inject external > dabt into the quest. > > Signed-off-by: Beata Michalska <beata.michalska@xxxxxxxxxx> > --- > target/arm/kvm.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 56 insertions(+), 1 deletion(-) > > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index eef3bbd..2dd8a9a 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -39,6 +39,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { > > static bool cap_has_mp_state; > static bool cap_has_inject_serror_esr; > +static bool cap_has_inject_ext_dabt; > > static ARMHostCPUFeatures arm_host_cpu_features; > > @@ -245,6 +246,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) > ret = -EINVAL; > } > > + if (kvm_check_extension(s, KVM_CAP_ARM_NISV_TO_USER)) { > + if (kvm_vm_enable_cap(s, KVM_CAP_ARM_NISV_TO_USER, 0)) { > + error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap"); > + } else { > + /* Set status for supporting the external dabt injection */ > + cap_has_inject_ext_dabt = kvm_check_extension(s, > + KVM_CAP_ARM_INJECT_EXT_DABT); > + } > + } > + > return ret; > } > > @@ -810,6 +821,45 @@ void kvm_arm_vm_state_change(void *opaque, int running, RunState state) > } > } > > +/** > + * kvm_arm_handle_dabt_nisv: > + * @cs: CPUState > + * @esr_iss: ISS encoding (limited) for the exception from Data Abort > + * ISV bit set to '0b0' -> no valid instruction syndrome > + * @fault_ipa: faulting address for the synchronous data abort > + * > + * Returns: 0 if the exception has been handled, < 0 otherwise > + */ > +static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, > + uint64_t fault_ipa) The indent of 'uint64_t fault_ipa' is off. Should be under CPUState. > +{ > + /* > + * Request KVM to inject the external data abort into the guest > + */ > + if (cap_has_inject_ext_dabt) { > + struct kvm_vcpu_events events = { }; > + /* > + * The external data abort event will be handled immediately by KVM > + * using the address fault that triggered the exit on given VCPU. > + * Requesting injection of the external data abort does not rely > + * on any other VCPU state. Therefore, in this particular case, the VCPU > + * synchronization can be exceptionally skipped. > + */ > + events.exception.ext_dabt_pending = 1; > + /* > + * KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS > + */ Single line comments may be done with /* ... */ > + return kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events); > + Extra blank line here. > + } else { > + error_report("Data abort exception triggered by guest memory access " > + "at physical address: 0x" TARGET_FMT_lx, > + (target_ulong)fault_ipa); > + error_printf("KVM unable to emulate faulting instruction.\n"); > + } > + return -1; > +} > + > int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) > { > int ret = 0; > @@ -820,7 +870,12 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) > ret = EXCP_DEBUG; > } /* otherwise return to guest */ > break; > - default: > + case KVM_EXIT_ARM_NISV: > + /* External DABT with no valid iss to decode */ > + ret = kvm_arm_handle_dabt_nisv(cs, run->arm_nisv.esr_iss, > + run->arm_nisv.fault_ipa); > + break; > + default: An extra space got added in front of 'default:' > qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", > __func__, run->exit_reason); > break; > -- > 2.7.4 > > Besides the format changes Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx> _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm