Re: [PATCH v5 22/25] arm64: mte: Enable swap of tagged pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 24/06/2020 18:52, Catalin Marinas wrote:
From: Steven Price <steven.price@xxxxxxx>

When swapping pages out to disk it is necessary to save any tags that
have been set, and restore when swapping back in. Make use of the new
page flag (PG_ARCH_2, locally named PG_mte_tagged) to identify pages
with tags. When swapping out these pages the tags are stored in memory
and later restored when the pages are brought back in. Because shmem can
swap pages back in without restoring the userspace PTE it is also
necessary to add a hook for shmem.

Signed-off-by: Steven Price <steven.price@xxxxxxx>
[catalin.marinas@xxxxxxx: move function prototypes to mte.h]
[catalin.marinas@xxxxxxx: drop '_tags' from arch_swap_restore_tags()]
Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx>
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
---

Notes:
     New in v4.

[...]
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 3e08aea56e7a..1712c504df15 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -10,6 +10,8 @@
  #include <linux/sched.h>
  #include <linux/sched/mm.h>
  #include <linux/string.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
  #include <linux/thread_info.h>
  #include <linux/uio.h>
@@ -18,15 +20,30 @@
  #include <asm/ptrace.h>
  #include <asm/sysreg.h>
+static void mte_sync_page_tags(struct page *page, pte_t *ptep, bool check_swap)
+{
+	pte_t old_pte = READ_ONCE(*ptep);
+
+	if (check_swap && is_swap_pte(old_pte)) {
+		swp_entry_t entry = pte_to_swp_entry(old_pte);
+
+		if (!non_swap_entry(entry) && mte_restore_tags(entry, page))
+			return;
+	}
+
+	mte_clear_page_tags(page_address(page));
+}
+
  void mte_sync_tags(pte_t *ptep, pte_t pte)
  {
  	struct page *page = pte_page(pte);
  	long i, nr_pages = compound_nr(page);
+	bool check_swap = nr_pages == 0;
/* if PG_mte_tagged is set, tags have already been initialised */
  	for (i = 0; i < nr_pages; i++, page++) {

This is broken - for check_swap to be true, nr_pages==0, which means we never enter the loop and nothing happens...

Except I don't believe compound_nr() will return 0 - it's defined as:

  static inline unsigned long compound_nr(struct page *page)
  {
  	return 1UL << compound_order(page);
  }

Changing it to nr_pages==1 works for me.

Steve




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux