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