feat(boot): Replace r0 dependency

Use pointer provenance to guarantee absence of UBs.
This commit is contained in:
Berkus Decker 2022-09-18 01:02:42 +03:00 committed by Berkus Decker
parent 568fdcb649
commit dae26262bc
11 changed files with 44 additions and 23 deletions

9
Cargo.lock generated
View File

@ -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"

View File

@ -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 }

View File

@ -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(

View File

@ -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

View File

@ -93,6 +93,6 @@ SECTIONS
__bss_start = .;
*(.bss*);
. = ALIGN(16);
__bss_end_exclusive = .;
__bss_size = . - __bss_start;
} :segment_data
}

View File

@ -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*) }

View File

@ -28,7 +28,6 @@ rpi3 = []
rpi4 = []
[dependencies]
r0 = "1.0"
qemu-exit = "3.0"
cortex-a = "7.5"
tock-registers = "0.7"

View File

@ -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() -> !;

View File

@ -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)]

View File

@ -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 }

View File

@ -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;