refactor: 📦 Improve boot code structure
Rename sections to not conflict during link. Update linker script docs to align on PAGE_SIZE.
This commit is contained in:
		
							parent
							
								
									12f51399df
								
							
						
					
					
						commit
						afbb317403
					
				| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// Make first function small enough so that compiler doesn't try
 | 
			
		||||
// to crate a huge stack frame before we have a chance to set SP.
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
#[link_section = ".text._start"]
 | 
			
		||||
#[link_section = ".text.chainboot.entry"]
 | 
			
		||||
pub unsafe extern "C" fn _start() -> ! {
 | 
			
		||||
    use {
 | 
			
		||||
        core::cell::UnsafeCell,
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ pub unsafe extern "C" fn _start() -> ! {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
#[link_section = ".text._start"]
 | 
			
		||||
#[link_section = ".text.chainboot"]
 | 
			
		||||
pub unsafe extern "C" fn reset() -> ! {
 | 
			
		||||
    use core::{
 | 
			
		||||
        cell::UnsafeCell,
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +40,8 @@ pub unsafe extern "C" fn reset() -> ! {
 | 
			
		|||
    // Subsequently, this code tries to read values from not-yet-existing data locations.
 | 
			
		||||
    extern "Rust" {
 | 
			
		||||
        // Boundaries of the .bss section, provided by the linker script
 | 
			
		||||
        static __bss_start: UnsafeCell<()>;
 | 
			
		||||
        static __bss_size: UnsafeCell<()>;
 | 
			
		||||
        static __BSS_START: UnsafeCell<()>;
 | 
			
		||||
        static __BSS_SIZE_U64S: UnsafeCell<()>;
 | 
			
		||||
        // Load address of the kernel binary
 | 
			
		||||
        static __binary_nonzero_lma: UnsafeCell<()>;
 | 
			
		||||
        // Address to relocate to and image size
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +73,10 @@ pub unsafe extern "C" fn reset() -> ! {
 | 
			
		|||
    // Zeroes the .bss section
 | 
			
		||||
    // Emulate
 | 
			
		||||
    // crate::stdmem::local_memset(__bss_start.get() as *mut u8, 0u8, __bss_size.get() as usize);
 | 
			
		||||
    let bss =
 | 
			
		||||
        core::slice::from_raw_parts_mut(__bss_start.get() as *mut u8, __bss_size.get() as usize);
 | 
			
		||||
    let bss = core::slice::from_raw_parts_mut(
 | 
			
		||||
        __BSS_START.get() as *mut u64,
 | 
			
		||||
        __BSS_SIZE_U64S.get() as usize,
 | 
			
		||||
    );
 | 
			
		||||
    for i in bss {
 | 
			
		||||
        *i = 0;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +93,7 @@ pub unsafe extern "C" fn reset() -> ! {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
#[link_section = ".text.boot"]
 | 
			
		||||
#[link_section = ".text.chainboot"]
 | 
			
		||||
unsafe fn local_memcpy(mut dest: *mut u8, mut src: *const u8, n: usize) {
 | 
			
		||||
    let dest_end = dest.add(n);
 | 
			
		||||
    while dest < dest_end {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,8 +51,8 @@ SECTIONS
 | 
			
		|||
 | 
			
		||||
    .text :
 | 
			
		||||
    {
 | 
			
		||||
        KEEP(*(.text._start))
 | 
			
		||||
        *(.text.stdmem)
 | 
			
		||||
        KEEP(*(.text.chainboot.entry))
 | 
			
		||||
        *(.text.chainboot)
 | 
			
		||||
    } :segment_start_code
 | 
			
		||||
 | 
			
		||||
    /* Align to 8 bytes, b/c relocating the binary is done in u64 chunks */
 | 
			
		||||
| 
						 | 
				
			
			@ -70,9 +70,7 @@ SECTIONS
 | 
			
		|||
    __binary_nonzero_vma = .;
 | 
			
		||||
    .text : AT (ADDR(.text) + SIZEOF(.text))
 | 
			
		||||
    {
 | 
			
		||||
        *(.text._start_rust)      /* The Rust entry point */
 | 
			
		||||
        /* *(text.memcpy) -- only relevant for Rust relocator impl which is currently impossible */
 | 
			
		||||
        *(.text*)                 /* Everything else */
 | 
			
		||||
        *(.text*)                 /* The Rust entry point and everything else */
 | 
			
		||||
    } :segment_code
 | 
			
		||||
 | 
			
		||||
    .rodata : ALIGN(8) { *(.rodata*) } :segment_code
 | 
			
		||||
| 
						 | 
				
			
			@ -87,12 +85,15 @@ SECTIONS
 | 
			
		|||
    . = ALIGN(8);
 | 
			
		||||
    __binary_nonzero_vma_end_exclusive = .;
 | 
			
		||||
 | 
			
		||||
    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
 | 
			
		||||
    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes at least */
 | 
			
		||||
    .bss (NOLOAD) : ALIGN(16)
 | 
			
		||||
    {
 | 
			
		||||
        __bss_start = .;
 | 
			
		||||
        *(.bss*);
 | 
			
		||||
        . = ALIGN(16);
 | 
			
		||||
        __bss_size = . - __bss_start;
 | 
			
		||||
        __BSS_START = .;
 | 
			
		||||
        *(.bss .bss.*)
 | 
			
		||||
        *(COMMON)
 | 
			
		||||
        . = ALIGN(PAGE_SIZE); /* Align up to page size */
 | 
			
		||||
        __BSS_SIZE_U64S = (. - __BSS_START) / 8;
 | 
			
		||||
    } :segment_data
 | 
			
		||||
 | 
			
		||||
    /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) *(.text.boot*)}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
#![reexport_test_harness_main = "test_main"]
 | 
			
		||||
#![no_main]
 | 
			
		||||
#![no_std]
 | 
			
		||||
#![no_builtins]
 | 
			
		||||
 | 
			
		||||
use {
 | 
			
		||||
    core::{hash::Hasher, panic::PanicInfo},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ PAGE_SIZE = 65536;
 | 
			
		|||
 | 
			
		||||
/* Symbols between __BOOT_START and __BOOT_END should be dropped after init is complete.
 | 
			
		||||
   Symbols between __RO_START and __RO_END are the kernel code.
 | 
			
		||||
   Symbols between __BSS_START and __BSS_END must be initialized to zero by r0 code in kernel.
 | 
			
		||||
   Symbols between __BSS_START and __BSS_END must be initialized to zero by startup code in the kernel.
 | 
			
		||||
*/
 | 
			
		||||
SECTIONS
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -20,12 +20,12 @@ SECTIONS
 | 
			
		|||
    __BOOT_START = .;
 | 
			
		||||
    .text :
 | 
			
		||||
    {
 | 
			
		||||
        KEEP(*(.text.boot.entry)) // Entry point must go first
 | 
			
		||||
        KEEP(*(.text.main.entry)) // Entry point must go first
 | 
			
		||||
        *(.text.boot)
 | 
			
		||||
        //. = ALIGN(PAGE_SIZE);
 | 
			
		||||
        *(.data.boot)
 | 
			
		||||
        . = ALIGN(PAGE_SIZE); /* Here boot code ends */
 | 
			
		||||
        __BOOT_END = .; // __BOOT_END must be 4KiB aligned
 | 
			
		||||
        . = ALIGN(PAGE_SIZE); /* Here the boot code ends */
 | 
			
		||||
        __BOOT_END = .; // __BOOT_END must be PAGE_SIZE aligned
 | 
			
		||||
        __RO_START = .;
 | 
			
		||||
        *(.text .text.*)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -41,8 +41,8 @@ SECTIONS
 | 
			
		|||
        FILL(0x00)
 | 
			
		||||
    }
 | 
			
		||||
    . = ALIGN(PAGE_SIZE); /* Fill up to page size */
 | 
			
		||||
    __RO_END = .; /* __RO_END must be 4KiB aligned */
 | 
			
		||||
    __DATA_START = .; /* __DATA_START must be 4KiB aligned */
 | 
			
		||||
    __RO_END = .; /* __RO_END must be PAGE_SIZE aligned */
 | 
			
		||||
    __DATA_START = .; /* __DATA_START must be PAGE_SIZE aligned */
 | 
			
		||||
 | 
			
		||||
    .data : /* @todo align data to 4K -- it's already aligned up to __RO_END marker now */
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -58,11 +58,11 @@ SECTIONS
 | 
			
		|||
        *(.bss .bss.*)
 | 
			
		||||
        *(COMMON)
 | 
			
		||||
        . = ALIGN(PAGE_SIZE); /* Align up to page size */
 | 
			
		||||
        __BSS_SIZE = . - __BSS_START;
 | 
			
		||||
        /* __BSS_END = .; unused */
 | 
			
		||||
        __BSS_END = .;
 | 
			
		||||
        __BSS_SIZE_U64S = (__BSS_END - __BSS_START) / 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
 | 
			
		||||
    /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) *(.text.chainboot*) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PROVIDE(current_el0_synchronous   = default_exception_handler);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,6 @@ use {
 | 
			
		|||
    tock_registers::interfaces::{Readable, Writeable},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Stack placed before first executable instruction
 | 
			
		||||
const STACK_START: u64 = 0x0008_0000; // Keep in sync with linker script
 | 
			
		||||
 | 
			
		||||
/// Type check the user-supplied entry function.
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! entry {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,71 +36,58 @@ macro_rules! entry {
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Reset function.
 | 
			
		||||
/// Entrypoint of the processor.
 | 
			
		||||
///
 | 
			
		||||
/// Initializes the bss section before calling into the user's `main()`.
 | 
			
		||||
/// Parks all cores except core0 and checks if we started in EL2/EL3. If
 | 
			
		||||
/// so, proceeds with setting up EL1.
 | 
			
		||||
///
 | 
			
		||||
/// This is invoked from the linker script, does arch-specific init
 | 
			
		||||
/// and passes control to the kernel boot function reset().
 | 
			
		||||
///
 | 
			
		||||
/// Dissection of various RPi core boot stubs is available
 | 
			
		||||
/// [here](https://leiradel.github.io/2019/01/20/Raspberry-Pi-Stubs.html).
 | 
			
		||||
///
 | 
			
		||||
/// # Safety
 | 
			
		||||
///
 | 
			
		||||
/// Totally unsafe! We're in the hardware land.
 | 
			
		||||
/// We assume that no statics are accessed before transition to main from this function.
 | 
			
		||||
#[link_section = ".text.boot"]
 | 
			
		||||
unsafe fn reset() -> ! {
 | 
			
		||||
    extern "Rust" {
 | 
			
		||||
        // Boundaries of the .bss section, provided by the linker script.
 | 
			
		||||
        static __BSS_START: UnsafeCell<()>;
 | 
			
		||||
        static __BSS_SIZE: UnsafeCell<()>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Zeroes the .bss section
 | 
			
		||||
    // 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);
 | 
			
		||||
/// We assume that no statics are accessed before transition to main from reset() function.
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
#[link_section = ".text.main.entry"]
 | 
			
		||||
pub unsafe extern "C" fn _boot_cores() -> ! {
 | 
			
		||||
    const CORE_0: u64 = 0;
 | 
			
		||||
    const CORE_MASK: u64 = 0x3;
 | 
			
		||||
    // Can't match values with dots in match, so use intermediate consts.
 | 
			
		||||
    #[cfg(qemu)]
 | 
			
		||||
    const EL3: u64 = CurrentEL::EL::EL3.value;
 | 
			
		||||
    const EL2: u64 = CurrentEL::EL::EL2.value;
 | 
			
		||||
    const EL1: u64 = CurrentEL::EL::EL1.value;
 | 
			
		||||
 | 
			
		||||
    extern "Rust" {
 | 
			
		||||
        fn main() -> !;
 | 
			
		||||
        // Stack top
 | 
			
		||||
        // Stack placed before first executable instruction
 | 
			
		||||
        static __STACK_START: UnsafeCell<()>;
 | 
			
		||||
    }
 | 
			
		||||
    // Set stack pointer. Used in case we started in EL1.
 | 
			
		||||
    SP.set(__STACK_START.get() as u64);
 | 
			
		||||
 | 
			
		||||
    shared_setup_and_enter_pre();
 | 
			
		||||
 | 
			
		||||
    if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
 | 
			
		||||
        match CurrentEL.get() {
 | 
			
		||||
            #[cfg(qemu)]
 | 
			
		||||
            EL3 => setup_and_enter_el1_from_el3(),
 | 
			
		||||
            EL2 => setup_and_enter_el1_from_el2(),
 | 
			
		||||
            EL1 => reset(),
 | 
			
		||||
            _ => endless_sleep(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    main()
 | 
			
		||||
    // if not core0 or not EL3/EL2/EL1, infinitely wait for events
 | 
			
		||||
    endless_sleep()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// [ARMv6 unaligned data access restrictions](https://developer.arm.com/documentation/ddi0333/h/unaligned-and-mixed-endian-data-access-support/unaligned-access-support/armv6-unaligned-data-access-restrictions?lang=en)
 | 
			
		||||
// dictates that compatibility bit U in CP15 must be set to 1 to allow Unaligned accesses while MMU is off.
 | 
			
		||||
// (In addition to SCTLR_EL1.A being 0)
 | 
			
		||||
// See also [CP15 C1 docs](https://developer.arm.com/documentation/ddi0290/g/system-control-coprocessor/system-control-processor-registers/c1--control-register).
 | 
			
		||||
// #[link_section = ".text.boot"]
 | 
			
		||||
// #[inline]
 | 
			
		||||
// fn enable_armv6_unaligned_access() {
 | 
			
		||||
//     unsafe {
 | 
			
		||||
//         core::arch::asm!(
 | 
			
		||||
//             "mrc p15, 0, {u}, c1, c0, 0",
 | 
			
		||||
//             "or {u}, {u}, {CR_U}",
 | 
			
		||||
//             "mcr p15, 0, {u}, c1, c0, 0",
 | 
			
		||||
//             u = out(reg) _,
 | 
			
		||||
//             CR_U = const 1 << 22
 | 
			
		||||
//         );
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
#[link_section = ".text.boot"]
 | 
			
		||||
#[inline]
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
fn shared_setup_and_enter_pre() {
 | 
			
		||||
    // Enable timer counter registers for EL1
 | 
			
		||||
    CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET);
 | 
			
		||||
| 
						 | 
				
			
			@ -136,9 +120,15 @@ fn shared_setup_and_enter_pre() {
 | 
			
		|||
#[link_section = ".text.boot"]
 | 
			
		||||
#[inline]
 | 
			
		||||
fn shared_setup_and_enter_post() -> ! {
 | 
			
		||||
    extern "Rust" {
 | 
			
		||||
        // Stack top
 | 
			
		||||
        static __STACK_START: UnsafeCell<()>;
 | 
			
		||||
    }
 | 
			
		||||
    // Set up SP_EL1 (stack pointer), which will be used by EL1 once
 | 
			
		||||
    // we "return" to it.
 | 
			
		||||
    SP_EL1.set(STACK_START);
 | 
			
		||||
    unsafe {
 | 
			
		||||
        SP_EL1.set(__STACK_START.get() as u64);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Use `eret` to "return" to EL1. This will result in execution of
 | 
			
		||||
    // `reset()` in EL1.
 | 
			
		||||
| 
						 | 
				
			
			@ -206,47 +196,52 @@ fn setup_and_enter_el1_from_el3() -> ! {
 | 
			
		|||
    shared_setup_and_enter_post()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Entrypoint of the processor.
 | 
			
		||||
/// Reset function.
 | 
			
		||||
///
 | 
			
		||||
/// Parks all cores except core0 and checks if we started in EL2/EL3. If
 | 
			
		||||
/// so, proceeds with setting up EL1.
 | 
			
		||||
///
 | 
			
		||||
/// This is invoked from the linker script, does arch-specific init
 | 
			
		||||
/// and passes control to the kernel boot function reset().
 | 
			
		||||
///
 | 
			
		||||
/// Dissection of various RPi core boot stubs is available
 | 
			
		||||
/// [here](https://leiradel.github.io/2019/01/20/Raspberry-Pi-Stubs.html).
 | 
			
		||||
/// Initializes the bss section before calling into the user's `main()`.
 | 
			
		||||
///
 | 
			
		||||
/// # Safety
 | 
			
		||||
///
 | 
			
		||||
/// Totally unsafe! We're in the hardware land.
 | 
			
		||||
/// We assume that no statics are accessed before transition to main from reset() function.
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
#[link_section = ".text.boot.entry"]
 | 
			
		||||
pub unsafe extern "C" fn _boot_cores() -> ! {
 | 
			
		||||
    const CORE_0: u64 = 0;
 | 
			
		||||
    const CORE_MASK: u64 = 0x3;
 | 
			
		||||
    // Can't match values with dots in match, so use intermediate consts.
 | 
			
		||||
    #[cfg(qemu)]
 | 
			
		||||
    const EL3: u64 = CurrentEL::EL::EL3.value;
 | 
			
		||||
    const EL2: u64 = CurrentEL::EL::EL2.value;
 | 
			
		||||
    const EL1: u64 = CurrentEL::EL::EL1.value;
 | 
			
		||||
 | 
			
		||||
    // Set stack pointer. Used in case we started in EL1.
 | 
			
		||||
    SP.set(STACK_START);
 | 
			
		||||
 | 
			
		||||
    shared_setup_and_enter_pre();
 | 
			
		||||
 | 
			
		||||
    if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
 | 
			
		||||
        match CurrentEL.get() {
 | 
			
		||||
            #[cfg(qemu)]
 | 
			
		||||
            EL3 => setup_and_enter_el1_from_el3(),
 | 
			
		||||
            EL2 => setup_and_enter_el1_from_el2(),
 | 
			
		||||
            EL1 => reset(),
 | 
			
		||||
            _ => endless_sleep(),
 | 
			
		||||
        }
 | 
			
		||||
/// We assume that no statics are accessed before transition to main from this function.
 | 
			
		||||
///
 | 
			
		||||
/// We are guaranteed to be in EL1 non-secure mode here.
 | 
			
		||||
#[link_section = ".text.boot"]
 | 
			
		||||
unsafe fn reset() -> ! {
 | 
			
		||||
    extern "Rust" {
 | 
			
		||||
        // Boundaries of the .bss section, provided by the linker script.
 | 
			
		||||
        static __BSS_START: UnsafeCell<()>;
 | 
			
		||||
        static __BSS_SIZE_U64S: UnsafeCell<()>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // if not core0 or not EL3/EL2/EL1, infinitely wait for events
 | 
			
		||||
    endless_sleep()
 | 
			
		||||
    // Zeroes the .bss section
 | 
			
		||||
    // 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 u64,
 | 
			
		||||
        __BSS_SIZE_U64S.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() -> !;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    main()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -124,10 +124,11 @@ pub fn kmain() -> ! {
 | 
			
		|||
    #[cfg(feature = "jtag")]
 | 
			
		||||
    machine::arch::jtag::wait_debugger();
 | 
			
		||||
 | 
			
		||||
    init_exception_traps();
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(feature = "noserial"))]
 | 
			
		||||
    init_uart_serial();
 | 
			
		||||
 | 
			
		||||
    init_exception_traps();
 | 
			
		||||
    init_mmu();
 | 
			
		||||
 | 
			
		||||
    #[cfg(test)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue