4 releases

new 0.3.2 Mar 7, 2025
0.3.1 Sep 14, 2024
0.3.0 Aug 27, 2024
0.1.0 Jul 26, 2024

#156 in Memory management

Download history 389/week @ 2024-11-14 366/week @ 2024-11-21 143/week @ 2024-11-28 181/week @ 2024-12-05 373/week @ 2024-12-12 186/week @ 2024-12-19 361/week @ 2024-12-26 309/week @ 2025-01-02 338/week @ 2025-01-09 69/week @ 2025-01-16 48/week @ 2025-01-23 54/week @ 2025-01-30 365/week @ 2025-02-06 338/week @ 2025-02-13 177/week @ 2025-02-20 371/week @ 2025-02-27

1,275 downloads per month

GPL-3.0-or-later OR Apache-2…

83KB
1.5K SLoC

memory_set

Crates.io Docs.rs CI

Data structures and operations for managing memory mappings.

It is useful to implement mmap, munmap and mprotect.

Examples

use memory_addr::{va, va_range, VirtAddr};
use memory_set::{MappingBackend, MemoryArea, MemorySet};

const MAX_ADDR: usize = 0x10000;

/// A mock memory flags.
type MockFlags = u8;
/// A mock page table, which is a simple array that maps addresses to flags.
type MockPageTable = [MockFlags; MAX_ADDR];

/// A mock mapping backend that manipulates the page table on `map` and `unmap`.
#[derive(Clone)]
struct MockBackend;

let mut pt = [0; MAX_ADDR];
let mut memory_set = MemorySet::<MockBackend>::new();

// Map [0x1000..0x5000).
memory_set.map(
    /* area: */ MemoryArea::new(va!(0x1000), 0x4000, 1, MockBackend),
    /* page_table: */ &mut pt,
    /* unmap_overlap */ false,
).unwrap();
// Unmap [0x2000..0x4000), will split the area into two parts.
memory_set.unmap(va!(0x2000), 0x2000, &mut pt).unwrap();

let areas = memory_set.iter().collect::<Vec<_>>();
assert_eq!(areas.len(), 2);
assert_eq!(areas[0].va_range(), va_range!(0x1000..0x2000));
assert_eq!(areas[1].va_range(), va_range!(0x4000..0x5000));

// Underlying operations to do when manipulating mappings.
impl MappingBackend for MockBackend {
    type Addr = VirtAddr;
    type Flags = MockFlags;
    type PageTable = MockPageTable;

    fn map(&self, start: VirtAddr, size: usize, flags: MockFlags, pt: &mut MockPageTable) -> bool {
        for entry in pt.iter_mut().skip(start.as_usize()).take(size) {
            if *entry != 0 {
                return false;
            }
            *entry = flags;
        }
        true
    }

    fn unmap(&self, start: VirtAddr, size: usize, pt: &mut MockPageTable) -> bool {
        for entry in pt.iter_mut().skip(start.as_usize()).take(size) {
            if *entry == 0 {
                return false;
            }
            *entry = 0;
        }
        true
    }

    fn protect(
        &self,
        start: VirtAddr,
        size: usize,
        new_flags: MockFlags,
        pt: &mut MockPageTable,
    ) -> bool {
        for entry in pt.iter_mut().skip(start.as_usize()).take(size) {
            if *entry == 0 {
                return false;
            }
            *entry = new_flags;
        }
        true
    }
}

Dependencies