diff --git a/src/runtime/src/kernel.rs b/src/runtime/src/kernel.rs index a590b1e..d60047d 100644 --- a/src/runtime/src/kernel.rs +++ b/src/runtime/src/kernel.rs @@ -9,6 +9,7 @@ use libsupport_zynq::boot::Core1; use dyld; use crate::rpc; use crate::rtio; +use crate::mem_protect; #[derive(Debug)] @@ -316,6 +317,7 @@ pub fn main_core1() { // Flush data cache entries for the image in DDR, including // Memory/Instruction Symchronization Barriers dcci_slice(library.image.data); + mem_protect::setup_core1(&library.image.data); core1_tx.send(Message::LoadCompleted); }, diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index 5015ad1..f4c8df7 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -45,7 +45,7 @@ pub fn main_core0() { log::set_max_level(log::LevelFilter::Debug); info!("NAR3/Zynq7000 starting..."); - mem_protect::setup(); + mem_protect::setup_core0(); ram::init_alloc_linker(); match config::Config::new() { diff --git a/src/runtime/src/mem_protect.rs b/src/runtime/src/mem_protect.rs index 684ce1a..30c0555 100644 --- a/src/runtime/src/mem_protect.rs +++ b/src/runtime/src/mem_protect.rs @@ -12,7 +12,7 @@ extern "C" { /// script for the runtime on core 0. /// /// Therefore these regions need to be aligned to 1 MB. -pub fn setup() { +pub fn setup_core0() { 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 }; @@ -37,3 +37,35 @@ pub fn setup() { }); } } + +pub fn setup_core1(kernel_data: &[u8]) { + let kernel_start = (&kernel_data[0] as *const _ as usize) & !(L1_PAGE_SIZE - 1); + let kernel_end = ((&kernel_data[kernel_data.len() - 1] as *const _ as usize) | (L1_PAGE_SIZE - 1)) + 1; + 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 >= kernel_start && addr < kernel_end { + // Kernel code/data: RWX + l1section.access = AccessPermissions::FullAccess; + l1section.exec = true; + } else if addr >= text_start && addr < text_end { + // Runtime 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; + } + }); + } +}