tg_kernel_vm/space/
mod.rs

1mod mapper;
2mod visitor;
3
4extern crate alloc;
5
6use crate::PageManager;
7use alloc::vec::Vec;
8use core::{fmt, ops::Range, ptr::NonNull};
9use mapper::Mapper;
10use page_table::{PageTable, PageTableFormatter, Pos, VAddr, VmFlags, VmMeta, PPN, VPN};
11use visitor::Visitor;
12
13/// 地址空间。
14pub struct AddressSpace<Meta: VmMeta, M: PageManager<Meta>> {
15    /// 虚拟地址块
16    pub areas: Vec<Range<VPN<Meta>>>,
17    page_manager: M,
18}
19
20impl<Meta: VmMeta, M: PageManager<Meta>> AddressSpace<Meta, M> {
21    /// 创建新地址空间。
22    #[inline]
23    pub fn new() -> Self {
24        Self {
25            areas: Vec::new(),
26            page_manager: M::new_root(),
27        }
28    }
29
30    /// 地址空间根页表的物理页号。
31    #[inline]
32    pub fn root_ppn(&self) -> PPN<Meta> {
33        self.page_manager.root_ppn()
34    }
35
36    /// 地址空间根页表
37    #[inline]
38    pub fn root(&self) -> PageTable<Meta> {
39        // SAFETY: page_manager.root_ptr() 返回的是有效的根页表指针,
40        // 由 PageManager::new_root() 创建时保证其有效性
41        unsafe { PageTable::from_root(self.page_manager.root_ptr()) }
42    }
43
44    /// 向地址空间增加映射关系。
45    pub fn map_extern(&mut self, range: Range<VPN<Meta>>, pbase: PPN<Meta>, flags: VmFlags<Meta>) {
46        self.areas.push(range.start..range.end);
47        let count = range.end.val() - range.start.val();
48        let mut root = self.root();
49        let mut mapper = Mapper::new(self, pbase..pbase + count, flags);
50        root.walk_mut(Pos::new(range.start, 0), &mut mapper);
51        if !mapper.ans() {
52            // 映射失败,需要回滚吗?
53            todo!()
54        }
55    }
56
57    /// 分配新的物理页,拷贝数据并建立映射。
58    pub fn map(
59        &mut self,
60        range: Range<VPN<Meta>>,
61        data: &[u8],
62        offset: usize,
63        mut flags: VmFlags<Meta>,
64    ) {
65        let count = range.end.val() - range.start.val();
66        let size = count << Meta::PAGE_BITS;
67        assert!(size >= data.len() + offset);
68        let page = self.page_manager.allocate(count, &mut flags);
69        // SAFETY: page 是刚分配的有效内存,大小为 size 字节。
70        // 我们按顺序填充:[0, offset) 清零,[offset, offset+data.len()) 拷贝数据,
71        // [offset+data.len(), size) 清零。
72        unsafe {
73            use core::slice::from_raw_parts_mut as slice;
74            let mut ptr = page.as_ptr();
75            slice(ptr, offset).fill(0);
76            ptr = ptr.add(offset);
77            slice(ptr, data.len()).copy_from_slice(data);
78            ptr = ptr.add(data.len());
79            slice(ptr, page.as_ptr().add(size).offset_from(ptr) as _).fill(0);
80        }
81        self.map_extern(range, self.page_manager.v_to_p(page), flags)
82    }
83
84    /// 检查 `flags` 的属性要求,然后将地址空间中的一个虚地址翻译成当前地址空间中的指针。
85    pub fn translate<T>(&self, addr: VAddr<Meta>, flags: VmFlags<Meta>) -> Option<NonNull<T>> {
86        let mut visitor = Visitor::new(self);
87        self.root().walk(Pos::new(addr.floor(), 0), &mut visitor);
88        visitor
89            .ans()
90            .filter(|pte| pte.flags().contains(flags))
91            .map(|pte| {
92                // SAFETY: pte 是有效的页表项,ppn 对应有效的物理页。
93                // p_to_v 返回当前地址空间中的有效指针。
94                // add(addr.offset()) 计算页内偏移,不会越界(offset < PAGE_SIZE)。
95                // 使用 new_unchecked 是因为 p_to_v 返回的是 NonNull,不可能为空。
96                unsafe {
97                    NonNull::new_unchecked(
98                        self.page_manager
99                            .p_to_v::<u8>(pte.ppn())
100                            .as_ptr()
101                            .add(addr.offset())
102                            .cast(),
103                    )
104                }
105            })
106    }
107
108    /// 遍历地址空间,将其中的地址映射添加进自己的地址空间中,重新分配物理页并拷贝所有数据及代码
109    pub fn cloneself(&self, new_addrspace: &mut AddressSpace<Meta, M>) {
110        let root = self.root();
111        let areas = &self.areas;
112        for (_, range) in areas.iter().enumerate() {
113            let mut visitor = Visitor::new(self);
114            // 虚拟地址块的首地址的 vpn
115            let vpn = range.start;
116            // 利用 visitor 访问页表,并获取这个虚拟地址块的页属性
117            root.walk(Pos::new(vpn, 0), &mut visitor);
118            // 利用 visitor 获取这个虚拟地址块的页属性,以及起始地址
119            let (mut flags, mut data_ptr) = visitor
120                .ans()
121                .filter(|pte| pte.is_valid())
122                .map(|pte| {
123                    // SAFETY: pte 是有效的页表项,p_to_v 返回有效的指针
124                    (pte.flags(), unsafe {
125                        NonNull::new_unchecked(self.page_manager.p_to_v::<u8>(pte.ppn()).as_ptr())
126                    })
127                })
128                .unwrap();
129            let vpn_range = range.start..range.end;
130            // 虚拟地址块中页数量
131            let count = range.end.val() - range.start.val();
132            let size = count << Meta::PAGE_BITS;
133            // 分配 count 个 flags 属性的物理页面
134            let paddr = new_addrspace.page_manager.allocate(count, &mut flags);
135            let ppn = new_addrspace.page_manager.v_to_p(paddr);
136            // SAFETY: data_ptr 指向源地址空间中 size 字节的有效数据,
137            // paddr 指向新分配的 size 字节内存,两者不重叠
138            unsafe {
139                use core::slice::from_raw_parts_mut as slice;
140                let data = slice(data_ptr.as_mut(), size);
141                let ptr = paddr.as_ptr();
142                slice(ptr, size).copy_from_slice(data);
143            }
144            new_addrspace.map_extern(vpn_range, ppn, flags);
145        }
146    }
147}
148
149impl<Meta: VmMeta, P: PageManager<Meta>> fmt::Debug for AddressSpace<Meta, P> {
150    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151        writeln!(f, "root: {:#x}", self.root_ppn().val())?;
152        write!(
153            f,
154            "{:?}",
155            PageTableFormatter {
156                pt: self.root(),
157                f: |ppn| self.page_manager.p_to_v(ppn)
158            }
159        )
160    }
161}