1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Kernel page allocation and management. 4 5 use crate::{ 6 alloc::{AllocError, Flags}, 7 bindings, 8 error::code::*, 9 error::Result, 10 uaccess::UserSliceReader, 11 }; 12 use core::{ 13 marker::PhantomData, 14 mem::ManuallyDrop, 15 ops::Deref, 16 ptr::{self, NonNull}, 17 }; 18 19 /// A bitwise shift for the page size. 20 pub const PAGE_SHIFT: usize = bindings::PAGE_SHIFT as usize; 21 22 /// The number of bytes in a page. 23 pub const PAGE_SIZE: usize = bindings::PAGE_SIZE; 24 25 /// A bitmask that gives the page containing a given address. 26 pub const PAGE_MASK: usize = !(PAGE_SIZE - 1); 27 28 /// Round up the given number to the next multiple of [`PAGE_SIZE`]. 29 /// 30 /// It is incorrect to pass an address where the next multiple of [`PAGE_SIZE`] doesn't fit in a 31 /// [`usize`]. 32 pub const fn page_align(addr: usize) -> usize { 33 // Parentheses around `PAGE_SIZE - 1` to avoid triggering overflow sanitizers in the wrong 34 // cases. 35 (addr + (PAGE_SIZE - 1)) & PAGE_MASK 36 } 37 38 /// Representation of a non-owning reference to a [`Page`]. 39 /// 40 /// This type provides a borrowed version of a [`Page`] that is owned by some other entity, e.g. a 41 /// [`Vmalloc`] allocation such as [`VBox`]. 42 /// 43 /// # Example 44 /// 45 /// ``` 46 /// # use kernel::{bindings, prelude::*}; 47 /// use kernel::page::{BorrowedPage, Page, PAGE_SIZE}; 48 /// # use core::{mem::MaybeUninit, ptr, ptr::NonNull }; 49 /// 50 /// fn borrow_page<'a>(vbox: &'a mut VBox<MaybeUninit<[u8; PAGE_SIZE]>>) -> BorrowedPage<'a> { 51 /// let ptr = ptr::from_ref(&**vbox); 52 /// 53 /// // SAFETY: `ptr` is a valid pointer to `Vmalloc` memory. 54 /// let page = unsafe { bindings::vmalloc_to_page(ptr.cast()) }; 55 /// 56 /// // SAFETY: `vmalloc_to_page` returns a valid pointer to a `struct page` for a valid 57 /// // pointer to `Vmalloc` memory. 58 /// let page = unsafe { NonNull::new_unchecked(page) }; 59 /// 60 /// // SAFETY: 61 /// // - `self.0` is a valid pointer to a `struct page`. 62 /// // - `self.0` is valid for the entire lifetime of `self`. 63 /// unsafe { BorrowedPage::from_raw(page) } 64 /// } 65 /// 66 /// let mut vbox = VBox::<[u8; PAGE_SIZE]>::new_uninit(GFP_KERNEL)?; 67 /// let page = borrow_page(&mut vbox); 68 /// 69 /// // SAFETY: There is no concurrent read or write to this page. 70 /// unsafe { page.fill_zero_raw(0, PAGE_SIZE)? }; 71 /// # Ok::<(), Error>(()) 72 /// ``` 73 /// 74 /// # Invariants 75 /// 76 /// The borrowed underlying pointer to a `struct page` is valid for the entire lifetime `'a`. 77 /// 78 /// [`VBox`]: kernel::alloc::VBox 79 /// [`Vmalloc`]: kernel::alloc::allocator::Vmalloc 80 pub struct BorrowedPage<'a>(ManuallyDrop<Page>, PhantomData<&'a Page>); 81 82 impl<'a> BorrowedPage<'a> { 83 /// Constructs a [`BorrowedPage`] from a raw pointer to a `struct page`. 84 /// 85 /// # Safety 86 /// 87 /// - `ptr` must point to a valid `bindings::page`. 88 /// - `ptr` must remain valid for the entire lifetime `'a`. 89 pub unsafe fn from_raw(ptr: NonNull<bindings::page>) -> Self { 90 let page = Page { page: ptr }; 91 92 // INVARIANT: The safety requirements guarantee that `ptr` is valid for the entire lifetime 93 // `'a`. 94 Self(ManuallyDrop::new(page), PhantomData) 95 } 96 } 97 98 impl<'a> Deref for BorrowedPage<'a> { 99 type Target = Page; 100 101 fn deref(&self) -> &Self::Target { 102 &self.0 103 } 104 } 105 106 /// A pointer to a page that owns the page allocation. 107 /// 108 /// # Invariants 109 /// 110 /// The pointer is valid, and has ownership over the page. 111 pub struct Page { 112 page: NonNull<bindings::page>, 113 } 114 115 // SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across 116 // threads is safe. 117 unsafe impl Send for Page {} 118 119 // SAFETY: Pages have no logic that relies on them not being accessed concurrently, so accessing 120 // them concurrently is safe. 121 unsafe impl Sync for Page {} 122 123 impl Page { 124 /// Allocates a new page. 125 /// 126 /// # Examples 127 /// 128 /// Allocate memory for a page. 129 /// 130 /// ``` 131 /// use kernel::page::Page; 132 /// 133 /// let page = Page::alloc_page(GFP_KERNEL)?; 134 /// # Ok::<(), kernel::alloc::AllocError>(()) 135 /// ``` 136 /// 137 /// Allocate memory for a page and zero its contents. 138 /// 139 /// ``` 140 /// use kernel::page::Page; 141 /// 142 /// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?; 143 /// # Ok::<(), kernel::alloc::AllocError>(()) 144 /// ``` 145 #[inline] 146 pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> { 147 // SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it 148 // is always safe to call this method. 149 let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) }; 150 let page = NonNull::new(page).ok_or(AllocError)?; 151 // INVARIANT: We just successfully allocated a page, so we now have ownership of the newly 152 // allocated page. We transfer that ownership to the new `Page` object. 153 Ok(Self { page }) 154 } 155 156 /// Returns a raw pointer to the page. 157 pub fn as_ptr(&self) -> *mut bindings::page { 158 self.page.as_ptr() 159 } 160 161 /// Runs a piece of code with this page mapped to an address. 162 /// 163 /// The page is unmapped when this call returns. 164 /// 165 /// # Using the raw pointer 166 /// 167 /// It is up to the caller to use the provided raw pointer correctly. The pointer is valid for 168 /// `PAGE_SIZE` bytes and for the duration in which the closure is called. The pointer might 169 /// only be mapped on the current thread, and when that is the case, dereferencing it on other 170 /// threads is UB. Other than that, the usual rules for dereferencing a raw pointer apply: don't 171 /// cause data races, the memory may be uninitialized, and so on. 172 /// 173 /// If multiple threads map the same page at the same time, then they may reference with 174 /// different addresses. However, even if the addresses are different, the underlying memory is 175 /// still the same for these purposes (e.g., it's still a data race if they both write to the 176 /// same underlying byte at the same time). 177 fn with_page_mapped<T>(&self, f: impl FnOnce(*mut u8) -> T) -> T { 178 // SAFETY: `page` is valid due to the type invariants on `Page`. 179 let mapped_addr = unsafe { bindings::kmap_local_page(self.as_ptr()) }; 180 181 let res = f(mapped_addr.cast()); 182 183 // This unmaps the page mapped above. 184 // 185 // SAFETY: Since this API takes the user code as a closure, it can only be used in a manner 186 // where the pages are unmapped in reverse order. This is as required by `kunmap_local`. 187 // 188 // In other words, if this call to `kunmap_local` happens when a different page should be 189 // unmapped first, then there must necessarily be a call to `kmap_local_page` other than the 190 // call just above in `with_page_mapped` that made that possible. In this case, it is the 191 // unsafe block that wraps that other call that is incorrect. 192 unsafe { bindings::kunmap_local(mapped_addr) }; 193 194 res 195 } 196 197 /// Runs a piece of code with a raw pointer to a slice of this page, with bounds checking. 198 /// 199 /// If `f` is called, then it will be called with a pointer that points at `off` bytes into the 200 /// page, and the pointer will be valid for at least `len` bytes. The pointer is only valid on 201 /// this task, as this method uses a local mapping. 202 /// 203 /// If `off` and `len` refers to a region outside of this page, then this method returns 204 /// [`EINVAL`] and does not call `f`. 205 /// 206 /// # Using the raw pointer 207 /// 208 /// It is up to the caller to use the provided raw pointer correctly. The pointer is valid for 209 /// `len` bytes and for the duration in which the closure is called. The pointer might only be 210 /// mapped on the current thread, and when that is the case, dereferencing it on other threads 211 /// is UB. Other than that, the usual rules for dereferencing a raw pointer apply: don't cause 212 /// data races, the memory may be uninitialized, and so on. 213 /// 214 /// If multiple threads map the same page at the same time, then they may reference with 215 /// different addresses. However, even if the addresses are different, the underlying memory is 216 /// still the same for these purposes (e.g., it's still a data race if they both write to the 217 /// same underlying byte at the same time). 218 fn with_pointer_into_page<T>( 219 &self, 220 off: usize, 221 len: usize, 222 f: impl FnOnce(*mut u8) -> Result<T>, 223 ) -> Result<T> { 224 let bounds_ok = off <= PAGE_SIZE && len <= PAGE_SIZE && (off + len) <= PAGE_SIZE; 225 226 if bounds_ok { 227 self.with_page_mapped(move |page_addr| { 228 // SAFETY: The `off` integer is at most `PAGE_SIZE`, so this pointer offset will 229 // result in a pointer that is in bounds or one off the end of the page. 230 f(unsafe { page_addr.add(off) }) 231 }) 232 } else { 233 Err(EINVAL) 234 } 235 } 236 237 /// Maps the page and reads from it into the given buffer. 238 /// 239 /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes 240 /// outside of the page, then this call returns [`EINVAL`]. 241 /// 242 /// # Safety 243 /// 244 /// * Callers must ensure that `dst` is valid for writing `len` bytes. 245 /// * Callers must ensure that this call does not race with a write to the same page that 246 /// overlaps with this read. 247 pub unsafe fn read_raw(&self, dst: *mut u8, offset: usize, len: usize) -> Result { 248 self.with_pointer_into_page(offset, len, move |src| { 249 // SAFETY: If `with_pointer_into_page` calls into this closure, then 250 // it has performed a bounds check and guarantees that `src` is 251 // valid for `len` bytes. 252 // 253 // There caller guarantees that there is no data race. 254 unsafe { ptr::copy_nonoverlapping(src, dst, len) }; 255 Ok(()) 256 }) 257 } 258 259 /// Maps the page and writes into it from the given buffer. 260 /// 261 /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes 262 /// outside of the page, then this call returns [`EINVAL`]. 263 /// 264 /// # Safety 265 /// 266 /// * Callers must ensure that `src` is valid for reading `len` bytes. 267 /// * Callers must ensure that this call does not race with a read or write to the same page 268 /// that overlaps with this write. 269 pub unsafe fn write_raw(&self, src: *const u8, offset: usize, len: usize) -> Result { 270 self.with_pointer_into_page(offset, len, move |dst| { 271 // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a 272 // bounds check and guarantees that `dst` is valid for `len` bytes. 273 // 274 // There caller guarantees that there is no data race. 275 unsafe { ptr::copy_nonoverlapping(src, dst, len) }; 276 Ok(()) 277 }) 278 } 279 280 /// Maps the page and zeroes the given slice. 281 /// 282 /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes 283 /// outside of the page, then this call returns [`EINVAL`]. 284 /// 285 /// # Safety 286 /// 287 /// Callers must ensure that this call does not race with a read or write to the same page that 288 /// overlaps with this write. 289 pub unsafe fn fill_zero_raw(&self, offset: usize, len: usize) -> Result { 290 self.with_pointer_into_page(offset, len, move |dst| { 291 // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a 292 // bounds check and guarantees that `dst` is valid for `len` bytes. 293 // 294 // There caller guarantees that there is no data race. 295 unsafe { ptr::write_bytes(dst, 0u8, len) }; 296 Ok(()) 297 }) 298 } 299 300 /// Copies data from userspace into this page. 301 /// 302 /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes 303 /// outside of the page, then this call returns [`EINVAL`]. 304 /// 305 /// Like the other `UserSliceReader` methods, data races are allowed on the userspace address. 306 /// However, they are not allowed on the page you are copying into. 307 /// 308 /// # Safety 309 /// 310 /// Callers must ensure that this call does not race with a read or write to the same page that 311 /// overlaps with this write. 312 pub unsafe fn copy_from_user_slice_raw( 313 &self, 314 reader: &mut UserSliceReader, 315 offset: usize, 316 len: usize, 317 ) -> Result { 318 self.with_pointer_into_page(offset, len, move |dst| { 319 // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a 320 // bounds check and guarantees that `dst` is valid for `len` bytes. Furthermore, we have 321 // exclusive access to the slice since the caller guarantees that there are no races. 322 reader.read_raw(unsafe { core::slice::from_raw_parts_mut(dst.cast(), len) }) 323 }) 324 } 325 } 326 327 impl Drop for Page { 328 #[inline] 329 fn drop(&mut self) { 330 // SAFETY: By the type invariants, we have ownership of the page and can free it. 331 unsafe { bindings::__free_pages(self.page.as_ptr(), 0) }; 332 } 333 } 334