From patchwork Mon Sep 29 08:04:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victor Kamensky X-Patchwork-Id: 4994231 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7A3FDBEEA6 for ; Mon, 29 Sep 2014 08:07:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A6F7B20254 for ; Mon, 29 Sep 2014 08:07:01 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A7404201FB for ; Mon, 29 Sep 2014 08:06:59 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XYVx0-0008O5-P1; Mon, 29 Sep 2014 08:04:54 +0000 Received: from mail-pd0-f175.google.com ([209.85.192.175]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XYVwo-0008Dw-KE for linux-arm-kernel@lists.infradead.org; Mon, 29 Sep 2014 08:04:43 +0000 Received: by mail-pd0-f175.google.com with SMTP id v10so15446415pde.20 for ; Mon, 29 Sep 2014 01:04:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=NA092TS0JtNjHTEYPpeD+ykogKVYEW/9B15914gousE=; b=TdBSaEJqBvA1n9tEi5OoybusyT5cyiwFU871nlvD1ZEg61+rRrbipxWCjb/LlHLWWR n3qssjmEkolZuwdKNDILr+fO1RMYGHtzlcpSefBiehcoWTaD6YcOdGuDpYn39Q8rxqUA 9ugyUFOrhXlDdFLOXaf8nhR+jDa9eyvxedPNmIjaA3enWg4gBPfKrj6i02VXY8LAfxL8 dhShut3P1Y1e7Dd/wkhGXDMpi1EMDHXs9bvJp/lCOvKzy/qAXjy0RixN09fyMecNNYdq sHltGw3eu/sF4t3+TFEAOJ8dPx0uhGoUxS1BVqVzxHhBUM+UomRM4uhtOfKIGAD6vhb0 IidA== X-Gm-Message-State: ALoCoQkpeDEnqk1tClcbqowaWuO34an7lrKMXxDwS4ibmn8zBXKMrzZauVtUDv1WX7cxTP3QicZ4 X-Received: by 10.66.244.132 with SMTP id xg4mr58791056pac.64.1411977861776; Mon, 29 Sep 2014 01:04:21 -0700 (PDT) Received: from kamensky-w530.hsd1.ca.comcast.net ([24.6.79.41]) by mx.google.com with ESMTPSA id x3sm11561675pdp.53.2014.09.29.01.04.19 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Sep 2014 01:04:20 -0700 (PDT) From: Victor Kamensky To: will.deacon@arm.com, mark.rutland@arm.com, catalin.marinas@arm.com, linux-arm-kernel@lists.infradead.org Subject: [PATCH] arm64: ptrace: hw_break_set take into account hardware breakpoints number Date: Mon, 29 Sep 2014 01:04:02 -0700 Message-Id: <1411977842-16515-2-git-send-email-victor.kamensky@linaro.org> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1411977842-16515-1-git-send-email-victor.kamensky@linaro.org> References: <1411977842-16515-1-git-send-email-victor.kamensky@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140929_010442_681381_DB769979 X-CRM114-Status: GOOD ( 15.11 ) X-Spam-Score: -0.8 (/) Cc: Matthew.Leach@arm.com, Victor Kamensky , ard.biesheuvel@linaro.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP hw_break_set function that performs ptrace_regset for hardware breakpoints and watchpoints needs to take into account actual number of hardware breakpoints and watchpoints available in CPU. Current code iterates over all 16 entries of 'struct user_hwdebug_state' and tries to reserve hardware breakpoint for each index, which fails if CPU supports less than 16 hardware breakpoints. One manifestation of the issue is that gdb fails to debug multithreaded user land application and exits with 'Unexpected error setting hardware debug registers' error - ptrace system call for hardware breakpoints regset fails with ENOSPC. Solution is to read number of available hardware breakpoints and watchpoints available in CPU and process only that number of first entries in passed 'struct user_hwdebug_state' regset. Code assumes that ptrace caller uses only first entries in 'struct user_hwdebug_state' up to number of hardware breakpoints and watchpoints supported by CPU. I.e there are no "ignore me, empty" entries in the middle of 'struct user_hwdebug_state' entries array. Signed-off-by: Victor Kamensky --- arch/arm64/kernel/ptrace.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index fe63ac5..4178ba1 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -248,22 +248,32 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, return 0; } -static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) +static int ptrace_hbp_get_num_slots(unsigned int note_type, u8 *num) { - u8 num; - u32 reg = 0; - switch (note_type) { case NT_ARM_HW_BREAK: - num = hw_breakpoint_slots(TYPE_INST); + *num = hw_breakpoint_slots(TYPE_INST); break; case NT_ARM_HW_WATCH: - num = hw_breakpoint_slots(TYPE_DATA); + *num = hw_breakpoint_slots(TYPE_DATA); break; default: return -EINVAL; } + return 0; +} + +static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) +{ + u8 num; + u32 reg = 0; + int err; + + err = ptrace_hbp_get_num_slots(note_type, &num); + if (err) + return err; + reg |= debug_monitors_arch(); reg <<= 8; reg |= num; @@ -432,6 +442,11 @@ static int hw_break_set(struct task_struct *target, int ret, idx = 0, offset, limit; u32 ctrl; u64 addr; + u8 num_slots; + + ret = ptrace_hbp_get_num_slots(note_type, &num_slots); + if (ret) + return ret; /* Resource info and pad */ offset = offsetof(struct user_hwdebug_state, dbg_regs); @@ -441,7 +456,7 @@ static int hw_break_set(struct task_struct *target, /* (address, ctrl) registers */ limit = regset->n * regset->size; - while (count && offset < limit) { + while ((count && offset < limit) && (idx < num_slots)) { ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, offset, offset + PTRACE_HBP_ADDR_SZ); if (ret)