Commit fbb31e5f authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch 'kvm-arm64/debug-5.13' into kvmarm-master/next



Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 53648ed3 96f4f680
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3334,7 +3334,8 @@ The top 16 bits of the control field are architecture specific control
flags which can include the following:

  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390]
  - KVM_GUESTDBG_USE_HW:        using hardware debug events [arm64]
  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
+1 −0
Original line number Diff line number Diff line
@@ -717,6 +717,7 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}

void kvm_arm_init_debug(void);
void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu);
void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
+2 −0
Original line number Diff line number Diff line
@@ -283,6 +283,8 @@
#define SYS_PMSIRR_EL1_INTERVAL_MASK	0xffffffUL

/* Filtering controls */
#define SYS_PMSNEVFR_EL1		sys_reg(3, 0, 9, 9, 1)

#define SYS_PMSFCR_EL1			sys_reg(3, 0, 9, 9, 4)
#define SYS_PMSFCR_EL1_FE_SHIFT		0
#define SYS_PMSFCR_EL1_FT_SHIFT		1
+2 −0
Original line number Diff line number Diff line
@@ -582,6 +582,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)

	vcpu->arch.has_run_once = true;

	kvm_arm_vcpu_init_debug(vcpu);

	if (likely(irqchip_in_kernel(kvm))) {
		/*
		 * Map the VGIC hardware resources before running a vcpu the
+61 −28
Original line number Diff line number Diff line
@@ -68,6 +68,65 @@ void kvm_arm_init_debug(void)
	__this_cpu_write(mdcr_el2, kvm_call_hyp_ret(__kvm_get_mdcr_el2));
}

/**
 * kvm_arm_setup_mdcr_el2 - configure vcpu mdcr_el2 value
 *
 * @vcpu:	the vcpu pointer
 *
 * This ensures we will trap access to:
 *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
 *  - Debug ROM Address (MDCR_EL2_TDRA)
 *  - OS related registers (MDCR_EL2_TDOSA)
 *  - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
 *  - Self-hosted Trace Filter controls (MDCR_EL2_TTRF)
 *  - Self-hosted Trace (MDCR_EL2_TTRF/MDCR_EL2_E2TB)
 */
static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
{
	/*
	 * This also clears MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK
	 * to disable guest access to the profiling and trace buffers
	 */
	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
				MDCR_EL2_TPMS |
				MDCR_EL2_TTRF |
				MDCR_EL2_TPMCR |
				MDCR_EL2_TDRA |
				MDCR_EL2_TDOSA);

	/* Is the VM being debugged by userspace? */
	if (vcpu->guest_debug)
		/* Route all software debug exceptions to EL2 */
		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;

	/*
	 * Trap debug register access when one of the following is true:
	 *  - Userspace is using the hardware to debug the guest
	 *  (KVM_GUESTDBG_USE_HW is set).
	 *  - The guest is not using debug (KVM_ARM64_DEBUG_DIRTY is clear).
	 */
	if ((vcpu->guest_debug & KVM_GUESTDBG_USE_HW) ||
	    !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;

	trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
}

/**
 * kvm_arm_vcpu_init_debug - setup vcpu debug traps
 *
 * @vcpu:	the vcpu pointer
 *
 * Set vcpu initial mdcr_el2 value.
 */
void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu)
{
	preempt_disable();
	kvm_arm_setup_mdcr_el2(vcpu);
	preempt_enable();
}

/**
 * kvm_arm_reset_debug_ptr - reset the debug ptr to point to the vcpu state
 */
@@ -83,13 +142,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
 * @vcpu:	the vcpu pointer
 *
 * This is called before each entry into the hypervisor to setup any
 * debug related registers. Currently this just ensures we will trap
 * access to:
 *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
 *  - Debug ROM Address (MDCR_EL2_TDRA)
 *  - OS related registers (MDCR_EL2_TDOSA)
 *  - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
 *  - Self-hosted Trace (MDCR_EL2_TTRF/MDCR_EL2_E2TB)
 * debug related registers.
 *
 * Additionally, KVM only traps guest accesses to the debug registers if
 * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
@@ -101,28 +154,14 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)

void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
{
	bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY);
	unsigned long mdscr, orig_mdcr_el2 = vcpu->arch.mdcr_el2;

	trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);

	/*
	 * This also clears MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK
	 * to disable guest access to the profiling and trace buffers
	 */
	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
				MDCR_EL2_TPMS |
				MDCR_EL2_TTRF |
				MDCR_EL2_TPMCR |
				MDCR_EL2_TDRA |
				MDCR_EL2_TDOSA);
	kvm_arm_setup_mdcr_el2(vcpu);

	/* Is Guest debugging in effect? */
	if (vcpu->guest_debug) {
		/* Route all software debug exceptions to EL2 */
		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;

		/* Save guest debug state */
		save_guest_debug_regs(vcpu);

@@ -176,7 +215,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)

			vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
			vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
			trap_debug = true;

			trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
						&vcpu->arch.debug_ptr->dbg_bcr[0],
@@ -191,10 +229,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
	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;

	/* If KDE or MDE are set, perform a full save/restore cycle. */
	if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
		vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
@@ -203,7 +237,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
	if (has_vhe() && orig_mdcr_el2 != vcpu->arch.mdcr_el2)
		write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);

	trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
	trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
}

Loading