Blame SOURCES/gdb-rhbz1854784-powerpc-remove-region-limit-dawr-4of7.patch

4f0e34
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
4f0e34
From: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
4f0e34
Date: Wed, 7 Jul 2021 18:49:42 -0400
4f0e34
Subject: gdb-rhbz1854784-powerpc-remove-region-limit-dawr-4of7.patch
4f0e34
4f0e34
;; Backport "[PowerPC] Fix debug register issues in ppc-linux-nat"
4f0e34
;; (Pedro Franco de Carvalho, RH BZ 1854784)
4f0e34
4f0e34
This patch fixes some issues with debug register handling for the powerpc
4f0e34
linux native target.
4f0e34
4f0e34
Currently, the target methods for installing and removing hardware
4f0e34
breakpoints and watchpoints in ppc-linux-nat.c affect all threads known to
4f0e34
linux-nat, including threads of different processes.
4f0e34
4f0e34
This patch changes ppc-linux-nat.c so that only the process of
4f0e34
inferior_ptid is affected by these target methods, as GDB expects.
4f0e34
4f0e34
This is done in the same way as various other architectures.  The
4f0e34
install/remove target methods only register a hardware breakpoint or
4f0e34
watchpoint, and then send a stop signal to the threads.  The debug
4f0e34
registers are only changed with ptrace right before each thread is next
4f0e34
resumed, using low_prepare_to_resume.
4f0e34
4f0e34
There are two interfaces to modify debug registers for linux running on
4f0e34
powerpc, with different sets of ptrace requests:
4f0e34
4f0e34
- PPC_PTRACE_GETHWDBGINFO, PPC_PTRACE_SETHWDEBUG, and
4f0e34
  PPC_PTRACE_DELHWDEBUG.
4f0e34
4f0e34
   Or
4f0e34
4f0e34
- PTRACE_SET_DEBUGREG and PTRACE_GET_DEBUGREG
4f0e34
4f0e34
The first set (HWDEBUG) is the more flexible one and allows setting
4f0e34
watchpoints with a variable watched region length and, for certain
4f0e34
embedded processors, multiple types of debug registers (e.g. hardware
4f0e34
breakpoints and hardware-assisted conditions for watchpoints).
4f0e34
Currently, server processors only provide one watchpoint.  The second one
4f0e34
(DEBUGREG) only allows setting one debug register, a watchpoint, so we
4f0e34
only use it if the first one is not available.
4f0e34
4f0e34
The HWDEBUG interface handles debug registers with slot numbers.  Once a
4f0e34
hardware watchpoint or breakpoint is installed (with
4f0e34
PPC_PTRACE_SETHWDEBUG), ptrace returns a slot number.  This slot number
4f0e34
can then be used to remove the watchpoint or breakpoint from the inferior
4f0e34
(with PPC_PTRACE_DELHWDEBUG).  The first interface also provides a
4f0e34
bitmask of available debug register features, which can be obtained with
4f0e34
PPC_PTRACE_GETHWDBGINFO.
4f0e34
4f0e34
When GDB first tries to use debug registers, we try the first interface
4f0e34
with a ptrace call, and if it isn't available, we fall back to the second
4f0e34
one, if available.  We use EIO as an indicator that an interface is not
4f0e34
available in the kernel.  For simplicity, with any other error we
4f0e34
immediately assume no interface is available.  Unfortunately this means
4f0e34
that if a process is killed by a signal right before we try to detect the
4f0e34
interface, we might get an ESRCH, which would prevent debug registers to
4f0e34
be used in the GDB session.  However, it isn't clear that we can safely
4f0e34
raise an exception and try again in the future in all the contexts where
4f0e34
we try to detect the interface.
4f0e34
4f0e34
If the HWDEBUG interface works but provides no feature bits, the target
4f0e34
falls back to the DEBUGREG interface.  When the kernel is configured
4f0e34
without CONFIG_HW_BREAKPOINTS (selected by CONFIG_PERF_EVENTS), there is
4f0e34
a bug that causes watchpoints installed with the HWDEBUG interface not to
4f0e34
trigger.  When this is the case, the feature bits will be zero, which is
4f0e34
used as the indicator to fall back to the DEBUGREG interface.  This isn't
4f0e34
ideal, but has always been the behavior of GDB before this patch, so I
4f0e34
decided not to change it.
4f0e34
4f0e34
A flag indicates for each thread if its debug registers need to be
4f0e34
updated the next time it is resumed.  The flag is set whenever the upper
4f0e34
layers request or remove a hardware watchpoint or breakpoint, or when a
4f0e34
new thread is detected.  Because some kernel configurations disable
4f0e34
watchpoints after they are hit, we also use the last stop reason of the
4f0e34
LWP to determine whether we should update the debug registers.  It isn't
4f0e34
clear that this is also true of BookE hardware breakpoints, but we also
4f0e34
check their stop reason to be on the safe side, since it doesn't hurt.
4f0e34
4f0e34
A map from process numbers to hardware watchpoint or breakpoint objects
4f0e34
keeps track of what has been requested by the upper layers of GDB, since
4f0e34
for GDB installing a hardware watchpoint or breakpoint means doing so for
4f0e34
the whole process.
4f0e34
4f0e34
When using the HWDEBUG interface we also have to keep track of which
4f0e34
slots were last installed in each thread with a map from threads to the
4f0e34
slots, so that they can be removed when needed.  When resuming a thread,
4f0e34
we remove all the slots using this map, then we install all the hardware
4f0e34
watchpoints and breakpoints from the per-process map of requests, and
4f0e34
then update the per-thread map accordingly.
4f0e34
4f0e34
This per-thread state is also used for copying the debug register state
4f0e34
after a fork or a clone is detected.  The kernel might do this depending
4f0e34
on the configuration.  Recent kernels running on server processors that
4f0e34
were configured with CONFIG_PERF_EVENTS (and therefore
4f0e34
CONFIG_HW_BREAKPOINTS) don't copy debug registers across forks and
4f0e34
clones.  Recent kernels without CONFIG_HW_BREAKPOINTS copy this state.  I
4f0e34
believe that on embedded processors (e.g. a ppc440) the debug register
4f0e34
state is copied, but I haven't been able to test this.  To handle both
4f0e34
cases, the per-thread state is always copied when forks and clones are
4f0e34
detected, and when we resume the thread and delete the debug register
4f0e34
slots before updating them, we ignore ENOENT errors.
4f0e34
4f0e34
We don't need to handle this when using the DEBUGREG interface since it
4f0e34
only allows one hardware watchpoint and doesn't return slot numbers, we
4f0e34
just set or clear this watchpoint when needed.
4f0e34
4f0e34
Since we signal running threads to stop after a request is processed, so
4f0e34
that we can update their debug registers when they are next resumed,
4f0e34
there will be a time between signalling the threads and their stop during
4f0e34
which the debug registers haven't been updated, even if the target
4f0e34
methods completed.
4f0e34
4f0e34
The tests in gdb.threads/watchpoint-fork.exp no longer fail with this
4f0e34
patch.
4f0e34
4f0e34
gdb/ChangeLog:
4f0e34
2020-03-30  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
4f0e34
4f0e34
	* ppc-linux-nat.c: Include <algorithm>, <unordered_map>, and
4f0e34
	<list>.  Remove inclusion of observable.h.
4f0e34
	(PPC_DEBUG_CURRENT_VERSION): Move up define.
4f0e34
	(struct arch_lwp_info): New struct.
4f0e34
	(class ppc_linux_dreg_interface): New class.
4f0e34
	(struct ppc_linux_process_info): New struct.
4f0e34
	(struct ppc_linux_nat_target) <low_delete_thread, low_new_fork>
4f0e34
	<low_new_clone, low_forget_process, low_prepare_to_resume>
4f0e34
	<copy_thread_dreg_state, mark_thread_stale>
4f0e34
	<mark_debug_registers_changed, register_hw_breakpoint>
4f0e34
	<clear_hw_breakpoint, register_wp, clear_wp>
4f0e34
	<can_use_watchpoint_cond_accel, calculate_dvc, check_condition>
4f0e34
	<num_memory_accesses, get_trigger_type>
4f0e34
	<create_watchpoint_request, hwdebug_point_cmp>
4f0e34
	<init_arch_lwp_info, get_arch_lwp_info>
4f0e34
	<low_stopped_by_watchpoint, low_stopped_data_address>: Declare as
4f0e34
	methods.
4f0e34
	<struct ptid_hash>: New inner struct.
4f0e34
	<m_dreg_interface, m_process_info, m_installed_hw_bps>: Declare
4f0e34
	members.
4f0e34
	(saved_dabr_value, hwdebug_info, max_slots_number)
4f0e34
	(struct hw_break_tuple, struct thread_points, ppc_threads)
4f0e34
	(have_ptrace_hwdebug_interface)
4f0e34
	(hwdebug_find_thread_points_by_tid)
4f0e34
	(hwdebug_insert_point, hwdebug_remove_point): Remove.
4f0e34
	(ppc_linux_nat_target::can_use_hw_breakpoint): Use
4f0e34
	m_dreg_interface, remove call to PTRACE_SET_DEBUGREG.
4f0e34
	(ppc_linux_nat_target::region_ok_for_hw_watchpoint): Add comment,
4f0e34
	use m_dreg_interface.
4f0e34
	(hwdebug_point_cmp): Change to...
4f0e34
	(ppc_linux_nat_target::hwdebug_point_cmp): ...this method.  Use
4f0e34
	reference arguments instead of pointers.
4f0e34
	(ppc_linux_nat_target::ranged_break_num_registers): Use
4f0e34
	m_dreg_interface.
4f0e34
	(ppc_linux_nat_target::insert_hw_breakpoint): Add comment, use
4f0e34
	m_dreg_interface.  Call register_hw_breakpoint.
4f0e34
	(ppc_linux_nat_target::remove_hw_breakpoint): Add comment, use
4f0e34
	m_dreg_interface.  Call clear_hw_breakpoint.
4f0e34
	(get_trigger_type): Change to...
4f0e34
	(ppc_linux_nat_target::get_trigger_type): ...this method.  Add
4f0e34
	comment.
4f0e34
	(ppc_linux_nat_target::insert_mask_watchpoint): Update comment,
4f0e34
	use m_dreg_interface.  Call register_hw_breakpoint.
4f0e34
	(ppc_linux_nat_target::remove_mask_watchpoint): Update comment,
4f0e34
	use m_dreg_interface.  Call clear_hw_breakpoint.
4f0e34
	(can_use_watchpoint_cond_accel): Change to...
4f0e34
	(ppc_linux_nat_target::can_use_watchpoint_cond_accel): ...this
4f0e34
	method.  Update comment, use m_dreg_interface and
4f0e34
	m_process_info.
4f0e34
	(calculate_dvc): Change to...
4f0e34
	(ppc_linux_nat_target::calculate_dvc): ...this method.  Use
4f0e34
	m_dreg_interface.
4f0e34
	(num_memory_accesses): Change to...
4f0e34
	(ppc_linux_nat_target::num_memory_accesses): ...this method.
4f0e34
	(check_condition): Change to...
4f0e34
	(ppc_linux_nat_target::check_condition): ...this method.
4f0e34
	(ppc_linux_nat_target::can_accel_watchpoint_condition): Update
4f0e34
	comment, use m_dreg_interface.
4f0e34
	(create_watchpoint_request): Change to...
4f0e34
	(ppc_linux_nat_target::create_watchpoint_request): ...this
4f0e34
	method.  Use m_dreg_interface.
4f0e34
	(ppc_linux_nat_target::insert_watchpoint): Add comment, use
4f0e34
	m_dreg_interface.  Call register_hw_breakpoint or register_wp.
4f0e34
	(ppc_linux_nat_target::remove_watchpoint): Add comment, use
4f0e34
	m_dreg_interface.  Call clear_hw_breakpoint or clear_wp.
4f0e34
	(ppc_linux_nat_target::low_forget_process)
4f0e34
	(ppc_linux_nat_target::low_new_fork)
4f0e34
	(ppc_linux_nat_target::low_new_clone)
4f0e34
	(ppc_linux_nat_target::low_delete_thread)
4f0e34
	(ppc_linux_nat_target::low_prepare_to_resume): New methods.
4f0e34
	(ppc_linux_nat_target::low_new_thread): Remove previous logic,
4f0e34
	only call mark_thread_stale.
4f0e34
	(ppc_linux_thread_exit): Remove.
4f0e34
	(ppc_linux_nat_target::stopped_data_address): Change to...
4f0e34
	(ppc_linux_nat_target::low_stopped_data_address): This. Add
4f0e34
	comment, use m_dreg_interface and m_thread_hw_breakpoints.
4f0e34
	(ppc_linux_nat_target::stopped_by_watchpoint): Change to...
4f0e34
	(ppc_linux_nat_target::stopped_by_watchpoint): This.  Add
4f0e34
	comment.  Call low_stopped_data_address.
4f0e34
	(ppc_linux_nat_target::watchpoint_addr_within_range): Use
4f0e34
	m_dreg_interface.
4f0e34
	(ppc_linux_nat_target::masked_watch_num_registers): Use
4f0e34
	m_dreg_interface.
4f0e34
	(ppc_linux_nat_target::copy_thread_dreg_state)
4f0e34
	(ppc_linux_nat_target::mark_thread_stale)
4f0e34
	(ppc_linux_nat_target::mark_debug_registers_changed)
4f0e34
	(ppc_linux_nat_target::register_hw_breakpoint)
4f0e34
	(ppc_linux_nat_target::clear_hw_breakpoint)
4f0e34
	(ppc_linux_nat_target::register_wp)
4f0e34
	(ppc_linux_nat_target::clear_wp)
4f0e34
	(ppc_linux_nat_target::init_arch_lwp_info)
4f0e34
	(ppc_linux_nat_target::get_arch_lwp_info): New methods.
4f0e34
	(_initialize_ppc_linux_nat): Remove observer callback.
4f0e34
4f0e34
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
4f0e34
--- a/gdb/aarch64-linux-nat.c
4f0e34
+++ b/gdb/aarch64-linux-nat.c
4f0e34
@@ -64,14 +64,14 @@ public:
4f0e34
   int can_use_hw_breakpoint (enum bptype, int, int) override;
4f0e34
   int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
4f0e34
   int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
 			 struct expression *) override;
4f0e34
   int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
 			 struct expression *) override;
4f0e34
   bool stopped_by_watchpoint () override;
4f0e34
   bool stopped_data_address (CORE_ADDR *) override;
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, LONGEST) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
4f0e34
 
4f0e34
   int can_do_single_step () override;
4f0e34
 
4f0e34
@@ -808,7 +808,7 @@ aarch64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
4f0e34
 /* Implement the "region_ok_for_hw_watchpoint" target_ops method.  */
4f0e34
 
4f0e34
 int
4f0e34
-aarch64_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+aarch64_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   return aarch64_linux_region_ok_for_watchpoint (addr, len);
4f0e34
 }
4f0e34
@@ -888,7 +888,7 @@ aarch64_linux_nat_target::stopped_by_watchpoint ()
4f0e34
 bool
4f0e34
 aarch64_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
4f0e34
 							CORE_ADDR start,
4f0e34
-							LONGEST length)
4f0e34
+							int length)
4f0e34
 {
4f0e34
   return start <= addr && start + length - 1 >= addr;
4f0e34
 }
4f0e34
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
4f0e34
--- a/gdb/arm-linux-nat.c
4f0e34
+++ b/gdb/arm-linux-nat.c
4f0e34
@@ -80,7 +80,7 @@ public:
4f0e34
 
4f0e34
   int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
4f0e34
 
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
 
4f0e34
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
 			 struct expression *) override;
4f0e34
@@ -91,7 +91,7 @@ public:
4f0e34
 
4f0e34
   bool stopped_data_address (CORE_ADDR *) override;
4f0e34
 
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, LONGEST) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
4f0e34
 
4f0e34
   const struct target_desc *read_description () override;
4f0e34
 
4f0e34
@@ -1093,7 +1093,7 @@ arm_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
 /* Are we able to use a hardware watchpoint for the LEN bytes starting at 
4f0e34
    ADDR?  */
4f0e34
 int
4f0e34
-arm_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+arm_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
4f0e34
   CORE_ADDR max_wp_length, aligned_addr;
4f0e34
@@ -1202,7 +1202,7 @@ arm_linux_nat_target::stopped_by_watchpoint ()
4f0e34
 bool
4f0e34
 arm_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
4f0e34
 						    CORE_ADDR start,
4f0e34
-						    LONGEST length)
4f0e34
+						    int length)
4f0e34
 {
4f0e34
   return start <= addr && start + length - 1 >= addr;
4f0e34
 }
4f0e34
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
4f0e34
--- a/gdb/mips-linux-nat.c
4f0e34
+++ b/gdb/mips-linux-nat.c
4f0e34
@@ -614,7 +614,7 @@ mips_linux_nat_target::stopped_data_address (CORE_ADDR *paddr)
4f0e34
    the specified region can be covered by the watch registers.  */
4f0e34
 
4f0e34
 int
4f0e34
-mips_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+mips_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   struct pt_watch_regs dummy_regs;
4f0e34
   int i;
4f0e34
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
4f0e34
--- a/gdb/ppc-linux-nat.c
4f0e34
+++ b/gdb/ppc-linux-nat.c
4f0e34
@@ -18,7 +18,6 @@
4f0e34
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
4f0e34
 
4f0e34
 #include "defs.h"
4f0e34
-#include "observable.h"
4f0e34
 #include "frame.h"
4f0e34
 #include "inferior.h"
4f0e34
 #include "gdbthread.h"
4f0e34
@@ -37,6 +36,9 @@
4f0e34
 #include <sys/procfs.h>
4f0e34
 #include "nat/gdb_ptrace.h"
4f0e34
 #include "inf-ptrace.h"
4f0e34
+#include <algorithm>
4f0e34
+#include <unordered_map>
4f0e34
+#include <list>
4f0e34
 
4f0e34
 /* Prototypes for supply_gregset etc.  */
4f0e34
 #include "gregset.h"
4f0e34
@@ -52,6 +54,13 @@
4f0e34
 #include "nat/ppc-linux.h"
4f0e34
 #include "linux-tdep.h"
4f0e34
 
4f0e34
+/* Function type for the CALLBACK argument of iterate_over_lwps_new.  */
4f0e34
+typedef int (iterate_over_lwps_new_ftype) (struct lwp_info *lwp);
4f0e34
+
4f0e34
+static struct lwp_info *iterate_over_lwps_new
4f0e34
+    (ptid_t filter,
4f0e34
+     gdb::function_view<iterate_over_lwps_new_ftype> callback);
4f0e34
+
4f0e34
 /* Similarly for the hardware watchpoint support.  These requests are used
4f0e34
    when the PowerPC HWDEBUG ptrace interface is not available.  */
4f0e34
 #ifndef PTRACE_GET_DEBUGREG
4f0e34
@@ -135,6 +144,10 @@ struct ppc_hw_breakpoint
4f0e34
 #define PPC_DEBUG_FEATURE_DATA_BP_DAWR	0x10
4f0e34
 #endif /* PPC_DEBUG_FEATURE_DATA_BP_DAWR */
4f0e34
 
4f0e34
+/* The version of the PowerPC HWDEBUG kernel interface that we will use, if
4f0e34
+   available.  */
4f0e34
+#define PPC_DEBUG_CURRENT_VERSION 1
4f0e34
+
4f0e34
 /* Similarly for the general-purpose (gp0 -- gp31)
4f0e34
    and floating-point registers (fp0 -- fp31).  */
4f0e34
 #ifndef PTRACE_GETREGS
4f0e34
@@ -269,6 +282,214 @@ int have_ptrace_getsetregs = 1;
4f0e34
    them and gotten an error.  */
4f0e34
 int have_ptrace_getsetfpregs = 1;
4f0e34
 
4f0e34
+/* Private arch info associated with each thread lwp_info object, used
4f0e34
+   for debug register handling.  */
4f0e34
+
4f0e34
+struct arch_lwp_info
4f0e34
+{
4f0e34
+  /* When true, indicates that the debug registers installed in the
4f0e34
+     thread no longer correspond to the watchpoints and breakpoints
4f0e34
+     requested by GDB.  */
4f0e34
+  bool debug_regs_stale;
4f0e34
+
4f0e34
+  /* We need a back-reference to the PTID of the thread so that we can
4f0e34
+     cleanup the debug register state of the thread in
4f0e34
+     low_delete_thread.  */
4f0e34
+  ptid_t lwp_ptid;
4f0e34
+};
4f0e34
+
4f0e34
+/* Class used to detect which set of ptrace requests that
4f0e34
+   ppc_linux_nat_target will use to install and remove hardware
4f0e34
+   breakpoints and watchpoints.
4f0e34
+
4f0e34
+   The interface is only detected once, testing the ptrace calls.  The
4f0e34
+   result can indicate that no interface is available.
4f0e34
+
4f0e34
+   The Linux kernel provides two different sets of ptrace requests to
4f0e34
+   handle hardware watchpoints and breakpoints for Power:
4f0e34
+
4f0e34
+   - PPC_PTRACE_GETHWDBGINFO, PPC_PTRACE_SETHWDEBUG, and
4f0e34
+     PPC_PTRACE_DELHWDEBUG.
4f0e34
+
4f0e34
+   Or
4f0e34
+
4f0e34
+   - PTRACE_SET_DEBUGREG and PTRACE_GET_DEBUGREG
4f0e34
+
4f0e34
+   The first set is the more flexible one and allows setting watchpoints
4f0e34
+   with a variable watched region length and, for BookE processors,
4f0e34
+   multiple types of debug registers (e.g. hardware breakpoints and
4f0e34
+   hardware-assisted conditions for watchpoints).  The second one only
4f0e34
+   allows setting one debug register, a watchpoint, so we only use it if
4f0e34
+   the first one is not available.  */
4f0e34
+
4f0e34
+class ppc_linux_dreg_interface
4f0e34
+{
4f0e34
+public:
4f0e34
+
4f0e34
+  ppc_linux_dreg_interface ()
4f0e34
+    : m_interface (), m_hwdebug_info ()
4f0e34
+  {
4f0e34
+  };
4f0e34
+
4f0e34
+  DISABLE_COPY_AND_ASSIGN (ppc_linux_dreg_interface);
4f0e34
+
4f0e34
+  /* One and only one of these three functions returns true, indicating
4f0e34
+     whether the corresponding interface is the one we detected.  The
4f0e34
+     interface must already have been detected as a precontidion.  */
4f0e34
+
4f0e34
+  bool hwdebug_p ()
4f0e34
+  {
4f0e34
+    gdb_assert (detected_p ());
4f0e34
+    return *m_interface == HWDEBUG;
4f0e34
+  }
4f0e34
+
4f0e34
+  bool debugreg_p ()
4f0e34
+  {
4f0e34
+    gdb_assert (detected_p ());
4f0e34
+    return *m_interface == DEBUGREG;
4f0e34
+  }
4f0e34
+
4f0e34
+  bool unavailable_p ()
4f0e34
+  {
4f0e34
+    gdb_assert (detected_p ());
4f0e34
+    return *m_interface == UNAVAILABLE;
4f0e34
+  }
4f0e34
+
4f0e34
+  /* Returns the debug register capabilities of the target.  Should only
4f0e34
+     be called if the interface is HWDEBUG.  */
4f0e34
+  const struct ppc_debug_info &hwdebug_info ()
4f0e34
+  {
4f0e34
+    gdb_assert (hwdebug_p ());
4f0e34
+
4f0e34
+    return m_hwdebug_info;
4f0e34
+  }
4f0e34
+
4f0e34
+  /* Returns true if the interface has already been detected.  This is
4f0e34
+     useful for cases when we know there is no work to be done if the
4f0e34
+     interface hasn't been detected yet.  */
4f0e34
+  bool detected_p ()
4f0e34
+  {
4f0e34
+    return m_interface.has_value ();
4f0e34
+  }
4f0e34
+
4f0e34
+  /* Detect the available interface, if any, if it hasn't been detected
4f0e34
+     before, using PTID for the necessary ptrace calls.  */
4f0e34
+
4f0e34
+  void detect (const ptid_t &ptid)
4f0e34
+  {
4f0e34
+    if (m_interface.has_value ())
4f0e34
+      return;
4f0e34
+
4f0e34
+    gdb_assert (ptid.lwp_p ());
4f0e34
+
4f0e34
+    bool no_features = false;
4f0e34
+
4f0e34
+    if (ptrace (PPC_PTRACE_GETHWDBGINFO, ptid.lwp (), 0, &m_hwdebug_info)
4f0e34
+	!= -1)
4f0e34
+      {
4f0e34
+	/* If there are no advertised features, we don't use the
4f0e34
+	   HWDEBUG interface and try the DEBUGREG interface instead.
4f0e34
+	   It shouldn't be necessary to do this, however, when the
4f0e34
+	   kernel is configured without CONFIG_HW_BREAKPOINTS (selected
4f0e34
+	   by CONFIG_PERF_EVENTS), there is a bug that causes
4f0e34
+	   watchpoints installed with the HWDEBUG interface not to
4f0e34
+	   trigger.  When this is the case, features will be zero,
4f0e34
+	   which we use as an indicator to fall back to the DEBUGREG
4f0e34
+	   interface.  */
4f0e34
+	if (m_hwdebug_info.features != 0)
4f0e34
+	  {
4f0e34
+	    m_interface.emplace (HWDEBUG);
4f0e34
+	    return;
4f0e34
+	  }
4f0e34
+	else
4f0e34
+	  no_features = true;
4f0e34
+      }
4f0e34
+
4f0e34
+    /* EIO indicates that the request is invalid, so we try DEBUGREG
4f0e34
+       next.  Technically, it can also indicate other failures, but we
4f0e34
+       can't differentiate those.
4f0e34
+
4f0e34
+       Other errors could happen for various reasons.  We could get an
4f0e34
+       ESRCH if the traced thread was killed by a signal.  Trying to
4f0e34
+       detect the interface with another thread in the future would be
4f0e34
+       complicated, as callers would have to handle an "unknown
4f0e34
+       interface" case.  It's also unclear if raising an exception
4f0e34
+       here would be safe.
4f0e34
+
4f0e34
+       Other errors, such as ENODEV, could be more permanent and cause
4f0e34
+       a failure for any thread.
4f0e34
+
4f0e34
+       For simplicity, with all errors other than EIO, we set the
4f0e34
+       interface to UNAVAILABLE and don't try DEBUGREG.  If DEBUGREG
4f0e34
+       fails too, we'll also set the interface to UNAVAILABLE.  It's
4f0e34
+       unlikely that trying the DEBUGREG interface with this same thread
4f0e34
+       would work, for errors other than EIO.  This means that these
4f0e34
+       errors will cause hardware watchpoints and breakpoints to become
4f0e34
+       unavailable throughout a GDB session.  */
4f0e34
+
4f0e34
+    if (no_features || errno == EIO)
4f0e34
+      {
4f0e34
+	unsigned long wp;
4f0e34
+
4f0e34
+	if (ptrace (PTRACE_GET_DEBUGREG, ptid.lwp (), 0, &wp) != -1)
4f0e34
+	  {
4f0e34
+	    m_interface.emplace (DEBUGREG);
4f0e34
+	    return;
4f0e34
+	  }
4f0e34
+      }
4f0e34
+
4f0e34
+    if (errno != EIO)
4f0e34
+      warning (_("Error when detecting the debug register interface. "
4f0e34
+		 "Debug registers will be unavailable."));
4f0e34
+
4f0e34
+    m_interface.emplace (UNAVAILABLE);
4f0e34
+    return;
4f0e34
+  }
4f0e34
+
4f0e34
+private:
4f0e34
+
4f0e34
+  /* HWDEBUG represents the set of calls PPC_PTRACE_GETHWDBGINFO,
4f0e34
+     PPC_PTRACE_SETHWDEBUG and PPC_PTRACE_DELHWDEBUG.
4f0e34
+
4f0e34
+     DEBUGREG represents the set of calls PTRACE_SET_DEBUGREG and
4f0e34
+     PTRACE_GET_DEBUGREG.
4f0e34
+
4f0e34
+     UNAVAILABLE can indicate that the kernel doesn't support any of the
4f0e34
+     two sets of requests or that there was an error when we tried to
4f0e34
+     detect wich interface is available.  */
4f0e34
+
4f0e34
+  enum debug_reg_interface
4f0e34
+    {
4f0e34
+     UNAVAILABLE,
4f0e34
+     HWDEBUG,
4f0e34
+     DEBUGREG
4f0e34
+    };
4f0e34
+
4f0e34
+  /* The interface option.  Initialized if has_value () returns true.  */
4f0e34
+  gdb::optional<enum debug_reg_interface> m_interface;
4f0e34
+
4f0e34
+  /* The info returned by the kernel with PPC_PTRACE_GETHWDBGINFO.  Only
4f0e34
+     valid if we determined that the interface is HWDEBUG.  */
4f0e34
+  struct ppc_debug_info m_hwdebug_info;
4f0e34
+};
4f0e34
+
4f0e34
+/* Per-process information.  This includes the hardware watchpoints and
4f0e34
+   breakpoints that GDB requested to this target.  */
4f0e34
+
4f0e34
+struct ppc_linux_process_info
4f0e34
+{
4f0e34
+  /* The list of hardware watchpoints and breakpoints that GDB requested
4f0e34
+     for this process.
4f0e34
+
4f0e34
+     Only used when the interface is HWDEBUG.  */
4f0e34
+  std::list<struct ppc_hw_breakpoint> requested_hw_bps;
4f0e34
+
4f0e34
+  /* The watchpoint value that GDB requested for this process.
4f0e34
+
4f0e34
+     Only used when the interface is DEBUGREG.  */
4f0e34
+  gdb::optional<long> requested_wp_val;
4f0e34
+};
4f0e34
+
4f0e34
 struct ppc_linux_nat_target final : public linux_nat_target
4f0e34
 {
4f0e34
   /* Add our register access methods.  */
4f0e34
@@ -284,7 +505,7 @@ struct ppc_linux_nat_target final : public linux_nat_target
4f0e34
   int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
4f0e34
     override;
4f0e34
 
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
 
4f0e34
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
 			 struct expression *) override;
4f0e34
@@ -298,13 +519,9 @@ struct ppc_linux_nat_target final : public linux_nat_target
4f0e34
   int remove_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type)
4f0e34
     override;
4f0e34
 
4f0e34
-  bool stopped_by_watchpoint () override;
4f0e34
-
4f0e34
-  bool stopped_data_address (CORE_ADDR *) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
4f0e34
 
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, LONGEST) override;
4f0e34
-
4f0e34
-  bool can_accel_watchpoint_condition (CORE_ADDR, LONGEST, int, struct expression *)
4f0e34
+  bool can_accel_watchpoint_condition (CORE_ADDR, int, int, struct expression *)
4f0e34
     override;
4f0e34
 
4f0e34
   int masked_watch_num_registers (CORE_ADDR, CORE_ADDR) override;
4f0e34
@@ -318,7 +535,95 @@ struct ppc_linux_nat_target final : public linux_nat_target
4f0e34
     override;
4f0e34
 
4f0e34
   /* Override linux_nat_target low methods.  */
4f0e34
+  bool low_stopped_by_watchpoint () override;
4f0e34
+
4f0e34
+  bool low_stopped_data_address (CORE_ADDR *) override;
4f0e34
+
4f0e34
   void low_new_thread (struct lwp_info *lp) override;
4f0e34
+
4f0e34
+  void low_delete_thread (arch_lwp_info *) override;
4f0e34
+
4f0e34
+  void low_new_fork (struct lwp_info *, pid_t) override;
4f0e34
+
4f0e34
+  void low_new_clone (struct lwp_info *, pid_t) override;
4f0e34
+
4f0e34
+  void low_forget_process (pid_t pid) override;
4f0e34
+
4f0e34
+  void low_prepare_to_resume (struct lwp_info *) override;
4f0e34
+
4f0e34
+private:
4f0e34
+
4f0e34
+  void copy_thread_dreg_state (const ptid_t &parent_ptid,
4f0e34
+			       const ptid_t &child_ptid);
4f0e34
+
4f0e34
+  void mark_thread_stale (struct lwp_info *lp);
4f0e34
+
4f0e34
+  void mark_debug_registers_changed (pid_t pid);
4f0e34
+
4f0e34
+  void register_hw_breakpoint (pid_t pid,
4f0e34
+			       const struct ppc_hw_breakpoint &bp);
4f0e34
+
4f0e34
+  void clear_hw_breakpoint (pid_t pid,
4f0e34
+			    const struct ppc_hw_breakpoint &a);
4f0e34
+
4f0e34
+  void register_wp (pid_t pid, long wp_value);
4f0e34
+
4f0e34
+  void clear_wp (pid_t pid);
4f0e34
+
4f0e34
+  bool can_use_watchpoint_cond_accel (void);
4f0e34
+
4f0e34
+  void calculate_dvc (CORE_ADDR addr, int len,
4f0e34
+		      CORE_ADDR data_value,
4f0e34
+		      uint32_t *condition_mode,
4f0e34
+		      uint64_t *condition_value);
4f0e34
+
4f0e34
+  int check_condition (CORE_ADDR watch_addr,
4f0e34
+		       struct expression *cond,
4f0e34
+		       CORE_ADDR *data_value, int *len);
4f0e34
+
4f0e34
+  int num_memory_accesses (const std::vector<value_ref_ptr> &chain);
4f0e34
+
4f0e34
+  int get_trigger_type (enum target_hw_bp_type type);
4f0e34
+
4f0e34
+  void create_watchpoint_request (struct ppc_hw_breakpoint *p,
4f0e34
+				  CORE_ADDR addr,
4f0e34
+				  int len,
4f0e34
+				  enum target_hw_bp_type type,
4f0e34
+				  struct expression *cond,
4f0e34
+				  int insert);
4f0e34
+
4f0e34
+  bool hwdebug_point_cmp (const struct ppc_hw_breakpoint &a,
4f0e34
+			  const struct ppc_hw_breakpoint &b);
4f0e34
+
4f0e34
+  void init_arch_lwp_info (struct lwp_info *lp);
4f0e34
+
4f0e34
+  arch_lwp_info *get_arch_lwp_info (struct lwp_info *lp);
4f0e34
+
4f0e34
+  /* The ptrace interface we'll use to install hardware watchpoints and
4f0e34
+     breakpoints (debug registers).  */
4f0e34
+  ppc_linux_dreg_interface m_dreg_interface;
4f0e34
+
4f0e34
+  /* A map from pids to structs containing info specific to each
4f0e34
+     process.  */
4f0e34
+  std::unordered_map<pid_t, ppc_linux_process_info> m_process_info;
4f0e34
+
4f0e34
+  /* Callable object to hash ptids by their lwp number.  */
4f0e34
+  struct ptid_hash
4f0e34
+  {
4f0e34
+    std::size_t operator() (const ptid_t &ptid) const
4f0e34
+    {
4f0e34
+      return std::hash<long>{} (ptid.lwp ());
4f0e34
+    }
4f0e34
+  };
4f0e34
+
4f0e34
+  /* A map from ptid_t objects to a list of pairs of slots and hardware
4f0e34
+     breakpoint objects.  This keeps track of which hardware breakpoints
4f0e34
+     and watchpoints were last installed in each slot of each thread.
4f0e34
+
4f0e34
+     Only used when the interface is HWDEBUG.  */
4f0e34
+  std::unordered_map 
4f0e34
+		      std::list<std::pair<long, ppc_hw_breakpoint>>,
4f0e34
+		      ptid_hash> m_installed_hw_bps;
4f0e34
 };
4f0e34
 
4f0e34
 static ppc_linux_nat_target the_ppc_linux_nat_target;
4f0e34
@@ -1725,102 +2030,50 @@ ppc_linux_nat_target::read_description ()
4f0e34
   return ppc_linux_match_description (features);
4f0e34
 }
4f0e34
 
4f0e34
-/* The cached DABR value, to install in new threads.
4f0e34
-   This variable is used when the PowerPC HWDEBUG ptrace
4f0e34
-   interface is not available.  */
4f0e34
-static long saved_dabr_value;
4f0e34
-
4f0e34
-/* Global structure that will store information about the available
4f0e34
-   features provided by the PowerPC HWDEBUG ptrace interface.  */
4f0e34
-static struct ppc_debug_info hwdebug_info;
4f0e34
-
4f0e34
-/* Global variable that holds the maximum number of slots that the
4f0e34
-   kernel will use.  This is only used when PowerPC HWDEBUG ptrace interface
4f0e34
-   is available.  */
4f0e34
-static size_t max_slots_number = 0;
4f0e34
-
4f0e34
-struct hw_break_tuple
4f0e34
-{
4f0e34
-  long slot;
4f0e34
-  struct ppc_hw_breakpoint *hw_break;
4f0e34
-};
4f0e34
-
4f0e34
-/* This is an internal VEC created to store information about *points inserted
4f0e34
-   for each thread.  This is used when PowerPC HWDEBUG ptrace interface is
4f0e34
-   available.  */
4f0e34
-typedef struct thread_points
4f0e34
-  {
4f0e34
-    /* The TID to which this *point relates.  */
4f0e34
-    int tid;
4f0e34
-    /* Information about the *point, such as its address, type, etc.
4f0e34
-
4f0e34
-       Each element inside this vector corresponds to a hardware
4f0e34
-       breakpoint or watchpoint in the thread represented by TID.  The maximum
4f0e34
-       size of these vector is MAX_SLOTS_NUMBER.  If the hw_break element of
4f0e34
-       the tuple is NULL, then the position in the vector is free.  */
4f0e34
-    struct hw_break_tuple *hw_breaks;
4f0e34
-  } *thread_points_p;
4f0e34
-DEF_VEC_P (thread_points_p);
4f0e34
-
4f0e34
-VEC(thread_points_p) *ppc_threads = NULL;
4f0e34
-
4f0e34
-/* The version of the PowerPC HWDEBUG kernel interface that we will use, if
4f0e34
-   available.  */
4f0e34
-#define PPC_DEBUG_CURRENT_VERSION 1
4f0e34
-
4f0e34
-/* Returns non-zero if we support the PowerPC HWDEBUG ptrace interface.  */
4f0e34
-static int
4f0e34
-have_ptrace_hwdebug_interface (void)
4f0e34
-{
4f0e34
-  static int have_ptrace_hwdebug_interface = -1;
4f0e34
-
4f0e34
-  if (have_ptrace_hwdebug_interface == -1)
4f0e34
-    {
4f0e34
-      int tid;
4f0e34
-
4f0e34
-      tid = inferior_ptid.lwp ();
4f0e34
-      if (tid == 0)
4f0e34
-	tid = inferior_ptid.pid ();
4f0e34
-
4f0e34
-      /* Check for kernel support for PowerPC HWDEBUG ptrace interface.  */
4f0e34
-      if (ptrace (PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info) >= 0)
4f0e34
-	{
4f0e34
-	  /* Check whether PowerPC HWDEBUG ptrace interface is functional and
4f0e34
-	     provides any supported feature.  */
4f0e34
-	  if (hwdebug_info.features != 0)
4f0e34
-	    {
4f0e34
-	      have_ptrace_hwdebug_interface = 1;
4f0e34
-	      max_slots_number = hwdebug_info.num_instruction_bps
4f0e34
-	        + hwdebug_info.num_data_bps
4f0e34
-	        + hwdebug_info.num_condition_regs;
4f0e34
-	      return have_ptrace_hwdebug_interface;
4f0e34
-	    }
4f0e34
-	}
4f0e34
-      /* Old school interface and no PowerPC HWDEBUG ptrace support.  */
4f0e34
-      have_ptrace_hwdebug_interface = 0;
4f0e34
-      memset (&hwdebug_info, 0, sizeof (struct ppc_debug_info));
4f0e34
-    }
4f0e34
-
4f0e34
-  return have_ptrace_hwdebug_interface;
4f0e34
-}
4f0e34
+/* Routines for installing hardware watchpoints and breakpoints.  When
4f0e34
+   GDB requests a hardware watchpoint or breakpoint to be installed, we
4f0e34
+   register the request for the pid of inferior_ptid in a map with one
4f0e34
+   entry per process.  We then issue a stop request to all the threads of
4f0e34
+   this process, and mark a per-thread flag indicating that their debug
4f0e34
+   registers should be updated.  Right before they are next resumed, we
4f0e34
+   remove all previously installed debug registers and install all the
4f0e34
+   ones GDB requested.  We then update a map with one entry per thread
4f0e34
+   that keeps track of what debug registers were last installed in each
4f0e34
+   thread.
4f0e34
+
4f0e34
+   We use this second map to remove installed registers before installing
4f0e34
+   the ones requested by GDB, and to copy the debug register state after
4f0e34
+   a thread clones or forks, since depending on the kernel configuration,
4f0e34
+   debug registers can be inherited.  */
4f0e34
+
4f0e34
+/* Check if we support and have enough resources to install a hardware
4f0e34
+   watchpoint or breakpoint.  See the description in target.h.  */
4f0e34
 
4f0e34
 int
4f0e34
-ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt, int ot)
4f0e34
+ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt,
4f0e34
+					     int ot)
4f0e34
 {
4f0e34
   int total_hw_wp, total_hw_bp;
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (m_dreg_interface.unavailable_p ())
4f0e34
+    return 0;
4f0e34
+
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
       /* When PowerPC HWDEBUG ptrace interface is available, the number of
4f0e34
 	 available hardware watchpoints and breakpoints is stored at the
4f0e34
 	 hwdebug_info struct.  */
4f0e34
-      total_hw_bp = hwdebug_info.num_instruction_bps;
4f0e34
-      total_hw_wp = hwdebug_info.num_data_bps;
4f0e34
+      total_hw_bp = m_dreg_interface.hwdebug_info ().num_instruction_bps;
4f0e34
+      total_hw_wp = m_dreg_interface.hwdebug_info ().num_data_bps;
4f0e34
     }
4f0e34
   else
4f0e34
     {
4f0e34
-      /* When we do not have PowerPC HWDEBUG ptrace interface, we should
4f0e34
-	 consider having 1 hardware watchpoint and no hardware breakpoints.  */
4f0e34
+      gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
+
4f0e34
+      /* With the DEBUGREG ptrace interface, we should consider having 1
4f0e34
+	 hardware watchpoint and no hardware breakpoints.  */
4f0e34
       total_hw_bp = 0;
4f0e34
       total_hw_wp = 1;
4f0e34
     }
4f0e34
@@ -1828,53 +2081,50 @@ ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt, int ot)
4f0e34
   if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
4f0e34
       || type == bp_access_watchpoint || type == bp_watchpoint)
4f0e34
     {
4f0e34
-      if (cnt + ot > total_hw_wp)
4f0e34
+      if (total_hw_wp == 0)
4f0e34
+	return 0;
4f0e34
+      else if (cnt + ot > total_hw_wp)
4f0e34
 	return -1;
4f0e34
+      else
4f0e34
+	return 1;
4f0e34
     }
4f0e34
   else if (type == bp_hardware_breakpoint)
4f0e34
     {
4f0e34
       if (total_hw_bp == 0)
4f0e34
-	{
4f0e34
-	  /* No hardware breakpoint support. */
4f0e34
-	  return 0;
4f0e34
-	}
4f0e34
-      if (cnt > total_hw_bp)
4f0e34
-	return -1;
4f0e34
-    }
4f0e34
-
4f0e34
-  if (!have_ptrace_hwdebug_interface ())
4f0e34
-    {
4f0e34
-      int tid;
4f0e34
-      ptid_t ptid = inferior_ptid;
4f0e34
-
4f0e34
-      /* We need to know whether ptrace supports PTRACE_SET_DEBUGREG
4f0e34
-	 and whether the target has DABR.  If either answer is no, the
4f0e34
-	 ptrace call will return -1.  Fail in that case.  */
4f0e34
-      tid = ptid.lwp ();
4f0e34
-      if (tid == 0)
4f0e34
-	tid = ptid.pid ();
4f0e34
-
4f0e34
-      if (ptrace (PTRACE_SET_DEBUGREG, tid, 0, 0) == -1)
4f0e34
 	return 0;
4f0e34
+      else if (cnt > total_hw_bp)
4f0e34
+	return -1;
4f0e34
+      else
4f0e34
+	return 1;
4f0e34
     }
4f0e34
 
4f0e34
-  return 1;
4f0e34
+  return 0;
4f0e34
 }
4f0e34
 
4f0e34
+/* Returns 1 if we can watch LEN bytes at address ADDR, 0 otherwise.  */
4f0e34
+
4f0e34
 int
4f0e34
-ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   /* Handle sub-8-byte quantities.  */
4f0e34
   if (len <= 0)
4f0e34
     return 0;
4f0e34
 
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (m_dreg_interface.unavailable_p ())
4f0e34
+    return 0;
4f0e34
+
4f0e34
   /* The PowerPC HWDEBUG ptrace interface tells if there are alignment
4f0e34
      restrictions for watchpoints in the processors.  In that case, we use that
4f0e34
      information to determine the hardcoded watchable region for
4f0e34
      watchpoints.  */
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
       int region_size;
4f0e34
+      const struct ppc_debug_info &hwdebug_info = (m_dreg_interface
4f0e34
+						   .hwdebug_info ());
4f0e34
+
4f0e34
       /* Embedded DAC-based processors, like the PowerPC 440 have ranged
4f0e34
 	 watchpoints and can watch any access within an arbitrary memory
4f0e34
 	 region. This is useful to watch arrays and structs, for instance.  It
4f0e34
@@ -1901,121 +2151,32 @@ ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
      ptrace interface, DAC-based processors (i.e., embedded processors) will
4f0e34
      use addresses aligned to 4-bytes due to the way the read/write flags are
4f0e34
      passed in the old ptrace interface.  */
4f0e34
-  else if (((linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
4f0e34
-	   && (addr + len) > (addr & ~3) + 4)
4f0e34
-	   || (addr + len) > (addr & ~7) + 8)
4f0e34
-    return 0;
4f0e34
-
4f0e34
-  return 1;
4f0e34
-}
4f0e34
-
4f0e34
-/* This function compares two ppc_hw_breakpoint structs field-by-field.  */
4f0e34
-static int
4f0e34
-hwdebug_point_cmp (struct ppc_hw_breakpoint *a, struct ppc_hw_breakpoint *b)
4f0e34
-{
4f0e34
-  return (a->trigger_type == b->trigger_type
4f0e34
-	  && a->addr_mode == b->addr_mode
4f0e34
-	  && a->condition_mode == b->condition_mode
4f0e34
-	  && a->addr == b->addr
4f0e34
-	  && a->addr2 == b->addr2
4f0e34
-	  && a->condition_value == b->condition_value);
4f0e34
-}
4f0e34
-
4f0e34
-/* This function can be used to retrieve a thread_points by the TID of the
4f0e34
-   related process/thread.  If nothing has been found, and ALLOC_NEW is 0,
4f0e34
-   it returns NULL.  If ALLOC_NEW is non-zero, a new thread_points for the
4f0e34
-   provided TID will be created and returned.  */
4f0e34
-static struct thread_points *
4f0e34
-hwdebug_find_thread_points_by_tid (int tid, int alloc_new)
4f0e34
-{
4f0e34
-  int i;
4f0e34
-  struct thread_points *t;
4f0e34
-
4f0e34
-  for (i = 0; VEC_iterate (thread_points_p, ppc_threads, i, t); i++)
4f0e34
-    if (t->tid == tid)
4f0e34
-      return t;
4f0e34
-
4f0e34
-  t = NULL;
4f0e34
-
4f0e34
-  /* Do we need to allocate a new point_item
4f0e34
-     if the wanted one does not exist?  */
4f0e34
-  if (alloc_new)
4f0e34
+  else
4f0e34
     {
4f0e34
-      t = XNEW (struct thread_points);
4f0e34
-      t->hw_breaks = XCNEWVEC (struct hw_break_tuple, max_slots_number);
4f0e34
-      t->tid = tid;
4f0e34
-      VEC_safe_push (thread_points_p, ppc_threads, t);
4f0e34
-    }
4f0e34
+      gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
 
4f0e34
-  return t;
4f0e34
-}
4f0e34
-
4f0e34
-/* This function is a generic wrapper that is responsible for inserting a
4f0e34
-   *point (i.e., calling `ptrace' in order to issue the request to the
4f0e34
-   kernel) and registering it internally in GDB.  */
4f0e34
-static void
4f0e34
-hwdebug_insert_point (struct ppc_hw_breakpoint *b, int tid)
4f0e34
-{
4f0e34
-  int i;
4f0e34
-  long slot;
4f0e34
-  gdb::unique_xmalloc_ptr<ppc_hw_breakpoint> p (XDUP (ppc_hw_breakpoint, b));
4f0e34
-  struct hw_break_tuple *hw_breaks;
4f0e34
-  struct thread_points *t;
4f0e34
-  struct hw_break_tuple *tuple;
4f0e34
-
4f0e34
-  errno = 0;
4f0e34
-  slot = ptrace (PPC_PTRACE_SETHWDEBUG, tid, 0, p.get ());
4f0e34
-  if (slot < 0)
4f0e34
-    perror_with_name (_("Unexpected error setting breakpoint or watchpoint"));
4f0e34
-
4f0e34
-  /* Everything went fine, so we have to register this *point.  */
4f0e34
-  t = hwdebug_find_thread_points_by_tid (tid, 1);
4f0e34
-  gdb_assert (t != NULL);
4f0e34
-  hw_breaks = t->hw_breaks;
4f0e34
-
4f0e34
-  /* Find a free element in the hw_breaks vector.  */
4f0e34
-  for (i = 0; i < max_slots_number; i++)
4f0e34
-    if (hw_breaks[i].hw_break == NULL)
4f0e34
-      {
4f0e34
-	hw_breaks[i].slot = slot;
4f0e34
-	hw_breaks[i].hw_break = p.release ();
4f0e34
-	break;
4f0e34
-      }
4f0e34
+      if (((linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
4f0e34
+	   && (addr + len) > (addr & ~3) + 4)
4f0e34
+	  || (addr + len) > (addr & ~7) + 8)
4f0e34
+	return 0;
4f0e34
+    }
4f0e34
 
4f0e34
-  gdb_assert (i != max_slots_number);
4f0e34
+  return 1;
4f0e34
 }
4f0e34
 
4f0e34
-/* This function is a generic wrapper that is responsible for removing a
4f0e34
-   *point (i.e., calling `ptrace' in order to issue the request to the
4f0e34
-   kernel), and unregistering it internally at GDB.  */
4f0e34
-static void
4f0e34
-hwdebug_remove_point (struct ppc_hw_breakpoint *b, int tid)
4f0e34
-{
4f0e34
-  int i;
4f0e34
-  struct hw_break_tuple *hw_breaks;
4f0e34
-  struct thread_points *t;
4f0e34
-
4f0e34
-  t = hwdebug_find_thread_points_by_tid (tid, 0);
4f0e34
-  gdb_assert (t != NULL);
4f0e34
-  hw_breaks = t->hw_breaks;
4f0e34
-
4f0e34
-  for (i = 0; i < max_slots_number; i++)
4f0e34
-    if (hw_breaks[i].hw_break && hwdebug_point_cmp (hw_breaks[i].hw_break, b))
4f0e34
-      break;
4f0e34
+/* This function compares two ppc_hw_breakpoint structs
4f0e34
+   field-by-field.  */
4f0e34
 
4f0e34
-  gdb_assert (i != max_slots_number);
4f0e34
-
4f0e34
-  /* We have to ignore ENOENT errors because the kernel implements hardware
4f0e34
-     breakpoints/watchpoints as "one-shot", that is, they are automatically
4f0e34
-     deleted when hit.  */
4f0e34
-  errno = 0;
4f0e34
-  if (ptrace (PPC_PTRACE_DELHWDEBUG, tid, 0, hw_breaks[i].slot) < 0)
4f0e34
-    if (errno != ENOENT)
4f0e34
-      perror_with_name (_("Unexpected error deleting "
4f0e34
-			  "breakpoint or watchpoint"));
4f0e34
-
4f0e34
-  xfree (hw_breaks[i].hw_break);
4f0e34
-  hw_breaks[i].hw_break = NULL;
4f0e34
+bool
4f0e34
+ppc_linux_nat_target::hwdebug_point_cmp (const struct ppc_hw_breakpoint &a,
4f0e34
+					 const struct ppc_hw_breakpoint &b)
4f0e34
+{
4f0e34
+  return (a.trigger_type == b.trigger_type
4f0e34
+	  && a.addr_mode == b.addr_mode
4f0e34
+	  && a.condition_mode == b.condition_mode
4f0e34
+	  && a.addr == b.addr
4f0e34
+	  && a.addr2 == b.addr2
4f0e34
+	  && a.condition_value == b.condition_value);
4f0e34
 }
4f0e34
 
4f0e34
 /* Return the number of registers needed for a ranged breakpoint.  */
4f0e34
@@ -2023,22 +2184,28 @@ hwdebug_remove_point (struct ppc_hw_breakpoint *b, int tid)
4f0e34
 int
4f0e34
 ppc_linux_nat_target::ranged_break_num_registers ()
4f0e34
 {
4f0e34
-  return ((have_ptrace_hwdebug_interface ()
4f0e34
-	   && hwdebug_info.features & PPC_DEBUG_FEATURE_INSN_BP_RANGE)?
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  return ((m_dreg_interface.hwdebug_p ()
4f0e34
+	   && (m_dreg_interface.hwdebug_info ().features
4f0e34
+	       & PPC_DEBUG_FEATURE_INSN_BP_RANGE))?
4f0e34
 	  2 : -1);
4f0e34
 }
4f0e34
 
4f0e34
-/* Insert the hardware breakpoint described by BP_TGT.  Returns 0 for
4f0e34
-   success, 1 if hardware breakpoints are not supported or -1 for failure.  */
4f0e34
+/* Register the hardware breakpoint described by BP_TGT, to be inserted
4f0e34
+   when the threads of inferior_ptid are resumed.  Returns 0 for success,
4f0e34
+   or -1 if the HWDEBUG interface that we need for hardware breakpoints
4f0e34
+   is not available.  */
4f0e34
 
4f0e34
 int
4f0e34
 ppc_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
 					    struct bp_target_info *bp_tgt)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
   struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
-  if (!have_ptrace_hwdebug_interface ())
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (!m_dreg_interface.hwdebug_p ())
4f0e34
     return -1;
4f0e34
 
4f0e34
   p.version = PPC_DEBUG_CURRENT_VERSION;
4f0e34
@@ -2061,20 +2228,25 @@ ppc_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
       p.addr2 = 0;
4f0e34
     }
4f0e34
 
4f0e34
-  ALL_LWPS (lp)
4f0e34
-    hwdebug_insert_point (&p, lp->ptid.lwp ());
4f0e34
+  register_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
 
4f0e34
   return 0;
4f0e34
 }
4f0e34
 
4f0e34
+/* Clear a registration for the hardware breakpoint given by type BP_TGT.
4f0e34
+   It will be removed from the threads of inferior_ptid when they are
4f0e34
+   next resumed.  Returns 0 for success, or -1 if the HWDEBUG interface
4f0e34
+   that we need for hardware breakpoints is not available.  */
4f0e34
+
4f0e34
 int
4f0e34
 ppc_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
 					    struct bp_target_info *bp_tgt)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
   struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
-  if (!have_ptrace_hwdebug_interface ())
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (!m_dreg_interface.hwdebug_p ())
4f0e34
     return -1;
4f0e34
 
4f0e34
   p.version = PPC_DEBUG_CURRENT_VERSION;
4f0e34
@@ -2097,14 +2269,16 @@ ppc_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
       p.addr2 = 0;
4f0e34
     }
4f0e34
 
4f0e34
-  ALL_LWPS (lp)
4f0e34
-    hwdebug_remove_point (&p, lp->ptid.lwp ());
4f0e34
+  clear_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
 
4f0e34
   return 0;
4f0e34
 }
4f0e34
 
4f0e34
-static int
4f0e34
-get_trigger_type (enum target_hw_bp_type type)
4f0e34
+/* Return the trigger value to set in a ppc_hw_breakpoint object for a
4f0e34
+   given hardware watchpoint TYPE.  We assume type is not hw_execute.  */
4f0e34
+
4f0e34
+int
4f0e34
+ppc_linux_nat_target::get_trigger_type (enum target_hw_bp_type type)
4f0e34
 {
4f0e34
   int t;
4f0e34
 
4f0e34
@@ -2118,19 +2292,18 @@ get_trigger_type (enum target_hw_bp_type type)
4f0e34
   return t;
4f0e34
 }
4f0e34
 
4f0e34
-/* Insert a new masked watchpoint at ADDR using the mask MASK.
4f0e34
-   RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
4f0e34
-   or hw_access for an access watchpoint.  Returns 0 on success and throws
4f0e34
-   an error on failure.  */
4f0e34
+/* Register a new masked watchpoint at ADDR using the mask MASK, to be
4f0e34
+   inserted when the threads of inferior_ptid are resumed.  RW may be
4f0e34
+   hw_read for a read watchpoint, hw_write for a write watchpoint or
4f0e34
+   hw_access for an access watchpoint.  */
4f0e34
 
4f0e34
 int
4f0e34
 ppc_linux_nat_target::insert_mask_watchpoint (CORE_ADDR addr,  CORE_ADDR mask,
4f0e34
 					      target_hw_bp_type rw)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
   struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
-  gdb_assert (have_ptrace_hwdebug_interface ());
4f0e34
+  gdb_assert (m_dreg_interface.hwdebug_p ());
4f0e34
 
4f0e34
   p.version = PPC_DEBUG_CURRENT_VERSION;
4f0e34
   p.trigger_type = get_trigger_type (rw);
4f0e34
@@ -2140,25 +2313,23 @@ ppc_linux_nat_target::insert_mask_watchpoint (CORE_ADDR addr,  CORE_ADDR mask,
4f0e34
   p.addr2 = mask;
4f0e34
   p.condition_value = 0;
4f0e34
 
4f0e34
-  ALL_LWPS (lp)
4f0e34
-    hwdebug_insert_point (&p, lp->ptid.lwp ());
4f0e34
+  register_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
 
4f0e34
   return 0;
4f0e34
 }
4f0e34
 
4f0e34
-/* Remove a masked watchpoint at ADDR with the mask MASK.
4f0e34
-   RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
4f0e34
-   or hw_access for an access watchpoint.  Returns 0 on success and throws
4f0e34
-   an error on failure.  */
4f0e34
+/* Clear a registration for a masked watchpoint at ADDR with the mask
4f0e34
+   MASK.  It will be removed from the threads of inferior_ptid when they
4f0e34
+   are next resumed.  RW may be hw_read for a read watchpoint, hw_write
4f0e34
+   for a write watchpoint or hw_access for an access watchpoint.  */
4f0e34
 
4f0e34
 int
4f0e34
 ppc_linux_nat_target::remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
4f0e34
 					      target_hw_bp_type rw)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
   struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
-  gdb_assert (have_ptrace_hwdebug_interface ());
4f0e34
+  gdb_assert (m_dreg_interface.hwdebug_p ());
4f0e34
 
4f0e34
   p.version = PPC_DEBUG_CURRENT_VERSION;
4f0e34
   p.trigger_type = get_trigger_type (rw);
4f0e34
@@ -2168,40 +2339,42 @@ ppc_linux_nat_target::remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
4f0e34
   p.addr2 = mask;
4f0e34
   p.condition_value = 0;
4f0e34
 
4f0e34
-  ALL_LWPS (lp)
4f0e34
-    hwdebug_remove_point (&p, lp->ptid.lwp ());
4f0e34
+  clear_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
 
4f0e34
   return 0;
4f0e34
 }
4f0e34
 
4f0e34
-/* Check whether we have at least one free DVC register.  */
4f0e34
-static int
4f0e34
-can_use_watchpoint_cond_accel (void)
4f0e34
+/* Check whether we have at least one free DVC register for the threads
4f0e34
+   of the pid of inferior_ptid.  */
4f0e34
+
4f0e34
+bool
4f0e34
+ppc_linux_nat_target::can_use_watchpoint_cond_accel (void)
4f0e34
 {
4f0e34
-  struct thread_points *p;
4f0e34
-  int tid = inferior_ptid.lwp ();
4f0e34
-  int cnt = hwdebug_info.num_condition_regs, i;
4f0e34
-  CORE_ADDR tmp_value;
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
 
4f0e34
-  if (!have_ptrace_hwdebug_interface () || cnt == 0)
4f0e34
-    return 0;
4f0e34
+  if (!m_dreg_interface.hwdebug_p ())
4f0e34
+    return false;
4f0e34
 
4f0e34
-  p = hwdebug_find_thread_points_by_tid (tid, 0);
4f0e34
+  int cnt = m_dreg_interface.hwdebug_info ().num_condition_regs;
4f0e34
 
4f0e34
-  if (p)
4f0e34
-    {
4f0e34
-      for (i = 0; i < max_slots_number; i++)
4f0e34
-	if (p->hw_breaks[i].hw_break != NULL
4f0e34
-	    && (p->hw_breaks[i].hw_break->condition_mode
4f0e34
-		!= PPC_BREAKPOINT_CONDITION_NONE))
4f0e34
-	  cnt--;
4f0e34
+  if (cnt == 0)
4f0e34
+    return false;
4f0e34
 
4f0e34
-      /* There are no available slots now.  */
4f0e34
-      if (cnt <= 0)
4f0e34
-	return 0;
4f0e34
-    }
4f0e34
+  auto process_it = m_process_info.find (inferior_ptid.pid ());
4f0e34
 
4f0e34
-  return 1;
4f0e34
+  /* No breakpoints or watchpoints have been requested for this process,
4f0e34
+     we have at least one free DVC register.  */
4f0e34
+  if (process_it == m_process_info.end ())
4f0e34
+    return true;
4f0e34
+
4f0e34
+  for (const ppc_hw_breakpoint &bp : process_it->second.requested_hw_bps)
4f0e34
+    if (bp.condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
4f0e34
+      cnt--;
4f0e34
+
4f0e34
+  if (cnt <= 0)
4f0e34
+    return false;
4f0e34
+
4f0e34
+  return true;
4f0e34
 }
4f0e34
 
4f0e34
 /* Calculate the enable bits and the contents of the Data Value Compare
4f0e34
@@ -2212,10 +2385,16 @@ can_use_watchpoint_cond_accel (void)
4f0e34
    On exit, CONDITION_MODE will hold the enable bits for the DVC, and
4f0e34
    CONDITION_VALUE will hold the value which should be put in the
4f0e34
    DVC register.  */
4f0e34
-static void
4f0e34
-calculate_dvc (CORE_ADDR addr, LONGEST len, CORE_ADDR data_value,
4f0e34
-	       uint32_t *condition_mode, uint64_t *condition_value)
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::calculate_dvc (CORE_ADDR addr, int len,
4f0e34
+				     CORE_ADDR data_value,
4f0e34
+				     uint32_t *condition_mode,
4f0e34
+				     uint64_t *condition_value)
4f0e34
 {
4f0e34
+  const struct ppc_debug_info &hwdebug_info = (m_dreg_interface.
4f0e34
+					       hwdebug_info ());
4f0e34
+
4f0e34
   LONGEST i, num_byte_enable;
4f0e34
   int align_offset, num_bytes_off_dvc, rightmost_enabled_byte;
4f0e34
   CORE_ADDR addr_end_data, addr_end_dvc;
4f0e34
@@ -2254,8 +2433,10 @@ calculate_dvc (CORE_ADDR addr, LONGEST len, CORE_ADDR data_value,
4f0e34
    Returns -1 if there's any register access involved, or if there are
4f0e34
    other kinds of values which are not acceptable in a condition
4f0e34
    expression (e.g., lval_computed or lval_internalvar).  */
4f0e34
-static int
4f0e34
-num_memory_accesses (const std::vector<value_ref_ptr> &chain)
4f0e34
+
4f0e34
+int
4f0e34
+ppc_linux_nat_target::num_memory_accesses (const std::vector<value_ref_ptr>
4f0e34
+					   &chain)
4f0e34
 {
4f0e34
   int found_memory_cnt = 0;
4f0e34
 
4f0e34
@@ -2303,9 +2484,11 @@ num_memory_accesses (const std::vector<value_ref_ptr> &chain)
4f0e34
    If the function returns 1, DATA_VALUE will contain the constant against
4f0e34
    which the watch value should be compared and LEN will contain the size
4f0e34
    of the constant.  */
4f0e34
-static int
4f0e34
-check_condition (CORE_ADDR watch_addr, struct expression *cond,
4f0e34
-		 CORE_ADDR *data_value, LONGEST *len)
4f0e34
+
4f0e34
+int
4f0e34
+ppc_linux_nat_target::check_condition (CORE_ADDR watch_addr,
4f0e34
+				       struct expression *cond,
4f0e34
+				       CORE_ADDR *data_value, int *len)
4f0e34
 {
4f0e34
   int pc = 1, num_accesses_left, num_accesses_right;
4f0e34
   struct value *left_val, *right_val;
4f0e34
@@ -2352,19 +2535,21 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
4f0e34
   return 1;
4f0e34
 }
4f0e34
 
4f0e34
-/* Return non-zero if the target is capable of using hardware to evaluate
4f0e34
-   the condition expression, thus only triggering the watchpoint when it is
4f0e34
+/* Return true if the target is capable of using hardware to evaluate the
4f0e34
+   condition expression, thus only triggering the watchpoint when it is
4f0e34
    true.  */
4f0e34
+
4f0e34
 bool
4f0e34
 ppc_linux_nat_target::can_accel_watchpoint_condition (CORE_ADDR addr,
4f0e34
-						      LONGEST len,
4f0e34
-						      int rw,
4f0e34
+						      int len, int rw,
4f0e34
 						      struct expression *cond)
4f0e34
 {
4f0e34
   CORE_ADDR data_value;
4f0e34
 
4f0e34
-  return (have_ptrace_hwdebug_interface ()
4f0e34
-	  && hwdebug_info.num_condition_regs > 0
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  return (m_dreg_interface.hwdebug_p ()
4f0e34
+	  && (m_dreg_interface.hwdebug_info ().num_condition_regs > 0)
4f0e34
 	  && check_condition (addr, cond, &data_value, &len));
4f0e34
 }
4f0e34
 
4f0e34
@@ -2373,11 +2558,16 @@ ppc_linux_nat_target::can_accel_watchpoint_condition (CORE_ADDR addr,
4f0e34
    evaluated by hardware.  INSERT tells if we are creating a request for
4f0e34
    inserting or removing the watchpoint.  */
4f0e34
 
4f0e34
-static void
4f0e34
-create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr,
4f0e34
-			   LONGEST len, enum target_hw_bp_type type,
4f0e34
-			   struct expression *cond, int insert)
4f0e34
+void
4f0e34
+ppc_linux_nat_target::create_watchpoint_request (struct ppc_hw_breakpoint *p,
4f0e34
+						 CORE_ADDR addr, int len,
4f0e34
+						 enum target_hw_bp_type type,
4f0e34
+						 struct expression *cond,
4f0e34
+						 int insert)
4f0e34
 {
4f0e34
+  const struct ppc_debug_info &hwdebug_info = (m_dreg_interface
4f0e34
+					       .hwdebug_info ());
4f0e34
+
4f0e34
   if (len == 1
4f0e34
       || !(hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE))
4f0e34
     {
4f0e34
@@ -2419,28 +2609,33 @@ create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr,
4f0e34
   p->addr = (uint64_t) addr;
4f0e34
 }
4f0e34
 
4f0e34
+/* Register a watchpoint, to be inserted when the threads of the group of
4f0e34
+   inferior_ptid are next resumed.  Returns 0 on success, and -1 if there
4f0e34
+   is no ptrace interface available to install the watchpoint.  */
4f0e34
+
4f0e34
 int
4f0e34
 ppc_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
4f0e34
 					 enum target_hw_bp_type type,
4f0e34
 					 struct expression *cond)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
-  int ret = -1;
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (m_dreg_interface.unavailable_p ())
4f0e34
+    return -1;
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
       struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
       create_watchpoint_request (&p, addr, len, type, cond, 1);
4f0e34
 
4f0e34
-      ALL_LWPS (lp)
4f0e34
-	hwdebug_insert_point (&p, lp->ptid.lwp ());
4f0e34
-
4f0e34
-      ret = 0;
4f0e34
+      register_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
     }
4f0e34
   else
4f0e34
     {
4f0e34
-      long dabr_value;
4f0e34
+      gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
+
4f0e34
+      long wp_value;
4f0e34
       long read_mode, write_mode;
4f0e34
 
4f0e34
       if (linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
4f0e34
@@ -2458,142 +2653,300 @@ ppc_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
4f0e34
 	  write_mode = 6;
4f0e34
 	}
4f0e34
 
4f0e34
-      dabr_value = addr & ~(read_mode | write_mode);
4f0e34
+      wp_value = addr & ~(read_mode | write_mode);
4f0e34
       switch (type)
4f0e34
 	{
4f0e34
 	  case hw_read:
4f0e34
 	    /* Set read and translate bits.  */
4f0e34
-	    dabr_value |= read_mode;
4f0e34
+	    wp_value |= read_mode;
4f0e34
 	    break;
4f0e34
 	  case hw_write:
4f0e34
 	    /* Set write and translate bits.  */
4f0e34
-	    dabr_value |= write_mode;
4f0e34
+	    wp_value |= write_mode;
4f0e34
 	    break;
4f0e34
 	  case hw_access:
4f0e34
 	    /* Set read, write and translate bits.  */
4f0e34
-	    dabr_value |= read_mode | write_mode;
4f0e34
+	    wp_value |= read_mode | write_mode;
4f0e34
 	    break;
4f0e34
 	}
4f0e34
 
4f0e34
-      saved_dabr_value = dabr_value;
4f0e34
-
4f0e34
-      ALL_LWPS (lp)
4f0e34
-	if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0,
4f0e34
-		    saved_dabr_value) < 0)
4f0e34
-	  return -1;
4f0e34
-
4f0e34
-      ret = 0;
4f0e34
+      register_wp (inferior_ptid.pid (), wp_value);
4f0e34
     }
4f0e34
 
4f0e34
-  return ret;
4f0e34
+  return 0;
4f0e34
 }
4f0e34
 
4f0e34
+/* Clear a registration for a hardware watchpoint.  It will be removed
4f0e34
+   from the threads of the group of inferior_ptid when they are next
4f0e34
+   resumed.  */
4f0e34
+
4f0e34
 int
4f0e34
 ppc_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
4f0e34
 					 enum target_hw_bp_type type,
4f0e34
 					 struct expression *cond)
4f0e34
 {
4f0e34
-  struct lwp_info *lp;
4f0e34
-  int ret = -1;
4f0e34
+  gdb_assert (!m_dreg_interface.unavailable_p ());
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
       struct ppc_hw_breakpoint p;
4f0e34
 
4f0e34
       create_watchpoint_request (&p, addr, len, type, cond, 0);
4f0e34
 
4f0e34
-      ALL_LWPS (lp)
4f0e34
-	hwdebug_remove_point (&p, lp->ptid.lwp ());
4f0e34
-
4f0e34
-      ret = 0;
4f0e34
+      clear_hw_breakpoint (inferior_ptid.pid (), p);
4f0e34
     }
4f0e34
   else
4f0e34
     {
4f0e34
-      saved_dabr_value = 0;
4f0e34
-      ALL_LWPS (lp)
4f0e34
-	if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0,
4f0e34
-		    saved_dabr_value) < 0)
4f0e34
-	  return -1;
4f0e34
+      gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
 
4f0e34
-      ret = 0;
4f0e34
+      clear_wp (inferior_ptid.pid ());
4f0e34
     }
4f0e34
 
4f0e34
-  return ret;
4f0e34
+  return 0;
4f0e34
 }
4f0e34
 
4f0e34
+/* Clean up the per-process info associated with PID.  When using the
4f0e34
+   HWDEBUG interface, we also erase the per-thread state of installed
4f0e34
+   debug registers for all the threads that belong to the group of PID.
4f0e34
+
4f0e34
+   Usually the thread state is cleaned up by low_delete_thread.  We also
4f0e34
+   do it here because low_new_thread is not called for the initial LWP,
4f0e34
+   so low_delete_thread won't be able to clean up this state.  */
4f0e34
+
4f0e34
 void
4f0e34
-ppc_linux_nat_target::low_new_thread (struct lwp_info *lp)
4f0e34
+ppc_linux_nat_target::low_forget_process (pid_t pid)
4f0e34
 {
4f0e34
-  int tid = lp->ptid.lwp ();
4f0e34
+  if ((!m_dreg_interface.detected_p ())
4f0e34
+      || (m_dreg_interface.unavailable_p ()))
4f0e34
+    return;
4f0e34
+
4f0e34
+  ptid_t pid_ptid (pid, 0, 0);
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  m_process_info.erase (pid);
4f0e34
+
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
-      int i;
4f0e34
-      struct thread_points *p;
4f0e34
-      struct hw_break_tuple *hw_breaks;
4f0e34
+      for (auto it = m_installed_hw_bps.begin ();
4f0e34
+	   it != m_installed_hw_bps.end ();)
4f0e34
+	{
4f0e34
+	  if (it->first.matches (pid_ptid))
4f0e34
+	    it = m_installed_hw_bps.erase (it);
4f0e34
+	  else
4f0e34
+	    it++;
4f0e34
+	}
4f0e34
+    }
4f0e34
+}
4f0e34
 
4f0e34
-      if (VEC_empty (thread_points_p, ppc_threads))
4f0e34
-	return;
4f0e34
+/* Copy the per-process state associated with the pid of PARENT to the
4f0e34
+   sate of CHILD_PID.  GDB expects that a forked process will have the
4f0e34
+   same hardware breakpoints and watchpoints as the parent.
4f0e34
 
4f0e34
-      /* Get a list of breakpoints from any thread.  */
4f0e34
-      p = VEC_last (thread_points_p, ppc_threads);
4f0e34
-      hw_breaks = p->hw_breaks;
4f0e34
+   If we're using the HWDEBUG interface, also copy the thread debug
4f0e34
+   register state for the ptid of PARENT to the state for CHILD_PID.
4f0e34
 
4f0e34
-      /* Copy that thread's breakpoints and watchpoints to the new thread.  */
4f0e34
-      for (i = 0; i < max_slots_number; i++)
4f0e34
-	if (hw_breaks[i].hw_break)
4f0e34
-	  {
4f0e34
-	    /* Older kernels did not make new threads inherit their parent
4f0e34
-	       thread's debug state, so we always clear the slot and replicate
4f0e34
-	       the debug state ourselves, ensuring compatibility with all
4f0e34
-	       kernels.  */
4f0e34
+   Like for clone events, we assume the kernel will copy the debug
4f0e34
+   registers from the parent thread to the child. The
4f0e34
+   low_prepare_to_resume function is made to work even if it doesn't.
4f0e34
 
4f0e34
-	    /* The ppc debug resource accounting is done through "slots".
4f0e34
-	       Ask the kernel the deallocate this specific *point's slot.  */
4f0e34
-	    ptrace (PPC_PTRACE_DELHWDEBUG, tid, 0, hw_breaks[i].slot);
4f0e34
+   We copy the thread state here and not in low_new_thread since we don't
4f0e34
+   have the pid of the parent in low_new_thread.  Even if we did,
4f0e34
+   low_new_thread might not be called immediately after the fork event is
4f0e34
+   detected.  For instance, with the checkpointing system (see
4f0e34
+   linux-fork.c), the thread won't be added until GDB decides to switch
4f0e34
+   to a new checkpointed process.  At that point, the debug register
4f0e34
+   state of the parent thread is unlikely to correspond to the state it
4f0e34
+   had at the point when it forked.  */
4f0e34
 
4f0e34
-	    hwdebug_insert_point (hw_breaks[i].hw_break, tid);
4f0e34
-	  }
4f0e34
+void
4f0e34
+ppc_linux_nat_target::low_new_fork (struct lwp_info *parent,
4f0e34
+				    pid_t child_pid)
4f0e34
+{
4f0e34
+  if ((!m_dreg_interface.detected_p ())
4f0e34
+      || (m_dreg_interface.unavailable_p ()))
4f0e34
+    return;
4f0e34
+
4f0e34
+  auto process_it = m_process_info.find (parent->ptid.pid ());
4f0e34
+
4f0e34
+  if (process_it != m_process_info.end ())
4f0e34
+    m_process_info[child_pid] = m_process_info[parent->ptid.pid ()];
4f0e34
+
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
+    {
4f0e34
+      ptid_t child_ptid (child_pid, child_pid, 0);
4f0e34
+
4f0e34
+      copy_thread_dreg_state (parent->ptid, child_ptid);
4f0e34
     }
4f0e34
-  else
4f0e34
-    ptrace (PTRACE_SET_DEBUGREG, tid, 0, saved_dabr_value);
4f0e34
 }
4f0e34
 
4f0e34
-static void
4f0e34
-ppc_linux_thread_exit (struct thread_info *tp, int silent)
4f0e34
+/* Copy the thread debug register state from the PARENT thread to the the
4f0e34
+   state for CHILD_LWP, if we're using the HWDEBUG interface.  We assume
4f0e34
+   the kernel copies the debug registers from one thread to another after
4f0e34
+   a clone event.  The low_prepare_to_resume function is made to work
4f0e34
+   even if it doesn't.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::low_new_clone (struct lwp_info *parent,
4f0e34
+				     pid_t child_lwp)
4f0e34
 {
4f0e34
-  int i;
4f0e34
-  int tid = tp->ptid.lwp ();
4f0e34
-  struct hw_break_tuple *hw_breaks;
4f0e34
-  struct thread_points *t = NULL, *p;
4f0e34
+  if ((!m_dreg_interface.detected_p ())
4f0e34
+      || (m_dreg_interface.unavailable_p ()))
4f0e34
+    return;
4f0e34
+
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
+    {
4f0e34
+      ptid_t child_ptid (parent->ptid.pid (), child_lwp, 0);
4f0e34
+
4f0e34
+      copy_thread_dreg_state (parent->ptid, child_ptid);
4f0e34
+    }
4f0e34
+}
4f0e34
+
4f0e34
+/* Initialize the arch-specific thread state for LP so that it contains
4f0e34
+   the ptid for lp, so that we can use it in low_delete_thread.  Mark the
4f0e34
+   new thread LP as stale so that we update its debug registers before
4f0e34
+   resuming it.  This is not called for the initial thread.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::low_new_thread (struct lwp_info *lp)
4f0e34
+{
4f0e34
+  init_arch_lwp_info (lp);
4f0e34
+
4f0e34
+  mark_thread_stale (lp);
4f0e34
+}
4f0e34
+
4f0e34
+/* Delete the per-thread debug register stale flag.  */
4f0e34
 
4f0e34
-  if (!have_ptrace_hwdebug_interface ())
4f0e34
+void
4f0e34
+ppc_linux_nat_target::low_delete_thread (struct arch_lwp_info
4f0e34
+					 *lp_arch_info)
4f0e34
+{
4f0e34
+  if (lp_arch_info != NULL)
4f0e34
+    {
4f0e34
+      if (m_dreg_interface.detected_p ()
4f0e34
+	  && m_dreg_interface.hwdebug_p ())
4f0e34
+	m_installed_hw_bps.erase (lp_arch_info->lwp_ptid);
4f0e34
+
4f0e34
+      xfree (lp_arch_info);
4f0e34
+    }
4f0e34
+}
4f0e34
+
4f0e34
+/* Install or delete debug registers in thread LP so that it matches what
4f0e34
+   GDB requested before it is resumed.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lp)
4f0e34
+{
4f0e34
+  if ((!m_dreg_interface.detected_p ())
4f0e34
+      || (m_dreg_interface.unavailable_p ()))
4f0e34
     return;
4f0e34
 
4f0e34
-  for (i = 0; VEC_iterate (thread_points_p, ppc_threads, i, p); i++)
4f0e34
-    if (p->tid == tid)
4f0e34
-      {
4f0e34
-	t = p;
4f0e34
-	break;
4f0e34
-      }
4f0e34
+  /* We have to re-install or clear the debug registers if we set the
4f0e34
+     stale flag.
4f0e34
+
4f0e34
+     In addition, some kernels configurations can disable a hardware
4f0e34
+     watchpoint after it is hit.  Usually, GDB will remove and re-install
4f0e34
+     a hardware watchpoint when the thread stops if "breakpoint
4f0e34
+     always-inserted" is off, or to single-step a watchpoint.  But so
4f0e34
+     that we don't rely on this behavior, if we stop due to a hardware
4f0e34
+     breakpoint or watchpoint, we also refresh our debug registers.  */
4f0e34
 
4f0e34
-  if (t == NULL)
4f0e34
+  arch_lwp_info *lp_arch_info = get_arch_lwp_info (lp);
4f0e34
+
4f0e34
+  bool stale_dregs = (lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
4f0e34
+		      || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT
4f0e34
+		      || lp_arch_info->debug_regs_stale);
4f0e34
+
4f0e34
+  if (!stale_dregs)
4f0e34
     return;
4f0e34
 
4f0e34
-  VEC_unordered_remove (thread_points_p, ppc_threads, i);
4f0e34
+  gdb_assert (lp->ptid.lwp_p ());
4f0e34
+
4f0e34
+  auto process_it = m_process_info.find (lp->ptid.pid ());
4f0e34
+
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
+    {
4f0e34
+      /* First, delete any hardware watchpoint or breakpoint installed in
4f0e34
+	 the inferior and update the thread state.  */
4f0e34
+      auto installed_it = m_installed_hw_bps.find (lp->ptid);
4f0e34
+
4f0e34
+      if (installed_it != m_installed_hw_bps.end ())
4f0e34
+	{
4f0e34
+	  auto &bp_list = installed_it->second;
4f0e34
+
4f0e34
+	  for (auto bp_it = bp_list.begin (); bp_it != bp_list.end ();)
4f0e34
+	    {
4f0e34
+	      /* We ignore ENOENT to account for various possible kernel
4f0e34
+		 behaviors, e.g. the kernel might or might not copy debug
4f0e34
+		 registers across forks and clones, and we always copy
4f0e34
+		 the debug register state when fork and clone events are
4f0e34
+		 detected.  */
4f0e34
+	      if (ptrace (PPC_PTRACE_DELHWDEBUG, lp->ptid.lwp (), 0,
4f0e34
+			  bp_it->first) == -1)
4f0e34
+		if (errno != ENOENT)
4f0e34
+		  perror_with_name (_("Error deleting hardware "
4f0e34
+				      "breakpoint or watchpoint"));
4f0e34
+
4f0e34
+	      /* We erase the entries one at a time after successfuly
4f0e34
+		 removing the corresponding slot form the thread so that
4f0e34
+		 if we throw an exception above in a future iteration the
4f0e34
+		 map remains consistent.  */
4f0e34
+	      bp_it = bp_list.erase (bp_it);
4f0e34
+	    }
4f0e34
 
4f0e34
-  hw_breaks = t->hw_breaks;
4f0e34
+	  gdb_assert (bp_list.empty ());
4f0e34
+	}
4f0e34
 
4f0e34
-  for (i = 0; i < max_slots_number; i++)
4f0e34
-    if (hw_breaks[i].hw_break)
4f0e34
-      xfree (hw_breaks[i].hw_break);
4f0e34
+      /* Now we install all the requested hardware breakpoints and
4f0e34
+	 watchpoints and update the thread state.  */
4f0e34
 
4f0e34
-  xfree (t->hw_breaks);
4f0e34
-  xfree (t);
4f0e34
+      if (process_it != m_process_info.end ())
4f0e34
+	{
4f0e34
+	  auto &bp_list = m_installed_hw_bps[lp->ptid];
4f0e34
+
4f0e34
+	  for (ppc_hw_breakpoint bp
4f0e34
+		 : process_it->second.requested_hw_bps)
4f0e34
+	    {
4f0e34
+	      long slot = ptrace (PPC_PTRACE_SETHWDEBUG, lp->ptid.lwp (),
4f0e34
+				  0, &bp);
4f0e34
+
4f0e34
+	      if (slot < 0)
4f0e34
+		perror_with_name (_("Error setting hardware "
4f0e34
+				    "breakpoint or watchpoint"));
4f0e34
+
4f0e34
+	      /* Keep track of which slots we installed in this
4f0e34
+		 thread.  */
4f0e34
+	      bp_list.emplace (bp_list.begin (), slot, bp);
4f0e34
+	    }
4f0e34
+	}
4f0e34
+    }
4f0e34
+  else
4f0e34
+    {
4f0e34
+      gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
+
4f0e34
+      /* Passing 0 to PTRACE_SET_DEBUGREG will clear the
4f0e34
+	 watchpoint.  */
4f0e34
+      long wp = 0;
4f0e34
+
4f0e34
+      /* GDB requested a watchpoint to be installed.  */
4f0e34
+      if (process_it != m_process_info.end ()
4f0e34
+	  && process_it->second.requested_wp_val.has_value ())
4f0e34
+	wp = *(process_it->second.requested_wp_val);
4f0e34
+
4f0e34
+      long ret = ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (),
4f0e34
+			 0, wp);
4f0e34
+
4f0e34
+      if (ret == -1)
4f0e34
+	perror_with_name (_("Error setting hardware watchpoint"));
4f0e34
+    }
4f0e34
+
4f0e34
+  lp_arch_info->debug_regs_stale = false;
4f0e34
 }
4f0e34
 
4f0e34
+/* Return true if INFERIOR_PTID is known to have been stopped by a
4f0e34
+   hardware watchpoint, false otherwise.  If true is returned, write the
4f0e34
+   address that the kernel reported as causing the SIGTRAP in ADDR_P.  */
4f0e34
+
4f0e34
 bool
4f0e34
-ppc_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
4f0e34
+ppc_linux_nat_target::low_stopped_data_address (CORE_ADDR *addr_p)
4f0e34
 {
4f0e34
   siginfo_t siginfo;
4f0e34
 
4f0e34
@@ -2604,48 +2957,57 @@ ppc_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
4f0e34
       || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
4f0e34
     return false;
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ())
4f0e34
+  gdb_assert (!m_dreg_interface.unavailable_p ());
4f0e34
+
4f0e34
+  /* Check if this signal corresponds to a hardware breakpoint.  We only
4f0e34
+     need to check this if we're using the HWDEBUG interface, since the
4f0e34
+     DEBUGREG interface only allows setting one hardware watchpoint.  */
4f0e34
+  if (m_dreg_interface.hwdebug_p ())
4f0e34
     {
4f0e34
-      int i;
4f0e34
-      struct thread_points *t;
4f0e34
-      struct hw_break_tuple *hw_breaks;
4f0e34
-      /* The index (or slot) of the *point is passed in the si_errno field.  */
4f0e34
+      /* The index (or slot) of the *point is passed in the si_errno
4f0e34
+	 field.  Currently, this is only the case if the kernel was
4f0e34
+	 configured with CONFIG_PPC_ADV_DEBUG_REGS.  If not, we assume
4f0e34
+	 the kernel will set si_errno to a value that doesn't correspond
4f0e34
+	 to any real slot.  */
4f0e34
       int slot = siginfo.si_errno;
4f0e34
 
4f0e34
-      t = hwdebug_find_thread_points_by_tid (inferior_ptid.lwp (), 0);
4f0e34
+      auto installed_it = m_installed_hw_bps.find (inferior_ptid);
4f0e34
 
4f0e34
-      /* Find out if this *point is a hardware breakpoint.
4f0e34
-	 If so, we should return 0.  */
4f0e34
-      if (t)
4f0e34
-	{
4f0e34
-	  hw_breaks = t->hw_breaks;
4f0e34
-	  for (i = 0; i < max_slots_number; i++)
4f0e34
-	   if (hw_breaks[i].hw_break && hw_breaks[i].slot == slot
4f0e34
-	       && hw_breaks[i].hw_break->trigger_type
4f0e34
-		    == PPC_BREAKPOINT_TRIGGER_EXECUTE)
4f0e34
-	     return false;
4f0e34
-	}
4f0e34
+      /* We must have installed slots for the thread if it got a
4f0e34
+	 TRAP_HWBKPT signal.  */
4f0e34
+      gdb_assert (installed_it != m_installed_hw_bps.end ());
4f0e34
+
4f0e34
+      for (const auto & slot_bp_pair : installed_it->second)
4f0e34
+	if (slot_bp_pair.first == slot
4f0e34
+	    && (slot_bp_pair.second.trigger_type
4f0e34
+		== PPC_BREAKPOINT_TRIGGER_EXECUTE))
4f0e34
+	  return false;
4f0e34
     }
4f0e34
 
4f0e34
   *addr_p = (CORE_ADDR) (uintptr_t) siginfo.si_addr;
4f0e34
   return true;
4f0e34
 }
4f0e34
 
4f0e34
+/* Return true if INFERIOR_PTID is known to have been stopped by a
4f0e34
+   hardware watchpoint, false otherwise.  */
4f0e34
+
4f0e34
 bool
4f0e34
-ppc_linux_nat_target::stopped_by_watchpoint ()
4f0e34
+ppc_linux_nat_target::low_stopped_by_watchpoint ()
4f0e34
 {
4f0e34
   CORE_ADDR addr;
4f0e34
-  return stopped_data_address (&addr);
4f0e34
+  return low_stopped_data_address (&addr);
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
 ppc_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
4f0e34
 						    CORE_ADDR start,
4f0e34
-						    LONGEST length)
4f0e34
+						    int length)
4f0e34
 {
4f0e34
+  gdb_assert (!m_dreg_interface.unavailable_p ());
4f0e34
+
4f0e34
   int mask;
4f0e34
 
4f0e34
-  if (have_ptrace_hwdebug_interface ()
4f0e34
+  if (m_dreg_interface.hwdebug_p ()
4f0e34
       && linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
4f0e34
     return start <= addr && start + length >= addr;
4f0e34
   else if (linux_get_hwcap (current_top_target ()) & PPC_FEATURE_BOOKE)
4f0e34
@@ -2662,10 +3024,14 @@ ppc_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
4f0e34
 /* Return the number of registers needed for a masked hardware watchpoint.  */
4f0e34
 
4f0e34
 int
4f0e34
-ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
4f0e34
+ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr,
4f0e34
+						  CORE_ADDR mask)
4f0e34
 {
4f0e34
-  if (!have_ptrace_hwdebug_interface ()
4f0e34
-	   || (hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0)
4f0e34
+  m_dreg_interface.detect (inferior_ptid);
4f0e34
+
4f0e34
+  if (!m_dreg_interface.hwdebug_p ()
4f0e34
+      || (m_dreg_interface.hwdebug_info ().features
4f0e34
+	  & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0)
4f0e34
     return -1;
4f0e34
   else if ((mask & 0xC0000000) != 0xC0000000)
4f0e34
     {
4f0e34
@@ -2678,14 +3044,204 @@ ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask
4f0e34
     return 2;
4f0e34
 }
4f0e34
 
4f0e34
+/* Copy the per-thread debug register state, if any, from thread
4f0e34
+   PARENT_PTID to thread CHILD_PTID, if the debug register being used is
4f0e34
+   HWDEBUG.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::copy_thread_dreg_state (const ptid_t &parent_ptid,
4f0e34
+					      const ptid_t &child_ptid)
4f0e34
+{
4f0e34
+  gdb_assert (m_dreg_interface.hwdebug_p ());
4f0e34
+
4f0e34
+  auto installed_it = m_installed_hw_bps.find (parent_ptid);
4f0e34
+
4f0e34
+  if (installed_it != m_installed_hw_bps.end ())
4f0e34
+    m_installed_hw_bps[child_ptid] = m_installed_hw_bps[parent_ptid];
4f0e34
+}
4f0e34
+
4f0e34
+/* Mark the debug register stale flag for the new thread, if we have
4f0e34
+   already detected which debug register interface we use.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::mark_thread_stale (struct lwp_info *lp)
4f0e34
+{
4f0e34
+  if ((!m_dreg_interface.detected_p ())
4f0e34
+      || (m_dreg_interface.unavailable_p ()))
4f0e34
+    return;
4f0e34
+
4f0e34
+  arch_lwp_info *lp_arch_info = get_arch_lwp_info (lp);
4f0e34
+
4f0e34
+  lp_arch_info->debug_regs_stale = true;
4f0e34
+}
4f0e34
+
4f0e34
+/* Mark all the threads of the group of PID as stale with respect to
4f0e34
+   debug registers and issue a stop request to each such thread that
4f0e34
+   isn't already stopped.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::mark_debug_registers_changed (pid_t pid)
4f0e34
+{
4f0e34
+  /* We do this in two passes to make sure all threads are marked even if
4f0e34
+     we get an exception when stopping one of them.  */
4f0e34
+
4f0e34
+  iterate_over_lwps_new (ptid_t (pid),
4f0e34
+		     [this] (struct lwp_info *lp) -> int {
4f0e34
+		       this->mark_thread_stale (lp);
4f0e34
+		       return 0;
4f0e34
+		     });
4f0e34
+
4f0e34
+  iterate_over_lwps_new (ptid_t (pid),
4f0e34
+		     [] (struct lwp_info *lp) -> int {
4f0e34
+		       if (!lwp_is_stopped (lp))
4f0e34
+			 linux_stop_lwp (lp);
4f0e34
+		       return 0;
4f0e34
+		     });
4f0e34
+}
4f0e34
+
4f0e34
+/* Register a hardware breakpoint or watchpoint BP for the pid PID, then
4f0e34
+   mark the stale flag for all threads of the group of PID, and issue a
4f0e34
+   stop request for them.  The breakpoint or watchpoint will be installed
4f0e34
+   the next time each thread is resumed.  Should only be used if the
4f0e34
+   debug register interface is HWDEBUG.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::register_hw_breakpoint (pid_t pid,
4f0e34
+					      const struct
4f0e34
+					      ppc_hw_breakpoint &bp)
4f0e34
+{
4f0e34
+  gdb_assert (m_dreg_interface.hwdebug_p ());
4f0e34
+
4f0e34
+  m_process_info[pid].requested_hw_bps.push_back (bp);
4f0e34
+
4f0e34
+  mark_debug_registers_changed (pid);
4f0e34
+}
4f0e34
+
4f0e34
+/* Clear a registration for a hardware breakpoint or watchpoint BP for
4f0e34
+   the pid PID, then mark the stale flag for all threads of the group of
4f0e34
+   PID, and issue a stop request for them.  The breakpoint or watchpoint
4f0e34
+   will be removed the next time each thread is resumed.  Should only be
4f0e34
+   used if the debug register interface is HWDEBUG.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::clear_hw_breakpoint (pid_t pid,
4f0e34
+					   const struct ppc_hw_breakpoint &bp)
4f0e34
+{
4f0e34
+  gdb_assert (m_dreg_interface.hwdebug_p ());
4f0e34
+
4f0e34
+  auto process_it = m_process_info.find (pid);
4f0e34
+
4f0e34
+  gdb_assert (process_it != m_process_info.end ());
4f0e34
+
4f0e34
+  auto bp_it = std::find_if (process_it->second.requested_hw_bps.begin (),
4f0e34
+			     process_it->second.requested_hw_bps.end (),
4f0e34
+			     [&bp, this]
4f0e34
+			     (const struct ppc_hw_breakpoint &curr)
4f0e34
+			     { return hwdebug_point_cmp (bp, curr); }
4f0e34
+			     );
4f0e34
+
4f0e34
+  /* If GDB is removing a watchpoint, it must have been inserted.  */
4f0e34
+  gdb_assert (bp_it != process_it->second.requested_hw_bps.end ());
4f0e34
+
4f0e34
+  process_it->second.requested_hw_bps.erase (bp_it);
4f0e34
+
4f0e34
+  mark_debug_registers_changed (pid);
4f0e34
+}
4f0e34
+
4f0e34
+/* Register the hardware watchpoint value WP_VALUE for the pid PID,
4f0e34
+   then mark the stale flag for all threads of the group of PID, and
4f0e34
+   issue a stop request for them.  The breakpoint or watchpoint will be
4f0e34
+   installed the next time each thread is resumed.  Should only be used
4f0e34
+   if the debug register interface is DEBUGREG.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::register_wp (pid_t pid, long wp_value)
4f0e34
+{
4f0e34
+  gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
+
4f0e34
+  /* Our other functions should have told GDB that we only have one
4f0e34
+     hardware watchpoint with this interface.  */
4f0e34
+  gdb_assert (!m_process_info[pid].requested_wp_val.has_value ());
4f0e34
+
4f0e34
+  m_process_info[pid].requested_wp_val.emplace (wp_value);
4f0e34
+
4f0e34
+  mark_debug_registers_changed (pid);
4f0e34
+}
4f0e34
+
4f0e34
+/* Clear the hardware watchpoint registration for the pid PID, then mark
4f0e34
+   the stale flag for all threads of the group of PID, and issue a stop
4f0e34
+   request for them.  The breakpoint or watchpoint will be installed the
4f0e34
+   next time each thread is resumed.  Should only be used if the debug
4f0e34
+   register interface is DEBUGREG.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::clear_wp (pid_t pid)
4f0e34
+{
4f0e34
+  gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
+
4f0e34
+  auto process_it = m_process_info.find (pid);
4f0e34
+
4f0e34
+  gdb_assert (process_it != m_process_info.end ());
4f0e34
+  gdb_assert (process_it->second.requested_wp_val.has_value ());
4f0e34
+
4f0e34
+  process_it->second.requested_wp_val.reset ();
4f0e34
+
4f0e34
+  mark_debug_registers_changed (pid);
4f0e34
+}
4f0e34
+
4f0e34
+/* Initialize the arch-specific thread state for LWP, if it not already
4f0e34
+   created.  */
4f0e34
+
4f0e34
+void
4f0e34
+ppc_linux_nat_target::init_arch_lwp_info (struct lwp_info *lp)
4f0e34
+{
4f0e34
+  if (lwp_arch_private_info (lp) == NULL)
4f0e34
+    {
4f0e34
+      lwp_set_arch_private_info (lp, XCNEW (struct arch_lwp_info));
4f0e34
+      lwp_arch_private_info (lp)->debug_regs_stale = false;
4f0e34
+      lwp_arch_private_info (lp)->lwp_ptid = lp->ptid;
4f0e34
+    }
4f0e34
+}
4f0e34
+
4f0e34
+/* Get the arch-specific thread state for LWP, creating it if
4f0e34
+   necessary.  */
4f0e34
+
4f0e34
+arch_lwp_info *
4f0e34
+ppc_linux_nat_target::get_arch_lwp_info (struct lwp_info *lp)
4f0e34
+{
4f0e34
+  init_arch_lwp_info (lp);
4f0e34
+
4f0e34
+  return lwp_arch_private_info (lp);
4f0e34
+}
4f0e34
+
4f0e34
+/* The post-gdb-8 version of iterate_over_lwps.  */
4f0e34
+
4f0e34
+static struct lwp_info *
4f0e34
+iterate_over_lwps_new (ptid_t filter,
4f0e34
+                       gdb::function_view<iterate_over_lwps_new_ftype> callback)
4f0e34
+{
4f0e34
+  struct lwp_info *lp, *lpnext;
4f0e34
+
4f0e34
+  for (lp = lwp_list; lp; lp = lpnext)
4f0e34
+    {
4f0e34
+      lpnext = lp->next;
4f0e34
+
4f0e34
+      if (lp->ptid.matches (filter))
4f0e34
+        {
4f0e34
+          if (callback (lp) != 0)
4f0e34
+            return lp;
4f0e34
+        }
4f0e34
+    }
4f0e34
+
4f0e34
+  return NULL;
4f0e34
+}
4f0e34
+
4f0e34
 void _initialize_ppc_linux_nat ();
4f0e34
 void
4f0e34
 _initialize_ppc_linux_nat (void)
4f0e34
 {
4f0e34
   linux_target = &the_ppc_linux_nat_target;
4f0e34
 
4f0e34
-  gdb::observers::thread_exit.attach (ppc_linux_thread_exit);
4f0e34
-
4f0e34
   /* Register the target.  */
4f0e34
   add_inf_child_target (linux_target);
4f0e34
 }
4f0e34
diff --git a/gdb/procfs.c b/gdb/procfs.c
4f0e34
--- a/gdb/procfs.c
4f0e34
+++ b/gdb/procfs.c
4f0e34
@@ -3358,7 +3358,7 @@ procfs_target::remove_watchpoint (CORE_ADDR addr, int len,
4f0e34
 }
4f0e34
 
4f0e34
 int
4f0e34
-procfs_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+procfs_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   /* The man page for proc(4) on Solaris 2.6 and up says that the
4f0e34
      system can support "thousands" of hardware watchpoints, but gives
4f0e34
diff --git a/gdb/remote.c b/gdb/remote.c
4f0e34
--- a/gdb/remote.c
4f0e34
+++ b/gdb/remote.c
4f0e34
@@ -454,7 +454,7 @@ public:
4f0e34
 
4f0e34
   bool stopped_data_address (CORE_ADDR *) override;
4f0e34
 
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, LONGEST) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
4f0e34
 
4f0e34
   int can_use_hw_breakpoint (enum bptype, int, int) override;
4f0e34
 
4f0e34
@@ -462,7 +462,7 @@ public:
4f0e34
 
4f0e34
   int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
4f0e34
 
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
 
4f0e34
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
 			 struct expression *) override;
4f0e34
@@ -10362,7 +10362,7 @@ remote_target::insert_watchpoint (CORE_ADDR addr, int len,
4f0e34
 
4f0e34
 bool
4f0e34
 remote_target::watchpoint_addr_within_range (CORE_ADDR addr,
4f0e34
-					     CORE_ADDR start, LONGEST length)
4f0e34
+					     CORE_ADDR start, int length)
4f0e34
 {
4f0e34
   CORE_ADDR diff = remote_address_masked (addr - start);
4f0e34
 
4f0e34
@@ -10413,7 +10413,7 @@ int remote_hw_watchpoint_length_limit = -1;
4f0e34
 int remote_hw_breakpoint_limit = -1;
4f0e34
 
4f0e34
 int
4f0e34
-remote_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+remote_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   if (remote_hw_watchpoint_length_limit == 0)
4f0e34
     return 0;
4f0e34
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
4f0e34
--- a/gdb/s390-linux-nat.c
4f0e34
+++ b/gdb/s390-linux-nat.c
4f0e34
@@ -122,7 +122,7 @@ public:
4f0e34
     override;
4f0e34
   int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
4f0e34
     override;
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
   bool have_continuable_watchpoint () override { return true; }
4f0e34
   bool stopped_by_watchpoint () override;
4f0e34
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
4f0e34
@@ -954,7 +954,7 @@ s390_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
4f0e34
 
4f0e34
 int
4f0e34
 s390_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr,
4f0e34
-						    LONGEST cnt)
4f0e34
+						    int cnt)
4f0e34
 {
4f0e34
   return 1;
4f0e34
 }
4f0e34
diff --git a/gdb/spu-multiarch.c b/gdb/spu-multiarch.c
4f0e34
--- a/gdb/spu-multiarch.c
4f0e34
+++ b/gdb/spu-multiarch.c
4f0e34
@@ -66,7 +66,7 @@ struct spu_multiarch_target final : public target_ops
4f0e34
 		     const gdb_byte *pattern, ULONGEST pattern_len,
4f0e34
 		     CORE_ADDR *found_addrp) override;
4f0e34
 
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
4f0e34
 
4f0e34
   struct gdbarch *thread_architecture (ptid_t) override;
4f0e34
 };
4f0e34
@@ -163,7 +163,7 @@ spu_multiarch_target::thread_architecture (ptid_t ptid)
4f0e34
 /* Override the to_region_ok_for_hw_watchpoint routine.  */
4f0e34
 
4f0e34
 int
4f0e34
-spu_multiarch_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+spu_multiarch_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   /* We cannot watch SPU local store.  */
4f0e34
   if (SPUADDR_SPU (addr) != -1)
4f0e34
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
4f0e34
--- a/gdb/target-delegates.c
4f0e34
+++ b/gdb/target-delegates.c
4f0e34
@@ -38,9 +38,9 @@ struct dummy_target : public target_ops
4f0e34
   int have_steppable_watchpoint () override;
4f0e34
   bool have_continuable_watchpoint () override;
4f0e34
   bool stopped_data_address (CORE_ADDR *arg0) override;
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONGEST arg2) override;
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1) override;
4f0e34
-  bool can_accel_watchpoint_condition (CORE_ADDR arg0, LONGEST arg1, int arg2, struct expression *arg3) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, int arg2) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR arg0, int arg1) override;
4f0e34
+  bool can_accel_watchpoint_condition (CORE_ADDR arg0, int arg1, int arg2, struct expression *arg3) override;
4f0e34
   int masked_watch_num_registers (CORE_ADDR arg0, CORE_ADDR arg1) override;
4f0e34
   int can_do_single_step () override;
4f0e34
   bool supports_terminal_ours () override;
4f0e34
@@ -206,9 +206,9 @@ struct debug_target : public target_ops
4f0e34
   int have_steppable_watchpoint () override;
4f0e34
   bool have_continuable_watchpoint () override;
4f0e34
   bool stopped_data_address (CORE_ADDR *arg0) override;
4f0e34
-  bool watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONGEST arg2) override;
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1) override;
4f0e34
-  bool can_accel_watchpoint_condition (CORE_ADDR arg0, LONGEST arg1, int arg2, struct expression *arg3) override;
4f0e34
+  bool watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, int arg2) override;
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR arg0, int arg1) override;
4f0e34
+  bool can_accel_watchpoint_condition (CORE_ADDR arg0, int arg1, int arg2, struct expression *arg3) override;
4f0e34
   int masked_watch_num_registers (CORE_ADDR arg0, CORE_ADDR arg1) override;
4f0e34
   int can_do_single_step () override;
4f0e34
   bool supports_terminal_ours () override;
4f0e34
@@ -1068,19 +1068,19 @@ debug_target::stopped_data_address (CORE_ADDR *arg0)
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-target_ops::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONGEST arg2)
4f0e34
+target_ops::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, int arg2)
4f0e34
 {
4f0e34
   return this->beneath ()->watchpoint_addr_within_range (arg0, arg1, arg2);
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-dummy_target::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONGEST arg2)
4f0e34
+dummy_target::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, int arg2)
4f0e34
 {
4f0e34
   return default_watchpoint_addr_within_range (this, arg0, arg1, arg2);
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-debug_target::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONGEST arg2)
4f0e34
+debug_target::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, int arg2)
4f0e34
 {
4f0e34
   bool result;
4f0e34
   fprintf_unfiltered (gdb_stdlog, "-> %s->watchpoint_addr_within_range (...)\n", this->beneath ()->shortname ());
4f0e34
@@ -1098,19 +1098,19 @@ debug_target::watchpoint_addr_within_range (CORE_ADDR arg0, CORE_ADDR arg1, LONG
4f0e34
 }
4f0e34
 
4f0e34
 int
4f0e34
-target_ops::region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1)
4f0e34
+target_ops::region_ok_for_hw_watchpoint (CORE_ADDR arg0, int arg1)
4f0e34
 {
4f0e34
   return this->beneath ()->region_ok_for_hw_watchpoint (arg0, arg1);
4f0e34
 }
4f0e34
 
4f0e34
 int
4f0e34
-dummy_target::region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1)
4f0e34
+dummy_target::region_ok_for_hw_watchpoint (CORE_ADDR arg0, int arg1)
4f0e34
 {
4f0e34
   return default_region_ok_for_hw_watchpoint (this, arg0, arg1);
4f0e34
 }
4f0e34
 
4f0e34
 int
4f0e34
-debug_target::region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1)
4f0e34
+debug_target::region_ok_for_hw_watchpoint (CORE_ADDR arg0, int arg1)
4f0e34
 {
4f0e34
   int result;
4f0e34
   fprintf_unfiltered (gdb_stdlog, "-> %s->region_ok_for_hw_watchpoint (...)\n", this->beneath ()->shortname ());
4f0e34
@@ -1126,19 +1126,19 @@ debug_target::region_ok_for_hw_watchpoint (CORE_ADDR arg0, LONGEST arg1)
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-target_ops::can_accel_watchpoint_condition (CORE_ADDR arg0, LONGEST arg1, int arg2, struct expression *arg3)
4f0e34
+target_ops::can_accel_watchpoint_condition (CORE_ADDR arg0, int arg1, int arg2, struct expression *arg3)
4f0e34
 {
4f0e34
   return this->beneath ()->can_accel_watchpoint_condition (arg0, arg1, arg2, arg3);
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-dummy_target::can_accel_watchpoint_condition (CORE_ADDR arg0, LONGEST arg1, int arg2, struct expression *arg3)
4f0e34
+dummy_target::can_accel_watchpoint_condition (CORE_ADDR arg0, int arg1, int arg2, struct expression *arg3)
4f0e34
 {
4f0e34
   return false;
4f0e34
 }
4f0e34
 
4f0e34
 bool
4f0e34
-debug_target::can_accel_watchpoint_condition (CORE_ADDR arg0, LONGEST arg1, int arg2, struct expression *arg3)
4f0e34
+debug_target::can_accel_watchpoint_condition (CORE_ADDR arg0, int arg1, int arg2, struct expression *arg3)
4f0e34
 {
4f0e34
   bool result;
4f0e34
   fprintf_unfiltered (gdb_stdlog, "-> %s->can_accel_watchpoint_condition (...)\n", this->beneath ()->shortname ());
4f0e34
diff --git a/gdb/target.h b/gdb/target.h
4f0e34
--- a/gdb/target.h
4f0e34
+++ b/gdb/target.h
4f0e34
@@ -557,15 +557,15 @@ struct target_ops
4f0e34
       TARGET_DEFAULT_RETURN (false);
4f0e34
     virtual bool stopped_data_address (CORE_ADDR *)
4f0e34
       TARGET_DEFAULT_RETURN (false);
4f0e34
-    virtual bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, LONGEST)
4f0e34
+    virtual bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int)
4f0e34
       TARGET_DEFAULT_FUNC (default_watchpoint_addr_within_range);
4f0e34
 
4f0e34
     /* Documentation of this routine is provided with the corresponding
4f0e34
        target_* macro.  */
4f0e34
-    virtual int region_ok_for_hw_watchpoint (CORE_ADDR, LONGEST)
4f0e34
+    virtual int region_ok_for_hw_watchpoint (CORE_ADDR, int)
4f0e34
       TARGET_DEFAULT_FUNC (default_region_ok_for_hw_watchpoint);
4f0e34
 
4f0e34
-    virtual bool can_accel_watchpoint_condition (CORE_ADDR, LONGEST, int,
4f0e34
+    virtual bool can_accel_watchpoint_condition (CORE_ADDR, int, int,
4f0e34
 						 struct expression *)
4f0e34
       TARGET_DEFAULT_RETURN (false);
4f0e34
     virtual int masked_watch_num_registers (CORE_ADDR, CORE_ADDR)
4f0e34
diff --git a/gdb/x86-nat.c b/gdb/x86-nat.c
4f0e34
--- a/gdb/x86-nat.c
4f0e34
+++ b/gdb/x86-nat.c
4f0e34
@@ -173,7 +173,7 @@ x86_remove_watchpoint (CORE_ADDR addr, int len,
4f0e34
    address ADDR and whose length is LEN bytes.  */
4f0e34
 
4f0e34
 int
4f0e34
-x86_region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len)
4f0e34
+x86_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
4f0e34
 {
4f0e34
   struct x86_debug_reg_state *state
4f0e34
     = x86_debug_reg_state (inferior_ptid.pid ());
4f0e34
diff --git a/gdb/x86-nat.h b/gdb/x86-nat.h
4f0e34
--- a/gdb/x86-nat.h
4f0e34
+++ b/gdb/x86-nat.h
4f0e34
@@ -49,7 +49,7 @@ extern void x86_forget_process (pid_t pid);
4f0e34
    definitions.  */
4f0e34
 
4f0e34
 extern int x86_can_use_hw_breakpoint (enum bptype type, int cnt, int othertype);
4f0e34
-extern int x86_region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len);
4f0e34
+extern int x86_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len);
4f0e34
 extern int x86_stopped_by_watchpoint ();
4f0e34
 extern int x86_stopped_data_address (CORE_ADDR *addr_p);
4f0e34
 extern int x86_insert_watchpoint (CORE_ADDR addr, int len,
4f0e34
@@ -82,7 +82,7 @@ struct x86_nat_target : public BaseTarget
4f0e34
   int can_use_hw_breakpoint (enum bptype type, int cnt, int othertype) override
4f0e34
   { return x86_can_use_hw_breakpoint (type, cnt, othertype); }
4f0e34
 
4f0e34
-  int region_ok_for_hw_watchpoint (CORE_ADDR addr, LONGEST len) override
4f0e34
+  int region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) override
4f0e34
   { return x86_region_ok_for_hw_watchpoint (addr, len); }
4f0e34
 
4f0e34
   int insert_watchpoint (CORE_ADDR addr, int len,