• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! x86_64 page size compat
4 //!
5 //! C header: [`include/linux/page_size_compat.h`](srctree/include/linux/page_size_compat.h).
6 //!
7 //! Rust helpers for x86_64 page size emulation.
8 
9 use kernel::{bindings, jump_label, page};
10 
11 /// __page_shift is the emulated page shift.
12 #[inline(always)]
__page_shift() -> usize13 pub fn __page_shift() -> usize {
14     // SAFETY: Accessing C static key
15     let emulated = unsafe {
16         jump_label::static_branch_unlikely!(
17             bindings::page_shift_compat_enabled,
18             bindings::static_key_false,
19             key
20         )
21     };
22 
23     if emulated {
24         // SAFETY: Reading static C variable page_shift_compat.
25         // page_size_compat is marked __ro_after_init in the C code.
26         let shift = unsafe { bindings::page_shift_compat };
27 
28         // page_shift_compat is sanitized and range checked by boot
29         // parameter parsing; so this conversion should always be safe.
30         shift.try_into().unwrap()
31     } else {
32         page::PAGE_SHIFT
33     }
34 }
35 
36 /// __page_size is the emulated page size.
37 #[inline(always)]
__page_size() -> usize38 pub fn __page_size() -> usize {
39     let shift = __page_shift();
40 
41     1usize << shift
42 }
43 
44 /// __page_mask can be used to align addresses to a __page boundary.
45 #[inline(always)]
__page_mask() -> usize46 pub fn __page_mask() -> usize {
47     let page_size = __page_size();
48 
49     !(page_size - 1)
50 }
51 
52 /// Aligns the given address UP to the nearest __page boundary.
53 #[inline(always)]
__page_align(addr: usize) -> usize54 pub fn __page_align(addr: usize) -> usize {
55     let page_size = __page_size();
56     let mask = !(page_size - 1);
57 
58     // Parentheses around `page_size - 1` to avoid triggering
59     // overflow sanitizers in the wrong cases.
60     (addr + (page_size - 1)) & mask
61 }
62 
63 /// Aligns the given address DOWN to the nearest __page boundary.
64 #[inline(always)]
__page_align_down(addr: usize) -> usize65 pub fn __page_align_down(addr: usize) -> usize {
66     let mask = __page_mask();
67 
68     addr & mask
69 }
70