diff --git a/src/runtime/link.x b/src/runtime/link.x index 4f551e1..9cd963b 100644 --- a/src/runtime/link.x +++ b/src/runtime/link.x @@ -17,19 +17,23 @@ MEMORY SECTIONS { - .text : + .text : ALIGN(0x1000000) { + __text_start = .; KEEP(*(.text.exceptions)); *(.text.boot); *(.text .text.*); + __text_end = .; } > SDRAM - .rodata : ALIGN(4) + .rodata : ALIGN(0x1000000) { + __rodata_start = .; *(.rodata .rodata.*); + __rodata_end = .; } > SDRAM - .data : ALIGN(4) + .data : ALIGN(0x1000000) { *(.data .data.*); } > SDRAM diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 4734b47..5015ad1 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -11,6 +11,7 @@ use log::{info, error}; use libboard_zynq::{timer::GlobalTimer, logger, devc}; use libsupport_zynq::ram; +mod mem_protect; mod sd_reader; mod config; mod proto_core_io; @@ -44,6 +45,7 @@ pub fn main_core0() { log::set_max_level(log::LevelFilter::Debug); info!("NAR3/Zynq7000 starting..."); + mem_protect::setup(); ram::init_alloc_linker(); match config::Config::new() { diff --git a/src/runtime/src/mem_protect.rs b/src/runtime/src/mem_protect.rs new file mode 100644 index 0000000..684ce1a --- /dev/null +++ b/src/runtime/src/mem_protect.rs @@ -0,0 +1,39 @@ +use libcortex_a9::mmu::{AccessPermissions, L1_PAGE_SIZE, L1Table}; + +/// Symbols defined by the linker script +extern "C" { + static __text_start: usize; + static __text_end: usize; + static __rodata_start: usize; + static __rodata_end: usize; +} + +/// Apply basic memory protection to the regions defined by the linker +/// script for the runtime on core 0. +/// +/// Therefore these regions need to be aligned to 1 MB. +pub fn setup() { + let text_start = unsafe { &__text_start as *const _ as usize }; + let text_end = unsafe { &__text_end as *const _ as usize }; + let rodata_start = unsafe { &__rodata_start as *const _ as usize }; + let rodata_end = unsafe { &__rodata_end as *const _ as usize }; + + let l1table = L1Table::get(); + for addr in (0..0xFFFF_FFFF).step_by(L1_PAGE_SIZE) { + l1table.update(addr as *const usize, |l1section| { + if addr >= text_start && addr < text_end { + // Code: R-X + l1section.access = AccessPermissions::ReadOnly; + l1section.exec = true; + } else if addr >= rodata_start && addr < rodata_end { + // Data: R-- + l1section.access = AccessPermissions::ReadOnly; + l1section.exec = false; + } else { + // Everything else: RW- + l1section.access = AccessPermissions::FullAccess; + l1section.exec = false; + } + }); + } +}