diff options
Diffstat (limited to 'string/test/mte.h')
-rw-r--r-- | string/test/mte.h | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/string/test/mte.h b/string/test/mte.h new file mode 100644 index 0000000..e67cbd9 --- /dev/null +++ b/string/test/mte.h @@ -0,0 +1,142 @@ +/* + * Memory tagging testing code. + * + * Copyright (c) 2020, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#ifndef __TEST_MTE_H +#define __TEST_MTE_H + +#include <stdlib.h> + +#if __ARM_FEATURE_MEMORY_TAGGING && WANT_MTE_TEST +#include <arm_acle.h> +#include <sys/mman.h> +#include <sys/prctl.h> + +// 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 |