11//! Implementation of [`MapArea`] and [`MemorySet`].
2-
32use super :: { frame_alloc, FrameTracker } ;
43use super :: { PTEFlags , PageTable , PageTableEntry } ;
54use super :: { PhysAddr , PhysPageNum , VirtAddr , VirtPageNum } ;
65use super :: { StepByOne , VPNRange } ;
7- use crate :: config:: {
8- KERNEL_STACK_SIZE , MEMORY_END , PAGE_SIZE , TRAMPOLINE , TRAP_CONTEXT_BASE , USER_STACK_SIZE ,
9- } ;
6+ use crate :: config:: { MEMORY_END , PAGE_SIZE , TRAMPOLINE , TRAP_CONTEXT_BASE , USER_STACK_SIZE } ;
107use crate :: sync:: UPSafeCell ;
118use alloc:: collections:: BTreeMap ;
129use alloc:: sync:: Arc ;
@@ -63,6 +60,21 @@ impl MemorySet {
6360 None ,
6461 ) ;
6562 }
63+ /// remove a area
64+ pub fn remove_area_with_start_vpn ( & mut self , start_vpn : VirtPageNum ) {
65+ if let Some ( ( idx, area) ) = self
66+ . areas
67+ . iter_mut ( )
68+ . enumerate ( )
69+ . find ( |( _, area) | area. vpn_range . get_start ( ) == start_vpn)
70+ {
71+ area. unmap ( & mut self . page_table ) ;
72+ self . areas . remove ( idx) ;
73+ }
74+ }
75+ /// Add a new MapArea into this MemorySet.
76+ /// Assuming that there are no conflicts in the virtual address
77+ /// space.
6678 fn push ( & mut self , mut map_area : MapArea , data : Option < & [ u8 ] > ) {
6779 map_area. map ( & mut self . page_table ) ;
6880 if let Some ( data) = data {
@@ -221,6 +233,26 @@ impl MemorySet {
221233 elf. header . pt2 . entry_point ( ) as usize ,
222234 )
223235 }
236+ /// Create a new address space by copy code&data from a exited process's address space.
237+ pub fn from_existed_user ( user_space : & Self ) -> Self {
238+ let mut memory_set = Self :: new_bare ( ) ;
239+ // map trampoline
240+ memory_set. map_trampoline ( ) ;
241+ // copy data sections/trap_context/user_stack
242+ for area in user_space. areas . iter ( ) {
243+ let new_area = MapArea :: from_another ( area) ;
244+ memory_set. push ( new_area, None ) ;
245+ // copy data from another space
246+ for vpn in area. vpn_range {
247+ let src_ppn = user_space. translate ( vpn) . unwrap ( ) . ppn ( ) ;
248+ let dst_ppn = memory_set. translate ( vpn) . unwrap ( ) . ppn ( ) ;
249+ dst_ppn
250+ . get_bytes_array ( )
251+ . copy_from_slice ( src_ppn. get_bytes_array ( ) ) ;
252+ }
253+ }
254+ memory_set
255+ }
224256 /// Change page table by writing satp CSR Register.
225257 pub fn activate ( & self ) {
226258 let satp = self . page_table . token ( ) ;
@@ -233,6 +265,12 @@ impl MemorySet {
233265 pub fn translate ( & self , vpn : VirtPageNum ) -> Option < PageTableEntry > {
234266 self . page_table . translate ( vpn)
235267 }
268+
269+ ///Remove all `MapArea`
270+ pub fn recycle_data_pages ( & mut self ) {
271+ self . areas . clear ( ) ;
272+ }
273+
236274 /// shrink the area to new_end
237275 #[ allow( unused) ]
238276 pub fn shrink_to ( & mut self , start : VirtAddr , new_end : VirtAddr ) -> bool {
@@ -287,6 +325,14 @@ impl MapArea {
287325 map_perm,
288326 }
289327 }
328+ pub fn from_another ( another : & Self ) -> Self {
329+ Self {
330+ vpn_range : VPNRange :: new ( another. vpn_range . get_start ( ) , another. vpn_range . get_end ( ) ) ,
331+ data_frames : BTreeMap :: new ( ) ,
332+ map_type : another. map_type ,
333+ map_perm : another. map_perm ,
334+ }
335+ }
290336 pub fn map_one ( & mut self , page_table : & mut PageTable , vpn : VirtPageNum ) {
291337 let ppn: PhysPageNum ;
292338 match self . map_type {
@@ -302,7 +348,6 @@ impl MapArea {
302348 let pte_flags = PTEFlags :: from_bits ( self . map_perm . bits ) . unwrap ( ) ;
303349 page_table. map ( vpn, ppn, pte_flags) ;
304350 }
305- #[ allow( unused) ]
306351 pub fn unmap_one ( & mut self , page_table : & mut PageTable , vpn : VirtPageNum ) {
307352 if self . map_type == MapType :: Framed {
308353 self . data_frames . remove ( & vpn) ;
@@ -314,7 +359,6 @@ impl MapArea {
314359 self . map_one ( page_table, vpn) ;
315360 }
316361 }
317- #[ allow( unused) ]
318362 pub fn unmap ( & mut self , page_table : & mut PageTable ) {
319363 for vpn in self . vpn_range {
320364 self . unmap_one ( page_table, vpn) ;
@@ -379,13 +423,6 @@ bitflags! {
379423 }
380424}
381425
382- /// Return (bottom, top) of a kernel stack in kernel space.
383- pub fn kernel_stack_position ( app_id : usize ) -> ( usize , usize ) {
384- let top = TRAMPOLINE - app_id * ( KERNEL_STACK_SIZE + PAGE_SIZE ) ;
385- let bottom = top - KERNEL_STACK_SIZE ;
386- ( bottom, top)
387- }
388-
389426/// remap test in kernel space
390427#[ allow( unused) ]
391428pub fn remap_test ( ) {
0 commit comments