xref: /aosp_15_r20/external/arm-optimized-routines/string/test/mte.h (revision 412f47f9e737e10ed5cc46ec6a8d7fa2264f8a14)
1*412f47f9SXin Li /*
2*412f47f9SXin Li  * Memory tagging testing code.
3*412f47f9SXin Li  *
4*412f47f9SXin Li  * Copyright (c) 2020, Arm Limited.
5*412f47f9SXin Li  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6*412f47f9SXin Li  */
7*412f47f9SXin Li 
8*412f47f9SXin Li #ifndef __TEST_MTE_H
9*412f47f9SXin Li #define __TEST_MTE_H
10*412f47f9SXin Li 
11*412f47f9SXin Li #include <stdlib.h>
12*412f47f9SXin Li 
13*412f47f9SXin Li #if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST
14*412f47f9SXin Li #include <arm_acle.h>
15*412f47f9SXin Li #include <sys/mman.h>
16*412f47f9SXin Li #include <sys/prctl.h>
17*412f47f9SXin Li 
18*412f47f9SXin Li // These depend on a not yet merged kernel ABI.
19*412f47f9SXin Li #define PR_SET_TAGGED_ADDR_CTRL 55
20*412f47f9SXin Li #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
21*412f47f9SXin Li #define PR_MTE_TCF_SHIFT 1
22*412f47f9SXin Li #define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
23*412f47f9SXin Li #define PR_MTE_TAG_SHIFT 3
24*412f47f9SXin Li #define PROT_MTE 0x20
25*412f47f9SXin Li 
26*412f47f9SXin Li #define MTE_GRANULE_SIZE 16
27*412f47f9SXin Li 
28*412f47f9SXin Li int
mte_enabled()29*412f47f9SXin Li mte_enabled ()
30*412f47f9SXin Li {
31*412f47f9SXin Li   static int enabled = -1;
32*412f47f9SXin Li   if (enabled == -1)
33*412f47f9SXin Li     {
34*412f47f9SXin Li       int res = prctl (PR_SET_TAGGED_ADDR_CTRL,
35*412f47f9SXin Li 		       PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC
36*412f47f9SXin Li 			 | (0xfffe << PR_MTE_TAG_SHIFT),
37*412f47f9SXin Li 		       0, 0, 0);
38*412f47f9SXin Li       enabled = (res == 0);
39*412f47f9SXin Li     }
40*412f47f9SXin Li   return enabled;
41*412f47f9SXin Li }
42*412f47f9SXin Li 
43*412f47f9SXin Li static void *
mte_mmap(size_t size)44*412f47f9SXin Li mte_mmap (size_t size)
45*412f47f9SXin Li {
46*412f47f9SXin Li   if (mte_enabled ())
47*412f47f9SXin Li     {
48*412f47f9SXin Li       return mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_MTE,
49*412f47f9SXin Li 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
50*412f47f9SXin Li     }
51*412f47f9SXin Li   else
52*412f47f9SXin Li     {
53*412f47f9SXin Li       return malloc (size);
54*412f47f9SXin Li     }
55*412f47f9SXin Li }
56*412f47f9SXin Li 
57*412f47f9SXin Li void *
alignup_mte(void * p)58*412f47f9SXin Li alignup_mte (void *p)
59*412f47f9SXin Li {
60*412f47f9SXin Li   return (void *) (((uintptr_t) p + MTE_GRANULE_SIZE - 1)
61*412f47f9SXin Li 		   & ~(MTE_GRANULE_SIZE - 1));
62*412f47f9SXin Li }
63*412f47f9SXin Li 
64*412f47f9SXin Li void *
aligndown_mte(void * p)65*412f47f9SXin Li aligndown_mte (void *p)
66*412f47f9SXin Li {
67*412f47f9SXin Li   return (void *) ((uintptr_t) p & ~(MTE_GRANULE_SIZE - 1));
68*412f47f9SXin Li }
69*412f47f9SXin Li 
70*412f47f9SXin Li void *
untag_pointer(void * p)71*412f47f9SXin Li untag_pointer (void *p)
72*412f47f9SXin Li {
73*412f47f9SXin Li   return (void *) ((unsigned long long) p & (~0ULL >> 8));
74*412f47f9SXin Li }
75*412f47f9SXin Li 
76*412f47f9SXin Li void
tag_buffer_helper(void * p,int len)77*412f47f9SXin Li tag_buffer_helper (void *p, int len)
78*412f47f9SXin Li {
79*412f47f9SXin Li   char *ptr = p;
80*412f47f9SXin Li   char *end = alignup_mte (ptr + len);
81*412f47f9SXin Li   ptr = aligndown_mte (p);
82*412f47f9SXin Li   for (; ptr < end; ptr += MTE_GRANULE_SIZE)
83*412f47f9SXin Li     {
84*412f47f9SXin Li       __arm_mte_set_tag (ptr);
85*412f47f9SXin Li     }
86*412f47f9SXin Li }
87*412f47f9SXin Li 
88*412f47f9SXin Li void *
tag_buffer(void * p,int len,int test_mte)89*412f47f9SXin Li tag_buffer (void *p, int len, int test_mte)
90*412f47f9SXin Li {
91*412f47f9SXin Li   if (test_mte && mte_enabled ())
92*412f47f9SXin Li     {
93*412f47f9SXin Li       p = __arm_mte_increment_tag (p, 1);
94*412f47f9SXin Li       tag_buffer_helper (p, len);
95*412f47f9SXin Li     }
96*412f47f9SXin Li   return p;
97*412f47f9SXin Li }
98*412f47f9SXin Li 
99*412f47f9SXin Li void *
untag_buffer(void * p,int len,int test_mte)100*412f47f9SXin Li untag_buffer (void *p, int len, int test_mte)
101*412f47f9SXin Li {
102*412f47f9SXin Li   p = untag_pointer (p);
103*412f47f9SXin Li   if (test_mte && mte_enabled ())
104*412f47f9SXin Li     {
105*412f47f9SXin Li       tag_buffer_helper (p, len);
106*412f47f9SXin Li     }
107*412f47f9SXin Li   return p;
108*412f47f9SXin Li }
109*412f47f9SXin Li 
110*412f47f9SXin Li #else  // __ARM_FEATURE_MEMORY_TAGGING
111*412f47f9SXin Li int
mte_enabled()112*412f47f9SXin Li mte_enabled ()
113*412f47f9SXin Li {
114*412f47f9SXin Li   return 0;
115*412f47f9SXin Li }
116*412f47f9SXin Li static void *
mte_mmap(size_t size)117*412f47f9SXin Li mte_mmap (size_t size)
118*412f47f9SXin Li {
119*412f47f9SXin Li   return malloc (size);
120*412f47f9SXin Li }
121*412f47f9SXin Li void *
tag_buffer(void * p,int len,int test_mte)122*412f47f9SXin Li tag_buffer (void *p, int len, int test_mte)
123*412f47f9SXin Li {
124*412f47f9SXin Li   (void) len;
125*412f47f9SXin Li   (void) test_mte;
126*412f47f9SXin Li   return p;
127*412f47f9SXin Li }
128*412f47f9SXin Li void *
untag_buffer(void * p,int len,int test_mte)129*412f47f9SXin Li untag_buffer (void *p, int len, int test_mte)
130*412f47f9SXin Li {
131*412f47f9SXin Li   (void) len;
132*412f47f9SXin Li   (void) test_mte;
133*412f47f9SXin Li   return p;
134*412f47f9SXin Li }
135*412f47f9SXin Li void *
untag_pointer(void * p)136*412f47f9SXin Li untag_pointer (void *p)
137*412f47f9SXin Li {
138*412f47f9SXin Li   return p;
139*412f47f9SXin Li }
140*412f47f9SXin Li #endif // __ARM_FEATURE_MEMORY_TAGGING
141*412f47f9SXin Li 
142*412f47f9SXin Li #endif
143