| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* Copyright (C) 2020 ARM Limited */ |
| |
| #ifndef _MTE_COMMON_UTIL_H |
| #define _MTE_COMMON_UTIL_H |
| |
| #include <signal.h> |
| #include <stdbool.h> |
| #include <stdlib.h> |
| #include <sys/auxv.h> |
| #include <sys/mman.h> |
| #include <sys/prctl.h> |
| #include "mte_def.h" |
| #include "kselftest.h" |
| |
| enum mte_mem_type { |
| USE_MALLOC, |
| USE_MMAP, |
| USE_MPROTECT, |
| }; |
| |
| enum mte_mode { |
| MTE_NONE_ERR, |
| MTE_SYNC_ERR, |
| MTE_ASYNC_ERR, |
| }; |
| |
| struct mte_fault_cxt { |
| /* Address start which triggers mte tag fault */ |
| unsigned long trig_addr; |
| /* Address range for mte tag fault and negative value means underflow */ |
| ssize_t trig_range; |
| /* siginfo si code */ |
| unsigned long trig_si_code; |
| /* Flag to denote if correct fault caught */ |
| bool fault_valid; |
| }; |
| |
| extern struct mte_fault_cxt cur_mte_cxt; |
| |
| /* MTE utility functions */ |
| void mte_default_handler(int signum, siginfo_t *si, void *uc); |
| void mte_register_signal(int signal, void (*handler)(int, siginfo_t *, void *)); |
| void mte_wait_after_trig(void); |
| void *mte_allocate_memory(size_t size, int mem_type, int mapping, bool tags); |
| void *mte_allocate_memory_tag_range(size_t size, int mem_type, int mapping, |
| size_t range_before, size_t range_after); |
| void *mte_allocate_file_memory(size_t size, int mem_type, int mapping, |
| bool tags, int fd); |
| void *mte_allocate_file_memory_tag_range(size_t size, int mem_type, int mapping, |
| size_t range_before, size_t range_after, int fd); |
| void mte_free_memory(void *ptr, size_t size, int mem_type, bool tags); |
| void mte_free_memory_tag_range(void *ptr, size_t size, int mem_type, |
| size_t range_before, size_t range_after); |
| void *mte_insert_tags(void *ptr, size_t size); |
| void mte_clear_tags(void *ptr, size_t size); |
| int mte_default_setup(void); |
| void mte_restore_setup(void); |
| int mte_switch_mode(int mte_option, unsigned long incl_mask); |
| void mte_initialize_current_context(int mode, uintptr_t ptr, ssize_t range); |
| |
| /* Common utility functions */ |
| int create_temp_file(void); |
| |
| /* Assembly MTE utility functions */ |
| void *mte_insert_random_tag(void *ptr); |
| void *mte_insert_new_tag(void *ptr); |
| void *mte_get_tag_address(void *ptr); |
| void mte_set_tag_address_range(void *ptr, int range); |
| void mte_clear_tag_address_range(void *ptr, int range); |
| void mte_disable_pstate_tco(void); |
| void mte_enable_pstate_tco(void); |
| unsigned int mte_get_pstate_tco(void); |
| |
| /* Test framework static inline functions/macros */ |
| static inline void evaluate_test(int err, const char *msg) |
| { |
| switch (err) { |
| case KSFT_PASS: |
| ksft_test_result_pass(msg); |
| break; |
| case KSFT_FAIL: |
| ksft_test_result_fail(msg); |
| break; |
| case KSFT_SKIP: |
| ksft_test_result_skip(msg); |
| break; |
| default: |
| ksft_test_result_error("Unknown return code %d from %s", |
| err, msg); |
| break; |
| } |
| } |
| |
| static inline int check_allocated_memory(void *ptr, size_t size, |
| int mem_type, bool tags) |
| { |
| if (ptr == NULL) { |
| ksft_print_msg("FAIL: memory allocation\n"); |
| return KSFT_FAIL; |
| } |
| |
| if (tags && !MT_FETCH_TAG((uintptr_t)ptr)) { |
| ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr); |
| mte_free_memory((void *)ptr, size, mem_type, false); |
| return KSFT_FAIL; |
| } |
| |
| return KSFT_PASS; |
| } |
| |
| static inline int check_allocated_memory_range(void *ptr, size_t size, int mem_type, |
| size_t range_before, size_t range_after) |
| { |
| if (ptr == NULL) { |
| ksft_print_msg("FAIL: memory allocation\n"); |
| return KSFT_FAIL; |
| } |
| |
| if (!MT_FETCH_TAG((uintptr_t)ptr)) { |
| ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr); |
| mte_free_memory_tag_range((void *)ptr, size, mem_type, range_before, |
| range_after); |
| return KSFT_FAIL; |
| } |
| return KSFT_PASS; |
| } |
| |
| #endif /* _MTE_COMMON_UTIL_H */ |