@@ -4,12 +4,17 @@ use core::{arch, mem};
4
4
// Kernel-provided user-mode helper functions:
5
5
// https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
6
6
unsafe fn __kuser_cmpxchg ( oldval : u32 , newval : u32 , ptr : * mut u32 ) -> bool {
7
- let f: extern "C" fn ( u32 , u32 , * mut u32 ) -> u32 = mem:: transmute ( 0xffff0fc0usize as * const ( ) ) ;
7
+ // FIXME(volatile): the third parameter is a volatile pointer
8
+ // SAFETY: kernel docs specify a known address with the given signature
9
+ let f = unsafe {
10
+ mem:: transmute :: < _ , extern "C" fn ( u32 , u32 , * mut u32 ) -> u32 > ( 0xffff0fc0usize as * const ( ) )
11
+ } ;
8
12
f ( oldval, newval, ptr) == 0
9
13
}
10
14
11
15
unsafe fn __kuser_memory_barrier ( ) {
12
- let f: extern "C" fn ( ) = mem:: transmute ( 0xffff0fa0usize as * const ( ) ) ;
16
+ // SAFETY: kernel docs specify a known address with the given signature
17
+ let f = unsafe { mem:: transmute :: < _ , extern "C" fn ( ) > ( 0xffff0fa0usize as * const ( ) ) } ;
13
18
f ( ) ;
14
19
}
15
20
@@ -67,8 +72,10 @@ fn insert_aligned(aligned: u32, val: u32, shift: u32, mask: u32) -> u32 {
67
72
/// - if `size_of::<T>() == 2`, `ptr` or `ptr` offset by 2 bytes must be valid for a relaxed atomic
68
73
/// read of 2 bytes.
69
74
/// - if `size_of::<T>() == 4`, `ptr` must be valid for a relaxed atomic read of 4 bytes.
75
+ // FIXME: assert some of the preconditions in debug mode
70
76
unsafe fn atomic_load_aligned < T > ( ptr : * mut u32 ) -> u32 {
71
- if mem:: size_of :: < T > ( ) == 4 {
77
+ const { assert ! ( size_of:: <T >( ) <= 4 ) } ;
78
+ if size_of :: < T > ( ) == 4 {
72
79
// SAFETY: As `T` has a size of 4, the caller garantees this is sound.
73
80
unsafe { AtomicU32 :: from_ptr ( ptr) . load ( Ordering :: Relaxed ) }
74
81
} else {
@@ -100,11 +107,13 @@ unsafe fn atomic_rmw<T, F: Fn(u32) -> u32, G: Fn(u32, u32) -> u32>(ptr: *mut T,
100
107
let ( shift, mask) = get_shift_mask ( ptr) ;
101
108
102
109
loop {
103
- let curval_aligned = atomic_load_aligned :: < T > ( aligned_ptr) ;
110
+ // FIXME(safety): preconditions review needed
111
+ let curval_aligned = unsafe { atomic_load_aligned :: < T > ( aligned_ptr) } ;
104
112
let curval = extract_aligned ( curval_aligned, shift, mask) ;
105
113
let newval = f ( curval) ;
106
114
let newval_aligned = insert_aligned ( curval_aligned, newval, shift, mask) ;
107
- if __kuser_cmpxchg ( curval_aligned, newval_aligned, aligned_ptr) {
115
+ // FIXME(safety): preconditions review needed
116
+ if unsafe { __kuser_cmpxchg ( curval_aligned, newval_aligned, aligned_ptr) } {
108
117
return g ( curval, newval) ;
109
118
}
110
119
}
@@ -116,13 +125,15 @@ unsafe fn atomic_cmpxchg<T>(ptr: *mut T, oldval: u32, newval: u32) -> u32 {
116
125
let ( shift, mask) = get_shift_mask ( ptr) ;
117
126
118
127
loop {
119
- let curval_aligned = atomic_load_aligned :: < T > ( aligned_ptr) ;
128
+ // FIXME(safety): preconditions review needed
129
+ let curval_aligned = unsafe { atomic_load_aligned :: < T > ( aligned_ptr) } ;
120
130
let curval = extract_aligned ( curval_aligned, shift, mask) ;
121
131
if curval != oldval {
122
132
return curval;
123
133
}
124
134
let newval_aligned = insert_aligned ( curval_aligned, newval, shift, mask) ;
125
- if __kuser_cmpxchg ( curval_aligned, newval_aligned, aligned_ptr) {
135
+ // FIXME(safety): preconditions review needed
136
+ if unsafe { __kuser_cmpxchg ( curval_aligned, newval_aligned, aligned_ptr) } {
126
137
return oldval;
127
138
}
128
139
}
@@ -132,7 +143,14 @@ macro_rules! atomic_rmw {
132
143
( $name: ident, $ty: ty, $op: expr, $fetch: expr) => {
133
144
intrinsics! {
134
145
pub unsafe extern "C" fn $name( ptr: * mut $ty, val: $ty) -> $ty {
135
- atomic_rmw( ptr, |x| $op( x as $ty, val) as u32 , |old, new| $fetch( old, new) ) as $ty
146
+ // FIXME(safety): preconditions review needed
147
+ unsafe {
148
+ atomic_rmw(
149
+ ptr,
150
+ |x| $op( x as $ty, val) as u32 ,
151
+ |old, new| $fetch( old, new)
152
+ ) as $ty
153
+ }
136
154
}
137
155
}
138
156
} ;
@@ -149,7 +167,8 @@ macro_rules! atomic_cmpxchg {
149
167
( $name: ident, $ty: ty) => {
150
168
intrinsics! {
151
169
pub unsafe extern "C" fn $name( ptr: * mut $ty, oldval: $ty, newval: $ty) -> $ty {
152
- atomic_cmpxchg( ptr, oldval as u32 , newval as u32 ) as $ty
170
+ // FIXME(safety): preconditions review needed
171
+ unsafe { atomic_cmpxchg( ptr, oldval as u32 , newval as u32 ) as $ty }
153
172
}
154
173
}
155
174
} ;
@@ -285,6 +304,7 @@ atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32);
285
304
286
305
intrinsics ! {
287
306
pub unsafe extern "C" fn __sync_synchronize( ) {
288
- __kuser_memory_barrier( ) ;
307
+ // SAFETY: preconditions are the same as the calling function.
308
+ unsafe { __kuser_memory_barrier( ) } ;
289
309
}
290
310
}
0 commit comments