From: Nadav Amit <nadav.amit@gmail.com>
To: Peter Xu <peterx@redhat.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 22:24:26 -0700 [thread overview]
Message-ID: <ACE999B2-6BF0-46EF-9830-9FC3E1F1282A@gmail.com> (raw)
In-Reply-To: <YqpHYhm5Tz1nH01c@xz-m1.local>
On Jun 15, 2022, at 1:56 PM, Peter Xu <peterx@redhat.com> wrote:
> 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()..
I was wrong about this part. Actually BUG_ON() does not have this effect.
Sorry for misleading you.
prev parent reply other threads:[~2022-06-16 5:24 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
2022-06-16 5:24 ` Nadav Amit [this message]
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=ACE999B2-6BF0-46EF-9830-9FC3E1F1282A@gmail.com \
--to=nadav.amit@gmail.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=peterx@redhat.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