keos_project2/pager.rs
1//! Pager, a trait for paging policy
2use crate::page_table::PageTable;
3use keos::{
4 KernelError,
5 addressing::Va,
6 fs::RegularFile,
7 mm::{PageRef, page_table::Permission},
8};
9
10/// The [`Pager`] trait defines the interface for memory paging operations,
11/// including memory mapping (`mmap`), unmapping (`munmap`), and resolving
12/// page through [`get_user_page`]. It serves as the core abstraction
13/// for implementing paging policies in the operating system.
14///
15/// This trait allows the OS to support multiple paging strategies by swapping
16/// in different implementations. Each [`Pager`] manages how virtual memory
17/// pages are backed, populated, and protected during execution.
18///
19/// In **Project 2**, you will use [`EagerPager`], which eagerly allocates all
20/// required pages at the time of `mmap`.
21///
22/// In **Project 3**, you will implement [`LazyPager`], which delays page
23/// allocation until the page is accessed (i.e., implements demand paging).
24///
25/// [`LazyPager`]: ../../keos_project3/lazy_pager/struct.LazyPager.html
26/// [`EagerPager`]: ../../keos_project2/eager_pager/struct.EagerPager.html
27/// [`get_user_page`]: Pager::get_user_page
28pub trait Pager {
29 /// Creates a new instance of the pager.
30 ///
31 /// This method initializes the internal state needed for the pager's
32 /// memory management operations.
33 fn new() -> Self;
34
35 /// Maps a virtual memory region into the process’s address space.
36 ///
37 /// This function is responsible for allocating and mapping virtual memory
38 /// pages. If a file is provided, it may also initialize the memory
39 /// contents from that file (starting at `offset`). The mapped memory
40 /// should be configured with the specified access `prot`.
41 ///
42 /// # Parameters
43 /// - `page_table`: The current page table of the process.
44 /// - `addr`: The starting virtual address of the mapping. Must be
45 /// page-aligned.
46 /// - `size`: The size of the region to map in bytes. Must be greater than
47 /// zero.
48 /// - `prot`: Memory protection flags (e.g., read, write, execute).
49 /// - `file`: Optional file backing for the mapping.
50 /// - `offset`: Offset into the file where the mapping begins.
51 ///
52 /// # Returns
53 /// - `Ok(n)`: Number of bytes successfully mapped.
54 /// - `Err([KernelError])`: If the operation fails, e.g., due to invalid
55 /// arguments, overlapping mappings, zero-length file, or a
56 /// non-page-aligned `addr`.
57 fn mmap(
58 &mut self,
59 page_table: &mut PageTable,
60 addr: Va,
61 size: usize,
62 prot: Permission,
63 file: Option<&RegularFile>,
64 offset: usize,
65 ) -> Result<usize, KernelError>
66 where
67 Self: Sized;
68
69 /// Unmaps a previously mapped memory region.
70 ///
71 /// This function removes memory mappings corresponding to `addr`.
72 ///
73 /// # Parameters
74 /// - `page_table`: The process’s page table to modify.
75 /// - `addr`: Starting virtual address of the region to unmap.
76 ///
77 /// # Returns
78 /// - `Ok(n)`: Number of bytes successfully unmapped.
79 /// - `Err([KernelError])`: On invalid addresses, unmapped regions, or other
80 /// errors.
81 fn munmap(&mut self, page_table: &mut PageTable, addr: Va) -> Result<usize, KernelError>
82 where
83 Self: Sized;
84
85 /// Resolves a virtual address to a page reference.
86 ///
87 /// This function checks whether a mapping exists for the virtual address
88 /// `addr` and, if so, returns the in-memory page and its access
89 /// permissions.
90 ///
91 /// # Parameters
92 /// - `page_table`: The current process's page table.
93 /// - `addr`: The virtual address to resolve.
94 ///
95 /// # Returns
96 /// - `Some((PageRef, Permission))`: If the page exists and is accessible.
97 /// - `None`: If no page is mapped at `addr`.
98 fn get_user_page(
99 &mut self,
100 page_table: &mut PageTable,
101 addr: Va,
102 ) -> Option<(PageRef<'_>, Permission)>
103 where
104 Self: Sized;
105
106 /// Checks whether access to the given virtual address is permitted.
107 ///
108 /// This function verifies that a virtual address `va` is part of a valid
109 /// memory mapping and that the requested access type (read or write) is
110 /// allowed by the page's protection flags.
111 ///
112 /// It is used by system calls and the kernel to ensure that user-level
113 /// memory accesses (e.g., writing to buffers or reading strings) are safe
114 /// and legal. This check prevents unauthorized access, such as writing to
115 /// read-only pages or accessing unmapped memory.
116 ///
117 /// Unlike `get_user_page`, this function does **not** resolve or load the
118 /// page into memory. It only checks that the memory mapping is valid for
119 /// the given access type.
120 ///
121 /// # Parameters
122 /// - `va`: The virtual address to check.
123 /// - `is_write`: Indicates whether the access is for writing (`true`) or
124 /// reading (`false`).
125 /// # Returns
126 /// - `true`: If the page exists and is accessible with the permission.
127 /// - `false`: If no page is mapped at `addr` or permission mismatches.
128 fn access_ok(&self, va: Va, is_write: bool) -> bool;
129}