|
@@ -18,12 +18,15 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
#include <linux/kvm_host.h>
|
|
#include <linux/kvm_host.h>
|
|
|
|
+#include <linux/hw_breakpoint.h>
|
|
|
|
|
|
#include <asm/debug-monitors.h>
|
|
#include <asm/debug-monitors.h>
|
|
#include <asm/kvm_asm.h>
|
|
#include <asm/kvm_asm.h>
|
|
#include <asm/kvm_arm.h>
|
|
#include <asm/kvm_arm.h>
|
|
#include <asm/kvm_emulate.h>
|
|
#include <asm/kvm_emulate.h>
|
|
|
|
|
|
|
|
+#include "trace.h"
|
|
|
|
+
|
|
/* These are the bits of MDSCR_EL1 we may manipulate */
|
|
/* These are the bits of MDSCR_EL1 we may manipulate */
|
|
#define MDSCR_EL1_DEBUG_MASK (DBG_MDSCR_SS | \
|
|
#define MDSCR_EL1_DEBUG_MASK (DBG_MDSCR_SS | \
|
|
DBG_MDSCR_KDE | \
|
|
DBG_MDSCR_KDE | \
|
|
@@ -44,11 +47,17 @@ static DEFINE_PER_CPU(u32, mdcr_el2);
|
|
static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
|
|
static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
vcpu->arch.guest_debug_preserved.mdscr_el1 = vcpu_sys_reg(vcpu, MDSCR_EL1);
|
|
vcpu->arch.guest_debug_preserved.mdscr_el1 = vcpu_sys_reg(vcpu, MDSCR_EL1);
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_dreg32("Saved MDSCR_EL1",
|
|
|
|
+ vcpu->arch.guest_debug_preserved.mdscr_el1);
|
|
}
|
|
}
|
|
|
|
|
|
static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
|
|
static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
vcpu_sys_reg(vcpu, MDSCR_EL1) = vcpu->arch.guest_debug_preserved.mdscr_el1;
|
|
vcpu_sys_reg(vcpu, MDSCR_EL1) = vcpu->arch.guest_debug_preserved.mdscr_el1;
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_dreg32("Restored MDSCR_EL1",
|
|
|
|
+ vcpu_sys_reg(vcpu, MDSCR_EL1));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -99,6 +108,8 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
|
|
bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
|
|
|
|
|
|
|
|
+ trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
|
|
|
|
+
|
|
vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
|
|
vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
|
|
vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
|
|
vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
|
|
MDCR_EL2_TPMCR |
|
|
MDCR_EL2_TPMCR |
|
|
@@ -140,6 +151,8 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
|
|
vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ trace_kvm_arm_set_dreg32("SPSR_EL2", *vcpu_cpsr(vcpu));
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* HW Breakpoints and watchpoints
|
|
* HW Breakpoints and watchpoints
|
|
*
|
|
*
|
|
@@ -156,6 +169,14 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
|
|
vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
|
|
vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
|
|
vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
|
|
trap_debug = true;
|
|
trap_debug = true;
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_bcr[0],
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_bvr[0]);
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_regset("WAPTS", get_num_wrps(),
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_wcr[0],
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_wvr[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -165,10 +186,15 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
|
/* Trap debug register access */
|
|
/* Trap debug register access */
|
|
if (trap_debug)
|
|
if (trap_debug)
|
|
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
|
|
vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
|
|
|
|
+ trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_sys_reg(vcpu, MDSCR_EL1));
|
|
}
|
|
}
|
|
|
|
|
|
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
|
|
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
|
|
+ trace_kvm_arm_clear_debug(vcpu->guest_debug);
|
|
|
|
+
|
|
if (vcpu->guest_debug) {
|
|
if (vcpu->guest_debug) {
|
|
restore_guest_debug_regs(vcpu);
|
|
restore_guest_debug_regs(vcpu);
|
|
|
|
|
|
@@ -176,8 +202,16 @@ void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
|
|
* If we were using HW debug we need to restore the
|
|
* If we were using HW debug we need to restore the
|
|
* debug_ptr to the guest debug state.
|
|
* debug_ptr to the guest debug state.
|
|
*/
|
|
*/
|
|
- if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW)
|
|
|
|
|
|
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
|
|
kvm_arm_reset_debug_ptr(vcpu);
|
|
kvm_arm_reset_debug_ptr(vcpu);
|
|
|
|
|
|
|
|
+ trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_bcr[0],
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_bvr[0]);
|
|
|
|
+
|
|
|
|
+ trace_kvm_arm_set_regset("WAPTS", get_num_wrps(),
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_wcr[0],
|
|
|
|
+ &vcpu->arch.debug_ptr->dbg_wvr[0]);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|