@@ -4,14 +4,16 @@ use super::recursive::*;
44use crate :: addr:: * ;
55
66/// This struct is a two level page table with `Mapper` trait implemented.
7- pub struct TwoLevelPageTable < ' a > {
7+ #[ cfg( riscv32) ]
8+ pub struct Rv32PageTable < ' a > {
89 root_table : & ' a mut PageTable ,
910 linear_offset : usize , // VA = PA + linear_offset
1011}
1112
12- impl < ' a > TwoLevelPageTable < ' a > {
13+ #[ cfg( riscv32) ]
14+ impl < ' a > Rv32PageTable < ' a > {
1315 pub fn new ( table : & ' a mut PageTable , linear_offset : usize ) -> Self {
14- TwoLevelPageTable {
16+ Rv32PageTable {
1517 root_table : table,
1618 linear_offset,
1719 }
@@ -36,7 +38,8 @@ impl<'a> TwoLevelPageTable<'a> {
3638 }
3739}
3840
39- impl < ' a > Mapper for TwoLevelPageTable < ' a > {
41+ #[ cfg( riscv32) ]
42+ impl < ' a > Mapper for Rv32PageTable < ' a > {
4043 fn map_to (
4144 & mut self ,
4245 page : Page ,
@@ -76,3 +79,229 @@ impl<'a> Mapper for TwoLevelPageTable<'a> {
7679 Ok ( & mut p1_table[ page. p1_index ( ) ] )
7780 }
7881}
82+
83+
84+ /// This struct is a three level page table with `Mapper` trait implemented.
85+ #[ cfg( riscv64) ]
86+ pub struct Rv39PageTable < ' a > {
87+ root_table : & ' a mut PageTable ,
88+ linear_offset : usize , // VA = PA + linear_offset
89+ }
90+
91+ #[ cfg( riscv64) ]
92+ impl < ' a > Rv39PageTable < ' a > {
93+ pub fn new ( table : & ' a mut PageTable , linear_offset : usize ) -> Self {
94+ Rv39PageTable {
95+ root_table : table,
96+ linear_offset,
97+ }
98+ }
99+
100+ fn create_p1_if_not_exist (
101+ & mut self ,
102+ p3_index : usize ,
103+ p2_index : usize ,
104+ allocator : & mut impl FrameAllocator ,
105+ ) -> Result < & mut PageTable , MapToError > {
106+ let p2_table = if self . root_table [ p3_index] . is_unused ( ) {
107+ let frame = allocator. alloc ( ) . ok_or ( MapToError :: FrameAllocationFailed ) ?;
108+ self . root_table [ p3_index] . set ( frame. clone ( ) , F :: VALID ) ;
109+ let p2_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
110+ p2_table. zero ( ) ;
111+ p2_table
112+ } else {
113+ let frame = self . root_table [ p3_index] . frame ( ) ;
114+ unsafe { frame. as_kernel_mut ( self . linear_offset ) }
115+ } ;
116+ if p2_table[ p2_index] . is_unused ( ) {
117+ let frame = allocator. alloc ( ) . ok_or ( MapToError :: FrameAllocationFailed ) ?;
118+ p2_table[ p2_index] . set ( frame. clone ( ) , F :: VALID ) ;
119+ let p1_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
120+ p1_table. zero ( ) ;
121+ Ok ( p1_table)
122+ } else {
123+ let frame = p2_table[ p2_index] . frame ( ) ;
124+ let p1_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
125+ Ok ( p1_table)
126+ }
127+ }
128+ }
129+
130+ #[ cfg( riscv64) ]
131+ impl < ' a > Mapper for Rv39PageTable < ' a > {
132+ fn map_to (
133+ & mut self ,
134+ page : Page ,
135+ frame : Frame ,
136+ flags : PageTableFlags ,
137+ allocator : & mut impl FrameAllocator ,
138+ ) -> Result < MapperFlush , MapToError > {
139+ let p1_table = self . create_p1_if_not_exist ( page. p3_index ( ) , page. p2_index ( ) , allocator) ?;
140+ if !p1_table[ page. p1_index ( ) ] . is_unused ( ) {
141+ return Err ( MapToError :: PageAlreadyMapped ) ;
142+ }
143+ p1_table[ page. p1_index ( ) ] . set ( frame, flags) ;
144+ Ok ( MapperFlush :: new ( page) )
145+ }
146+
147+ fn unmap ( & mut self , page : Page ) -> Result < ( Frame , MapperFlush ) , UnmapError > {
148+ if self . root_table [ page. p3_index ( ) ] . is_unused ( ) {
149+ return Err ( UnmapError :: PageNotMapped ) ;
150+ }
151+ let p2_frame = self . root_table [ page. p3_index ( ) ] . frame ( ) ;
152+ let p2_table: & mut PageTable = unsafe { p2_frame. as_kernel_mut ( self . linear_offset ) } ;
153+
154+ if p2_table[ page. p2_index ( ) ] . is_unused ( ) {
155+ return Err ( UnmapError :: PageNotMapped ) ;
156+ }
157+ let p1_frame = p2_table[ page. p2_index ( ) ] . frame ( ) ;
158+ let p1_table: & mut PageTable = unsafe { p1_frame. as_kernel_mut ( self . linear_offset ) } ;
159+ let p1_entry = & mut p1_table[ page. p1_index ( ) ] ;
160+ if !p1_entry. flags ( ) . contains ( F :: VALID ) {
161+ return Err ( UnmapError :: PageNotMapped ) ;
162+ }
163+ let frame = p1_entry. frame ( ) ;
164+ p1_entry. set_unused ( ) ;
165+ Ok ( ( frame, MapperFlush :: new ( page) ) )
166+ }
167+
168+ fn ref_entry ( & mut self , page : Page ) -> Result < & mut PageTableEntry , FlagUpdateError > {
169+ if self . root_table [ page. p3_index ( ) ] . is_unused ( ) {
170+ return Err ( FlagUpdateError :: PageNotMapped ) ;
171+ }
172+ let p2_frame = self . root_table [ page. p3_index ( ) ] . frame ( ) ;
173+ let p2_table: & mut PageTable = unsafe { p2_frame. as_kernel_mut ( self . linear_offset ) } ;
174+ if p2_table[ page. p2_index ( ) ] . is_unused ( ) {
175+ return Err ( FlagUpdateError :: PageNotMapped ) ;
176+ }
177+
178+ let p1_frame = p2_table[ page. p2_index ( ) ] . frame ( ) ;
179+ let p1_table: & mut PageTable = unsafe { p1_frame. as_kernel_mut ( self . linear_offset ) } ;
180+ Ok ( & mut p1_table[ page. p1_index ( ) ] )
181+ }
182+ }
183+
184+ /// This struct is a four level page table with `Mapper` trait implemented.
185+ #[ cfg( riscv64) ]
186+ pub struct Rv48PageTable < ' a > {
187+ root_table : & ' a mut PageTable ,
188+ linear_offset : usize , // VA = PA + linear_offset
189+ }
190+
191+ #[ cfg( riscv64) ]
192+ impl < ' a > Rv48PageTable < ' a > {
193+ pub fn new ( table : & ' a mut PageTable , linear_offset : usize ) -> Self {
194+ Rv48PageTable {
195+ root_table : table,
196+ linear_offset,
197+ }
198+ }
199+
200+ fn create_p1_if_not_exist (
201+ & mut self ,
202+ p4_index : usize ,
203+ p3_index : usize ,
204+ p2_index : usize ,
205+ allocator : & mut impl FrameAllocator ,
206+ ) -> Result < & mut PageTable , MapToError > {
207+ let p3_table = if self . root_table [ p4_index] . is_unused ( ) {
208+ let frame = allocator. alloc ( ) . ok_or ( MapToError :: FrameAllocationFailed ) ?;
209+ self . root_table [ p4_index] . set ( frame. clone ( ) , F :: VALID ) ;
210+ let p3_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
211+ p3_table. zero ( ) ;
212+ p3_table
213+ } else {
214+ let frame = self . root_table [ p4_index] . frame ( ) ;
215+ unsafe { frame. as_kernel_mut ( self . linear_offset ) }
216+ } ;
217+
218+ let p2_table = if p3_table[ p3_index] . is_unused ( ) {
219+ let frame = allocator. alloc ( ) . ok_or ( MapToError :: FrameAllocationFailed ) ?;
220+ self . root_table [ p3_index] . set ( frame. clone ( ) , F :: VALID ) ;
221+ let p2_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
222+ p2_table. zero ( ) ;
223+ p2_table
224+ } else {
225+ let frame = self . root_table [ p3_index] . frame ( ) ;
226+ unsafe { frame. as_kernel_mut ( self . linear_offset ) }
227+ } ;
228+
229+ if p2_table[ p2_index] . is_unused ( ) {
230+ let frame = allocator. alloc ( ) . ok_or ( MapToError :: FrameAllocationFailed ) ?;
231+ p2_table[ p2_index] . set ( frame. clone ( ) , F :: VALID ) ;
232+ let p1_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
233+ p1_table. zero ( ) ;
234+ Ok ( p1_table)
235+ } else {
236+ let frame = p2_table[ p2_index] . frame ( ) ;
237+ let p1_table: & mut PageTable = unsafe { frame. as_kernel_mut ( self . linear_offset ) } ;
238+ Ok ( p1_table)
239+ }
240+ }
241+ }
242+
243+ #[ cfg( riscv64) ]
244+ impl < ' a > Mapper for Rv48PageTable < ' a > {
245+ fn map_to (
246+ & mut self ,
247+ page : Page ,
248+ frame : Frame ,
249+ flags : PageTableFlags ,
250+ allocator : & mut impl FrameAllocator ,
251+ ) -> Result < MapperFlush , MapToError > {
252+ let p1_table = self . create_p1_if_not_exist ( page. p4_index ( ) , page. p3_index ( ) , page. p2_index ( ) , allocator) ?;
253+ if !p1_table[ page. p1_index ( ) ] . is_unused ( ) {
254+ return Err ( MapToError :: PageAlreadyMapped ) ;
255+ }
256+ p1_table[ page. p1_index ( ) ] . set ( frame, flags) ;
257+ Ok ( MapperFlush :: new ( page) )
258+ }
259+
260+ fn unmap ( & mut self , page : Page ) -> Result < ( Frame , MapperFlush ) , UnmapError > {
261+ if self . root_table [ page. p4_index ( ) ] . is_unused ( ) {
262+ return Err ( UnmapError :: PageNotMapped ) ;
263+ }
264+ let p3_frame = self . root_table [ page. p4_index ( ) ] . frame ( ) ;
265+ let p3_table: & mut PageTable = unsafe { p3_frame. as_kernel_mut ( self . linear_offset ) } ;
266+
267+ if p3_table[ page. p3_index ( ) ] . is_unused ( ) {
268+ return Err ( UnmapError :: PageNotMapped ) ;
269+ }
270+ let p2_frame = p3_table[ page. p3_index ( ) ] . frame ( ) ;
271+ let p2_table: & mut PageTable = unsafe { p2_frame. as_kernel_mut ( self . linear_offset ) } ;
272+
273+ if p2_table[ page. p2_index ( ) ] . is_unused ( ) {
274+ return Err ( UnmapError :: PageNotMapped ) ;
275+ }
276+ let p1_frame = p2_table[ page. p2_index ( ) ] . frame ( ) ;
277+ let p1_table: & mut PageTable = unsafe { p1_frame. as_kernel_mut ( self . linear_offset ) } ;
278+ let p1_entry = & mut p1_table[ page. p1_index ( ) ] ;
279+ if !p1_entry. flags ( ) . contains ( F :: VALID ) {
280+ return Err ( UnmapError :: PageNotMapped ) ;
281+ }
282+ let frame = p1_entry. frame ( ) ;
283+ p1_entry. set_unused ( ) ;
284+ Ok ( ( frame, MapperFlush :: new ( page) ) )
285+ }
286+
287+ fn ref_entry ( & mut self , page : Page ) -> Result < & mut PageTableEntry , FlagUpdateError > {
288+ if self . root_table [ page. p4_index ( ) ] . is_unused ( ) {
289+ return Err ( FlagUpdateError :: PageNotMapped ) ;
290+ }
291+ let p3_frame = self . root_table [ page. p4_index ( ) ] . frame ( ) ;
292+ let p3_table: & mut PageTable = unsafe { p3_frame. as_kernel_mut ( self . linear_offset ) } ;
293+
294+ if p3_table[ page. p3_index ( ) ] . is_unused ( ) {
295+ return Err ( FlagUpdateError :: PageNotMapped ) ;
296+ }
297+ let p2_frame = p3_table[ page. p3_index ( ) ] . frame ( ) ;
298+ let p2_table: & mut PageTable = unsafe { p2_frame. as_kernel_mut ( self . linear_offset ) } ;
299+ if p2_table[ page. p2_index ( ) ] . is_unused ( ) {
300+ return Err ( FlagUpdateError :: PageNotMapped ) ;
301+ }
302+
303+ let p1_frame = p2_table[ page. p2_index ( ) ] . frame ( ) ;
304+ let p1_table: & mut PageTable = unsafe { p1_frame. as_kernel_mut ( self . linear_offset ) } ;
305+ Ok ( & mut p1_table[ page. p1_index ( ) ] )
306+ }
307+ }
0 commit comments