1/* SPDX-License-Identifier: GPL-2.0 */
2/* Copyright (C) 2020 ARM Limited */
3
4#ifndef _MTE_COMMON_UTIL_H
5#define _MTE_COMMON_UTIL_H
6
7#include <signal.h>
8#include <stdbool.h>
9#include <stdlib.h>
10#include <sys/auxv.h>
11#include <sys/mman.h>
12#include <sys/prctl.h>
13#include "mte_def.h"
14#include "kselftest.h"
15
16enum mte_mem_type {
17	USE_MALLOC,
18	USE_MMAP,
19	USE_MPROTECT,
20};
21
22enum mte_mode {
23	MTE_NONE_ERR,
24	MTE_SYNC_ERR,
25	MTE_ASYNC_ERR,
26};
27
28struct mte_fault_cxt {
29	/* Address start which triggers mte tag fault */
30	unsigned long trig_addr;
31	/* Address range for mte tag fault and negative value means underflow */
32	ssize_t trig_range;
33	/* siginfo si code */
34	unsigned long trig_si_code;
35	/* Flag to denote if correct fault caught */
36	bool fault_valid;
37};
38
39extern struct mte_fault_cxt cur_mte_cxt;
40
41/* MTE utility functions */
42void mte_default_handler(int signum, siginfo_t *si, void *uc);
43void mte_register_signal(int signal, void (*handler)(int, siginfo_t *, void *));
44void mte_wait_after_trig(void);
45void *mte_allocate_memory(size_t size, int mem_type, int mapping, bool tags);
46void *mte_allocate_memory_tag_range(size_t size, int mem_type, int mapping,
47				    size_t range_before, size_t range_after);
48void *mte_allocate_file_memory(size_t size, int mem_type, int mapping,
49			       bool tags, int fd);
50void *mte_allocate_file_memory_tag_range(size_t size, int mem_type, int mapping,
51					 size_t range_before, size_t range_after, int fd);
52void mte_free_memory(void *ptr, size_t size, int mem_type, bool tags);
53void mte_free_memory_tag_range(void *ptr, size_t size, int mem_type,
54			       size_t range_before, size_t range_after);
55void *mte_insert_tags(void *ptr, size_t size);
56void mte_clear_tags(void *ptr, size_t size);
57int mte_default_setup(void);
58void mte_restore_setup(void);
59int mte_switch_mode(int mte_option, unsigned long incl_mask);
60void mte_initialize_current_context(int mode, uintptr_t ptr, ssize_t range);
61
62/* Common utility functions */
63int create_temp_file(void);
64
65/* Assembly MTE utility functions */
66void *mte_insert_random_tag(void *ptr);
67void *mte_insert_new_tag(void *ptr);
68void *mte_get_tag_address(void *ptr);
69void mte_set_tag_address_range(void *ptr, int range);
70void mte_clear_tag_address_range(void *ptr, int range);
71void mte_disable_pstate_tco(void);
72void mte_enable_pstate_tco(void);
73unsigned int mte_get_pstate_tco(void);
74
75/* Test framework static inline functions/macros */
76static inline void evaluate_test(int err, const char *msg)
77{
78	switch (err) {
79	case KSFT_PASS:
80		ksft_test_result_pass(msg);
81		break;
82	case KSFT_FAIL:
83		ksft_test_result_fail(msg);
84		break;
85	case KSFT_SKIP:
86		ksft_test_result_skip(msg);
87		break;
88	default:
89		ksft_test_result_error("Unknown return code %d from %s",
90				       err, msg);
91		break;
92	}
93}
94
95static inline int check_allocated_memory(void *ptr, size_t size,
96					 int mem_type, bool tags)
97{
98	if (ptr == NULL) {
99		ksft_print_msg("FAIL: memory allocation\n");
100		return KSFT_FAIL;
101	}
102
103	if (tags && !MT_FETCH_TAG((uintptr_t)ptr)) {
104		ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr);
105		mte_free_memory((void *)ptr, size, mem_type, false);
106		return KSFT_FAIL;
107	}
108
109	return KSFT_PASS;
110}
111
112static inline int check_allocated_memory_range(void *ptr, size_t size, int mem_type,
113					       size_t range_before, size_t range_after)
114{
115	if (ptr == NULL) {
116		ksft_print_msg("FAIL: memory allocation\n");
117		return KSFT_FAIL;
118	}
119
120	if (!MT_FETCH_TAG((uintptr_t)ptr)) {
121		ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr);
122		mte_free_memory_tag_range((void *)ptr, size, mem_type, range_before,
123					  range_after);
124		return KSFT_FAIL;
125	}
126	return KSFT_PASS;
127}
128
129#endif /* _MTE_COMMON_UTIL_H */
130