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

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