|
@@ -105,10 +105,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
|
MDCR_EL2_TDRA |
|
|
|
MDCR_EL2_TDOSA);
|
|
|
|
|
|
- /* Trap on access to debug registers? */
|
|
|
- if (trap_debug)
|
|
|
- vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
|
|
|
-
|
|
|
/* Is Guest debugging in effect? */
|
|
|
if (vcpu->guest_debug) {
|
|
|
/* Route all software debug exceptions to EL2 */
|
|
@@ -143,11 +139,45 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
|
} else {
|
|
|
vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * HW Breakpoints and watchpoints
|
|
|
+ *
|
|
|
+ * We simply switch the debug_ptr to point to our new
|
|
|
+ * external_debug_state which has been populated by the
|
|
|
+ * debug ioctl. The existing KVM_ARM64_DEBUG_DIRTY
|
|
|
+ * mechanism ensures the registers are updated on the
|
|
|
+ * world switch.
|
|
|
+ */
|
|
|
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
|
|
|
+ /* Enable breakpoints/watchpoints */
|
|
|
+ vcpu_sys_reg(vcpu, MDSCR_EL1) |= DBG_MDSCR_MDE;
|
|
|
+
|
|
|
+ vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
|
|
|
+ vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
|
|
|
+ trap_debug = true;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ BUG_ON(!vcpu->guest_debug &&
|
|
|
+ vcpu->arch.debug_ptr != &vcpu->arch.vcpu_debug_state);
|
|
|
+
|
|
|
+ /* Trap debug register access */
|
|
|
+ if (trap_debug)
|
|
|
+ vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
|
|
|
}
|
|
|
|
|
|
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
- if (vcpu->guest_debug)
|
|
|
+ if (vcpu->guest_debug) {
|
|
|
restore_guest_debug_regs(vcpu);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we were using HW debug we need to restore the
|
|
|
+ * debug_ptr to the guest debug state.
|
|
|
+ */
|
|
|
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW)
|
|
|
+ kvm_arm_reset_debug_ptr(vcpu);
|
|
|
+
|
|
|
+ }
|
|
|
}
|