xref: /linux/tools/testing/vma/include/custom.h (revision bd44d91d0ccc6da5ed91844b89a23a7df4938548)
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 
3 #pragma once
4 
5 /*
6  * Contains declarations that exist in the kernel which have been CUSTOMISED for
7  * testing purposes to faciliate userland VMA testing.
8  */
9 
10 #ifdef CONFIG_MMU
11 extern unsigned long mmap_min_addr;
12 extern unsigned long dac_mmap_min_addr;
13 #else
14 #define mmap_min_addr		0UL
15 #define dac_mmap_min_addr	0UL
16 #endif
17 
18 #define VM_WARN_ON(_expr) (WARN_ON(_expr))
19 #define VM_WARN_ON_ONCE(_expr) (WARN_ON_ONCE(_expr))
20 #define VM_WARN_ON_VMG(_expr, _vmg) (WARN_ON(_expr))
21 #define VM_BUG_ON(_expr) (BUG_ON(_expr))
22 #define VM_BUG_ON_VMA(_expr, _vma) (BUG_ON(_expr))
23 
24 #define TASK_SIZE ((1ul << 47)-PAGE_SIZE)
25 
26 /*
27  * The shared stubs do not implement this, it amounts to an fprintf(STDERR,...)
28  * either way :)
29  */
30 #define pr_warn_once pr_err
31 
32 #define pgtable_supports_soft_dirty() 1
33 
34 struct anon_vma {
35 	struct anon_vma *root;
36 	struct rb_root_cached rb_root;
37 
38 	/* Test fields. */
39 	bool was_cloned;
40 	bool was_unlinked;
41 };
42 
43 static inline void unlink_anon_vmas(struct vm_area_struct *vma)
44 {
45 	/* For testing purposes, indicate that the anon_vma was unlinked. */
46 	vma->anon_vma->was_unlinked = true;
47 }
48 
49 static inline void vma_start_write(struct vm_area_struct *vma)
50 {
51 	/* Used to indicate to tests that a write operation has begun. */
52 	vma->vm_lock_seq++;
53 }
54 
55 static inline __must_check
56 int vma_start_write_killable(struct vm_area_struct *vma)
57 {
58 	/* Used to indicate to tests that a write operation has begun. */
59 	vma->vm_lock_seq++;
60 	return 0;
61 }
62 
63 static inline int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
64 				 enum vma_operation operation)
65 {
66 	/* For testing purposes. We indicate that an anon_vma has been cloned. */
67 	if (src->anon_vma != NULL) {
68 		dst->anon_vma = src->anon_vma;
69 		dst->anon_vma->was_cloned = true;
70 	}
71 
72 	return 0;
73 }
74 
75 static inline int __anon_vma_prepare(struct vm_area_struct *vma)
76 {
77 	struct anon_vma *anon_vma = calloc(1, sizeof(struct anon_vma));
78 
79 	if (!anon_vma)
80 		return -ENOMEM;
81 
82 	anon_vma->root = anon_vma;
83 	vma->anon_vma = anon_vma;
84 
85 	return 0;
86 }
87 
88 static inline int anon_vma_prepare(struct vm_area_struct *vma)
89 {
90 	if (likely(vma->anon_vma))
91 		return 0;
92 
93 	return __anon_vma_prepare(vma);
94 }
95 
96 static inline void vma_lock_init(struct vm_area_struct *vma, bool reset_refcnt)
97 {
98 	if (reset_refcnt)
99 		refcount_set(&vma->vm_refcnt, 0);
100 }
101 
102 static __always_inline vma_flags_t __mk_vma_flags(size_t count,
103 		const vma_flag_t *bits)
104 {
105 	vma_flags_t flags;
106 	int i;
107 
108 	/*
109 	 * For testing purposes: allow invalid bit specification so we can
110 	 * easily test.
111 	 */
112 	vma_flags_clear_all(&flags);
113 	for (i = 0; i < count; i++)
114 		if (bits[i] < NUM_VMA_FLAG_BITS)
115 			vma_flags_set_flag(&flags, bits[i]);
116 	return flags;
117 }
118 
119 static inline unsigned long vma_kernel_pagesize(struct vm_area_struct *vma)
120 {
121 	return PAGE_SIZE;
122 }
123 
124 /* Place here until needed in the kernel code. */
125 static __always_inline bool vma_flags_same_mask(vma_flags_t *flags,
126 						vma_flags_t flags_other)
127 {
128 	const unsigned long *bitmap = flags->__vma_flags;
129 	const unsigned long *bitmap_other = flags_other.__vma_flags;
130 
131 	return bitmap_equal(bitmap, bitmap_other, NUM_VMA_FLAG_BITS);
132 }
133 #define vma_flags_same(flags, ...) \
134 	vma_flags_same_mask(flags, mk_vma_flags(__VA_ARGS__))
135 #define VMA_SPECIAL_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_DONTEXPAND_BIT, \
136 				       VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)
137 #ifdef CONFIG_MEM_SOFT_DIRTY
138 #define VMA_STICKY_FLAGS mk_vma_flags(VMA_SOFTDIRTY_BIT, VMA_MAYBE_GUARD_BIT)
139 #else
140 #define VMA_STICKY_FLAGS mk_vma_flags(VMA_MAYBE_GUARD_BIT)
141 #endif
142