linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
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.

      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