Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New MPU Interface #1159

Merged
merged 19 commits into from Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
699 changes: 508 additions & 191 deletions arch/cortex-m4/src/mpu.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions boards/ek-tm4c1294xl/src/main.rs
Expand Up @@ -242,6 +242,8 @@ pub unsafe fn reset_handler() {

let mut chip = tm4c129x::chip::Tm4c129x::new();

let mpu = static_init!(cortexm4::mpu::MPU, cortexm4::mpu::MPU::new());

tm4c1294.console.initialize();

debug!("Initialization complete. Entering main loop...\r");
Expand All @@ -255,6 +257,7 @@ pub unsafe fn reset_handler() {
kernel::procs::load_processes(
board_kernel,
&cortexm4::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
&mut APP_MEMORY,
&mut PROCESSES,
Expand All @@ -264,6 +267,7 @@ pub unsafe fn reset_handler() {
board_kernel.kernel_loop(
&tm4c1294,
&mut chip,
mpu,
Some(&tm4c1294.ipc),
&main_loop_capability,
);
Expand Down
4 changes: 2 additions & 2 deletions boards/hail/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion boards/hail/src/main.rs
Expand Up @@ -576,6 +576,8 @@ pub unsafe fn reset_handler() {
hail.nrf51822.reset();
hail.nrf51822.initialize();

let mpu = static_init!(cortexm4::mpu::MPU, cortexm4::mpu::MPU::new());

// Uncomment to measure overheads for TakeCell and MapCell:
// test_take_map_cell::test_take_map_cell();

Expand All @@ -591,11 +593,18 @@ pub unsafe fn reset_handler() {
kernel::procs::load_processes(
board_kernel,
&cortexm4::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
&mut APP_MEMORY,
&mut PROCESSES,
FAULT_RESPONSE,
&process_management_capability,
);
board_kernel.kernel_loop(&hail, &mut chip, Some(&hail.ipc), &main_loop_capability);
board_kernel.kernel_loop(
&hail,
&mut chip,
mpu,
Some(&hail.ipc),
&main_loop_capability,
);
}
5 changes: 4 additions & 1 deletion boards/imix/src/main.rs
Expand Up @@ -372,6 +372,8 @@ pub unsafe fn reset_handler() {

let mut chip = sam4l::chip::Sam4l::new();

let mpu = static_init!(cortexm4::mpu::MPU, cortexm4::mpu::MPU::new());

// Need to reset the nRF on boot, toggle it's SWDIO
imix.nrf51822.reset();
imix.nrf51822.initialize();
Expand All @@ -392,12 +394,13 @@ pub unsafe fn reset_handler() {
kernel::procs::load_processes(
board_kernel,
&cortexm4::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
&mut APP_MEMORY,
&mut PROCESSES,
FAULT_RESPONSE,
&process_mgmt_cap,
);

board_kernel.kernel_loop(&imix, &mut chip, Some(&imix.ipc), &main_cap);
board_kernel.kernel_loop(&imix, &mut chip, mpu, Some(&imix.ipc), &main_cap);
}
5 changes: 4 additions & 1 deletion boards/launchxl/src/main.rs
Expand Up @@ -354,6 +354,8 @@ pub unsafe fn reset_handler() {

let mut chip = cc26x2::chip::Cc26X2::new();

let mpu = static_init!(cortexm4::mpu::MPU, cortexm4::mpu::MPU::new());

extern "C" {
/// Beginning of the ROM region containing app images.
static _sapps: u8;
Expand All @@ -364,12 +366,13 @@ pub unsafe fn reset_handler() {
kernel::procs::load_processes(
board_kernel,
&cortexm4::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
&mut APP_MEMORY,
&mut PROCESSES,
FAULT_RESPONSE,
&process_management_capability,
);

board_kernel.kernel_loop(&launchxl, &mut chip, Some(&ipc), &main_loop_capability);
board_kernel.kernel_loop(&launchxl, &mut chip, mpu, Some(&ipc), &main_loop_capability);
}
4 changes: 4 additions & 0 deletions boards/nordic/nrf51dk/src/main.rs
Expand Up @@ -397,6 +397,8 @@ pub unsafe fn reset_handler() {
chip.systick().reset();
chip.systick().enable(true);

let mpu = static_init!((), ());

debug!("Initialization complete. Entering main loop");

extern "C" {
Expand All @@ -406,6 +408,7 @@ pub unsafe fn reset_handler() {
kernel::procs::load_processes(
board_kernel,
&cortexm0::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
&mut APP_MEMORY,
&mut PROCESSES,
Expand All @@ -416,6 +419,7 @@ pub unsafe fn reset_handler() {
board_kernel.kernel_loop(
&platform,
&mut chip,
mpu,
Some(&kernel::ipc::IPC::new(
board_kernel,
&memory_allocation_capability,
Expand Down
4 changes: 4 additions & 0 deletions boards/nordic/nrf52dk_base/src/lib.rs
Expand Up @@ -420,6 +420,8 @@ pub unsafe fn setup_board(

let mut chip = nrf52::chip::NRF52::new();

let mpu = static_init!(cortexm4::mpu::MPU, cortexm4::mpu::MPU::new());

debug!("Initialization complete. Entering main loop\r");
debug!("{}", &nrf52::ficr::FICR_INSTANCE);

Expand All @@ -430,6 +432,7 @@ pub unsafe fn setup_board(
kernel::procs::load_processes(
board_kernel,
&cortexm4::syscall::SysCall::new(),
mpu,
&_sapps as *const u8,
app_memory,
process_pointers,
Expand All @@ -440,6 +443,7 @@ pub unsafe fn setup_board(
board_kernel.kernel_loop(
&platform,
&mut chip,
mpu,
Some(&platform.ipc),
&main_loop_capability,
);
Expand Down
7 changes: 0 additions & 7 deletions chips/cc26x2/src/chip.rs
Expand Up @@ -7,28 +7,21 @@ use rtc;
use uart;

pub struct Cc26X2 {
mpu: cortexm4::mpu::MPU,
phil-levis marked this conversation as resolved.
Show resolved Hide resolved
systick: cortexm4::systick::SysTick,
}

impl Cc26X2 {
pub unsafe fn new() -> Cc26X2 {
Cc26X2 {
mpu: cortexm4::mpu::MPU::new(),
// The systick clocks with 48MHz by default
systick: cortexm4::systick::SysTick::new_with_calibration(48 * 1000000),
}
}
}

impl kernel::Chip for Cc26X2 {
type MPU = cortexm4::mpu::MPU;
type SysTick = cortexm4::systick::SysTick;

fn mpu(&self) -> &Self::MPU {
&self.mpu
}

fn systick(&self) -> &Self::SysTick {
&self.systick
}
Expand Down
5 changes: 0 additions & 5 deletions chips/nrf51/src/chip.rs
Expand Up @@ -16,13 +16,8 @@ impl NRF51 {
}

impl kernel::Chip for NRF51 {
type MPU = ();
type SysTick = ();

fn mpu(&self) -> &Self::MPU {
&self.0
}

fn systick(&self) -> &Self::SysTick {
&self.0
}
Expand Down
7 changes: 0 additions & 7 deletions chips/nrf52/src/chip.rs
Expand Up @@ -12,14 +12,12 @@ use spi;
use uart;

pub struct NRF52 {
mpu: cortexm4::mpu::MPU,
systick: cortexm4::systick::SysTick,
}

impl NRF52 {
pub unsafe fn new() -> NRF52 {
NRF52 {
mpu: cortexm4::mpu::MPU::new(),
// The NRF52's systick is uncalibrated, but is clocked from the
// 64Mhz CPU clock.
systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
Expand All @@ -28,13 +26,8 @@ impl NRF52 {
}

impl kernel::Chip for NRF52 {
type MPU = cortexm4::mpu::MPU;
type SysTick = cortexm4::systick::SysTick;

fn mpu(&self) -> &Self::MPU {
&self.mpu
}

fn systick(&self) -> &Self::SysTick {
&self.systick
}
Expand Down
7 changes: 0 additions & 7 deletions chips/sam4l/src/chip.rs
Expand Up @@ -22,7 +22,6 @@ use usart;
use usbc;

pub struct Sam4l {
pub mpu: cortexm4::mpu::MPU,
pub systick: cortexm4::systick::SysTick,
}

Expand Down Expand Up @@ -61,14 +60,12 @@ impl Sam4l {
dma::DMA_CHANNELS[13].initialize(&mut adc::ADC0, dma::DMAWidth::Width16Bit);

Sam4l {
mpu: cortexm4::mpu::MPU::new(),
systick: cortexm4::systick::SysTick::new(),
}
}
}

impl Chip for Sam4l {
type MPU = cortexm4::mpu::MPU;
type SysTick = cortexm4::systick::SysTick;

fn service_pending_interrupts(&mut self) {
Expand Down Expand Up @@ -155,10 +152,6 @@ impl Chip for Sam4l {
unsafe { cortexm4::nvic::has_pending() || deferred_call::has_tasks() }
}

fn mpu(&self) -> &cortexm4::mpu::MPU {
&self.mpu
}

fn systick(&self) -> &cortexm4::systick::SysTick {
&self.systick
}
Expand Down
7 changes: 0 additions & 7 deletions chips/tm4c129x/src/chip.rs
Expand Up @@ -6,21 +6,18 @@ use kernel::Chip;
use uart;

pub struct Tm4c129x {
pub mpu: cortexm4::mpu::MPU,
pub systick: cortexm4::systick::SysTick,
}

impl Tm4c129x {
pub unsafe fn new() -> Tm4c129x {
Tm4c129x {
mpu: cortexm4::mpu::MPU::new(),
systick: cortexm4::systick::SysTick::new(),
}
}
}

impl Chip for Tm4c129x {
type MPU = cortexm4::mpu::MPU;
type SysTick = cortexm4::systick::SysTick;

fn service_pending_interrupts(&mut self) {
Expand Down Expand Up @@ -50,10 +47,6 @@ impl Chip for Tm4c129x {
unsafe { cortexm4::nvic::has_pending() }
}

fn mpu(&self) -> &cortexm4::mpu::MPU {
&self.mpu
}

fn systick(&self) -> &cortexm4::systick::SysTick {
&self.systick
}
Expand Down
8 changes: 4 additions & 4 deletions doc/Memory_Isolation.md
Expand Up @@ -18,7 +18,7 @@ memory layout](Memory_Layout.md).

Memory isolation is a key property of Tock. Without it, processes could just
access any part of memory, and the security of the entire system would be
compromised. Although Rust preserves memory safety (e.g. no double frees or
compromised. The reason for this is that although Rust preserves memory safety (e.g. no double frees or
buffer overflows) and type safety at compile-time, this doesn't prevent
processes, which can be written in any language, from accessing certain
addresses which they should not have access to in memory. Some other component
Expand All @@ -40,8 +40,8 @@ process, Tock reconfigures the MPU for that process.

When the system is executing kernel code, the MPU is disabled. This means there
are no hardware restrictions preventing the kernel from accessing the entire
address space. In practice however, the Rust type system restricts what the
kernel can do. For example, a capsule (which cannot use `unsafe`) cannot access
address space. Instead, what the kernel can do is restricted by the
Rust type system. For example, a capsule (which cannot use `unsafe`) cannot access
a process's memory because it cannot create and dereference an arbitrary
pointer. In general, Tock tries to minimize the amount of trusted code (i.e.
code that can call `unsafe`), and tries to encapsulate code that does need
Expand All @@ -62,7 +62,7 @@ cannot access arbitrary addresses in flash, and are certainly prohibited from
accessing bootloader or kernel code. They are also prohibited from reading or
writing the nonvolatile regions of other processes.

Processes generally have access to their own memory in flash. Certain regions,
Processes do have access to their own memory in flash. Certain regions,
including their Tock Binary Format (TBF) header and a protected region after the
header, are read-only, as the kernel must be able to ensure the integrity of the
header. In particular, the kernel needs to know the total size of the app to find
Expand Down
9 changes: 7 additions & 2 deletions doc/Memory_Layout.md
Expand Up @@ -18,6 +18,7 @@ kernel, applications, and supporting state.
* [SAM4L](#sam4l)
+ [Flash](#flash-1)
+ [RAM](#ram-1)
+ [Overview](#overview)

<!-- tocstop -->

Expand Down Expand Up @@ -84,8 +85,6 @@ The figure below shows the memory space of one process.

## Hardware Implementations

Here is an example of how things are laid out in practice.

### SAM4L

The SAM4L is a microcontroller used on the Hail and Imix platforms, among
Expand All @@ -107,3 +106,9 @@ others. The structure of its flash and RAM is as follows.
| Address Range | Length (bytes) | Content | Description |
|-----------------------|----------------|--------------------|---------------------------------------------------------------------------------------------------|
| 0x20000000-0x2000FFFF | 64k | Kernel and app RAM | The kernel links with all of the RAM, and then allocates a buffer internally for application use. |

#### Overview

The following image gives an example of how things are currently laid out in practice. It shows the address space of both flash and RAM with three running applications: crc, ip_sense and analog_comparator.

![Process memory layout](process_memory_layout.png)
Binary file added doc/process_memory_layout.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions kernel/src/lib.rs
Expand Up @@ -9,6 +9,7 @@
#![feature(asm, core_intrinsics, ptr_internals, const_fn)]
#![feature(use_extern_macros, try_from, used, panic_info_message)]
#![feature(in_band_lifetimes, crate_visibility_modifier)]
#![feature(associated_type_defaults)]
#![warn(unreachable_pub)]
#![no_std]

Expand Down
5 changes: 4 additions & 1 deletion kernel/src/mem.rs
Expand Up @@ -91,7 +91,10 @@ impl<L, T> AppSlice<L, T> {
.process
.kernel
.process_map_or(false, appid.idx(), |process| {
process.add_mpu_region(self.ptr() as *const u8, self.len() as u32)
match process.add_mpu_region(self.ptr() as *const u8, self.len(), self.len()) {
Some(_) => true,
None => false,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can just be process.add_mpu_region(self.ptr() as *const u8, self.len(), self.len()).is_ok(), but I'm not completely sure.

})
} else {
false
Expand Down
2 changes: 0 additions & 2 deletions kernel/src/platform/mod.rs
Expand Up @@ -16,12 +16,10 @@ pub trait Platform {

/// Interface for individual MCUs.
pub trait Chip {
type MPU: mpu::MPU;
type SysTick: systick::SysTick;

fn service_pending_interrupts(&mut self);
fn has_pending_interrupts(&self) -> bool;
fn mpu(&self) -> &Self::MPU;
fn systick(&self) -> &Self::SysTick;
fn sleep(&self);
unsafe fn atomic<F, R>(&self, f: F) -> R
Expand Down