powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes
[platform/kernel/linux-starfive.git] / arch / loongarch / include / asm / kasan.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_KASAN_H
3 #define __ASM_KASAN_H
4
5 #ifndef __ASSEMBLY__
6
7 #include <linux/linkage.h>
8 #include <linux/mmzone.h>
9 #include <asm/addrspace.h>
10 #include <asm/io.h>
11 #include <asm/pgtable.h>
12
13 #define __HAVE_ARCH_SHADOW_MAP
14
15 #define KASAN_SHADOW_SCALE_SHIFT 3
16 #define KASAN_SHADOW_OFFSET     _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
17
18 #define XRANGE_SHIFT (48)
19
20 /* Valid address length */
21 #define XRANGE_SHADOW_SHIFT     (PGDIR_SHIFT + PAGE_SHIFT - 3)
22 /* Used for taking out the valid address */
23 #define XRANGE_SHADOW_MASK      GENMASK_ULL(XRANGE_SHADOW_SHIFT - 1, 0)
24 /* One segment whole address space size */
25 #define XRANGE_SIZE             (XRANGE_SHADOW_MASK + 1)
26
27 /* 64-bit segment value. */
28 #define XKPRANGE_UC_SEG         (0x8000)
29 #define XKPRANGE_CC_SEG         (0x9000)
30 #define XKVRANGE_VC_SEG         (0xffff)
31
32 /* Cached */
33 #define XKPRANGE_CC_START               CACHE_BASE
34 #define XKPRANGE_CC_SIZE                XRANGE_SIZE
35 #define XKPRANGE_CC_KASAN_OFFSET        (0)
36 #define XKPRANGE_CC_SHADOW_SIZE         (XKPRANGE_CC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
37 #define XKPRANGE_CC_SHADOW_END          (XKPRANGE_CC_KASAN_OFFSET + XKPRANGE_CC_SHADOW_SIZE)
38
39 /* UnCached */
40 #define XKPRANGE_UC_START               UNCACHE_BASE
41 #define XKPRANGE_UC_SIZE                XRANGE_SIZE
42 #define XKPRANGE_UC_KASAN_OFFSET        XKPRANGE_CC_SHADOW_END
43 #define XKPRANGE_UC_SHADOW_SIZE         (XKPRANGE_UC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
44 #define XKPRANGE_UC_SHADOW_END          (XKPRANGE_UC_KASAN_OFFSET + XKPRANGE_UC_SHADOW_SIZE)
45
46 /* VMALLOC (Cached or UnCached)  */
47 #define XKVRANGE_VC_START               MODULES_VADDR
48 #define XKVRANGE_VC_SIZE                round_up(KFENCE_AREA_END - MODULES_VADDR + 1, PGDIR_SIZE)
49 #define XKVRANGE_VC_KASAN_OFFSET        XKPRANGE_UC_SHADOW_END
50 #define XKVRANGE_VC_SHADOW_SIZE         (XKVRANGE_VC_SIZE >> KASAN_SHADOW_SCALE_SHIFT)
51 #define XKVRANGE_VC_SHADOW_END          (XKVRANGE_VC_KASAN_OFFSET + XKVRANGE_VC_SHADOW_SIZE)
52
53 /* KAsan shadow memory start right after vmalloc. */
54 #define KASAN_SHADOW_START              round_up(KFENCE_AREA_END, PGDIR_SIZE)
55 #define KASAN_SHADOW_SIZE               (XKVRANGE_VC_SHADOW_END - XKPRANGE_CC_KASAN_OFFSET)
56 #define KASAN_SHADOW_END                round_up(KASAN_SHADOW_START + KASAN_SHADOW_SIZE, PGDIR_SIZE)
57
58 #define XKPRANGE_CC_SHADOW_OFFSET       (KASAN_SHADOW_START + XKPRANGE_CC_KASAN_OFFSET)
59 #define XKPRANGE_UC_SHADOW_OFFSET       (KASAN_SHADOW_START + XKPRANGE_UC_KASAN_OFFSET)
60 #define XKVRANGE_VC_SHADOW_OFFSET       (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET)
61
62 extern bool kasan_early_stage;
63 extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
64
65 #define kasan_arch_is_ready kasan_arch_is_ready
66 static __always_inline bool kasan_arch_is_ready(void)
67 {
68         return !kasan_early_stage;
69 }
70
71 static inline void *kasan_mem_to_shadow(const void *addr)
72 {
73         if (!kasan_arch_is_ready()) {
74                 return (void *)(kasan_early_shadow_page);
75         } else {
76                 unsigned long maddr = (unsigned long)addr;
77                 unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff;
78                 unsigned long offset = 0;
79
80                 maddr &= XRANGE_SHADOW_MASK;
81                 switch (xrange) {
82                 case XKPRANGE_CC_SEG:
83                         offset = XKPRANGE_CC_SHADOW_OFFSET;
84                         break;
85                 case XKPRANGE_UC_SEG:
86                         offset = XKPRANGE_UC_SHADOW_OFFSET;
87                         break;
88                 case XKVRANGE_VC_SEG:
89                         offset = XKVRANGE_VC_SHADOW_OFFSET;
90                         break;
91                 default:
92                         WARN_ON(1);
93                         return NULL;
94                 }
95
96                 return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset);
97         }
98 }
99
100 static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
101 {
102         unsigned long addr = (unsigned long)shadow_addr;
103
104         if (unlikely(addr > KASAN_SHADOW_END) ||
105                 unlikely(addr < KASAN_SHADOW_START)) {
106                 WARN_ON(1);
107                 return NULL;
108         }
109
110         if (addr >= XKVRANGE_VC_SHADOW_OFFSET)
111                 return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START);
112         else if (addr >= XKPRANGE_UC_SHADOW_OFFSET)
113                 return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START);
114         else if (addr >= XKPRANGE_CC_SHADOW_OFFSET)
115                 return (void *)(((addr - XKPRANGE_CC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_CC_START);
116         else {
117                 WARN_ON(1);
118                 return NULL;
119         }
120 }
121
122 void kasan_init(void);
123 asmlinkage void kasan_early_init(void);
124
125 #endif
126 #endif