Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 834bf887 authored by Alex Bennée's avatar Alex Bennée Committed by Marc Zyngier
Browse files

KVM: arm64: enable KVM_CAP_SET_GUEST_DEBUG



Finally advertise the KVM capability for SET_GUEST_DEBUG. Once arm
support is added this check can be moved to the common
kvm_vm_ioctl_check_extension() code.

Signed-off-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Acked-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 5540546b
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -2694,7 +2694,7 @@ The top 16 bits of the control field are architecture specific control
flags which can include the following:
flags which can include the following:


  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390]
  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
@@ -2709,6 +2709,11 @@ updated to the correct (supplied) values.
The second part of the structure is architecture specific and
The second part of the structure is architecture specific and
typically contains a set of debug registers.
typically contains a set of debug registers.


For arm64 the number of debug registers is implementation defined and
can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
indicating the number of supported registers.

When debug events exit the main run loop with the reason
When debug events exit the main run loop with the reason
KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
structure containing architecture specific debug information.
structure containing architecture specific debug information.
+14 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@
#ifndef __ASM_HW_BREAKPOINT_H
#ifndef __ASM_HW_BREAKPOINT_H
#define __ASM_HW_BREAKPOINT_H
#define __ASM_HW_BREAKPOINT_H


#include <asm/cputype.h>

#ifdef __KERNEL__
#ifdef __KERNEL__


struct arch_hw_breakpoint_ctrl {
struct arch_hw_breakpoint_ctrl {
@@ -132,5 +134,17 @@ static inline void ptrace_hw_copy_thread(struct task_struct *task)


extern struct pmu perf_ops_bp;
extern struct pmu perf_ops_bp;


/* Determine number of BRP registers available. */
static inline int get_num_brps(void)
{
	return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
}

/* Determine number of WRP registers available. */
static inline int get_num_wrps(void)
{
	return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
}

#endif	/* __KERNEL__ */
#endif	/* __KERNEL__ */
#endif	/* __ASM_BREAKPOINT_H */
#endif	/* __ASM_BREAKPOINT_H */
+5 −1
Original line number Original line Diff line number Diff line
@@ -116,13 +116,17 @@ struct kvm_vcpu_arch {
	 * debugging the guest from the host and to maintain separate host and
	 * debugging the guest from the host and to maintain separate host and
	 * guest state during world switches. vcpu_debug_state are the debug
	 * guest state during world switches. vcpu_debug_state are the debug
	 * registers of the vcpu as the guest sees them.  host_debug_state are
	 * registers of the vcpu as the guest sees them.  host_debug_state are
	 * the host registers which are saved and restored during world switches.
	 * the host registers which are saved and restored during
	 * world switches. external_debug_state contains the debug
	 * values we want to debug the guest. This is set via the
	 * KVM_SET_GUEST_DEBUG ioctl.
	 *
	 *
	 * debug_ptr points to the set of debug registers that should be loaded
	 * debug_ptr points to the set of debug registers that should be loaded
	 * onto the hardware when running the guest.
	 * onto the hardware when running the guest.
	 */
	 */
	struct kvm_guest_debug_arch *debug_ptr;
	struct kvm_guest_debug_arch *debug_ptr;
	struct kvm_guest_debug_arch vcpu_debug_state;
	struct kvm_guest_debug_arch vcpu_debug_state;
	struct kvm_guest_debug_arch external_debug_state;


	/* Pointer to host CPU context */
	/* Pointer to host CPU context */
	kvm_cpu_context_t *host_cpu_context;
	kvm_cpu_context_t *host_cpu_context;
+0 −12
Original line number Original line Diff line number Diff line
@@ -48,18 +48,6 @@ static DEFINE_PER_CPU(int, stepping_kernel_bp);
static int core_num_brps;
static int core_num_brps;
static int core_num_wrps;
static int core_num_wrps;


/* Determine number of BRP registers available. */
static int get_num_brps(void)
{
	return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
}

/* Determine number of WRP registers available. */
static int get_num_wrps(void)
{
	return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
}

int hw_breakpoint_slots(int type)
int hw_breakpoint_slots(int type)
{
{
	/*
	/*
+35 −5
Original line number Original line Diff line number Diff line
@@ -105,10 +105,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
				MDCR_EL2_TDRA |
				MDCR_EL2_TDRA |
				MDCR_EL2_TDOSA);
				MDCR_EL2_TDOSA);


	/* Trap on access to debug registers? */
	if (trap_debug)
		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;

	/* Is Guest debugging in effect? */
	/* Is Guest debugging in effect? */
	if (vcpu->guest_debug) {
	if (vcpu->guest_debug) {
		/* Route all software debug exceptions to EL2 */
		/* Route all software debug exceptions to EL2 */
@@ -143,11 +139,45 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
		} else {
		} else {
			vcpu_sys_reg(vcpu, MDSCR_EL1) &= ~DBG_MDSCR_SS;
			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)
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
{
{
	if (vcpu->guest_debug)
	if (vcpu->guest_debug) {
		restore_guest_debug_regs(vcpu);
		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);

	}
}
}
Loading