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}