From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10517 invoked by alias); 29 Aug 2007 19:34:47 -0000 Received: (qmail 10509 invoked by uid 22791); 29 Aug 2007 19:34:46 -0000 X-Spam-Check-By: sourceware.org Received: from igw1.br.ibm.com (HELO igw1.br.ibm.com) (32.104.18.24) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 29 Aug 2007 19:34:33 +0000 Received: from mailhub3.br.ibm.com (mailhub3 [9.18.232.110]) by igw1.br.ibm.com (Postfix) with ESMTP id A637914837D for ; Wed, 29 Aug 2007 16:17:10 -0300 (BRT) Received: from d24av02.br.ibm.com (d24av02.br.ibm.com [9.18.232.47]) by mailhub3.br.ibm.com (8.13.8/8.13.8/NCO v8.5) with ESMTP id l7TJXEf6491646 for ; Wed, 29 Aug 2007 16:33:15 -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 l7TJXEiE022573 for ; Wed, 29 Aug 2007 16:33:14 -0300 Received: from [9.18.238.24] ([9.18.238.24]) by d24av02.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id l7TJXCTR022471; Wed, 29 Aug 2007 16:33:14 -0300 Subject: GDB Watchpoints and the PTRACE interface for different ppc processors From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: pmac@au1.ibm.com Cc: gdb@sourceware.org Content-Type: text/plain Date: Wed, 29 Aug 2007 19:34:00 -0000 Message-Id: <1188415991.4390.49.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.6.1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2007-08/txt/msg00249.txt.bz2 Hi Paul, I'm writting this in the hope of getting a better solution to the current PTRACE interface problem we are facing on GDB while trying to cope with two different processors that have different debug register formats (PowerPC 440 and PowerPC 970). The main question is, should GDB deal with all the bit-setting logic for each specific processor and send the PTRACE parameters ready to be assigned to the task's debug register? Or should the kernel receive high level definitions of watchpoints (GDB would just request a read watchpoint, or a write watchpoint) through PTRACE and would have all the logic required to set the correct bits for each specific processor? Follows below a detailed explanation of the problem. I was originally working on supporting Hardware Watchpoints on the PowerPC 440 processors. These processors carry a DBCR0 register that controls the two possible modes of operation for a watchpoint: read/write. So we have two bits that must to be set in that specific register in order to enable the mode we want. These bits are located in the middle of the register. If i'm not mistaken, they are located on bits 13 and 14, in a 32-bit wide DBCR0. So, this is how we set the watchpoint on gdb's side for the 440's: =============GDB code======================= long dabr_value; dabr_value = addr & ~3; /* Clear the 2 bits we're going to use */ switch (rw) { case hw_read: /* Set read bit. */ dabr_value |= 1; break; case hw_write: /* Set write bit. */ dabr_value |= 2; break; case hw_access: /* Set read, write bits. */ dabr_value |= 3; break; } ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value); ============================================ So, basically we set two bits (the last bits, 30 and 31) for read/write modes and send that information to the kernel through PTRACE request PTRACE_SET_DEBUGREG. On the kernel side we have the following: ===========Kernel code============ if (data & 1) task->thread.dbcr0 |= DBCR_D1R; if (data & 2) task->thread.dbcr0 |= DBCR_D1W; ================================== In this code, the kernel checks the previously set bits (30 and 31) on data (dabr_value) and move the bit values to the correct position (13 and 14) through two defined constants (DBCR_D1R and DBCR_D1W). This magic happens inside the kernel. Additionally, there are other bits that are set automatically by the kernel without GDB knowing that. This covers the case for the PowerPC 440 processors. As for the 970/970FX (JS20/21), we have a different debug register, called DABR, that we use to set hardware watchpoints. We still have to set the read/write bits for it, but in this case, the bits are located in the last bits (62 and 63) in a 64-bit wide register, different than the 440's bits positions. Additionaly, for the 970, we also set a third flag in GDB, the "Breakpoint Translation Enable" flag (bit 61). So, for the 970's case, we have the following GDB code: =============GDB code======================= long dabr_value; ptid_t ptid = inferior_ptid; dabr_value = addr & ~7; /* Clear the 3 bits we're going to use */ switch (rw) { case hw_read: /* Set read bit + translate bit. */ dabr_value |= 5; break; case hw_write: /* Set write bit + translate bit. */ dabr_value |= 6; break; case hw_access: /* Set read, write bits + translate bit. */ dabr_value |= 7; break; } ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value); ============================================ In here we're using 3 bits to set the needed flags. The kernel code for the 970's is the following. ===========Kernel code============ task->thread.dabr = data; ================================== So, the kernel-side just assigns the parameter we've passed via PTRACE on GDB to the task's debug register. There is no bit position shifting involved in this case (as opposed to the 440's kernel code), and GDB is also setting an additional flag (Breakpoint translation enable). Best regards, -- Luis Machado IBM Linux Technology Center e-mail: luisgpm@linux.vnet.ibm.com