/* * Memory tagging testing code. * * Copyright (c) 2020, Arm Limited. * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception */ #ifndef __TEST_MTE_H #define __TEST_MTE_H #include #if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST #include #include #include // These depend on a not yet merged kernel ABI. #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_TAGGED_ADDR_ENABLE (1UL << 0) #define PR_MTE_TCF_SHIFT 1 #define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) #define PR_MTE_TAG_SHIFT 3 #define PROT_MTE 0x20 #define MTE_GRANULE_SIZE 16 int mte_enabled () { static int enabled = -1; if (enabled == -1) { int res = prctl (PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0); enabled = (res == 0); } return enabled; } static void * mte_mmap (size_t size) { if (mte_enabled ()) { return mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } else { return malloc (size); } } void * alignup_mte (void *p) { return (void *) (((uintptr_t) p + MTE_GRANULE_SIZE - 1) & ~(MTE_GRANULE_SIZE - 1)); } void * aligndown_mte (void *p) { return (void *) ((uintptr_t) p & ~(MTE_GRANULE_SIZE - 1)); } void * untag_pointer (void *p) { return (void *) ((unsigned long long) p & (~0ULL >> 8)); } void tag_buffer_helper (void *p, int len) { char *ptr = p; char *end = alignup_mte (ptr + len); ptr = aligndown_mte (p); for (; ptr < end; ptr += MTE_GRANULE_SIZE) { __arm_mte_set_tag (ptr); } } void * tag_buffer (void *p, int len, int test_mte) { if (test_mte && mte_enabled ()) { p = __arm_mte_increment_tag (p, 1); tag_buffer_helper (p, len); } return p; } void * untag_buffer (void *p, int len, int test_mte) { p = untag_pointer (p); if (test_mte && mte_enabled ()) { tag_buffer_helper (p, len); } return p; } #else // __ARM_FEATURE_MEMORY_TAGGING int mte_enabled () { return 0; } static void * mte_mmap (size_t size) { return malloc (size); } void * tag_buffer (void *p, int len, int test_mte) { (void) len; (void) test_mte; return p; } void * untag_buffer (void *p, int len, int test_mte) { (void) len; (void) test_mte; return p; } void * untag_pointer (void *p) { return p; } #endif // __ARM_FEATURE_MEMORY_TAGGING #endif