From: Rob Herring <robh@kernel.org> Date: 2021-07-28 23:02:39
This series is preparation for supporting perf user counter access on arm64.
Originally, the arm64 implementation was just a copy of the x86 version, but
Will did not like the mm_context state tracking nor the IPIs (mm_cpumask
doesn't work for arm64). The hook into switch_mm and the IPIs feel like
working around limitations in the perf core (aka the platform problem).
So this series aims to solve that such that all the state for RDPMC is
tracked and controlled via the perf core.
Alternatively, I could avoid all the x86 changes here with a new PMU
callback (.set_user_access()?) and plumb that into the perf core context
and mmap code. However, it's better in the long run if there's a common
implementation.
So far, I've only tested the perf core changes with the arm64 version of
the code which is similar to the x86 version here. I'm hoping for some
quick feedback on the direction here and whether I've missed some usecase
that isn't handled.
Rob
Rob Herring (3):
x86: perf: Move RDPMC event flag to a common definition
perf/x86: Control RDPMC access from .enable() hook
perf/x86: Call mmap event callbacks on event's CPU
arch/x86/events/core.c | 113 +++++++++++++++--------------
arch/x86/events/perf_event.h | 2 +-
arch/x86/include/asm/mmu.h | 1 -
arch/x86/include/asm/mmu_context.h | 6 --
arch/x86/include/asm/perf_event.h | 1 -
arch/x86/mm/tlb.c | 29 +-------
include/linux/perf_event.h | 9 ++-
kernel/events/core.c | 56 +++++++++++---
8 files changed, 113 insertions(+), 104 deletions(-)
--
2.27.0
From: Rob Herring <robh@kernel.org> Date: 2021-07-28 23:02:44
In preparation to enable user counter access on arm64 and to move some
of the user access handling to perf core, create a common event flag for
user counter access and convert x86 to use it.
Since the architecture specific flags start at the LSB, starting at the
MSB for common flags.
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <redacted>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Kan Liang <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Borislav Petkov <bp@alien8.de>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-perf-users@vger.kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
arch/x86/events/core.c | 10 +++++-----
arch/x86/events/perf_event.h | 2 +-
include/linux/perf_event.h | 2 ++
3 files changed, 8 insertions(+), 6 deletions(-)
From: Rob Herring <robh@kernel.org> Date: 2021-07-28 23:02:46
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <redacted>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: Borislav Petkov <bp@alien8.de>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
Not sure, but I think the set_attr_rdpmc() IPI needs to hold the perf
ctx lock?
arch/x86/events/core.c | 75 +++++++++++++++++++-----------
arch/x86/include/asm/mmu_context.h | 6 ---
arch/x86/include/asm/perf_event.h | 1 -
arch/x86/mm/tlb.c | 29 +-----------
4 files changed, 49 insertions(+), 62 deletions(-)
@@ -727,11 +727,52 @@ static void x86_pmu_disable(struct pmu *pmu)static_call(x86_pmu_disable_all)();}+staticvoidperf_clear_dirty_counters(structcpu_hw_events*cpuc)+{+inti;++/* Don't need to clear the assigned counter. */+for(i=0;i<cpuc->n_events;i++)+__clear_bit(cpuc->assign[i],cpuc->dirty);++if(bitmap_empty(cpuc->dirty,X86_PMC_IDX_MAX))+return;++for_each_set_bit(i,cpuc->dirty,X86_PMC_IDX_MAX){+/* Metrics and fake events don't have corresponding HW counters. */+if(is_metric_idx(i)||(i==INTEL_PMC_IDX_FIXED_VLBR))+continue;+elseif(i>=INTEL_PMC_IDX_FIXED)+wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0+(i-INTEL_PMC_IDX_FIXED),0);+else+wrmsrl(x86_pmu_event_addr(i),0);+}++bitmap_zero(cpuc->dirty,X86_PMC_IDX_MAX);+}++staticvoidx86_pmu_set_user_access(structcpu_hw_events*cpuc)+{+if(static_branch_unlikely(&rdpmc_always_available_key)||+(!static_branch_unlikely(&rdpmc_never_available_key)&&+atomic_read(&(this_cpu_read(cpu_tlbstate.loaded_mm)->context.perf_rdpmc_allowed)))){+/*+*Cleartheexistingdirtycountersto+*preventtheleakforanRDPMCtask.+*/+perf_clear_dirty_counters(cpuc);+cr4_set_bits_irqsoff(X86_CR4_PCE);+}else+cr4_clear_bits_irqsoff(X86_CR4_PCE);+}+voidx86_pmu_enable_all(intadded){structcpu_hw_events*cpuc=this_cpu_ptr(&cpu_hw_events);intidx;+x86_pmu_set_user_access(cpuc);+for(idx=0;idx<x86_pmu.num_counters;idx++){structhw_perf_event*hwc=&cpuc->events[idx]->hw;
@@ -2476,29 +2517,9 @@ static int x86_pmu_event_init(struct perf_event *event)returnerr;}-voidperf_clear_dirty_counters(void)+staticvoidx86_pmu_set_user_access_ipi(void*unused){-structcpu_hw_events*cpuc=this_cpu_ptr(&cpu_hw_events);-inti;--/* Don't need to clear the assigned counter. */-for(i=0;i<cpuc->n_events;i++)-__clear_bit(cpuc->assign[i],cpuc->dirty);--if(bitmap_empty(cpuc->dirty,X86_PMC_IDX_MAX))-return;--for_each_set_bit(i,cpuc->dirty,X86_PMC_IDX_MAX){-/* Metrics and fake events don't have corresponding HW counters. */-if(is_metric_idx(i)||(i==INTEL_PMC_IDX_FIXED_VLBR))-continue;-elseif(i>=INTEL_PMC_IDX_FIXED)-wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0+(i-INTEL_PMC_IDX_FIXED),0);-else-wrmsrl(x86_pmu_event_addr(i),0);-}--bitmap_zero(cpuc->dirty,X86_PMC_IDX_MAX);+x86_pmu_set_user_access(this_cpu_ptr(&cpu_hw_events));}staticvoidx86_pmu_event_mapped(structperf_event*event,structmm_struct*mm)
From: Rob Herring <robh@kernel.org> Date: 2021-07-28 23:02:51
Mark suggested that mmapping of events should be treated like other
event changes in that the PMU callbacks run on the CPU the event is on.
Given that the only implementation of .event_(un)mapped() (on x86) end up
running on each CPU, this makes sense.
Since the .event_(un)mapped() callbacks are now called on multiple CPUs,
the tracking of enabling RDPMC is moved to the context in the perf core.
This allows removing perf_rdpmc_allowed, and for arm64 to share the same
user access tracking.
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <redacted>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Kan Liang <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Borislav Petkov <bp@alien8.de>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-perf-users@vger.kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
Note that the intent here is to only call event_mapped() on the first mmap
and event_unmapped on the last unmapping using the event->mmap_count. I'm
not sure if there's some flaw with that idea?
arch/x86/events/core.c | 38 +++++++-------------------
arch/x86/include/asm/mmu.h | 1 -
include/linux/perf_event.h | 7 +++--
kernel/events/core.c | 56 ++++++++++++++++++++++++++++++++------
4 files changed, 61 insertions(+), 41 deletions(-)
@@ -46,7 +46,6 @@ typedef struct {void__user*vdso;/* vdso base address */conststructvdso_image*vdso_image;/* vdso image in use */-atomic_tperf_rdpmc_allowed;/* nonzero if rdpmc is allowed */#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS/**Onebitperprotectionkeysayswhetheruserspacecan
From: Andy Lutomirski <luto@kernel.org> Date: 2021-08-12 16:50:47
On 7/28/21 4:02 PM, Rob Herring wrote:
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Is this series supposed to be a user-visible change or not? I'm confused.
If you intend to have an entire mm have access to RDPMC if an event is
mapped, then surely access needs to be context switched for the whole
mm. If you intend to only have the thread to which the event is bound
have access, then the only reason I see to use IPIs is to revoke access
on munmap from the wrong thread. But even that latter case could be
handled with a more targeted approach, not a broadcast to all of mm_cpumask.
Can you clarify what the overall intent is and what this particular
patch is trying to do?
From: Rob Herring <robh@kernel.org> Date: 2021-08-12 18:16:59
On Thu, Aug 12, 2021 at 11:50 AM Andy Lutomirski [off-list ref] wrote:
On 7/28/21 4:02 PM, Rob Herring wrote:
quoted
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Is this series supposed to be a user-visible change or not? I'm confused.
It should not be user-visible. Or at least not user-visible for what
any user would notice. If an event is not part of the perf context on
another thread sharing the mm, does that thread need rdpmc access? No
access would be a user-visible change, but I struggle with how that's
a useful scenario?
If you intend to have an entire mm have access to RDPMC if an event is
mapped, then surely access needs to be context switched for the whole
mm. If you intend to only have the thread to which the event is bound
have access, then the only reason I see to use IPIs is to revoke access
on munmap from the wrong thread. But even that latter case could be
handled with a more targeted approach, not a broadcast to all of mm_cpumask.
Right, that's what patch 3 does. When we mmap/munmap an event, then
the perf core invokes the callback only on the active contexts in
which the event resides.
Can you clarify what the overall intent is and what this particular
patch is trying to do?
But if you remove this, then what handles context switching?
perf. On a context switch, perf is going to context switch the events
and set the access based on an event in the context being mmapped.
Though I guess if rdpmc needs to be enabled without any events opened,
this is not going to work. So maybe I need to keep the
rdpmc_always_available_key and rdpmc_never_available_key cases here.
The always available case is something we specifically don't want to
support for arm64. I'm trying to start with access more locked down,
rather than trying to lock it down after the fact as x86 is doing.
Rob
On Thu, Aug 12, 2021, at 11:16 AM, Rob Herring wrote:
On Thu, Aug 12, 2021 at 11:50 AM Andy Lutomirski [off-list ref] wrote:
quoted
On 7/28/21 4:02 PM, Rob Herring wrote:
quoted
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Is this series supposed to be a user-visible change or not? I'm confused.
It should not be user-visible. Or at least not user-visible for what
any user would notice. If an event is not part of the perf context on
another thread sharing the mm, does that thread need rdpmc access? No
access would be a user-visible change, but I struggle with how that's
a useful scenario?
This is what I mean by user-visible -- it changes semantics in a way that a user program could detect. I'm not saying it's a problem, but I do think you need to document the new semantics.
quoted
If you intend to have an entire mm have access to RDPMC if an event is
mapped, then surely access needs to be context switched for the whole
mm. If you intend to only have the thread to which the event is bound
have access, then the only reason I see to use IPIs is to revoke access
on munmap from the wrong thread. But even that latter case could be
handled with a more targeted approach, not a broadcast to all of mm_cpumask.
Right, that's what patch 3 does. When we mmap/munmap an event, then
the perf core invokes the callback only on the active contexts in
which the event resides.
quoted
Can you clarify what the overall intent is and what this particular
patch is trying to do?
But if you remove this, then what handles context switching?
perf. On a context switch, perf is going to context switch the events
and set the access based on an event in the context being mmapped.
Though I guess if rdpmc needs to be enabled without any events opened,
this is not going to work. So maybe I need to keep the
rdpmc_always_available_key and rdpmc_never_available_key cases here.
You seem to have a weird combination of per-thread and per-mm stuff going on in this patch, though. Maybe it's all reasonable after patch 3 is applied, but this patch is very hard to review in its current state.
From: Rob Herring <robh@kernel.org> Date: 2021-08-26 19:09:30
On Thu, Aug 26, 2021 at 1:13 PM Andy Lutomirski [off-list ref] wrote:
On Thu, Aug 12, 2021, at 11:16 AM, Rob Herring wrote:
quoted
On Thu, Aug 12, 2021 at 11:50 AM Andy Lutomirski [off-list ref] wrote:
quoted
On 7/28/21 4:02 PM, Rob Herring wrote:
quoted
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Is this series supposed to be a user-visible change or not? I'm confused.
It should not be user-visible. Or at least not user-visible for what
any user would notice. If an event is not part of the perf context on
another thread sharing the mm, does that thread need rdpmc access? No
access would be a user-visible change, but I struggle with how that's
a useful scenario?
This is what I mean by user-visible -- it changes semantics in a way that a user program could detect. I'm not saying it's a problem, but I do think you need to document the new semantics.
After testing some scenarios and finding perf_event_tests[1], this
series isn't going to work for x86 unless rdpmc is restricted to task
events only or allowed to segfault on CPU events when read on the
wrong CPU rather than just returning garbage. It's been discussed
before here[2].
Ultimately, I'm just trying to define the behavior for arm64 where we
don't have an existing ABI to maintain and don't have to recreate the
mistakes of x86 rdpmc ABI. Tying the access to mmap is messy. As we
explicitly request user access on perf_event_open(), I think it may be
better to just enable access when the event's context is active and
ignore mmap(). Maybe you have an opinion there since you added the
mmap() part?
Rob
[1] https://github.com/deater/perf_event_tests
[2] https://lore.kernel.org/lkml/alpine.DEB.2.21.1901101229010.3358@macbook-air/
On Thu, Aug 26, 2021, at 12:09 PM, Rob Herring wrote:
On Thu, Aug 26, 2021 at 1:13 PM Andy Lutomirski [off-list ref] wrote:
quoted
On Thu, Aug 12, 2021, at 11:16 AM, Rob Herring wrote:
quoted
On Thu, Aug 12, 2021 at 11:50 AM Andy Lutomirski [off-list ref] wrote:
quoted
On 7/28/21 4:02 PM, Rob Herring wrote:
quoted
Rather than controlling RDPMC access behind the scenes from switch_mm(),
move RDPMC access controls to the PMU .enable() hook. The .enable() hook
is called whenever the perf CPU or task context changes which is when
the RDPMC access may need to change.
This is the first step in moving the RDPMC state tracking out of the mm
context to the perf context.
Is this series supposed to be a user-visible change or not? I'm confused.
It should not be user-visible. Or at least not user-visible for what
any user would notice. If an event is not part of the perf context on
another thread sharing the mm, does that thread need rdpmc access? No
access would be a user-visible change, but I struggle with how that's
a useful scenario?
This is what I mean by user-visible -- it changes semantics in a way that a user program could detect. I'm not saying it's a problem, but I do think you need to document the new semantics.
After testing some scenarios and finding perf_event_tests[1], this
series isn't going to work for x86 unless rdpmc is restricted to task
events only or allowed to segfault on CPU events when read on the
wrong CPU rather than just returning garbage. It's been discussed
before here[2].
Ultimately, I'm just trying to define the behavior for arm64 where we
don't have an existing ABI to maintain and don't have to recreate the
mistakes of x86 rdpmc ABI. Tying the access to mmap is messy. As we
explicitly request user access on perf_event_open(), I think it may be
better to just enable access when the event's context is active and
ignore mmap(). Maybe you have an opinion there since you added the
mmap() part?
That makes sense to me. The mmap() part was always a giant kludge.
There is fundamentally a race, at least if rseq isn’t used: if you check that you’re on the right CPU, do RDPMC, and throw out the result if you were on the wrong CPU (determined by looking at the mmap), you still would very much prefer not to fault.
Maybe rseq or a vDSO helper is the right solution for ARM.
On Thu, Aug 26, 2021, at 12:09 PM, Rob Herring wrote:
quoted
After testing some scenarios and finding perf_event_tests[1], this
series isn't going to work for x86 unless rdpmc is restricted to task
events only or allowed to segfault on CPU events when read on the
wrong CPU rather than just returning garbage. It's been discussed
before here[2].
Ultimately, I'm just trying to define the behavior for arm64 where we
don't have an existing ABI to maintain and don't have to recreate the
mistakes of x86 rdpmc ABI. Tying the access to mmap is messy. As we
explicitly request user access on perf_event_open(), I think it may be
better to just enable access when the event's context is active and
ignore mmap(). Maybe you have an opinion there since you added the
mmap() part?
That makes sense to me. The mmap() part was always a giant kludge.
There is fundamentally a race, at least if rseq isn’t used: if you check
that you’re on the right CPU, do RDPMC, and throw out the result if you
were on the wrong CPU (determined by looking at the mmap), you still
would very much prefer not to fault.
Maybe rseq or a vDSO helper is the right solution for ARM.
as the author of those perf_event tests for rdpmc, I have to say if ARM
comes up with a cleaner implementation I'd be glad to have x86 transition
to something better.
The rdpmc code is a huge mess and has all kinds of corner cases. I'm not
sure anyone besides the PAPI library tries to use it, and while it's a
nice performance improvement to use rdpmc it is really hard to get things
working right.
As a PAPI developer we actually have run into the issue where the CPU
switches and we were reporting the wrong results. Also if I recall (it's
been a while) we were having issues where the setup lets you attach to a
process on another CPU for monitoring using the rdpmc interface and it
returns results even though I think that will rarely ever work in
practice.
Vince
From: Peter Zijlstra <peterz@infradead.org> Date: 2021-08-30 08:52:30
On Sun, Aug 29, 2021 at 11:05:55PM -0400, Vince Weaver wrote:
as the author of those perf_event tests for rdpmc, I have to say if ARM
comes up with a cleaner implementation I'd be glad to have x86 transition
to something better.
The rdpmc code is a huge mess and has all kinds of corner cases. I'm not
sure anyone besides the PAPI library tries to use it, and while it's a
nice performance improvement to use rdpmc it is really hard to get things
working right.
As a PAPI developer we actually have run into the issue where the CPU
switches and we were reporting the wrong results. Also if I recall (it's
been a while) we were having issues where the setup lets you attach to a
process on another CPU for monitoring using the rdpmc interface and it
returns results even though I think that will rarely ever work in
practice.
There's just not much we can do to validate the usage, fundamentally at
RDPMC time we're not running any kernel code, so we can't validate the
conditions under which we're called.
I suppose one way would be to create a mode where RDPMC is disabled but
emulated -- which completely voids the reason for using RDPMC in the
first place (performance), but would allow us to validate the usage.
Fundamentally, we must call RDPMC only for events that are currently
actuve on *this* CPU. Currently we rely on userspace to DTRT and if it
doesn't we have no way of knowing and it gets to keep the pieces.
There's just not much we can do to validate the usage, fundamentally at
RDPMC time we're not running any kernel code, so we can't validate the
conditions under which we're called.
I suppose one way would be to create a mode where RDPMC is disabled but
emulated -- which completely voids the reason for using RDPMC in the
first place (performance), but would allow us to validate the usage.
Fundamentally, we must call RDPMC only for events that are currently
actuve on *this* CPU. Currently we rely on userspace to DTRT and if it
doesn't we have no way of knowing and it gets to keep the pieces.
yes, though it would be nice for cases where things will never work (such
as process-attach? I think even if pinned to the same CPU that won't
work?) Maybe somehow the mmap page could be set in a way to indicate we
should fall back to the syscall. Maybe set pc->index to an invalid value
so we can use the existing syscall fallback code.
We could force every userspace program to know allthe unsupoorted cases
but it seems like it could be easier and less failure-prone to centralize
this in the kernel.
I was looking into maybe creating a patch for this but the magic perf
mmap page implementation is complex enough that I'm not sure I'm qualified
to mess with it.
Vince
From: Rob Herring <robh@kernel.org> Date: 2021-08-30 20:58:44
On Sun, Aug 29, 2021 at 10:06 PM Vince Weaver [off-list ref] wrote:
On Fri, 27 Aug 2021, Andy Lutomirski wrote:
quoted
On Thu, Aug 26, 2021, at 12:09 PM, Rob Herring wrote:
quoted
quoted
After testing some scenarios and finding perf_event_tests[1], this
series isn't going to work for x86 unless rdpmc is restricted to task
events only or allowed to segfault on CPU events when read on the
wrong CPU rather than just returning garbage. It's been discussed
before here[2].
Ultimately, I'm just trying to define the behavior for arm64 where we
don't have an existing ABI to maintain and don't have to recreate the
mistakes of x86 rdpmc ABI. Tying the access to mmap is messy. As we
explicitly request user access on perf_event_open(), I think it may be
better to just enable access when the event's context is active and
ignore mmap(). Maybe you have an opinion there since you added the
mmap() part?
That makes sense to me. The mmap() part was always a giant kludge.
There is fundamentally a race, at least if rseq isn’t used: if you check
that you’re on the right CPU, do RDPMC, and throw out the result if you
were on the wrong CPU (determined by looking at the mmap), you still
would very much prefer not to fault.
Maybe rseq or a vDSO helper is the right solution for ARM.
There was a version using rseq[1]. AIUI, that would solve the reading
from the wrong CPU problem. I don't think using rseq would change the
kernel implementation other than whether we enable events on specific
CPUs.
as the author of those perf_event tests for rdpmc, I have to say if ARM
comes up with a cleaner implementation I'd be glad to have x86 transition
to something better.
Thanks for chiming in.
My plan is to be more restricted in terms of what works, and fail or
disable user access for what's not supported. Unless I hear events on
specific CPUs is really important, that means only monitoring of a
thread on all (for big.LITTLE, all homogeneous) CPUs is supported.
That doesn't require a better/cleaner interface. It just means cpu
must be -1 for perf_event_open if you want rdpmc. The difference on
Arm is just that we can enforce/indicate that.
We could also enable CPU events, but abort if read on the wrong CPU.
The user in that case either has to control the thread affinity or
possibly use rseq.
The rdpmc code is a huge mess and has all kinds of corner cases. I'm not
sure anyone besides the PAPI library tries to use it, and while it's a
nice performance improvement to use rdpmc it is really hard to get things
working right.
Yes, I've been reading thru the bugs you reported and related tests. I
just wish I found them sooner...
As a PAPI developer we actually have run into the issue where the CPU
switches and we were reporting the wrong results. Also if I recall (it's
been a while) we were having issues where the setup lets you attach to a
process on another CPU for monitoring using the rdpmc interface and it
returns results even though I think that will rarely ever work in
practice.
From: Rob Herring <robh@kernel.org> Date: 2021-08-30 21:40:50
On Mon, Aug 30, 2021 at 3:21 PM Vince Weaver [off-list ref] wrote:
On Mon, 30 Aug 2021, Peter Zijlstra wrote:
quoted
There's just not much we can do to validate the usage, fundamentally at
RDPMC time we're not running any kernel code, so we can't validate the
conditions under which we're called.
I suppose one way would be to create a mode where RDPMC is disabled but
emulated -- which completely voids the reason for using RDPMC in the
first place (performance), but would allow us to validate the usage.
Fundamentally, we must call RDPMC only for events that are currently
actuve on *this* CPU. Currently we rely on userspace to DTRT and if it
doesn't we have no way of knowing and it gets to keep the pieces.
yes, though it would be nice for cases where things will never work (such
as process-attach? I think even if pinned to the same CPU that won't
work?) Maybe somehow the mmap page could be set in a way to indicate we
should fall back to the syscall. Maybe set pc->index to an invalid value
so we can use the existing syscall fallback code.
We could force every userspace program to know allthe unsupoorted cases
but it seems like it could be easier and less failure-prone to centralize
this in the kernel.
I was looking into maybe creating a patch for this but the magic perf
mmap page implementation is complex enough that I'm not sure I'm qualified
to mess with it.