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]
+  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, 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]
 The second part of the structure is architecture specific and
 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
 KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
 structure containing architecture specific debug information.
 
 #ifndef __ASM_HW_BREAKPOINT_H
 #define __ASM_HW_BREAKPOINT_H
 
+#include <asm/cputype.h>
+
 #ifdef __KERNEL__
 
 struct arch_hw_breakpoint_ctrl {
 
 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 /* __ASM_BREAKPOINT_H */
 
         * debugging the guest from the host and to maintain separate host and
         * guest state during world switches. vcpu_debug_state are the debug
         * 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
         * onto the hardware when running the guest.
         */
        struct kvm_guest_debug_arch *debug_ptr;
        struct kvm_guest_debug_arch vcpu_debug_state;
+       struct kvm_guest_debug_arch external_debug_state;
 
        /* Pointer to host CPU context */
        kvm_cpu_context_t *host_cpu_context;
 
 static int core_num_brps;
 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)
 {
        /*
 
                                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 */
                } 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);
+
+       }
 }
 
 
 #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE |    \
                            KVM_GUESTDBG_USE_SW_BP | \
+                           KVM_GUESTDBG_USE_HW | \
                            KVM_GUESTDBG_SINGLESTEP)
 
 /**
 
        if (dbg->control & KVM_GUESTDBG_ENABLE) {
                vcpu->guest_debug = dbg->control;
+
+               /* Hardware assisted Break and Watch points */
+               if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
+                       vcpu->arch.external_debug_state = dbg->arch;
+               }
+
        } else {
                /* If not enabled clear all flags */
                vcpu->guest_debug = 0;
 
        run->debug.arch.hsr = hsr;
 
        switch (hsr >> ESR_ELx_EC_SHIFT) {
+       case ESR_ELx_EC_WATCHPT_LOW:
+               run->debug.arch.far = vcpu->arch.fault.far_el2;
+               /* fall through */
        case ESR_ELx_EC_SOFTSTP_LOW:
+       case ESR_ELx_EC_BREAKPT_LOW:
        case ESR_ELx_EC_BKPT32:
        case ESR_ELx_EC_BRK64:
                break;
        [ESR_ELx_EC_IABT_LOW]   = kvm_handle_guest_abort,
        [ESR_ELx_EC_DABT_LOW]   = kvm_handle_guest_abort,
        [ESR_ELx_EC_SOFTSTP_LOW]= kvm_handle_guest_debug,
+       [ESR_ELx_EC_WATCHPT_LOW]= kvm_handle_guest_debug,
+       [ESR_ELx_EC_BREAKPT_LOW]= kvm_handle_guest_debug,
        [ESR_ELx_EC_BKPT32]     = kvm_handle_guest_debug,
        [ESR_ELx_EC_BRK64]      = kvm_handle_guest_debug,
 };
 
 #include <linux/errno.h>
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
+#include <linux/hw_breakpoint.h>
 
 #include <kvm/arm_arch_timer.h>
 
        return !!(pfr0 & 0x20);
 }
 
+/**
+ * kvm_arch_dev_ioctl_check_extension
+ *
+ * We currently assume that the number of HW registers is uniform
+ * across all CPUs (see cpuinfo_sanity_check).
+ */
 int kvm_arch_dev_ioctl_check_extension(long ext)
 {
        int r;
        case KVM_CAP_ARM_EL1_32BIT:
                r = cpu_has_32bit_el1();
                break;
+       case KVM_CAP_GUEST_DEBUG_HW_BPS:
+               r = get_num_brps();
+               break;
+       case KVM_CAP_GUEST_DEBUG_HW_WPS:
+               r = get_num_wrps();
+               break;
+       case KVM_CAP_SET_GUEST_DEBUG:
+               r = 1;
+               break;
        default:
                r = 0;
        }