mte.h 3.3 KB
Newer Older
1 2 3 4 5 6 7
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020 ARM Ltd.
 */
#ifndef __ASM_MTE_H
#define __ASM_MTE_H

8 9 10
#include <asm/compiler.h>
#include <asm/mte-def.h>

11 12
#ifndef __ASSEMBLY__

13
#include <linux/bitfield.h>
14
#include <linux/page-flags.h>
15
#include <linux/types.h>
16 17 18

#include <asm/pgtable-types.h>

19 20
extern u64 gcr_kernel_excl;

21
void mte_clear_page_tags(void *addr);
22 23 24 25
unsigned long mte_copy_tags_from_user(void *to, const void __user *from,
				      unsigned long n);
unsigned long mte_copy_tags_to_user(void __user *to, void *from,
				    unsigned long n);
26 27 28 29 30 31 32 33
int mte_save_tags(struct page *page);
void mte_save_page_tags(const void *page_addr, void *tag_storage);
bool mte_restore_tags(swp_entry_t entry, struct page *page);
void mte_restore_page_tags(void *page_addr, const void *tag_storage);
void mte_invalidate_tags(int type, pgoff_t offset);
void mte_invalidate_tags_area(int type);
void *mte_allocate_tag_storage(void);
void mte_free_tag_storage(char *storage);
34

35 36
#ifdef CONFIG_ARM64_MTE

37 38 39
/* track which pages have valid allocation tags */
#define PG_mte_tagged	PG_arch_2

40
void mte_zero_clear_page_tags(void *addr);
41
void mte_sync_tags(pte_t *ptep, pte_t pte);
42
void mte_copy_page_tags(void *kto, const void *kfrom);
43
void mte_thread_init_user(void);
44
void mte_thread_switch(struct task_struct *next);
45
void mte_suspend_enter(void);
46
void mte_suspend_exit(void);
47 48
long set_mte_ctrl(struct task_struct *task, unsigned long arg);
long get_mte_ctrl(struct task_struct *task);
49 50
int mte_ptrace_copy_tags(struct task_struct *child, long request,
			 unsigned long addr, unsigned long data);
51

52
#else /* CONFIG_ARM64_MTE */
53

54 55 56
/* unused if !CONFIG_ARM64_MTE, silence the compiler */
#define PG_mte_tagged	0

57 58 59
static inline void mte_zero_clear_page_tags(void *addr)
{
}
60 61 62
static inline void mte_sync_tags(pte_t *ptep, pte_t pte)
{
}
63 64 65
static inline void mte_copy_page_tags(void *kto, const void *kfrom)
{
}
66
static inline void mte_thread_init_user(void)
67 68
{
}
69 70 71
static inline void mte_thread_switch(struct task_struct *next)
{
}
72 73 74
static inline void mte_suspend_enter(void)
{
}
75 76 77
static inline void mte_suspend_exit(void)
{
}
78
static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg)
79 80 81
{
	return 0;
}
82
static inline long get_mte_ctrl(struct task_struct *task)
83 84 85
{
	return 0;
}
86 87 88 89 90 91
static inline int mte_ptrace_copy_tags(struct task_struct *child,
				       long request, unsigned long addr,
				       unsigned long data)
{
	return -EIO;
}
92

93
#endif /* CONFIG_ARM64_MTE */
94

95 96 97 98 99 100 101 102
#ifdef CONFIG_KASAN_HW_TAGS
/* Whether the MTE asynchronous mode is enabled. */
DECLARE_STATIC_KEY_FALSE(mte_async_mode);

static inline bool system_uses_mte_async_mode(void)
{
	return static_branch_unlikely(&mte_async_mode);
}
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

void mte_check_tfsr_el1(void);

static inline void mte_check_tfsr_entry(void)
{
	mte_check_tfsr_el1();
}

static inline void mte_check_tfsr_exit(void)
{
	/*
	 * The asynchronous faults are sync'ed automatically with
	 * TFSR_EL1 on kernel entry but for exit an explicit dsb()
	 * is required.
	 */
	dsb(nsh);
	isb();

	mte_check_tfsr_el1();
}
123 124 125 126 127
#else
static inline bool system_uses_mte_async_mode(void)
{
	return false;
}
128 129 130 131 132 133 134 135 136
static inline void mte_check_tfsr_el1(void)
{
}
static inline void mte_check_tfsr_entry(void)
{
}
static inline void mte_check_tfsr_exit(void)
{
}
137 138
#endif /* CONFIG_KASAN_HW_TAGS */

139 140
#endif /* __ASSEMBLY__ */
#endif /* __ASM_MTE_H  */