Skip to content

Commit

Permalink
arm64: mte: Tags-aware aware memcmp_pages() implementation
Browse files Browse the repository at this point in the history
When the Memory Tagging Extension is enabled, two pages are identical
only if both their data and tags are identical.

Make the generic memcmp_pages() a __weak function and add an
arm64-specific implementation which returns non-zero if any of the two
pages contain valid MTE tags (PG_mte_tagged set). There isn't much
benefit in comparing the tags of two pages since these are normally used
for heap allocations and likely to differ anyway.

Co-developed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
  • Loading branch information
Catalin Marinas committed Sep 4, 2020
1 parent 738c878 commit 4d1a8a2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
26 changes: 26 additions & 0 deletions arch/arm64/kernel/mte.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <linux/bitops.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/thread_info.h>

#include <asm/cpufeature.h>
Expand All @@ -23,6 +24,31 @@ void mte_sync_tags(pte_t *ptep, pte_t pte)
}
}

int memcmp_pages(struct page *page1, struct page *page2)
{
char *addr1, *addr2;
int ret;

addr1 = page_address(page1);
addr2 = page_address(page2);
ret = memcmp(addr1, addr2, PAGE_SIZE);

if (!system_supports_mte() || ret)
return ret;

/*
* If the page content is identical but at least one of the pages is
* tagged, return non-zero to avoid KSM merging. If only one of the
* pages is tagged, set_pte_at() may zero or change the tags of the
* other page via mte_sync_tags().
*/
if (test_bit(PG_mte_tagged, &page1->flags) ||
test_bit(PG_mte_tagged, &page2->flags))
return addr1 != addr2;

return ret;
}

void flush_mte_state(void)
{
if (!system_supports_mte())
Expand Down
2 changes: 1 addition & 1 deletion mm/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
return res;
}

int memcmp_pages(struct page *page1, struct page *page2)
int __weak memcmp_pages(struct page *page1, struct page *page2)
{
char *addr1, *addr2;
int ret;
Expand Down

0 comments on commit 4d1a8a2

Please sign in to comment.