Re: [PATCH v3] perf tests: mmap-basic: fix user rdpmc detection logic

Michael Petlan <[email protected]> Wed, 5 Aug 2026 12:43:49 +0200 (CEST)
Newsgroups org.kernel.vger.linux-perf-users
Message-ID <[email protected]>
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--659969-1385548246-1785926634=:4835
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8BIT

Hi James and Ian,

what do you think about the v3? Can we get it merged? Thanks.

Regards,
Michael

On Wed, 11 Mar 2026, Qiao Zhao wrote:
> Hi James, Ian,
> 
> Just a gentle ping on this patch.
> Could you take a look when convenient?
> 
> Thanks,
> Qiao
> 
> On Thu, Mar 5, 2026 at 11:08 AM Qiao Zhao <[email protected]> wrote:
> >
> > Hi James, Ian,
> >
> > Do you mind reviewing this v3 change?  Thanks a lot!
> >
> > - Qiao
> >
> > On Mon, Mar 2, 2026 at 1:56 PM Qiao Zhao <[email protected]> wrote:
> > >
> > > The mmap-basic test incorrectly determined rdpmc availability in
> > > several environments, leading to unexpected failures on arm64 and
> > > other architectures.
> > >
> > > Previously the rdpmc capability decision lived in test_stat_user_read(),
> > > which caused inconsistent behaviour when:
> > >  - perf_user_access sysctl state is unknown
> > >  - architectures expose cap_user_rdpmc differently
> > >  - arm64 platforms where rdpmc semantics differ from x86
> > >
> > > As suggested during review, move the rdpmc capability decision into
> > > set_user_read() so that the user_read state and expected behavior
> > > are decided in a single place.
> > >
> > > Changes in v3:
> > >  - Moves perf_user_access handling into set_user_read()
> > >  - Simplify test_stat_user_read() expectation logic
> > >  - Use unified rdpmc_supported calculation
> > >  - Handle USER_READ_UNKNOWN consistently
> > >
> > > v2:
> > > https://lore.kernel.org/linux-perf-users/[email protected]/
> > >
> > > Note:
> > > A potential cleanup around perf_event.h mentioned during review is
> > > intentionally deferred and will be handled in a follow-up change
> > > to keep this fix minimal and focused.
> > >
> > > Tested on:
> > >  - ARM64 (armv8_pmuv3): all mmap-basic user-space counter tests pass
> > >  - X86(include hybrid): all mmap-basic tests pass
> > >  - IBM Power9: all mmap-basic tests pass
> > >
> > > Signed-off-by: Qiao Zhao <[email protected]>
> > > ---
> > >  tools/perf/tests/mmap-basic.c | 55 +++++++++++++++++++++++++----------
> > >  1 file changed, 39 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
> > > index 3313c236104e..3633e7c87dc1 100644
> > > --- a/tools/perf/tests/mmap-basic.c
> > > +++ b/tools/perf/tests/mmap-basic.c
> > > @@ -185,38 +185,57 @@ static enum user_read_state set_user_read(struct perf_pmu *pmu, enum user_read_s
> > >  {
> > >         char buf[2] = {0, '\n'};
> > >         ssize_t len;
> > > -       int events_fd, rdpmc_fd;
> > > +       int events_fd, fd;
> > >         enum user_read_state old_user_read = USER_READ_UNKNOWN;
> > >
> > >         if (enabled == USER_READ_UNKNOWN)
> > >                 return USER_READ_UNKNOWN;
> > >
> > > +       // Try the PMU rdpmc sysfs interface or similar
> > >         events_fd = perf_pmu__event_source_devices_fd();
> > > -       if (events_fd < 0)
> > > -               return USER_READ_UNKNOWN;
> > > -
> > > -       rdpmc_fd = perf_pmu__pathname_fd(events_fd, pmu->name, "rdpmc", O_RDWR);
> > > -       if (rdpmc_fd < 0) {
> > > +       if (events_fd >= 0) {
> > > +               fd = perf_pmu__pathname_fd(events_fd, pmu->name, "rdpmc", O_RDWR);
> > > +               if (fd >= 0) {
> > > +                       len = read(fd, buf, sizeof(buf));
> > > +                       if (len == sizeof(buf))
> > > +                               old_user_read = (buf[0] == '1') ?
> > > +                                       USER_READ_ENABLED :
> > > +                                       USER_READ_DISABLED;
> > > +
> > > +                       if (enabled != old_user_read) {
> > > +                               buf[0] = (enabled == USER_READ_ENABLED) ? '1' : '0';
> > > +                               len = write(fd, buf, sizeof(buf));
> > > +                               if (len != sizeof(buf))
> > > +                                       pr_debug("%s write failed\n", __func__);
> > > +                       }
> > > +                       close(fd);
> > > +                       close(events_fd);
> > > +                       return old_user_read;
> > > +               }
> > >                 close(events_fd);
> > > -               return USER_READ_UNKNOWN;
> > >         }
> > >
> > > -       len = read(rdpmc_fd, buf, sizeof(buf));
> > > -       if (len != sizeof(buf))
> > > -               pr_debug("%s read failed\n", __func__);
> > > +       // Fallback: perf_user_access interface (arm64, riscv, or similar)
> > > +       fd = open("/proc/sys/kernel/perf_user_access", O_RDWR);
> > > +       if (fd < 0)
> > > +               return USER_READ_UNKNOWN;
> > >
> > >         // Note, on Intel hybrid disabling on 1 PMU will implicitly disable on
> > >         // all the core PMUs.
> > > -       old_user_read = (buf[0] == '1') ? USER_READ_ENABLED : USER_READ_DISABLED;
> > > +       len = read(fd, buf, sizeof(buf));
> > > +       if (len == sizeof(buf))
> > > +               old_user_read = (buf[0] == '1') ?
> > > +                       USER_READ_ENABLED :
> > > +                       USER_READ_DISABLED;
> > >
> > >         if (enabled != old_user_read) {
> > >                 buf[0] = (enabled == USER_READ_ENABLED) ? '1' : '0';
> > > -               len = write(rdpmc_fd, buf, sizeof(buf));
> > > +               len = write(fd, buf, sizeof(buf));
> > >                 if (len != sizeof(buf))
> > >                         pr_debug("%s write failed\n", __func__);
> > >         }
> > > -       close(rdpmc_fd);
> > > -       close(events_fd);
> > > +
> > > +       close(fd);
> > >         return old_user_read;
> > >  }
> > >
> > > @@ -295,12 +314,16 @@ static int test_stat_user_read(u64 event, enum user_read_state enabled)
> > >                         goto cleanup;
> > >                 }
> > >
> > > +#if defined(__aarch64__) || defined(__riscv)
> > > +               rdpmc_supported = pc->cap_user_rdpmc;
> > > +#else
> > >                 if (saved_user_read_state == USER_READ_UNKNOWN)
> > > -                       rdpmc_supported = pc->cap_user_rdpmc && pc->index;
> > > +                       rdpmc_supported = pc->cap_user_rdpmc;
> > >                 else
> > >                         rdpmc_supported = (enabled == USER_READ_ENABLED);
> > > +#endif
> > >
> > > -               if (rdpmc_supported && (!pc->cap_user_rdpmc || !pc->index)) {
> > > +               if (rdpmc_supported && !pc->cap_user_rdpmc) {
> > >                         pr_err("User space counter reading for PMU %s [Failed unexpected supported counter access %d %d]\n",
> > >                                 pmu->name, pc->cap_user_rdpmc, pc->index);
> > >                         ret = TEST_FAIL;
> > > --
> > > 2.49.0
> > >
> 
> 
--659969-1385548246-1785926634=:4835--