Received: by 10.192.165.148 with SMTP id m20csp2337471imm; Sun, 6 May 2018 12:21:34 -0700 (PDT) X-Google-Smtp-Source: AB8JxZr3F/Q5qRbvr8ZaNVedaHyb+XC6qXB1E/56RqgsUfgu819VKlpQcUgjQX3gvXjrobYGXU9o X-Received: by 10.98.47.68 with SMTP id v65mr2079462pfv.83.1525634494538; Sun, 06 May 2018 12:21:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525634494; cv=none; d=google.com; s=arc-20160816; b=nHS2rNq/D0/fAFP29BBGg3gLenq3fU/cQFRk5fi1nElypOY0H2CFUwKkssYPNKqKk9 unECMYNApZXl/23elERb1kZ45Km12btrIK22/85mX/7jZjaf+iyK7C+KslUuR7Is1GeI lRUynY3FN0jBQJH69Wh4Nd8xHExnX+waOc1Fh8Tp7IkZU8B45FuJtH+esCG/kN/yApgs SdGZI/hZ3J8d0PJ++sc97gSK3kbpi9erJl4rbXFF+Xxhhjv4QijyI2F9aBnLVI0mq2S/ qNK2aKcayIw43tCil/pFfgHVN5oxOJUY0nG2x50FuuIdIHhURLHPOqZTFE33bINKvnrY oCSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=HZh/XVQ0bFmYieeSoaM6LWls1zvgsWL0MeNP7o6tN84=; b=MtxjCNNXjrehUga0sgrrzWPfy8Xl/qWNkGmAOZz3LFBk7/7QXh6nynLPlbTBDOUiaB GnPk/an/1TyfVjzBplVAeM6x1yJ9akoao5jI0ms6Rw1q+KAUnRZB9Ftog5Y/W3lZdVPH Bznp56Ezxgb1letWhSY3sAyp/2PWKdrhIlXFNn09eFv/YbcNA82o0sEZONzmes7/WYiQ lJJehvfQWuciozrdNNBXZQ+YbTQnJzO9Lq3EsEy8Gupd3Cq1gxmEa5yELd7gbWkN+h/s 2wuQjXVmFTEJCPU+nLQ7J7Q0WAJBjj1lNsjbWEtCs1hKLAc5hmuzCKkmSysQ6FuhyJdh jKJw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=dWNHcpya; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33-v6si20482767pls.491.2018.05.06.12.21.07; Sun, 06 May 2018 12:21:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=dWNHcpya; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751976AbeEFTUg (ORCPT + 99 others); Sun, 6 May 2018 15:20:36 -0400 Received: from mail.kernel.org ([198.145.29.99]:38672 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751950AbeEFTUa (ORCPT ); Sun, 6 May 2018 15:20:30 -0400 Received: from lerouge.home (LFbn-NCY-1-193-82.w83-194.abo.wanadoo.fr [83.194.41.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 57F2221837; Sun, 6 May 2018 19:20:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1525634429; bh=SRFWmdOEOZLPxurwMFRCql9PB8K4Vf1IDouD1WfJYKk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dWNHcpyadmDlGKiV0o/0TRHfk7KnR8goa4eKclCmRfeikW3Lzk8SGpejxlpMyvSMG uUcfJ0OxIddxVYSTZ9W4E4PY+GyZVePmUiHZeh5KClF7T6gh5OF7z1F/jO+kU176Km mA/rxMdwJwcgq0ksqjlknsczzQBaMSnuQqbHAQ0s= From: Frederic Weisbecker To: LKML Cc: Frederic Weisbecker , Jiri Olsa , Namhyung Kim , Peter Zijlstra , Linus Torvalds , Yoshinori Sato , Benjamin Herrenschmidt , Catalin Marinas , Chris Zankel , Paul Mackerras , Thomas Gleixner , Will Deacon , Michael Ellerman , Rich Felker , Ingo Molnar , Mark Rutland , Alexander Shishkin , Andy Lutomirski , Arnaldo Carvalho de Melo , Max Filippov Subject: [PATCH 4/9] arm: Split breakpoint validation into "check" and "commit" Date: Sun, 6 May 2018 21:19:50 +0200 Message-Id: <1525634395-23380-5-git-send-email-frederic@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1525634395-23380-1-git-send-email-frederic@kernel.org> References: <1525634395-23380-1-git-send-email-frederic@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The breakpoint code mixes up attribute check and commit into a single code entity. Therefore the validation may return an error due to incorrect atributes while still leaving halfway modified architecture breakpoint struct. Prepare fox fixing this misdesign and separate both logics. Signed-off-by: Frederic Weisbecker Cc: Linus Torvalds Cc: Andy Lutomirski Cc: Yoshinori Sato Cc: Rich Felker Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Will Deacon Cc: Mark Rutland Cc: Max Filippov Cc: Chris Zankel Cc: Catalin Marinas Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim --- arch/arm/kernel/hw_breakpoint.c | 176 +++++++++++++++++++++++----------------- 1 file changed, 103 insertions(+), 73 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 629e251..1769d3a 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -515,45 +515,33 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, return 0; } -/* - * Construct an arch_hw_breakpoint from a perf_event. - */ -static int arch_build_bp_info(struct perf_event *bp) +static int hw_breakpoint_arch_check(struct perf_event *bp, + const struct perf_event_attr *attr) { - struct arch_hw_breakpoint *info = counter_arch_bp(bp); + u32 offset, alignment_mask = 0x3; + + /* Ensure that we are in monitor debug mode. */ + if (!monitor_mode_enabled()) + return -ENODEV; /* Type */ - switch (bp->attr.bp_type) { + switch (attr->bp_type) { case HW_BREAKPOINT_X: - info->ctrl.type = ARM_BREAKPOINT_EXECUTE; - break; case HW_BREAKPOINT_R: - info->ctrl.type = ARM_BREAKPOINT_LOAD; - break; case HW_BREAKPOINT_W: - info->ctrl.type = ARM_BREAKPOINT_STORE; - break; case HW_BREAKPOINT_RW: - info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; break; default: return -EINVAL; } /* Len */ - switch (bp->attr.bp_len) { + switch (attr->bp_len) { case HW_BREAKPOINT_LEN_1: - info->ctrl.len = ARM_BREAKPOINT_LEN_1; - break; case HW_BREAKPOINT_LEN_2: - info->ctrl.len = ARM_BREAKPOINT_LEN_2; - break; case HW_BREAKPOINT_LEN_4: - info->ctrl.len = ARM_BREAKPOINT_LEN_4; - break; case HW_BREAKPOINT_LEN_8: - info->ctrl.len = ARM_BREAKPOINT_LEN_8; - if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE) + if ((attr->bp_type != HW_BREAKPOINT_X) && max_watchpoint_len >= 8) break; default: @@ -566,50 +554,17 @@ static int arch_build_bp_info(struct perf_event *bp) * by the hardware and must be aligned to the appropriate number of * bytes. */ - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE && - info->ctrl.len != ARM_BREAKPOINT_LEN_2 && - info->ctrl.len != ARM_BREAKPOINT_LEN_4) + if (attr->bp_type == HW_BREAKPOINT_X && + attr->bp_len != HW_BREAKPOINT_LEN_2 && + attr->bp_len != HW_BREAKPOINT_LEN_4) return -EINVAL; - /* Address */ - info->address = bp->attr.bp_addr; - - /* Privilege */ - info->ctrl.privilege = ARM_BREAKPOINT_USER; - if (arch_check_bp_in_kernelspace(bp)) - info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; - - /* Enabled? */ - info->ctrl.enabled = !bp->attr.disabled; - - /* Mismatch */ - info->ctrl.mismatch = 0; - - return 0; -} - -/* - * Validate the arch-specific HW Breakpoint register settings. - */ -int arch_validate_hwbkpt_settings(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - int ret = 0; - u32 offset, alignment_mask = 0x3; - - /* Ensure that we are in monitor debug mode. */ - if (!monitor_mode_enabled()) - return -ENODEV; - - /* Build the arch_hw_breakpoint. */ - ret = arch_build_bp_info(bp); - if (ret) - goto out; - /* Check address alignment. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) + if (attr->bp_len == HW_BREAKPOINT_LEN_8) alignment_mask = 0x7; - offset = info->address & alignment_mask; + + offset = attr->bp_addr & alignment_mask; + switch (offset) { case 0: /* Aligned */ @@ -617,20 +572,16 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) case 1: case 2: /* Allow halfword watchpoints and breakpoints. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) + if (attr->bp_len == HW_BREAKPOINT_LEN_2) break; case 3: /* Allow single byte watchpoint. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) + if (attr->bp_len == HW_BREAKPOINT_LEN_1) break; default: - ret = -EINVAL; - goto out; + return -EINVAL; } - info->address &= ~alignment_mask; - info->ctrl.len <<= offset; - if (is_default_overflow_handler(bp)) { /* * Mismatch breakpoints are required for single-stepping @@ -655,13 +606,92 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) * reports them. */ if (!debug_exception_updates_fsr() && - (info->ctrl.type == ARM_BREAKPOINT_LOAD || - info->ctrl.type == ARM_BREAKPOINT_STORE)) + (attr->bp_type == HW_BREAKPOINT_R || + attr->bp_type == HW_BREAKPOINT_W)) return -EINVAL; } -out: - return ret; + return 0; +} + +static void hw_breakpoint_arch_commit(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + struct perf_event_attr *attr = &bp->attr; + u32 offset, alignment_mask = 0x3; + + /* Type */ + switch (attr->bp_type) { + case HW_BREAKPOINT_X: + info->ctrl.type = ARM_BREAKPOINT_EXECUTE; + break; + case HW_BREAKPOINT_R: + info->ctrl.type = ARM_BREAKPOINT_LOAD; + break; + case HW_BREAKPOINT_W: + info->ctrl.type = ARM_BREAKPOINT_STORE; + break; + case HW_BREAKPOINT_RW: + info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; + break; + default: + WARN_ON_ONCE(1); + } + + /* Len */ + switch (attr->bp_len) { + case HW_BREAKPOINT_LEN_1: + info->ctrl.len = ARM_BREAKPOINT_LEN_1; + break; + case HW_BREAKPOINT_LEN_2: + info->ctrl.len = ARM_BREAKPOINT_LEN_2; + break; + case HW_BREAKPOINT_LEN_4: + info->ctrl.len = ARM_BREAKPOINT_LEN_4; + break; + case HW_BREAKPOINT_LEN_8: + info->ctrl.len = ARM_BREAKPOINT_LEN_8; + break; + default: + WARN_ON_ONCE(1); + } + + /* Address */ + info->address = attr->bp_addr; + + /* Privilege */ + info->ctrl.privilege = ARM_BREAKPOINT_USER; + if (arch_check_bp_in_kernelspace(bp)) + info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; + + /* Enabled? */ + info->ctrl.enabled = !attr->disabled; + + /* Mismatch */ + info->ctrl.mismatch = 0; + + if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) + alignment_mask = 0x7; + + offset = info->address & alignment_mask; + info->address &= ~alignment_mask; + info->ctrl.len <<= offset; +} + +/* + * Validate the arch-specific HW Breakpoint register settings. + */ +int arch_validate_hwbkpt_settings(struct perf_event *bp) +{ + int err; + + err = hw_breakpoint_arch_check(bp, &bp->attr); + if (err) + return err; + + hw_breakpoint_arch_commit(bp); + + return 0; } /* -- 2.7.4