linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: David Hildenbrand <david@redhat.com>
To: Ryan Roberts <ryan.roberts@arm.com>,
	Barry Song <21cnbao@gmail.com>,
	Steven Price <steven.price@arm.com>
Cc: akpm@linux-foundation.org, catalin.marinas@arm.com,
	will@kernel.org, linux-kernel@vger.kernel.org,
	linux-mm@kvack.org, mhocko@suse.com, shy828301@gmail.com,
	v-songbaohua@oppo.com, wangkefeng.wang@huawei.com,
	willy@infradead.org, xiang@kernel.org, ying.huang@intel.com,
	yuzhao@google.com
Subject: Re: [RFC V3 PATCH] arm64: mm: swap: save and restore mte tags for large folios
Date: Mon, 27 Nov 2023 13:01:07 +0100	[thread overview]
Message-ID: <c5c82611-3153-4d56-b799-a1df3c953efe@redhat.com> (raw)
In-Reply-To: <679a144a-db47-4d05-bbf7-b6a0514f5ed0@arm.com>

On 27.11.23 12:56, Ryan Roberts wrote:
> On 24/11/2023 18:14, Barry Song wrote:
>> On Fri, Nov 24, 2023 at 10:55 PM Steven Price <steven.price@arm.com> wrote:
>>>
>>> On 24/11/2023 09:01, Ryan Roberts wrote:
>>>> On 24/11/2023 08:55, David Hildenbrand wrote:
>>>>> On 24.11.23 02:35, Barry Song wrote:
>>>>>> On Mon, Nov 20, 2023 at 11:57 PM Ryan Roberts <ryan.roberts@arm.com> wrote:
>>>>>>>
>>>>>>> On 20/11/2023 09:11, David Hildenbrand wrote:
>>>>>>>> On 17.11.23 19:41, Barry Song wrote:
>>>>>>>>> On Fri, Nov 17, 2023 at 7:28 PM David Hildenbrand <david@redhat.com> wrote:
>>>>>>>>>>
>>>>>>>>>> On 17.11.23 01:15, Barry Song wrote:
>>>>>>>>>>> On Fri, Nov 17, 2023 at 7:47 AM Barry Song <21cnbao@gmail.com> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> On Thu, Nov 16, 2023 at 5:36 PM David Hildenbrand <david@redhat.com> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 15.11.23 21:49, Barry Song wrote:
>>>>>>>>>>>>>> On Wed, Nov 15, 2023 at 11:16 PM David Hildenbrand <david@redhat.com>
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 14.11.23 02:43, Barry Song wrote:
>>>>>>>>>>>>>>>> This patch makes MTE tags saving and restoring support large folios,
>>>>>>>>>>>>>>>> then we don't need to split them into base pages for swapping out
>>>>>>>>>>>>>>>> on ARM64 SoCs with MTE.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> arch_prepare_to_swap() should take folio rather than page as parameter
>>>>>>>>>>>>>>>> because we support THP swap-out as a whole.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Meanwhile, arch_swap_restore() should use page parameter rather than
>>>>>>>>>>>>>>>> folio as swap-in always works at the granularity of base pages right
>>>>>>>>>>>>>>>> now.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> ... but then we always have order-0 folios and can pass a folio, or what
>>>>>>>>>>>>>>> am I missing?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Hi David,
>>>>>>>>>>>>>> you missed the discussion here:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> https://lore.kernel.org/lkml/CAGsJ_4yXjex8txgEGt7+WMKp4uDQTn-fR06ijv4Ac68MkhjMDw@mail.gmail.com/
>>>>>>>>>>>>>> https://lore.kernel.org/lkml/CAGsJ_4xmBAcApyK8NgVQeX_Znp5e8D4fbbhGguOkNzmh1Veocg@mail.gmail.com/
>>>>>>>>>>>>>
>>>>>>>>>>>>> Okay, so you want to handle the refault-from-swapcache case where you
>>>>>>>>>>>>> get a
>>>>>>>>>>>>> large folio.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I was mislead by your "folio as swap-in always works at the granularity of
>>>>>>>>>>>>> base pages right now" comment.
>>>>>>>>>>>>>
>>>>>>>>>>>>> What you actually wanted to say is "While we always swap in small
>>>>>>>>>>>>> folios, we
>>>>>>>>>>>>> might refault large folios from the swapcache, and we only want to restore
>>>>>>>>>>>>> the tags for the page of the large folio we are faulting on."
>>>>>>>>>>>>>
>>>>>>>>>>>>> But, I do if we can't simply restore the tags for the whole thing at once
>>>>>>>>>>>>> at make the interface page-free?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Let me elaborate:
>>>>>>>>>>>>>
>>>>>>>>>>>>> IIRC, if we have a large folio in the swapcache, the swap
>>>>>>>>>>>>> entries/offset are
>>>>>>>>>>>>> contiguous. If you know you are faulting on page[1] of the folio with a
>>>>>>>>>>>>> given swap offset, you can calculate the swap offset for page[0] simply by
>>>>>>>>>>>>> subtracting from the offset.
>>>>>>>>>>>>>
>>>>>>>>>>>>> See page_swap_entry() on how we perform this calculation.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> So you can simply pass the large folio and the swap entry corresponding
>>>>>>>>>>>>> to the first page of the large folio, and restore all tags at once.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So the interface would be
>>>>>>>>>>>>>
>>>>>>>>>>>>> arch_prepare_to_swap(struct folio *folio);
>>>>>>>>>>>>> void arch_swap_restore(struct page *folio, swp_entry_t start_entry);
>>>>>>>>>>>>>
>>>>>>>>>>>>> I'm sorry if that was also already discussed.
>>>>>>>>>>>>
>>>>>>>>>>>> This has been discussed. Steven, Ryan and I all don't think this is a good
>>>>>>>>>>>> option. in case we have a large folio with 16 basepages, as do_swap_page
>>>>>>>>>>>> can only map one base page for each page fault, that means we have
>>>>>>>>>>>> to restore 16(tags we restore in each page fault) * 16(the times of page
>>>>>>>>>>>> faults)
>>>>>>>>>>>> for this large folio.
>>>>>>>>>>>>
>>>>>>>>>>>> and still the worst thing is the page fault in the Nth PTE of large folio
>>>>>>>>>>>> might free swap entry as that swap has been in.
>>>>>>>>>>>> do_swap_page()
>>>>>>>>>>>> {
>>>>>>>>>>>>        /*
>>>>>>>>>>>>         * Remove the swap entry and conditionally try to free up the
>>>>>>>>>>>> swapcache.
>>>>>>>>>>>>         * We're already holding a reference on the page but haven't
>>>>>>>>>>>> mapped it
>>>>>>>>>>>>         * yet.
>>>>>>>>>>>>         */
>>>>>>>>>>>>         swap_free(entry);
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> So in the page faults other than N, I mean 0~N-1 and N+1 to 15, you might
>>>>>>>>>>>> access
>>>>>>>>>>>> a freed tag.
>>>>>>>>>>>
>>>>>>>>>>> And David, one more information is that to keep the parameter of
>>>>>>>>>>> arch_swap_restore() unchanged as folio,
>>>>>>>>>>> i actually tried an ugly approach in rfc v2:
>>>>>>>>>>>
>>>>>>>>>>> +void arch_swap_restore(swp_entry_t entry, struct folio *folio)
>>>>>>>>>>> +{
>>>>>>>>>>> + if (system_supports_mte()) {
>>>>>>>>>>> +      /*
>>>>>>>>>>> +       * We don't support large folios swap in as whole yet, but
>>>>>>>>>>> +       * we can hit a large folio which is still in swapcache
>>>>>>>>>>> +       * after those related processes' PTEs have been unmapped
>>>>>>>>>>> +       * but before the swapcache folio  is dropped, in this case,
>>>>>>>>>>> +       * we need to find the exact page which "entry" is mapping
>>>>>>>>>>> +       * to. If we are not hitting swapcache, this folio won't be
>>>>>>>>>>> +       * large
>>>>>>>>>>> +     */
>>>>>>>>>>> + struct page *page = folio_file_page(folio, swp_offset(entry));
>>>>>>>>>>> + mte_restore_tags(entry, page);
>>>>>>>>>>> + }
>>>>>>>>>>> +}
>>>>>>>>>>>
>>>>>>>>>>> And obviously everybody in the discussion hated it :-)
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I can relate :D
>>>>>>>>>>
>>>>>>>>>>> i feel the only way to keep API unchanged using folio is that we
>>>>>>>>>>> support restoring PTEs
>>>>>>>>>>> all together for the whole large folio and we support the swap-in of
>>>>>>>>>>> large folios. This is
>>>>>>>>>>> in my list to do, I will send a patchset based on Ryan's large anon
>>>>>>>>>>> folios series after a
>>>>>>>>>>> while. till that is really done, it seems using page rather than folio
>>>>>>>>>>> is a better choice.
>>>>>>>>>>
>>>>>>>>>> I think just restoring all tags and remembering for a large folio that
>>>>>>>>>> they have been restored might be the low hanging fruit. But as always,
>>>>>>>>>> devil is in the detail :)
>>>>>>>>>
>>>>>>>>> Hi David,
>>>>>>>>> thanks for all your suggestions though my feeling is this is too complex and
>>>>>>>>> is not worth it for at least  three reasons.
>>>>>>>>
>>>>>>>> Fair enough.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> 1. In multi-thread and particularly multi-processes, we need some locks to
>>>>>>>>> protect and help know if one process is the first one to restore tags and if
>>>>>>>>> someone else is restoring tags when one process wants to restore. there
>>>>>>>>> is not this kind of fine-grained lock at all.
>>>>>>>>
>>>>>>>> We surely always hold the folio lock on swapin/swapout, no? So when these
>>>>>>>> functions are called.
>>>>>>>>
>>>>>>>> So that might just work already -- unless I am missing something important.
>>>>>>>
>>>>>>> We already have a page flag that we use to mark the page as having had its mte
>>>>>>> state associated; PG_mte_tagged. This is currently per-page (and IIUC, Matthew
>>>>>>> has been working to remove as many per-page flags as possible). Couldn't we just
>>>>>>> make arch_swap_restore() take a folio, restore the tags for *all* the pages and
>>>>>>> repurpose that flag to be per-folio (so head page only)? It looks like the the
>>>>>>> mte code already manages all the serialization requirements too. Then
>>>>>>> arch_swap_restore() can just exit early if it sees the flag is already set on
>>>>>>> the folio.
>>>>>>>
>>>>>>> One (probably nonsense) concern that just sprung to mind about having MTE work
>>>>>>> with large folios in general; is it possible that user space could cause a large
>>>>>>> anon folio to be allocated (THP), then later mark *part* of it to be tagged with
>>>>>>> MTE? In this case you would need to apply tags to part of the folio only.
>>>>>>> Although I have a vague recollection that any MTE areas have to be marked at
>>>>>>> mmap time and therefore this type of thing is impossible?
>>>>>>
>>>>>> right, we might need to consider only a part of folio needs to be
>>>>>> mapped and restored MTE tags.
>>>>>> do_swap_page() can have a chance to hit a large folio but it only
>>>>>> needs to fault-in a page.
>>>>>>
>>>>>> A case can be quite simple as below,
>>>>>>
>>>>>> 1. anon folio shared by process A and B
>>>>>> 2. add_to_swap() as a large folio;
>>>>>> 3. try to unmap A and B;
>>>>>> 4. after A is unmapped(ptes become swap entries), we do a
>>>>>> MADV_DONTNEED on a part of the folio. this can
>>>>>> happen very easily as userspace is still working in 4KB level;
>>>>>> userspace heap management can free an
>>>>>> basepage area by MADV_DONTNEED;
>>>>>> madvise(address, MADV_DONTNEED, 4KB);
>>>>>> 5. A refault on address + 8KB, we will hit large folio in
>>>>>> do_swap_page() but we will only need to map
>>>>>> one basepage, we will never need this DONTNEEDed in process A.
>>>>>>
>>>>>> another more complicated case can be mprotect and munmap a part of
>>>>>> large folios. since userspace
>>>>>> has no idea of large folios in their mind, they can do all strange
>>>>>> things. are we sure in all cases,
>>>>>> large folios have been splitted into small folios?
>>>>
>>>> I don;'t think these examples you cite are problematic. Although user space
>>>> thinks about things in 4K pages, the kernel does things in units of folios. So a
>>>> folio is either fully swapped out or not swapped out at all. MTE tags can be
>>>> saved/restored per folio, even if only part of that folio ends up being mapped
>>>> back into user space.
>>
>> I am not so optimistic :-)
>>
>> but zap_pte_range() due to DONTNEED on a part of swapped-out folio can
>> free a part of swap
>> entries? thus, free a part of MTE tags in a folio?
>> after process's large folios are swapped out, all PTEs in a large
>> folio become swap
>> entries, but DONTNEED on a part of this area will only set a part of
>> swap entries to
>> PTE_NONE, thus decrease the swapcount of this part?
>>
>> zap_pte_range
>>      ->
>>            entry = pte_to_swp_entry
>>                    -> free_swap_and_cache(entry)
>>                        -> mte tags invalidate
> 
> OK I see what you mean.
> 
> Just trying to summarize this, I think there are 2 questions behind all this:
> 
> 1) Can we save/restore MTE tags on at the granularity of a folio?
> 
> I think the answer is no; we can enable MTE on a individual pages within a folio
> with mprotect, and we can throw away tags on individual pages as you describe
> above. So we have to continue to handle tags per-page.

Can you enlighten me why the scheme proposed by Steven doesn't work?

I mean, having a mixture of tagged vs. untagged is assumed to be the 
corner case, right?

-- 
Cheers,

David / dhildenb



  reply	other threads:[~2023-11-27 12:01 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-14  1:43 [RFC V3 PATCH] arm64: mm: swap: save and restore mte tags for large folios Barry Song
2023-11-15 14:40 ` Steven Price
2023-11-15 15:16 ` David Hildenbrand
2023-11-15 20:49   ` Barry Song
2023-11-15 22:45     ` Yang Shi
2023-11-16  9:36     ` David Hildenbrand
2023-11-16 23:47       ` Barry Song
2023-11-17  0:15         ` Barry Song
2023-11-17 11:28           ` David Hildenbrand
2023-11-17 18:41             ` Barry Song
2023-11-20  9:11               ` David Hildenbrand
2023-11-20 10:57                 ` Ryan Roberts
2023-11-20 14:50                   ` Steven Price
2023-11-24  1:35                   ` Barry Song
2023-11-24  8:55                     ` David Hildenbrand
2023-11-24  9:01                       ` Ryan Roberts
2023-11-24  9:55                         ` Steven Price
2023-11-24 18:14                           ` Barry Song
2023-11-27 11:56                             ` Ryan Roberts
2023-11-27 12:01                               ` David Hildenbrand [this message]
2023-11-27 12:14                                 ` Ryan Roberts
2023-11-27 14:16                                   ` David Hildenbrand
2023-11-27 14:52                                     ` Ryan Roberts
2023-11-27 15:42                                       ` David Hildenbrand
2023-12-07  3:22                                     ` Barry Song
2023-12-07 10:03                                       ` David Hildenbrand
2023-12-08  0:00                                         ` Barry Song
2023-11-17 11:25         ` David Hildenbrand
2023-11-17 19:36         ` Matthew Wilcox
2023-11-17 20:36           ` Barry Song

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=c5c82611-3153-4d56-b799-a1df3c953efe@redhat.com \
    --to=david@redhat.com \
    --cc=21cnbao@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=catalin.marinas@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=ryan.roberts@arm.com \
    --cc=shy828301@gmail.com \
    --cc=steven.price@arm.com \
    --cc=v-songbaohua@oppo.com \
    --cc=wangkefeng.wang@huawei.com \
    --cc=will@kernel.org \
    --cc=willy@infradead.org \
    --cc=xiang@kernel.org \
    --cc=ying.huang@intel.com \
    --cc=yuzhao@google.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;
as well as URLs for NNTP newsgroup(s).