|
| 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 |
0 commit comments