1459: rp/multicore: fix undefined behavior in multicore spawn. r=Dirbaio a=Dirbaio

It is UB to pass `entry` to core1 as `&mut`, because core0 keeps an aliasing pointer to that memory region, and actually writes to it (when `spawn_core1` returns, the stack frame gets deallocated and the memory gets reused). This violates noalias requirements.

Added the fence just in case, een though it works without.

bors r+

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
bors[bot] 2023-05-15 23:26:58 +00:00 committed by GitHub
commit 34a0c2172b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -122,11 +122,16 @@ where
extern "C" fn core1_startup<F: FnOnce() -> bad::Never>( extern "C" fn core1_startup<F: FnOnce() -> bad::Never>(
_: u64, _: u64,
_: u64, _: u64,
entry: &mut ManuallyDrop<F>, entry: *mut ManuallyDrop<F>,
stack_bottom: *mut usize, stack_bottom: *mut usize,
) -> ! { ) -> ! {
core1_setup(stack_bottom); core1_setup(stack_bottom);
let entry = unsafe { ManuallyDrop::take(entry) };
let entry = unsafe { ManuallyDrop::take(&mut *entry) };
// make sure the preceding read doesn't get reordered past the following fifo write
compiler_fence(Ordering::SeqCst);
// Signal that it's safe for core 0 to get rid of the original value now. // Signal that it's safe for core 0 to get rid of the original value now.
fifo_write(1); fifo_write(1);
@ -164,7 +169,7 @@ where
// Push `entry`. // Push `entry`.
stack_ptr = stack_ptr.sub(1); stack_ptr = stack_ptr.sub(1);
stack_ptr.cast::<&mut ManuallyDrop<F>>().write(&mut entry); stack_ptr.cast::<*mut ManuallyDrop<F>>().write(&mut entry);
} }
// Make sure the compiler does not reorder the stack writes after to after the // Make sure the compiler does not reorder the stack writes after to after the