1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Non-trivial C macros cannot be used in Rust. Similarly, inlined C functions |
4 | * cannot be called either. This file explicitly creates functions ("helpers") |
5 | * that wrap those so that they can be called from Rust. |
6 | * |
7 | * Even though Rust kernel modules should never use directly the bindings, some |
8 | * of these helpers need to be exported because Rust generics and inlined |
9 | * functions may not get their code generated in the crate where they are |
10 | * defined. Other helpers, called from non-inline functions, may not be |
11 | * exported, in principle. However, in general, the Rust compiler does not |
12 | * guarantee codegen will be performed for a non-inline function either. |
13 | * Therefore, this file exports all the helpers. In the future, this may be |
14 | * revisited to reduce the number of exports after the compiler is informed |
15 | * about the places codegen is required. |
16 | * |
17 | * All symbols are exported as GPL-only to guarantee no GPL-only feature is |
18 | * accidentally exposed. |
19 | * |
20 | * Sorted alphabetically. |
21 | */ |
22 | |
23 | #include <kunit/test-bug.h> |
24 | #include <linux/bug.h> |
25 | #include <linux/build_bug.h> |
26 | #include <linux/err.h> |
27 | #include <linux/errname.h> |
28 | #include <linux/mutex.h> |
29 | #include <linux/refcount.h> |
30 | #include <linux/sched/signal.h> |
31 | #include <linux/spinlock.h> |
32 | #include <linux/wait.h> |
33 | #include <linux/workqueue.h> |
34 | |
35 | __noreturn void rust_helper_BUG(void) |
36 | { |
37 | BUG(); |
38 | } |
39 | EXPORT_SYMBOL_GPL(rust_helper_BUG); |
40 | |
41 | void rust_helper_mutex_lock(struct mutex *lock) |
42 | { |
43 | mutex_lock(lock); |
44 | } |
45 | EXPORT_SYMBOL_GPL(rust_helper_mutex_lock); |
46 | |
47 | void rust_helper___spin_lock_init(spinlock_t *lock, const char *name, |
48 | struct lock_class_key *key) |
49 | { |
50 | #ifdef CONFIG_DEBUG_SPINLOCK |
51 | __raw_spin_lock_init(lock: spinlock_check(lock), name, key, inner: LD_WAIT_CONFIG); |
52 | #else |
53 | spin_lock_init(lock); |
54 | #endif |
55 | } |
56 | EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init); |
57 | |
58 | void rust_helper_spin_lock(spinlock_t *lock) |
59 | { |
60 | spin_lock(lock); |
61 | } |
62 | EXPORT_SYMBOL_GPL(rust_helper_spin_lock); |
63 | |
64 | void rust_helper_spin_unlock(spinlock_t *lock) |
65 | { |
66 | spin_unlock(lock); |
67 | } |
68 | EXPORT_SYMBOL_GPL(rust_helper_spin_unlock); |
69 | |
70 | void rust_helper_init_wait(struct wait_queue_entry *wq_entry) |
71 | { |
72 | init_wait(wq_entry); |
73 | } |
74 | EXPORT_SYMBOL_GPL(rust_helper_init_wait); |
75 | |
76 | int rust_helper_signal_pending(struct task_struct *t) |
77 | { |
78 | return signal_pending(p: t); |
79 | } |
80 | EXPORT_SYMBOL_GPL(rust_helper_signal_pending); |
81 | |
82 | refcount_t rust_helper_REFCOUNT_INIT(int n) |
83 | { |
84 | return (refcount_t)REFCOUNT_INIT(n); |
85 | } |
86 | EXPORT_SYMBOL_GPL(rust_helper_REFCOUNT_INIT); |
87 | |
88 | void rust_helper_refcount_inc(refcount_t *r) |
89 | { |
90 | refcount_inc(r); |
91 | } |
92 | EXPORT_SYMBOL_GPL(rust_helper_refcount_inc); |
93 | |
94 | bool rust_helper_refcount_dec_and_test(refcount_t *r) |
95 | { |
96 | return refcount_dec_and_test(r); |
97 | } |
98 | EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test); |
99 | |
100 | __force void *rust_helper_ERR_PTR(long err) |
101 | { |
102 | return ERR_PTR(error: err); |
103 | } |
104 | EXPORT_SYMBOL_GPL(rust_helper_ERR_PTR); |
105 | |
106 | bool rust_helper_IS_ERR(__force const void *ptr) |
107 | { |
108 | return IS_ERR(ptr); |
109 | } |
110 | EXPORT_SYMBOL_GPL(rust_helper_IS_ERR); |
111 | |
112 | long rust_helper_PTR_ERR(__force const void *ptr) |
113 | { |
114 | return PTR_ERR(ptr); |
115 | } |
116 | EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR); |
117 | |
118 | const char *rust_helper_errname(int err) |
119 | { |
120 | return errname(err); |
121 | } |
122 | EXPORT_SYMBOL_GPL(rust_helper_errname); |
123 | |
124 | struct task_struct *rust_helper_get_current(void) |
125 | { |
126 | return current; |
127 | } |
128 | EXPORT_SYMBOL_GPL(rust_helper_get_current); |
129 | |
130 | void rust_helper_get_task_struct(struct task_struct *t) |
131 | { |
132 | get_task_struct(t); |
133 | } |
134 | EXPORT_SYMBOL_GPL(rust_helper_get_task_struct); |
135 | |
136 | void rust_helper_put_task_struct(struct task_struct *t) |
137 | { |
138 | put_task_struct(t); |
139 | } |
140 | EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); |
141 | |
142 | struct kunit *rust_helper_kunit_get_current_test(void) |
143 | { |
144 | return kunit_get_current_test(); |
145 | } |
146 | EXPORT_SYMBOL_GPL(rust_helper_kunit_get_current_test); |
147 | |
148 | void rust_helper_init_work_with_key(struct work_struct *work, work_func_t func, |
149 | bool onstack, const char *name, |
150 | struct lock_class_key *key) |
151 | { |
152 | __init_work(work, onstack); |
153 | work->data = (atomic_long_t)WORK_DATA_INIT(); |
154 | lockdep_init_map(lock: &work->lockdep_map, name, key, subclass: 0); |
155 | INIT_LIST_HEAD(list: &work->entry); |
156 | work->func = func; |
157 | } |
158 | EXPORT_SYMBOL_GPL(rust_helper_init_work_with_key); |
159 | |
160 | /* |
161 | * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can |
162 | * use it in contexts where Rust expects a `usize` like slice (array) indices. |
163 | * `usize` is defined to be the same as C's `uintptr_t` type (can hold any |
164 | * pointer) but not necessarily the same as `size_t` (can hold the size of any |
165 | * single object). Most modern platforms use the same concrete integer type for |
166 | * both of them, but in case we find ourselves on a platform where |
167 | * that's not true, fail early instead of risking ABI or |
168 | * integer-overflow issues. |
169 | * |
170 | * If your platform fails this assertion, it means that you are in |
171 | * danger of integer-overflow bugs (even if you attempt to add |
172 | * `--no-size_t-is-usize`). It may be easiest to change the kernel ABI on |
173 | * your platform such that `size_t` matches `uintptr_t` (i.e., to increase |
174 | * `size_t`, because `uintptr_t` has to be at least as big as `size_t`). |
175 | */ |
176 | static_assert( |
177 | sizeof(size_t) == sizeof(uintptr_t) && |
178 | __alignof__(size_t) == __alignof__(uintptr_t), |
179 | "Rust code expects C `size_t` to match Rust `usize`" |
180 | ); |
181 | |