feat(boot): ✨ Replace r0 dependency
Use pointer provenance to guarantee absence of UBs.
This commit is contained in:
parent
568fdcb649
commit
dae26262bc
|
@ -99,7 +99,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"cortex-a",
|
||||
"machine",
|
||||
"r0",
|
||||
"seahash",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
|
@ -389,7 +388,6 @@ dependencies = [
|
|||
"cortex-a",
|
||||
"once_cell",
|
||||
"qemu-exit",
|
||||
"r0",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
|
@ -458,7 +456,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"cortex-a",
|
||||
"machine",
|
||||
"r0",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
|
@ -546,12 +543,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
|
|
|
@ -27,7 +27,6 @@ rpi4 = ["machine/rpi4"]
|
|||
|
||||
[dependencies]
|
||||
machine = { path = "../../machine" }
|
||||
r0 = "1.0"
|
||||
cortex-a = "7.5"
|
||||
tock-registers = "0.7"
|
||||
ux = { version = "0.1", default-features = false }
|
||||
|
|
|
@ -28,7 +28,7 @@ pub unsafe extern "C" fn _start() -> ! {
|
|||
extern "Rust" {
|
||||
// Boundaries of the .bss section, provided by the linker script
|
||||
static __bss_start: UnsafeCell<()>;
|
||||
static __bss_end_exclusive: UnsafeCell<()>;
|
||||
static __bss_size: UnsafeCell<()>;
|
||||
// Load address of the kernel binary
|
||||
static __binary_nonzero_lma: UnsafeCell<()>;
|
||||
// Address to relocate to and image size
|
||||
|
@ -42,7 +42,11 @@ pub unsafe extern "C" fn _start() -> ! {
|
|||
SP.set(__boot_core_stack_end_exclusive.get() as u64);
|
||||
|
||||
// Zeroes the .bss section
|
||||
r0::zero_bss(__bss_start.get() as u64, __bss_end_exclusive.get() as u64);
|
||||
let bss =
|
||||
core::slice::from_raw_parts_mut(__bss_start.get() as *mut u8, __bss_size.get() as usize);
|
||||
for i in bss {
|
||||
*i = 0;
|
||||
}
|
||||
|
||||
// Relocate the code
|
||||
core::ptr::copy_nonoverlapping(
|
||||
|
|
|
@ -50,7 +50,8 @@ _start:
|
|||
|
||||
// Initialize bss.
|
||||
ADR_ABS x0, __bss_start
|
||||
ADR_ABS x1, __bss_end_exclusive
|
||||
ADR_ABS x1, __bss_size
|
||||
add x1, x0, x1
|
||||
|
||||
.L_bss_init_loop:
|
||||
cmp x0, x1
|
||||
|
|
|
@ -93,6 +93,6 @@ SECTIONS
|
|||
__bss_start = .;
|
||||
*(.bss*);
|
||||
. = ALIGN(16);
|
||||
__bss_end_exclusive = .;
|
||||
__bss_size = . - __bss_start;
|
||||
} :segment_data
|
||||
}
|
||||
|
|
|
@ -58,7 +58,8 @@ SECTIONS
|
|||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(PAGE_SIZE); /* Align up to page size */
|
||||
__BSS_END = .;
|
||||
__BSS_SIZE = . - __BSS_START;
|
||||
/* __BSS_END = .; unused */
|
||||
}
|
||||
|
||||
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
|
||||
|
|
|
@ -28,7 +28,6 @@ rpi3 = []
|
|||
rpi4 = []
|
||||
|
||||
[dependencies]
|
||||
r0 = "1.0"
|
||||
qemu-exit = "3.0"
|
||||
cortex-a = "7.5"
|
||||
tock-registers = "0.7"
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
|
||||
use {
|
||||
crate::endless_sleep,
|
||||
core::{
|
||||
cell::UnsafeCell,
|
||||
slice,
|
||||
sync::atomic::{self, Ordering},
|
||||
},
|
||||
cortex_a::{asm, registers::*},
|
||||
tock_registers::interfaces::{Readable, Writeable},
|
||||
};
|
||||
|
@ -43,15 +48,33 @@ macro_rules! entry {
|
|||
/// Totally unsafe! We're in the hardware land.
|
||||
#[link_section = ".text.boot"]
|
||||
unsafe fn reset() -> ! {
|
||||
extern "C" {
|
||||
// Boundaries of the .bss section, provided by the linker script
|
||||
// The type, `u64`, indicates that the memory is 8-byte aligned
|
||||
static mut __BSS_START: u64;
|
||||
static mut __BSS_END: u64;
|
||||
extern "Rust" {
|
||||
// Boundaries of the .bss section, provided by the linker script.
|
||||
static __BSS_START: UnsafeCell<()>;
|
||||
static __BSS_SIZE: UnsafeCell<()>;
|
||||
}
|
||||
|
||||
// Zeroes the .bss section
|
||||
r0::zero_bss(&mut __BSS_START, &mut __BSS_END);
|
||||
// Based on https://gist.github.com/skoe/dbd3add2fc3baa600e9ebc995ddf0302 and discussions
|
||||
// on pointer provenance in closing r0 issues (https://github.com/rust-embedded/cortex-m-rt/issues/300)
|
||||
|
||||
// NB: https://doc.rust-lang.org/nightly/core/ptr/index.html#provenance
|
||||
// Importing pointers like `__BSS_START` and `__BSS_END` and performing pointer
|
||||
// arithmetic on them directly may lead to Undefined Behavior, because the
|
||||
// compiler may assume they come from different allocations and thus performing
|
||||
// undesirable optimizations on them.
|
||||
// So we use a painter-and-a-size as described in provenance section.
|
||||
|
||||
let bss = slice::from_raw_parts_mut(__BSS_START.get() as *mut u8, __BSS_SIZE.get() as usize);
|
||||
for i in bss {
|
||||
*i = 0;
|
||||
}
|
||||
|
||||
// Don't cross this line with loads and stores. The initializations
|
||||
// done above could be "invisible" to the compiler, because we write to the
|
||||
// same memory location that is used by statics after this point.
|
||||
// Additionally, we assume that no statics are accessed before this point.
|
||||
atomic::compiler_fence(Ordering::SeqCst);
|
||||
|
||||
extern "Rust" {
|
||||
fn main() -> !;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![feature(allocator_api)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
|
|
|
@ -28,7 +28,6 @@ rpi4 = ["machine/rpi4"]
|
|||
|
||||
[dependencies]
|
||||
machine = { path = "../machine" }
|
||||
r0 = "1.0"
|
||||
cortex-a = "7.5"
|
||||
tock-registers = "0.7"
|
||||
ux = { version = "0.1", default-features = false }
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
#![no_main]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(machine::tests::test_runner)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![deny(missing_docs)]
|
||||
#![deny(warnings)]
|
||||
#![deny(unused)]
|
||||
#![feature(allocator_api)]
|
||||
|
||||
#[cfg(not(test))]
|
||||
use core::panic::PanicInfo;
|
||||
|
|
Loading…
Reference in New Issue