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_sync(void); 81 void mte_enable_kernel_async(void); 82 void mte_init_tags(u64 max_tag); 83 84 void mte_set_report_once(bool state); 85 bool mte_report_once(void); 86 87 #else /* CONFIG_ARM64_MTE */ 88 89 static inline u8 mte_get_ptr_tag(void *ptr) 90 { 91 return 0xFF; 92 } 93 94 static inline u8 mte_get_mem_tag(void *addr) 95 { 96 return 0xFF; 97 } 98 99 static inline u8 mte_get_random_tag(void) 100 { 101 return 0xFF; 102 } 103 104 static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag) 105 { 106 } 107 108 static inline void mte_enable_kernel_sync(void) 109 { 110 } 111 112 static inline void mte_enable_kernel_async(void) 113 { 114 } 115 116 static inline void mte_init_tags(u64 max_tag) 117 { 118 } 119 120 static inline void mte_set_report_once(bool state) 121 { 122 } 123 124 static inline bool mte_report_once(void) 125 { 126 return false; 127 } 128 129 #endif /* CONFIG_ARM64_MTE */ 130 131 #endif /* __ASSEMBLY__ */ 132 133 #endif /* __ASM_MTE_KASAN_H */ 134