* ppc-linux-nat.c: Include "auxv.h" and "elf/common.h".
authorLuis Machado <luisgpm@br.ibm.com>
Fri, 8 Aug 2008 15:30:27 +0000 (15:30 +0000)
committerLuis Machado <luisgpm@br.ibm.com>
Fri, 8 Aug 2008 15:30:27 +0000 (15:30 +0000)
Define PPC_FEATURE_BOOKE.
(ppc_linux_get_hwcap): New function.
(ppc_linux_region_ok_for_hw_watchpoint): Handle PowerPC 440
4-bytes alignment restrictions.
(ppc_linux_insert_watchpoint): Handle PowerPC 440-specific
positioning of the read/write flags.
(ppc_linux_watchpoint_addr_within_range): Handle PowerPC 440
4-bytes alignment.

gdb/ChangeLog
gdb/ppc-linux-nat.c

index ca67fec9cffc4e622e8aa3f0a4c487eca4ecb4bb..5e6ad60772453e9f5ffa657bae20ac10579c609a 100644 (file)
@@ -1,3 +1,15 @@
+2008-08-08  Luis Machado  <luisgpm@br.ibm.com>
+
+       * ppc-linux-nat.c: Include "auxv.h" and "elf/common.h".
+       Define PPC_FEATURE_BOOKE.       
+       (ppc_linux_get_hwcap): New function.
+       (ppc_linux_region_ok_for_hw_watchpoint): Handle PowerPC 440
+       4-bytes alignment restrictions.
+       (ppc_linux_insert_watchpoint): Handle PowerPC 440-specific
+       positioning of the read/write flags.
+       (ppc_linux_watchpoint_addr_within_range): Handle PowerPC 440
+       4-bytes alignment.
+
 2008-08-08  Pedro Alves  <pedro@codesourcery.com>
 
        Use ptid_t.tid to store thread ids instead of ptid_t.pid.
index f9ea83896140e5c93017ed62d037cbbf2dbb9abc..c4652f7c355fffc72276d768f86fcbc622ec4963 100644 (file)
 #include "ppc-tdep.h"
 #include "ppc-linux-tdep.h"
 
+/* Required when using the AUXV.  */
+#include "elf/common.h"
+#include "auxv.h"
+
 /* This sometimes isn't defined.  */
 #ifndef PT_ORIG_R3
 #define PT_ORIG_R3 34
 #define PT_TRAP 40
 #endif
 
+#ifndef PPC_FEATURE_BOOKE
+#define PPC_FEATURE_BOOKE 0x00008000
+#endif
+
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
    configure time check.  Some older glibc's (for instance 2.2.1)
    don't have a specific powerpc version of ptrace.h, and fall back on
@@ -822,6 +830,17 @@ ppc_linux_check_watch_resources (int type, int cnt, int ot)
   return 1;
 }
 
+/* Fetch the AT_HWCAP entry from the aux vector.  */
+unsigned long ppc_linux_get_hwcap (void)
+{
+  CORE_ADDR field;
+
+  if (target_auxv_search (&current_target, AT_PLATFORM, &field))
+    return (unsigned long) field;
+
+  return 0;
+}
+
 static int
 ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
@@ -829,8 +848,13 @@ ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
   if (len <= 0)
     return 0;
 
-  /* addr+len must fall in the 8 byte watchable region.  */
-  if ((addr + len) > (addr & ~7) + 8)
+  /* addr+len must fall in the 8 byte watchable region for DABR-based
+     processors.  DAC-based processors, like the PowerPC 440, will use
+     addresses aligned to 4-bytes due to the way the read/write flags are
+     passed at the moment.  */
+  if (((ppc_linux_get_hwcap () & PPC_FEATURE_BOOKE)
+      && (addr + len) > (addr & ~3) + 4)
+      || (addr + len) > (addr & ~7) + 8)
     return 0;
 
   return 1;
@@ -846,21 +870,37 @@ ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
   struct lwp_info *lp;
   ptid_t ptid;
   long dabr_value;
+  long read_mode, write_mode;
 
-  dabr_value = addr & ~7;
+  if (ppc_linux_get_hwcap () & PPC_FEATURE_BOOKE)
+  {
+  /* PowerPC 440 requires only the read/write flags to be passed
+     to the kernel.  */
+    read_mode  = 1;
+    write_mode = 2;
+  }
+  else
+  {
+  /* PowerPC 970 and other DABR-based processors are required to pass
+     the Breakpoint Translation bit together with the flags.  */
+    read_mode  = 5;
+    write_mode = 6;
+  }
+
+  dabr_value = addr & ~(read_mode | write_mode);
   switch (rw)
     {
     case hw_read:
       /* Set read and translate bits.  */
-      dabr_value |= 5;
+      dabr_value |= read_mode;
       break;
     case hw_write:
       /* Set write and translate bits.  */
-      dabr_value |= 6;
+      dabr_value |= write_mode;
       break;
     case hw_access:
       /* Set read, write and translate bits.  */
-      dabr_value |= 7;
+      dabr_value |= read_mode | write_mode;
       break;
     }
 
@@ -920,9 +960,17 @@ ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
                                        CORE_ADDR addr,
                                        CORE_ADDR start, int length)
 {
-  addr &= ~7;
-  /* Check whether [start, start+length-1] intersects [addr, addr+7]. */
-  return start <= addr + 7 && start + length - 1 >= addr;
+  int mask;
+
+  if (ppc_linux_get_hwcap () & PPC_FEATURE_BOOKE)
+    mask = 3;
+  else
+    mask = 7;
+
+  addr &= ~mask;
+
+  /* Check whether [start, start+length-1] intersects [addr, addr+mask]. */
+  return start <= addr + mask && start + length - 1 >= addr;
 }
 
 static void