On Thu, Apr 15, 2021 at 10:48AM +0200, Peter Zijlstra wrote:
On Wed, Apr 14, 2021 at 04:33:22PM +0200, Marco Elver wrote:
> On Wed, Apr 14, 2021 at 10:10PM +0800, kernel test robot wrote:
> > tree:
https://git.kernel.org/pub/scm/linux/kernel/git/peterz/queue.git
perf/core
> > head: 0da503cd07380952599b67ded6efe030d78ea42d
> > commit: c7d4112e9f0e69edd649665836ce72008b95ab9f [18/22] perf: Add support for
SIGTRAP on perf events
> [...]
> > If you fix the issue, kindly add following tag as appropriate
> > Reported-by: kernel test robot <lkp(a)intel.com>
> [...]
> > 6416 info.si_errno = event->attr.type;
> > 6417 info.si_perf = event->attr.sig_data;
> > > 6418 info.si_addr = (void *)event->sig_addr;
> > 6419 force_sig_info(&info);
>
> I think it wants the below (feel free to squash into "perf: Add support
> for SIGTRAP on perf events").
>
> Thanks,
> -- Marco
>
[...]
Now the silly robot complains about:
CC kernel/events/core.o
../kernel/events/core.c: In function ‘perf_sigtrap’:
../kernel/events/core.c:6418:17: warning: cast to pointer from integer of different size
[-Wint-to-pointer-cast]
6418 | info.si_addr = (void __user *)event->sig_addr;
for all 32bit builds (because sig_addr is u64 and the pointer cast
truncates bits).
This had me look a little harder at sig_addr and I figured it should be
next to the pending fields for cache locality.
I've ended up with the below delta, does that work for you?
Thanks, that works for me. Do note that I explicitly chose u64 for
sig_addr/pending_addr because data->addr is u64. There might be a new
warning about the u64 to unsigned long assignment on 32 bit arches.
Perhaps it needs something ugly like this:
info.si_addr = (void __user *)(unsigned long)event->pending_addr;
if pending_addr wants to be u64. Or just
event->pending_addr = (unsigned long)data->addr;
if data->addr being u64 on 32 bit arches is simply overkill.
Thanks,
-- Marco
> ---
>
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -735,6 +735,7 @@ struct perf_event {
> int pending_wakeup;
> int pending_kill;
> int pending_disable;
> + unsigned long pending_addr; /* SIGTRAP */
> struct irq_work pending;
>
> atomic_t event_limit;
> @@ -778,9 +779,6 @@ struct perf_event {
> void *security;
> #endif
> struct list_head sb_list;
> -
> - /* Address associated with event, which can be passed to siginfo_t. */
> - u64 sig_addr;
> #endif /* CONFIG_PERF_EVENTS */
> };
>
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -6415,7 +6415,7 @@ static void perf_sigtrap(struct perf_eve
> info.si_code = TRAP_PERF;
> info.si_errno = event->attr.type;
> info.si_perf = event->attr.sig_data;
> - info.si_addr = (void __user *)event->sig_addr;
> + info.si_addr = (void __user *)event->pending_addr;
> force_sig_info(&info);
> }
>
> @@ -9137,7 +9137,7 @@ static int __perf_event_overflow(struct
> if (events && atomic_dec_and_test(&event->event_limit)) {
> ret = 1;
> event->pending_kill = POLL_HUP;
> - event->sig_addr = data->addr;
> + event->pending_addr = data->addr;
>
> perf_event_disable_inatomic(event);
> }