keos_project2/eager_pager.rs
1//! # Pager with Eager Paging Policy
2//!
3//! The [`EagerPager`] is a concrete implementation of the [`Pager`] trait used
4//! in Project 2 to manage memory mapping behavior during `mmap` system calls.
5//! As its name implies, it follows an **eager allocation strategy**: physical
6//! pages are allocated and mapped into the page table **immediately** at the
7//! time of `mmap`, regardless of whether they are subsequently accessed.
8//!
9//! This approach ensures that all virtual pages in the mapped region are backed
10//! by initialized physical memory at the time of mapping. These pages are
11//! typically zero-filled and mapped with the requested permissions (e.g., read,
12//! write, execute). This simplifies the memory model and avoids page faults
13//! after mapping, making [`EagerPager`] a useful baseline for implementing
14//! memory management in early-stage systems like KeOS.
15//!
16//! The paging interface is defined by the [`Pager`] trait, which abstracts the
17//! core functionality for virtual memory: allocation (`mmap`), deallocation
18//! (`munmap`), access resolution (`get_user_page`), and permission checking
19//! (`access_ok`).
20//!
21//! In later stages of KeOS (Project 3), you will implement demand paging using
22//! `LazyPager`, which defers physical memory allocation until the first
23//! access (e.g., page fault). That approach provides a more efficient
24//! and realistic memory model used by modern operating systems.
25//!
26//! ## Memory Loading
27//!
28//! The eager pager supports both anonymous and file-backed memory mappings.
29//! **Anonymous mappings** in eager paging are typically backed by
30//! zero-initialized memory. On the other side, when mapping a **file-backed
31//! page**, the [`RegularFile::mmap`] method must be used to register the
32//! mapping. In Project 5, you will extend this method with the **page cache**,
33//! a core mechanism that allows shared, read-consistent access to file data
34//! across processes. Although [`EagerPager`] currently does not utilize the
35//! page cache, the [`RegularFile`] interface and paging trait are designed to
36//! accommodate it cleanly for future extensions.
37//!
38//! Note that, KeOS does not provide write-back behavior for the file-backed
39//! pages.
40//!
41//! ## Implementation Requirements
42//! You need to implement the followings:
43//! - [`EagerPager::mmap`]
44//! - [`EagerPager::munmap`]
45//! - [`EagerPager::get_user_page`]
46//! - [`EagerPager::access_ok`]
47//!
48//! By implementing the eager pager, your kernel now have sufficient
49//! functionalities to load user program in the next [`section`].
50//!
51//! [`section`]: crate::loader
52use crate::{page_table::PageTable, pager::Pager};
53use alloc::collections::btree_map::BTreeMap;
54use keos::{
55 KernelError,
56 addressing::Va,
57 fs::RegularFile,
58 mm::{PageRef, page_table::Permission},
59};
60
61/// Represent a mapping of contiguous memory.
62pub struct Mapping {
63 /// Size of the area.
64 mapping_size: usize,
65 /// Permission of the area.
66 perm: Permission,
67}
68
69/// [`EagerPager`] is a struct that implements the [`Pager`] trait.
70/// It represents a pager strategy that is responsible for eager memory paging.
71pub struct EagerPager {
72 mappings: BTreeMap<Va, Mapping>,
73}
74
75impl Pager for EagerPager {
76 /// Creates a new instance of [`EagerPager`].
77 ///
78 /// This constructor initializes an empty [`EagerPager`] struct.
79 fn new() -> Self {
80 Self {
81 mappings: BTreeMap::new(),
82 }
83 }
84
85 /// Memory map function (`mmap`) for eager paging.
86 ///
87 /// This function maps the given memory region into page table.
88 /// Returns an address for the mapped area.
89 fn mmap(
90 &mut self,
91 page_table: &mut PageTable,
92 addr: Va,
93 size: usize,
94 prot: Permission,
95 file: Option<&RegularFile>,
96 offset: usize,
97 ) -> Result<usize, KernelError> {
98 todo!()
99 }
100
101 /// Memory unmap function (`munmap`) for eager paging.
102 ///
103 /// This function would unmap a previously mapped memory region, releasing
104 /// any associated resources.
105 fn munmap(&mut self, page_table: &mut PageTable, addr: Va) -> Result<usize, KernelError> {
106 todo!()
107 }
108
109 /// Find a mapped page at the given virtual address.
110 ///
111 /// This function searches for a memory page mapped at `addr` and, if found,
112 /// returns a tuple of [`PageRef`] to the page and its corresponding
113 /// [`Permission`] flags.
114 fn get_user_page(
115 &mut self,
116 page_table: &mut PageTable,
117 addr: Va,
118 ) -> Option<(PageRef<'_>, Permission)> {
119 // HINT: use `PageRef::from_pa`
120 todo!()
121 }
122
123 /// Checks whether access to the given virtual address is permitted.
124 ///
125 /// This function verifies that a virtual address `va` is part of a valid
126 /// memory mapping and that the requested access type (read or write) is
127 /// allowed by the page's protection flags.
128 fn access_ok(&self, va: Va, is_write: bool) -> bool {
129 todo!()
130 }
131}