From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13592 invoked by alias); 5 Aug 2008 19:57:56 -0000 Received: (qmail 13566 invoked by uid 22791); 5 Aug 2008 19:57:54 -0000 X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 05 Aug 2008 19:57:03 +0000 Received: from mailhub1.br.ibm.com (unknown [9.18.232.109]) by igw3.br.ibm.com (Postfix) with ESMTP id 5F1543900D0 for ; Tue, 5 Aug 2008 16:37:44 -0300 (BRST) Received: from d24av02.br.ibm.com (d24av02.br.ibm.com [9.18.232.47]) by mailhub1.br.ibm.com (8.13.8/8.13.8/NCO v9.0) with ESMTP id m75Jup8X1556576 for ; Tue, 5 Aug 2008 16:56:59 -0300 Received: from d24av02.br.ibm.com (loopback [127.0.0.1]) by d24av02.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m75Jughb025122 for ; Tue, 5 Aug 2008 16:56:42 -0300 Received: from [9.18.238.154] (dyn531929.br.ibm.com [9.18.238.154]) by d24av02.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m75Jugx1025119 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 5 Aug 2008 16:56:42 -0300 Subject: [patch-ppc] Hardware watchpoint support for 44x/BookE-based systems From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: gdb-patches@sourceware.org Content-Type: text/plain Date: Tue, 05 Aug 2008 19:57:00 -0000 Message-Id: <1217966200.19330.40.camel@gargoyle> Mime-Version: 1.0 X-Mailer: Evolution 2.12.1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-08/txt/msg00087.txt.bz2 Hi, Currently GDB only supports DABR-based processors (POWER5/5+/6, PowerPC970 etc). DABR-based processors store the address to be watched together with 3 other bits, one for the Breakpoint Translation and two others to control read/write modes. Thus we have a 8-byte alignment restriction. Embedded processors, like the PowerPC 440/BookE, use a different mechanism, the DAC register, which has the sole purpose of storing a whole 32-bit data address. But GDB's implementation and also the kernel code didn't think about these when the support was first implemented. Recently, the kernel has been patched ( http://patchwork.ozlabs.org/linuxppc/patch?id=19790 ) to enable 44X hardware watchpoint support, and it is a good idea to have the same support in GDB. In order to properly identify the 44x/BookE processors, the AT_HWCAP entry from the AUXV has been used. Also, alignment restrictions were set to cope with the requirements for these processors. Note also that only bits for read/write modes are set so that we preserve at least 4-bytes alignment. Passing the Breakpoint Translation bit would imply in an 8-bytes alignment for a 32-bit processor. So, in the end, addresses will be aligned to 4-bytes for the 44x/BookE's and to 8-bytes in the other DABR-based processors. Tested on both DABR-based and DAC-based processors, no regressions found. Luis --- 2008-08-05 Luis Machado * 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. Index: gdb/ppc-linux-nat.c =================================================================== --- gdb.orig/ppc-linux-nat.c 2008-08-04 06:10:00.000000000 -0700 +++ gdb/ppc-linux-nat.c 2008-08-05 09:36:13.000000000 -0700 @@ -44,6 +44,10 @@ #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 @@ -52,6 +56,10 @@ #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 @@ -1014,6 +1022,17 @@ 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 (¤t_target, AT_PLATFORM, &field)) + return (unsigned long) field; + + return 0; +} + static int ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) { @@ -1021,8 +1040,13 @@ 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; @@ -1038,21 +1062,37 @@ 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; } @@ -1112,9 +1152,17 @@ 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