mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Kuniyuki Iwashima <kuniyu@google.com>
To: torvalds@linux-foundation.org
Cc: axboe@kernel.dk, brauner@kernel.org, dave.hansen@intel.com,
	 dave.hansen@linux.intel.com, david.laight.linux@gmail.com,
	 edumazet@google.com, kuni1840@gmail.com, kuniyu@google.com,
	 linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] epoll: Use user_write_access_begin() and unsafe_put_user() in epoll_put_uevent().
Date: Tue, 28 Oct 2025 19:25:31 +0000	[thread overview]
Message-ID: <20251028192734.2591319-1-kuniyu@google.com> (raw)
In-Reply-To: <CAHk-=wj7s3VKFP2vLmEHhHZ=VBkr5v8J-Y47uzidnt=Kt+dzng@mail.gmail.com>

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Tue, 28 Oct 2025 12:02:33 -0700
> On Tue, 28 Oct 2025 at 10:56, Kuniyuki Iwashima <kuniyu@google.com> wrote:
> >
> > Let's use user_write_access_begin() and unsafe_put_user() in
> > epoll_put_uevent().
> >
> > We saw 2% more pps with udp_rr by saving a stac/clac pair.
> 
> This patch looks fine to me. Simple and targeted.
> 
> > Another option would be to use can_do_masked_user_access()
> > and masked_user_access_begin(), but we saw 3% regression. (See Link)
> 
> So I find this intriguing, because generally,
> masked_user_access_begin() should _never_ be slower than
> user_write_access_begin().
> 
> user_write_access_begin() ends up doing a __uaccess_begin_nospec() on
> x86, which is not just the STAC instruction, but also a barrier.
> 
> In contrast, masked_user_access_begin() obviously also has the STAC,
> but it avoids the barrier and only uses a simple conditional mask.
> 
> So I get the feeling that you did something wrong. In particular,
> following your link, I see you describe that case (2) as
> 
>   2) masked_user_access_begin() + masked_user_access_begin()
>   97% pps compared to 1).
>   96% calls of ep_try_send_events().
> 
> and you mention masked_user_access_begin() *twice*.

Oh sorry, this was my copy-and-paste mistake, and it should have
been can_do_masked_user_access() + masked_user_access_begin().


> 
> Which would certainly explain why it's slower.
> 
> Can you show what the patch you used is?

I used the diff below as the masked version.

I noticed user_access_begin() is used in "else if ()", but I
think it should not matter as long as tested on x86_64 platform
where can_do_masked_user_access() is true.

So, I think the diff is basically the same with the attached one.

---8<---
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index ccb478eb174b..c530d83f89d0 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -82,11 +82,23 @@ static inline struct epoll_event __user *
 epoll_put_uevent(__poll_t revents, __u64 data,
                 struct epoll_event __user *uevent)
 {
-       if (__put_user(revents, &uevent->events) ||
-           __put_user(data, &uevent->data))
+       if (can_do_masked_user_access()) {
+               uevent = masked_user_access_begin(uevent);
+       } else if (!user_access_begin(uevent, sizeof(*uevent))) {
+               /*
+                * dead branch for __must_check.
+                * ep_check_params() already checked access_ok().
+                */
                return NULL;
-
-       return uevent+1;
+       }
+
+       unsafe_put_user(revents, &uevent->events, efault);
+       unsafe_put_user(data, &uevent->data, efault);
+       user_access_end();
+       return uevent + 1;
+efault:
+       user_access_end();
+       return NULL;
 }
 #endif
 
---8<---


> 
> Because I think the proper patch should look something like the
> attached.. For me, that generates
> 
> 
>         movabs $0x123456789abcdef,%rcx
>         cmp    %rcx,%r15
>         cmova  %rcx,%r15
>         stac
>         mov    %r12d,(%r15)
>         mov    %rax,0x4(%r15)
>         clac
> 
> which honestly should be pretty much optimal.

I had this with the masked version, taken from perf + 'a'.

---8<---
        │       movabs $0x7ffffffff000,%rcx
   0.05 │       cmp    %rcx,%r15
   0.18 │       cmova  %rcx,%r15
  72.69 │       stac
   0.08 │       lea    0x28(%rsp),%r12
   0.09 │       mov    %r14d,(%r15)
   0.06 │       mov    %rax,0x4(%r15)
   6.42 │       clac
---8<---

One possibility that Eric mentioned 2 weeks ago is that cmov
might be expensive on the Zen 2 platform.


> 
> (That 0x123456789abcdef is just a placeholder for the USER_PTR_MAX
> value - it gets rewritten at boot to the right value).
> 
> NOTE! The attached patch has absolutely not been tested. I only used
> it to verify the code generation visually, so you should definitely
> check it yourself.
> 

  parent reply	other threads:[~2025-10-28 19:27 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-28 17:56 Kuniyuki Iwashima
2025-10-28 19:02 ` Linus Torvalds
2025-10-28 19:12   ` Linus Torvalds
2025-10-28 19:25   ` Kuniyuki Iwashima [this message]
2025-10-28 19:44     ` Linus Torvalds

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=20251028192734.2591319-1-kuniyu@google.com \
    --to=kuniyu@google.com \
    --cc=axboe@kernel.dk \
    --cc=brauner@kernel.org \
    --cc=dave.hansen@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=david.laight.linux@gmail.com \
    --cc=edumazet@google.com \
    --cc=kuni1840@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®