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