arm64: kasan: simplify and inline MTE functions
[linux-2.6-microblaze.git] / arch / arm64 / include / asm / mte-kasan.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020 ARM Ltd.
4  */
5 #ifndef __ASM_MTE_KASAN_H
6 #define __ASM_MTE_KASAN_H
7
8 #include <asm/mte-def.h>
9
10 #ifndef __ASSEMBLY__
11
12 #include <linux/types.h>
13
14 #ifdef CONFIG_ARM64_MTE
15
16 /*
17  * These functions are meant to be only used from KASAN runtime through
18  * the arch_*() interface defined in asm/memory.h.
19  * These functions don't include system_supports_mte() checks,
20  * as KASAN only calls them when MTE is supported and enabled.
21  */
22
23 static inline u8 mte_get_ptr_tag(void *ptr)
24 {
25         /* Note: The format of KASAN tags is 0xF<x> */
26         u8 tag = 0xF0 | (u8)(((u64)(ptr)) >> MTE_TAG_SHIFT);
27
28         return tag;
29 }
30
31 /* Get allocation tag for the address. */
32 static inline u8 mte_get_mem_tag(void *addr)
33 {
34         asm(__MTE_PREAMBLE "ldg %0, [%0]"
35                 : "+r" (addr));
36
37         return mte_get_ptr_tag(addr);
38 }
39
40 /* Generate a random tag. */
41 static inline u8 mte_get_random_tag(void)
42 {
43         void *addr;
44
45         asm(__MTE_PREAMBLE "irg %0, %0"
46                 : "=r" (addr));
47
48         return mte_get_ptr_tag(addr);
49 }
50
51 /*
52  * Assign allocation tags for a region of memory based on the pointer tag.
53  * Note: The address must be non-NULL and MTE_GRANULE_SIZE aligned and
54  * size must be non-zero and MTE_GRANULE_SIZE aligned.
55  */
56 static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag)
57 {
58         u64 curr, end;
59
60         if (!size)
61                 return;
62
63         curr = (u64)__tag_set(addr, tag);
64         end = curr + size;
65
66         do {
67                 /*
68                  * 'asm volatile' is required to prevent the compiler to move
69                  * the statement outside of the loop.
70                  */
71                 asm volatile(__MTE_PREAMBLE "stg %0, [%0]"
72                              :
73                              : "r" (curr)
74                              : "memory");
75
76                 curr += MTE_GRANULE_SIZE;
77         } while (curr != end);
78 }
79
80 void mte_enable_kernel(void);
81 void mte_init_tags(u64 max_tag);
82
83 void mte_set_report_once(bool state);
84 bool mte_report_once(void);
85
86 #else /* CONFIG_ARM64_MTE */
87
88 static inline u8 mte_get_ptr_tag(void *ptr)
89 {
90         return 0xFF;
91 }
92
93 static inline u8 mte_get_mem_tag(void *addr)
94 {
95         return 0xFF;
96 }
97
98 static inline u8 mte_get_random_tag(void)
99 {
100         return 0xFF;
101 }
102
103 static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag)
104 {
105 }
106
107 static inline void mte_enable_kernel(void)
108 {
109 }
110
111 static inline void mte_init_tags(u64 max_tag)
112 {
113 }
114
115 static inline void mte_set_report_once(bool state)
116 {
117 }
118
119 static inline bool mte_report_once(void)
120 {
121         return false;
122 }
123
124 #endif /* CONFIG_ARM64_MTE */
125
126 #endif /* __ASSEMBLY__ */
127
128 #endif /* __ASM_MTE_KASAN_H  */