[PATCH 0/1] THP_SWAP support for ARM64 SoC with MTE
Barry Song
21cnbao at gmail.com
Fri Mar 22 04:41:35 PDT 2024
From: Barry Song <v-songbaohua at oppo.com>
The patch has been extracted from the larger folios swap-in series [1],
incorporating some new modifications.
Introducing THP_SWAP support for ARM64 SoCs with MTE is essential, particularly
due to its significance for widely used ARM64 products in the market. Without
this support, Ryan's mTHP swap-out without splitting series won't operate
effectively on these SoCs.
Therefore, it's imperative for this update to be implemented sooner
rather than later.
There are a couple of differences with the code in [1]:
1. minor code cleanup, Ryan
2. always pass the first swap entry of a folio to arch_swap_restore, Ryan
[1] https://lore.kernel.org/linux-mm/20240304081348.197341-2-21cnbao@gmail.com/
Barry Song (1):
arm64: mm: swap: support THP_SWAP on hardware with MTE
arch/arm64/include/asm/pgtable.h | 19 ++------------
arch/arm64/mm/mteswap.c | 45 ++++++++++++++++++++++++++++++++
include/linux/huge_mm.h | 12 ---------
include/linux/pgtable.h | 2 +-
mm/internal.h | 14 ++++++++++
mm/memory.c | 2 +-
mm/page_io.c | 2 +-
mm/shmem.c | 2 +-
mm/swap_slots.c | 2 +-
mm/swapfile.c | 2 +-
10 files changed, 67 insertions(+), 35 deletions(-)
Appendix
I also have a small test program specifically designed for running MTE
on a THP that I can share with those who are interested in this subject.
/*
* To be compiled with -march=armv8.5-a+memtag
*/
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/auxv.h>
#include <sys/mman.h>
#include <sys/prctl.h>
/*
* From arch/arm64/include/uapi/asm/hwcap.h
*/
#define HWCAP2_MTE (1 << 18)
/*
* From arch/arm64/include/uapi/asm/mman.h
*/
#define PROT_MTE 0x20
/*
* From include/uapi/linux/prctl.h
*/
#define PR_SET_TAGGED_ADDR_CTRL 55
#define PR_GET_TAGGED_ADDR_CTRL 56
# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
# define PR_MTE_TCF_SHIFT 1
# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
# define PR_MTE_TAG_SHIFT 3
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
/*
* Insert a random logical tag into the given pointer.
*/
#define insert_random_tag(ptr) ({ \
uint64_t __val; \
asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \
__val; \
})
/*
* Set the allocation tag on the destination address.
*/
#define set_tag(tagged_addr) do { \
asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
} while (0)
int main()
{
unsigned char *a, *p[512];
unsigned long page_sz = 4 * 1024UL;
unsigned long mem_sz = 2 * 1024 * 1024UL;
unsigned long hwcap2 = getauxval(AT_HWCAP2);
int i;
if (!(hwcap2 & HWCAP2_MTE))
return EXIT_FAILURE;
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC |
(0xfffe << PR_MTE_TAG_SHIFT),
0, 0, 0)) {
perror("prctl() failed");
return EXIT_FAILURE;
}
a = mmap(0, mem_sz * 2, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (a == MAP_FAILED) {
perror("mmap() failed");
return EXIT_FAILURE;
}
/* make sure a is aligned with 2MiB THP */
a = (unsigned char *)(((unsigned long)a + mem_sz - 1) & ~(mem_sz - 1));
madvise(a, mem_sz, MADV_HUGEPAGE);
memset(a, 0x11, mem_sz);
if (mprotect(a, mem_sz, PROT_READ | PROT_WRITE | PROT_MTE)) {
perror("mprotect() failed");
return EXIT_FAILURE;
}
printf("set tag for each 4KiB page\n");
for (i = 0; i < 512; i++) {
p[i] = a + i * page_sz;
p[i] = (unsigned char *)insert_random_tag(p[i]);
set_tag(p[i]);
p[i][0] = 0x33;
}
printf("swap-out the whole THP\n");
madvise(a, mem_sz, MADV_PAGEOUT);
printf("swap-in each page of the original THP\n");
for (i = 0; i < 512; i++) {
if (p[i][0] != 0x33) {
printf("test fails, unmatched value after swap-in\n");
return EXIT_FAILURE;
}
}
printf("we should get here\n");
for (i = 0; i < 512; i++) {
printf("page :%d val: expect segment fault, is %02x\n", i, p[i][16]);
}
printf("we shouldn't get here\n");
return EXIT_FAILURE;
}
--
2.34.1
More information about the linux-arm-kernel
mailing list