LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland@arm.com>
To: Frederic Weisbecker <frederic@kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>, Jiri Olsa <jolsa@redhat.com>,
Namhyung Kim <namhyung@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Yoshinori Sato <ysato@users.sourceforge.jp>,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Chris Zankel <chris@zankel.net>,
Paul Mackerras <paulus@samba.org>,
Thomas Gleixner <tglx@linutronix.de>,
Will Deacon <will.deacon@arm.com>,
Michael Ellerman <mpe@ellerman.id.au>,
Rich Felker <dalias@libc.org>, Ingo Molnar <mingo@kernel.org>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Andy Lutomirski <luto@kernel.org>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Max Filippov <jcmvbkbc@gmail.com>
Subject: Re: [PATCH 4/9] arm: Split breakpoint validation into "check" and "commit"
Date: Tue, 8 May 2018 12:13:23 +0100 [thread overview]
Message-ID: <20180508111323.mmjo4ky4txzi4gx4@lakrids.cambridge.arm.com> (raw)
In-Reply-To: <1525634395-23380-5-git-send-email-frederic@kernel.org>
Hi Frederick,
On Sun, May 06, 2018 at 09:19:50PM +0200, Frederic Weisbecker wrote:
> 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.
Could you elaborate on what the problem is? I would have expected that
when arch_build_bp_info() returns an error code, we wouldn't
subsequently use the arch_hw_breakpoint information. Where does that
happen?
I understand that there was a problem on x86 -- I'm just having
difficulty figuring it out.
I also see that the check and commit hooks have to duplicate a
reasonable amount of logic, e.g. the switch on bp->attr.type. Can we
instead refactor the existing arch_build_bp_info() hooks to use a
temporary arch_hw_breakpoint, and then struct assign it after all the
error cases, e.g.
static int arch_build_bp_info(struct perf_event *bp)
{
struct arch_hw_breakpoint hbp;
if (some_condition(bp))
hbp->field = 0xf00;
switch (bp->attr.type) {
case FOO:
return -EINVAL;
case BAR:
hbp->other_field = 7;
break;
};
if (failure_case(foo))
return err;
*counter_arch_bp(bp) = hbp;
}
... or is that also problematic?
Thanks,
Mark.
> Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
> Cc: Rich Felker <dalias@libc.org>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Max Filippov <jcmvbkbc@gmail.com>
> Cc: Chris Zankel <chris@zankel.net>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> ---
> 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
>
next prev parent reply other threads:[~2018-05-08 11:13 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-06 19:19 [PATCH 0/9] breakpoint: Rework arch validation Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 1/9] x86/breakpoint: Split validation into "check" and "commit" Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 2/9] sh: Remove "struct arch_hw_breakpoint::name" unused field Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 3/9] sh: Split breakpoint validation into "check" and "commit" Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 4/9] arm: " Frederic Weisbecker
2018-05-08 11:13 ` Mark Rutland [this message]
2018-05-08 11:14 ` Mark Rutland
2018-05-09 11:32 ` Mark Rutland
2018-05-09 19:51 ` Andy Lutomirski
2018-05-11 2:37 ` Frederic Weisbecker
2018-05-15 13:35 ` Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 5/9] xtensa: " Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 6/9] arm64: " Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 7/9] powerpc: " Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 8/9] perf/breakpoint: Split breakpoint " Frederic Weisbecker
2018-05-07 0:46 ` Joel Fernandes
2018-05-15 13:53 ` Frederic Weisbecker
2018-05-15 15:18 ` Joel Fernandes
2018-05-09 9:17 ` Peter Zijlstra
2018-05-15 6:57 ` Ingo Molnar
2018-05-15 13:58 ` Frederic Weisbecker
2018-05-16 3:11 ` Frederic Weisbecker
2018-05-16 4:58 ` Andy Lutomirski
2018-05-19 2:42 ` Frederic Weisbecker
2018-05-06 19:19 ` [PATCH 9/9] perf/breakpoint: Only commit breakpoint to arch upon slot reservation success Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180508111323.mmjo4ky4txzi4gx4@lakrids.cambridge.arm.com \
--to=mark.rutland@arm.com \
--cc=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=benh@kernel.crashing.org \
--cc=catalin.marinas@arm.com \
--cc=chris@zankel.net \
--cc=dalias@libc.org \
--cc=frederic@kernel.org \
--cc=jcmvbkbc@gmail.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@kernel.org \
--cc=mpe@ellerman.id.au \
--cc=namhyung@kernel.org \
--cc=paulus@samba.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=will.deacon@arm.com \
--cc=ysato@users.sourceforge.jp \
--subject='Re: [PATCH 4/9] arm: Split breakpoint validation into "check" and "commit"' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).