From: Peter Xu <peterx@redhat.com>
To: Nadav Amit <nadav.amit@gmail.com>
Cc: Mike Rapoport <rppt@linux.ibm.com>,
John Hubbard <jhubbard@nvidia.com>,
David Hildenbrand <david@redhat.com>,
Linux MM <linux-mm@kvack.org>,
Mike Kravetz <mike.kravetz@oracle.com>,
Hugh Dickins <hughd@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
Axel Rasmussen <axelrasmussen@google.com>
Subject: Re: [PATCH RFC] userfaultfd: introduce UFFDIO_COPY_MODE_YOUNG
Date: Wed, 15 Jun 2022 16:56:02 -0400 [thread overview]
Message-ID: <YqpHYhm5Tz1nH01c@xz-m1.local> (raw)
In-Reply-To: <E0C2E17D-9E76-4638-B3D6-F3D3BA894771@gmail.com>
On Wed, Jun 15, 2022 at 12:42:13PM -0700, Nadav Amit wrote:
> >> (3) also has the downside of stack-protector that would be added due to
> >> stack-protector strong, which is not-that-bad, but I hate it.
> >
> > Any short (but further) explanations?
>
> Sure, but it might not be short.
>
> So one time Mathew Wilcox tried to convert some function arguments into a
> struct that would hold the arguments and transfer it as a single argument,
> and he found out that the binary size actually increased. Since I like to
> waste my time, I analyzed why.
>
> IIRC, there were two main reasons.
>
> The first one is that the kernel by default uses the “strong”
> stack-protector. It means that not all functions would have a stack
> protector, and actually only quite few would. One main reason that you have
> a stack protector is that you provide dereference a local variable. So if
> you have a local struct that hold the arguments - you get a stack protector,
> and it does introduce slight overhead (~10ns IIRC). There may be some pragma
> to prevent the stack protector, but clearly I will be shot if I used it.
>
> The second reason is that the compiler either reloads data from the struct
> you use to hold the arguments or might spill it to the stack if you try to
> cache it.
>
> Consider the following two scenarios:
>
> A. You access an argument multiple times:
>
> local1 = args->arg1;
> another_fn(); // Or some store to the heap
> local2 = args->arg1;
>
> // You use local1 and local2
>
> In this case the compiler would reload args->arg1 from memory, even if there
> is a register that holds the value. The compiler is concerned that another_fn()
> might have overwritten args->arg1 or - in the case of a store - that the value
> was overwritten. The reload might prevent further optimizations of the compiler.
>
> B. You cache the argument locally (aka, you decided to be “smart”):
>
> arg1 = args->arg1;
> local1 = arg1;
> another_fn();
> local2 = arg1;
>
> You may think that this prevents the reload. But this might even be worse.
> The compiler might run out of registers spill arg1 to the stack and then
> access it from the stack. Or it might need to spill something else, or
> shuffle registers around.
>
> So what can you do? You can mark another_fn() as pure if it is so, which
> does help in very certain cases. There are various limitations though. IIRC,
> gcc (or is it clang?) ignores it for inline functions. So if you have an
> inline function which does some write that you don’t care about you cannot
> force the compiler to ignore it.
>
> Note that at least gcc (IIRC) regards inline assembly as something that might
> write to arbitrary memory address. So having BUG_ON() would require a reload
> of the argument from the struct.
Ah, I never knew that side of BUG_ON()..
>
> You may say: “what about the restrict keyword?” Well, this is nice in
> theory, but it does not always help and the implementation of gcc and clang
> are not even the same in this regard. IIRC, in one of them (I forgot which),
> the restrict keyword will prevent the reload if instead another_fn() there
> was a store, but once you call a different function, that compiler says “all
> bets are off, I ignore the restrict” and would reload/spill arg1 (depending
> on A or B).
Thanks, I understand now.
I did a check-up and my most-used distro (fedora) doesn't really have the
strong stack protector enabled.. centos/rhel has.
It seems to me besides the two points you mentioned above to increase the
obj being generated (and also the performance impact), afaiu it also
shrinks the number of vars to push/pop, so even if the lump-sum would be
similar to before there's still a valid reason to have it since it provides
more safety on stack checks.
But I really am not an expert on this so I'd not be able to make any
appropriate conclusion or provide any useful input.. It's just that it'll
not be a question to answer to uffd code but a more general question, as
using a struct pointer to pass over things are really common, afaict, in
not only mm but the Linux repository as a whole.
--
Peter Xu
next prev parent reply other threads:[~2022-06-15 20:56 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-13 20:40 Nadav Amit
2022-06-14 15:22 ` David Hildenbrand
2022-06-14 16:18 ` Nadav Amit
2022-06-14 17:14 ` David Hildenbrand
2022-06-14 18:56 ` Mike Rapoport
2022-06-14 19:25 ` Nadav Amit
2022-06-14 20:40 ` John Hubbard
2022-06-14 20:56 ` Nadav Amit
2022-06-14 21:40 ` John Hubbard
2022-06-14 21:52 ` Nadav Amit
2022-06-14 21:59 ` John Hubbard
2022-06-15 7:26 ` Mike Rapoport
2022-06-15 15:43 ` Peter Xu
2022-06-15 16:58 ` Nadav Amit
2022-06-15 18:39 ` Peter Xu
2022-06-15 19:42 ` Nadav Amit
2022-06-15 20:56 ` Peter Xu [this message]
2022-06-16 5:24 ` Nadav Amit
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=YqpHYhm5Tz1nH01c@xz-m1.local \
--to=peterx@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=david@redhat.com \
--cc=hughd@google.com \
--cc=jhubbard@nvidia.com \
--cc=linux-mm@kvack.org \
--cc=mike.kravetz@oracle.com \
--cc=nadav.amit@gmail.com \
--cc=rppt@linux.ibm.com \
/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