1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
// SPDX-License-Identifier: GPL-2.0
//! Memory management.
//!
//! C header: [`include/linux/mm.h`](../../../../include/linux/mm.h)
use crate::{bindings, pages, to_result, Result};
/// Virtual memory.
pub mod virt {
use super::*;
/// A wrapper for the kernel's `struct vm_area_struct`.
///
/// It represents an area of virtual memory.
///
/// # Invariants
///
/// `vma` is always non-null and valid.
pub struct Area {
vma: *mut bindings::vm_area_struct,
}
impl Area {
/// Creates a new instance of a virtual memory area.
///
/// # Safety
///
/// Callers must ensure that `vma` is non-null and valid for the duration of the new area's
/// lifetime.
pub(crate) unsafe fn from_ptr(vma: *mut bindings::vm_area_struct) -> Self {
// INVARIANTS: The safety requirements guarantee the invariants.
Self { vma }
}
/// Returns the flags associated with the virtual memory area.
///
/// The possible flags are a combination of the constants in [`flags`].
pub fn flags(&self) -> usize {
// SAFETY: `self.vma` is valid by the type invariants.
unsafe { (*self.vma).vm_flags as _ }
}
/// Sets the flags associated with the virtual memory area.
///
/// The possible flags are a combination of the constants in [`flags`].
pub fn set_flags(&mut self, flags: usize) {
// SAFETY: `self.vma` is valid by the type invariants.
unsafe { (*self.vma).vm_flags = flags as _ };
}
/// Returns the start address of the virtual memory area.
pub fn start(&self) -> usize {
// SAFETY: `self.vma` is valid by the type invariants.
unsafe { (*self.vma).vm_start as _ }
}
/// Returns the end address of the virtual memory area.
pub fn end(&self) -> usize {
// SAFETY: `self.vma` is valid by the type invariants.
unsafe { (*self.vma).vm_end as _ }
}
/// Maps a single page at the given address within the virtual memory area.
pub fn insert_page(&mut self, address: usize, page: &pages::Pages<0>) -> Result {
// SAFETY: The page is guaranteed to be order 0 by the type system. The range of
// `address` is already checked by `vm_insert_page`. `self.vma` and `page.pages` are
// guaranteed by their repective type invariants to be valid.
to_result(unsafe { bindings::vm_insert_page(self.vma, address as _, page.pages) })
}
}
/// Container for [`Area`] flags.
pub mod flags {
use crate::bindings;
/// No flags are set.
pub const NONE: usize = bindings::VM_NONE as _;
/// Mapping allows reads.
pub const READ: usize = bindings::VM_READ as _;
/// Mapping allows writes.
pub const WRITE: usize = bindings::VM_WRITE as _;
/// Mapping allows execution.
pub const EXEC: usize = bindings::VM_EXEC as _;
/// Mapping is shared.
pub const SHARED: usize = bindings::VM_SHARED as _;
/// Mapping may be updated to allow reads.
pub const MAYREAD: usize = bindings::VM_MAYREAD as _;
/// Mapping may be updated to allow writes.
pub const MAYWRITE: usize = bindings::VM_MAYWRITE as _;
/// Mapping may be updated to allow execution.
pub const MAYEXEC: usize = bindings::VM_MAYEXEC as _;
/// Mapping may be updated to be shared.
pub const MAYSHARE: usize = bindings::VM_MAYSHARE as _;
/// Do not copy this vma on fork.
pub const DONTCOPY: usize = bindings::VM_DONTCOPY as _;
/// Cannot expand with mremap().
pub const DONTEXPAND: usize = bindings::VM_DONTEXPAND as _;
/// Lock the pages covered when they are faulted in.
pub const LOCKONFAULT: usize = bindings::VM_LOCKONFAULT as _;
/// Is a VM accounted object.
pub const ACCOUNT: usize = bindings::VM_ACCOUNT as _;
/// should the VM suppress accounting.
pub const NORESERVE: usize = bindings::VM_NORESERVE as _;
/// Huge TLB Page VM.
pub const HUGETLB: usize = bindings::VM_HUGETLB as _;
/// Synchronous page faults.
pub const SYNC: usize = bindings::VM_SYNC as _;
/// Architecture-specific flag.
pub const ARCH_1: usize = bindings::VM_ARCH_1 as _;
/// Wipe VMA contents in child..
pub const WIPEONFORK: usize = bindings::VM_WIPEONFORK as _;
/// Do not include in the core dump.
pub const DONTDUMP: usize = bindings::VM_DONTDUMP as _;
/// Not soft dirty clean area.
pub const SOFTDIRTY: usize = bindings::VM_SOFTDIRTY as _;
/// Can contain "struct page" and pure PFN pages.
pub const MIXEDMAP: usize = bindings::VM_MIXEDMAP as _;
/// MADV_HUGEPAGE marked this vma.
pub const HUGEPAGE: usize = bindings::VM_HUGEPAGE as _;
/// MADV_NOHUGEPAGE marked this vma.
pub const NOHUGEPAGE: usize = bindings::VM_NOHUGEPAGE as _;
/// KSM may merge identical pages.
pub const MERGEABLE: usize = bindings::VM_MERGEABLE as _;
}
}