131914882SAlex Richardson /*
231914882SAlex Richardson * Memory tagging testing code.
331914882SAlex Richardson *
431914882SAlex Richardson * Copyright (c) 2020, Arm Limited.
5*072a4ba8SAndrew Turner * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
631914882SAlex Richardson */
731914882SAlex Richardson
831914882SAlex Richardson #ifndef __TEST_MTE_H
931914882SAlex Richardson #define __TEST_MTE_H
1031914882SAlex Richardson
1131914882SAlex Richardson #include <stdlib.h>
1231914882SAlex Richardson
1331914882SAlex Richardson #if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST
1431914882SAlex Richardson #include <arm_acle.h>
1531914882SAlex Richardson #include <sys/mman.h>
1631914882SAlex Richardson #include <sys/prctl.h>
1731914882SAlex Richardson
1831914882SAlex Richardson // These depend on a not yet merged kernel ABI.
1931914882SAlex Richardson #define PR_SET_TAGGED_ADDR_CTRL 55
2031914882SAlex Richardson #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
2131914882SAlex Richardson #define PR_MTE_TCF_SHIFT 1
2231914882SAlex Richardson #define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
2331914882SAlex Richardson #define PR_MTE_TAG_SHIFT 3
2431914882SAlex Richardson #define PROT_MTE 0x20
2531914882SAlex Richardson
2631914882SAlex Richardson #define MTE_GRANULE_SIZE 16
2731914882SAlex Richardson
2831914882SAlex Richardson int
mte_enabled()2931914882SAlex Richardson mte_enabled ()
3031914882SAlex Richardson {
3131914882SAlex Richardson static int enabled = -1;
3231914882SAlex Richardson if (enabled == -1)
3331914882SAlex Richardson {
3431914882SAlex Richardson int res = prctl (PR_SET_TAGGED_ADDR_CTRL,
3531914882SAlex Richardson PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC
3631914882SAlex Richardson | (0xfffe << PR_MTE_TAG_SHIFT),
3731914882SAlex Richardson 0, 0, 0);
3831914882SAlex Richardson enabled = (res == 0);
3931914882SAlex Richardson }
4031914882SAlex Richardson return enabled;
4131914882SAlex Richardson }
4231914882SAlex Richardson
4331914882SAlex Richardson static void *
mte_mmap(size_t size)4431914882SAlex Richardson mte_mmap (size_t size)
4531914882SAlex Richardson {
4631914882SAlex Richardson if (mte_enabled ())
4731914882SAlex Richardson {
4831914882SAlex Richardson return mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_MTE,
4931914882SAlex Richardson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
5031914882SAlex Richardson }
5131914882SAlex Richardson else
5231914882SAlex Richardson {
5331914882SAlex Richardson return malloc (size);
5431914882SAlex Richardson }
5531914882SAlex Richardson }
5631914882SAlex Richardson
5731914882SAlex Richardson void *
alignup_mte(void * p)5831914882SAlex Richardson alignup_mte (void *p)
5931914882SAlex Richardson {
6031914882SAlex Richardson return (void *) (((uintptr_t) p + MTE_GRANULE_SIZE - 1)
6131914882SAlex Richardson & ~(MTE_GRANULE_SIZE - 1));
6231914882SAlex Richardson }
6331914882SAlex Richardson
6431914882SAlex Richardson void *
aligndown_mte(void * p)6531914882SAlex Richardson aligndown_mte (void *p)
6631914882SAlex Richardson {
6731914882SAlex Richardson return (void *) ((uintptr_t) p & ~(MTE_GRANULE_SIZE - 1));
6831914882SAlex Richardson }
6931914882SAlex Richardson
7031914882SAlex Richardson void *
untag_pointer(void * p)7131914882SAlex Richardson untag_pointer (void *p)
7231914882SAlex Richardson {
7331914882SAlex Richardson return (void *) ((unsigned long long) p & (~0ULL >> 8));
7431914882SAlex Richardson }
7531914882SAlex Richardson
7631914882SAlex Richardson void
tag_buffer_helper(void * p,int len)7731914882SAlex Richardson tag_buffer_helper (void *p, int len)
7831914882SAlex Richardson {
7931914882SAlex Richardson char *ptr = p;
8031914882SAlex Richardson char *end = alignup_mte (ptr + len);
8131914882SAlex Richardson ptr = aligndown_mte (p);
8231914882SAlex Richardson for (; ptr < end; ptr += MTE_GRANULE_SIZE)
8331914882SAlex Richardson {
8431914882SAlex Richardson __arm_mte_set_tag (ptr);
8531914882SAlex Richardson }
8631914882SAlex Richardson }
8731914882SAlex Richardson
8831914882SAlex Richardson void *
tag_buffer(void * p,int len,int test_mte)8931914882SAlex Richardson tag_buffer (void *p, int len, int test_mte)
9031914882SAlex Richardson {
9131914882SAlex Richardson if (test_mte && mte_enabled ())
9231914882SAlex Richardson {
9331914882SAlex Richardson p = __arm_mte_increment_tag (p, 1);
9431914882SAlex Richardson tag_buffer_helper (p, len);
9531914882SAlex Richardson }
9631914882SAlex Richardson return p;
9731914882SAlex Richardson }
9831914882SAlex Richardson
9931914882SAlex Richardson void *
untag_buffer(void * p,int len,int test_mte)10031914882SAlex Richardson untag_buffer (void *p, int len, int test_mte)
10131914882SAlex Richardson {
10231914882SAlex Richardson p = untag_pointer (p);
10331914882SAlex Richardson if (test_mte && mte_enabled ())
10431914882SAlex Richardson {
10531914882SAlex Richardson tag_buffer_helper (p, len);
10631914882SAlex Richardson }
10731914882SAlex Richardson return p;
10831914882SAlex Richardson }
10931914882SAlex Richardson
11031914882SAlex Richardson #else // __ARM_FEATURE_MEMORY_TAGGING
11131914882SAlex Richardson int
mte_enabled()11231914882SAlex Richardson mte_enabled ()
11331914882SAlex Richardson {
11431914882SAlex Richardson return 0;
11531914882SAlex Richardson }
11631914882SAlex Richardson static void *
mte_mmap(size_t size)11731914882SAlex Richardson mte_mmap (size_t size)
11831914882SAlex Richardson {
11931914882SAlex Richardson return malloc (size);
12031914882SAlex Richardson }
12131914882SAlex Richardson void *
tag_buffer(void * p,int len,int test_mte)12231914882SAlex Richardson tag_buffer (void *p, int len, int test_mte)
12331914882SAlex Richardson {
12431914882SAlex Richardson (void) len;
12531914882SAlex Richardson (void) test_mte;
12631914882SAlex Richardson return p;
12731914882SAlex Richardson }
12831914882SAlex Richardson void *
untag_buffer(void * p,int len,int test_mte)12931914882SAlex Richardson untag_buffer (void *p, int len, int test_mte)
13031914882SAlex Richardson {
13131914882SAlex Richardson (void) len;
13231914882SAlex Richardson (void) test_mte;
13331914882SAlex Richardson return p;
13431914882SAlex Richardson }
13531914882SAlex Richardson void *
untag_pointer(void * p)13631914882SAlex Richardson untag_pointer (void *p)
13731914882SAlex Richardson {
13831914882SAlex Richardson return p;
13931914882SAlex Richardson }
14031914882SAlex Richardson #endif // __ARM_FEATURE_MEMORY_TAGGING
14131914882SAlex Richardson
14231914882SAlex Richardson #endif
143