page.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! Kernel page allocation and management.
  3. use crate::{
  4. alloc::{AllocError, Flags},
  5. bindings,
  6. error::code::*,
  7. error::Result,
  8. uaccess::UserSliceReader,
  9. };
  10. use core::ptr::{self, NonNull};
  11. /// A bitwise shift for the page size.
  12. pub const PAGE_SHIFT: usize = bindings::PAGE_SHIFT as usize;
  13. /// The number of bytes in a page.
  14. pub const PAGE_SIZE: usize = bindings::PAGE_SIZE;
  15. /// A bitmask that gives the page containing a given address.
  16. pub const PAGE_MASK: usize = !(PAGE_SIZE - 1);
  17. /// A pointer to a page that owns the page allocation.
  18. ///
  19. /// # Invariants
  20. ///
  21. /// The pointer is valid, and has ownership over the page.
  22. pub struct Page {
  23. page: NonNull<bindings::page>,
  24. }
  25. // SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across
  26. // threads is safe.
  27. unsafe impl Send for Page {}
  28. // SAFETY: Pages have no logic that relies on them not being accessed concurrently, so accessing
  29. // them concurrently is safe.
  30. unsafe impl Sync for Page {}
  31. impl Page {
  32. /// Allocates a new page.
  33. ///
  34. /// # Examples
  35. ///
  36. /// Allocate memory for a page.
  37. ///
  38. /// ```
  39. /// use kernel::page::Page;
  40. ///
  41. /// # fn dox() -> Result<(), kernel::alloc::AllocError> {
  42. /// let page = Page::alloc_page(GFP_KERNEL)?;
  43. /// # Ok(()) }
  44. /// ```
  45. ///
  46. /// Allocate memory for a page and zero its contents.
  47. ///
  48. /// ```
  49. /// use kernel::page::Page;
  50. ///
  51. /// # fn dox() -> Result<(), kernel::alloc::AllocError> {
  52. /// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?;
  53. /// # Ok(()) }
  54. /// ```
  55. pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
  56. // SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
  57. // is always safe to call this method.
  58. let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
  59. let page = NonNull::new(page).ok_or(AllocError)?;
  60. // INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
  61. // allocated page. We transfer that ownership to the new `Page` object.
  62. Ok(Self { page })
  63. }
  64. /// Returns a raw pointer to the page.
  65. pub fn as_ptr(&self) -> *mut bindings::page {
  66. self.page.as_ptr()
  67. }
  68. /// Runs a piece of code with this page mapped to an address.
  69. ///
  70. /// The page is unmapped when this call returns.
  71. ///
  72. /// # Using the raw pointer
  73. ///
  74. /// It is up to the caller to use the provided raw pointer correctly. The pointer is valid for
  75. /// `PAGE_SIZE` bytes and for the duration in which the closure is called. The pointer might
  76. /// only be mapped on the current thread, and when that is the case, dereferencing it on other
  77. /// threads is UB. Other than that, the usual rules for dereferencing a raw pointer apply: don't
  78. /// cause data races, the memory may be uninitialized, and so on.
  79. ///
  80. /// If multiple threads map the same page at the same time, then they may reference with
  81. /// different addresses. However, even if the addresses are different, the underlying memory is
  82. /// still the same for these purposes (e.g., it's still a data race if they both write to the
  83. /// same underlying byte at the same time).
  84. fn with_page_mapped<T>(&self, f: impl FnOnce(*mut u8) -> T) -> T {
  85. // SAFETY: `page` is valid due to the type invariants on `Page`.
  86. let mapped_addr = unsafe { bindings::kmap_local_page(self.as_ptr()) };
  87. let res = f(mapped_addr.cast());
  88. // This unmaps the page mapped above.
  89. //
  90. // SAFETY: Since this API takes the user code as a closure, it can only be used in a manner
  91. // where the pages are unmapped in reverse order. This is as required by `kunmap_local`.
  92. //
  93. // In other words, if this call to `kunmap_local` happens when a different page should be
  94. // unmapped first, then there must necessarily be a call to `kmap_local_page` other than the
  95. // call just above in `with_page_mapped` that made that possible. In this case, it is the
  96. // unsafe block that wraps that other call that is incorrect.
  97. unsafe { bindings::kunmap_local(mapped_addr) };
  98. res
  99. }
  100. /// Runs a piece of code with a raw pointer to a slice of this page, with bounds checking.
  101. ///
  102. /// If `f` is called, then it will be called with a pointer that points at `off` bytes into the
  103. /// page, and the pointer will be valid for at least `len` bytes. The pointer is only valid on
  104. /// this task, as this method uses a local mapping.
  105. ///
  106. /// If `off` and `len` refers to a region outside of this page, then this method returns
  107. /// [`EINVAL`] and does not call `f`.
  108. ///
  109. /// # Using the raw pointer
  110. ///
  111. /// It is up to the caller to use the provided raw pointer correctly. The pointer is valid for
  112. /// `len` bytes and for the duration in which the closure is called. The pointer might only be
  113. /// mapped on the current thread, and when that is the case, dereferencing it on other threads
  114. /// is UB. Other than that, the usual rules for dereferencing a raw pointer apply: don't cause
  115. /// data races, the memory may be uninitialized, and so on.
  116. ///
  117. /// If multiple threads map the same page at the same time, then they may reference with
  118. /// different addresses. However, even if the addresses are different, the underlying memory is
  119. /// still the same for these purposes (e.g., it's still a data race if they both write to the
  120. /// same underlying byte at the same time).
  121. fn with_pointer_into_page<T>(
  122. &self,
  123. off: usize,
  124. len: usize,
  125. f: impl FnOnce(*mut u8) -> Result<T>,
  126. ) -> Result<T> {
  127. let bounds_ok = off <= PAGE_SIZE && len <= PAGE_SIZE && (off + len) <= PAGE_SIZE;
  128. if bounds_ok {
  129. self.with_page_mapped(move |page_addr| {
  130. // SAFETY: The `off` integer is at most `PAGE_SIZE`, so this pointer offset will
  131. // result in a pointer that is in bounds or one off the end of the page.
  132. f(unsafe { page_addr.add(off) })
  133. })
  134. } else {
  135. Err(EINVAL)
  136. }
  137. }
  138. /// Maps the page and reads from it into the given buffer.
  139. ///
  140. /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes
  141. /// outside of the page, then this call returns [`EINVAL`].
  142. ///
  143. /// # Safety
  144. ///
  145. /// * Callers must ensure that `dst` is valid for writing `len` bytes.
  146. /// * Callers must ensure that this call does not race with a write to the same page that
  147. /// overlaps with this read.
  148. pub unsafe fn read_raw(&self, dst: *mut u8, offset: usize, len: usize) -> Result {
  149. self.with_pointer_into_page(offset, len, move |src| {
  150. // SAFETY: If `with_pointer_into_page` calls into this closure, then
  151. // it has performed a bounds check and guarantees that `src` is
  152. // valid for `len` bytes.
  153. //
  154. // There caller guarantees that there is no data race.
  155. unsafe { ptr::copy_nonoverlapping(src, dst, len) };
  156. Ok(())
  157. })
  158. }
  159. /// Maps the page and writes into it from the given buffer.
  160. ///
  161. /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes
  162. /// outside of the page, then this call returns [`EINVAL`].
  163. ///
  164. /// # Safety
  165. ///
  166. /// * Callers must ensure that `src` is valid for reading `len` bytes.
  167. /// * Callers must ensure that this call does not race with a read or write to the same page
  168. /// that overlaps with this write.
  169. pub unsafe fn write_raw(&self, src: *const u8, offset: usize, len: usize) -> Result {
  170. self.with_pointer_into_page(offset, len, move |dst| {
  171. // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a
  172. // bounds check and guarantees that `dst` is valid for `len` bytes.
  173. //
  174. // There caller guarantees that there is no data race.
  175. unsafe { ptr::copy_nonoverlapping(src, dst, len) };
  176. Ok(())
  177. })
  178. }
  179. /// Maps the page and zeroes the given slice.
  180. ///
  181. /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes
  182. /// outside of the page, then this call returns [`EINVAL`].
  183. ///
  184. /// # Safety
  185. ///
  186. /// Callers must ensure that this call does not race with a read or write to the same page that
  187. /// overlaps with this write.
  188. pub unsafe fn fill_zero_raw(&self, offset: usize, len: usize) -> Result {
  189. self.with_pointer_into_page(offset, len, move |dst| {
  190. // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a
  191. // bounds check and guarantees that `dst` is valid for `len` bytes.
  192. //
  193. // There caller guarantees that there is no data race.
  194. unsafe { ptr::write_bytes(dst, 0u8, len) };
  195. Ok(())
  196. })
  197. }
  198. /// Copies data from userspace into this page.
  199. ///
  200. /// This method will perform bounds checks on the page offset. If `offset .. offset+len` goes
  201. /// outside of the page, then this call returns [`EINVAL`].
  202. ///
  203. /// Like the other `UserSliceReader` methods, data races are allowed on the userspace address.
  204. /// However, they are not allowed on the page you are copying into.
  205. ///
  206. /// # Safety
  207. ///
  208. /// Callers must ensure that this call does not race with a read or write to the same page that
  209. /// overlaps with this write.
  210. pub unsafe fn copy_from_user_slice_raw(
  211. &self,
  212. reader: &mut UserSliceReader,
  213. offset: usize,
  214. len: usize,
  215. ) -> Result {
  216. self.with_pointer_into_page(offset, len, move |dst| {
  217. // SAFETY: If `with_pointer_into_page` calls into this closure, then it has performed a
  218. // bounds check and guarantees that `dst` is valid for `len` bytes. Furthermore, we have
  219. // exclusive access to the slice since the caller guarantees that there are no races.
  220. reader.read_raw(unsafe { core::slice::from_raw_parts_mut(dst.cast(), len) })
  221. })
  222. }
  223. }
  224. impl Drop for Page {
  225. fn drop(&mut self) {
  226. // SAFETY: By the type invariants, we have ownership of the page and can free it.
  227. unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
  228. }
  229. }