@@ -506,20 +506,19 @@ impl AddrSpace {
506506 // - shared pages (If there is a shared page in the vma)
507507 // - cow
508508 #[ cfg( feature = "cow" ) ]
509- if let Ok ( ( paddr, _, page_size) ) = self . pt . query ( vaddr) {
510- if !access_flags. contains ( MappingFlags :: WRITE ) {
511- return false ;
509+ if access_flags. contains ( MappingFlags :: WRITE ) {
510+ if let Ok ( ( paddr, _, page_size) ) = self . pt . query ( vaddr) {
511+ // 1. page fault caused by write
512+ // 2. pte exists
513+ // 3. Not shared memory
514+ return Self :: handle_cow_fault (
515+ vaddr,
516+ paddr,
517+ orig_flags,
518+ page_size,
519+ & mut self . pt ,
520+ ) ;
512521 }
513- // 1. page fault caused by write
514- // 2. pte exists
515- // 3. Not shared memory
516- return Self :: handle_cow_fault (
517- vaddr,
518- paddr,
519- orig_flags,
520- page_size,
521- & mut self . pt ,
522- ) ;
523522 }
524523
525524 return area
@@ -562,92 +561,83 @@ impl AddrSpace {
562561 Backend :: Alloc { populate : _, align } => {
563562 // Forcing `populate = false` is to prevent the subsequent `new_aspace.areas.map`
564563 // from mapping page table entries for the virtual addresses.
565- & Backend :: new_alloc ( false , * align)
564+ Backend :: new_alloc ( false , * align)
566565 }
567- other => other,
566+ other => other. clone ( ) ,
568567 } ;
569568
570569 // Remap the memory area in the new address space.
571- let new_area =
572- MemoryArea :: new ( area. start ( ) , area. size ( ) , area. flags ( ) , backend. clone ( ) ) ;
570+ let new_area = MemoryArea :: new ( area. start ( ) , area. size ( ) , area. flags ( ) , backend) ;
573571 new_aspace
574572 . areas
575573 . map ( new_area, & mut new_aspace. pt , false )
576574 . map_err ( mapping_err_to_ax_err) ?;
577575
578- let align = match * backend {
579- Backend :: Alloc { align, .. } => align,
576+ let align = match area . backend ( ) {
577+ Backend :: Alloc { align, .. } => * align,
580578 // Linear-backed regions are usually allocated by the kernel and are shared
581579 Backend :: Linear { .. } => continue ,
582580 } ;
583581
584582 #[ cfg( feature = "cow" ) ]
585- let flags = {
586- let mut f = area. flags ( ) ;
587- f. remove ( MappingFlags :: WRITE ) ;
588- f
589- } ;
583+ let flags = area. flags ( ) . clone ( ) - MappingFlags :: WRITE ;
590584
591585 for vaddr in PageIterWrapper :: new ( area. start ( ) , area. end ( ) , align)
592586 . expect ( "Failed to create page iterator" )
593587 {
594- //If the page is mapped in the old page table:
595- // - Update its permissions in the old page table using `flags`.
596- // - Map the same physical page into the new page table at the same
597- // virtual address, with the same page size and `flags`.
598- #[ cfg( feature = "cow" ) ]
599- {
600- match self . pt . query ( vaddr) {
601- Ok ( ( paddr, _, page_size) ) => {
602- frame_table ( ) . inc_ref ( paddr) ;
603-
604- self . pt
605- . protect ( vaddr, flags)
606- . map ( |( _, tlb) | tlb. flush ( ) )
607- . expect ( "protect failed" ) ;
608- new_aspace
609- . pt
610- . map ( vaddr, paddr, page_size, flags)
611- . map ( |tlb| tlb. flush ( ) )
612- . expect ( "map failed" ) ;
613- }
614- // If the page is not mapped, skip it.
615- Err ( PagingError :: NotMapped ) => continue ,
616- Err ( _) => return Err ( AxError :: BadAddress ) ,
617- }
618- }
619-
620588 // Copy data from old memory area to new memory area.
621- #[ cfg( not( feature = "cow" ) ) ]
622- {
623- let addr = match self . pt . query ( vaddr) {
624- Ok ( ( paddr, _, _) ) => paddr,
625- // If the page is not mapped, skip it.
626- Err ( PagingError :: NotMapped ) => continue ,
627- Err ( _) => return Err ( AxError :: BadAddress ) ,
628- } ;
629- let new_addr = match new_aspace. pt . query ( vaddr) {
630- Ok ( ( paddr, _, _) ) => paddr,
631- // If the page is not mapped, try map it.
632- Err ( PagingError :: NotMapped ) => {
633- if !backend. handle_page_fault ( vaddr, area. flags ( ) , & mut new_aspace. pt ) {
634- return Err ( AxError :: NoMemory ) ;
635- }
636- match new_aspace. pt . query ( vaddr) {
637- Ok ( ( paddr, _, _) ) => paddr,
638- Err ( _) => return Err ( AxError :: BadAddress ) ,
639- }
589+ let addr = match self . pt . query ( vaddr) {
590+ #[ cfg( not( feature = "cow" ) ) ]
591+ Ok ( ( paddr, _, _) ) => paddr,
592+ #[ cfg( feature = "cow" ) ]
593+ Ok ( ( paddr, _, page_size) ) => {
594+ //If the page is mapped in the old page table:
595+ // - Update its permissions in the old page table using `flags`.
596+ // - Map the same physical page into the new page table at the same
597+ // virtual address, with the same page size and `flags`.
598+ frame_table ( ) . inc_ref ( paddr) ;
599+
600+ self . pt
601+ . protect ( vaddr, flags)
602+ . map ( |( _, tlb) | tlb. flush ( ) )
603+ . expect ( "protect failed" ) ;
604+ new_aspace
605+ . pt
606+ . map ( vaddr, paddr, page_size, flags)
607+ . map ( |tlb| tlb. flush ( ) )
608+ . expect ( "map failed" ) ;
609+
610+ continue ;
611+ }
612+ // If the page is not mapped, skip it.
613+ Err ( PagingError :: NotMapped ) => continue ,
614+ Err ( _) => return Err ( AxError :: BadAddress ) ,
615+ } ;
616+ let new_addr = match new_aspace. pt . query ( vaddr) {
617+ Ok ( ( paddr, _, _) ) => paddr,
618+ // If the page is not mapped, try map it.
619+ Err ( PagingError :: NotMapped ) => {
620+ if !area. backend ( ) . handle_page_fault (
621+ vaddr,
622+ area. flags ( ) ,
623+ & mut new_aspace. pt ,
624+ ) {
625+ return Err ( AxError :: NoMemory ) ;
640626 }
641- Err ( _) => return Err ( AxError :: BadAddress ) ,
642- } ;
643- unsafe {
644- core:: ptr:: copy_nonoverlapping (
645- phys_to_virt ( addr) . as_ptr ( ) ,
646- phys_to_virt ( new_addr) . as_mut_ptr ( ) ,
647- PAGE_SIZE_4K ,
648- )
649- } ;
650- }
627+ match new_aspace. pt . query ( vaddr) {
628+ Ok ( ( paddr, _, _) ) => paddr,
629+ Err ( _) => return Err ( AxError :: BadAddress ) ,
630+ }
631+ }
632+ Err ( _) => return Err ( AxError :: BadAddress ) ,
633+ } ;
634+ unsafe {
635+ core:: ptr:: copy_nonoverlapping (
636+ phys_to_virt ( addr) . as_ptr ( ) ,
637+ phys_to_virt ( new_addr) . as_mut_ptr ( ) ,
638+ PAGE_SIZE_4K ,
639+ )
640+ } ;
651641 }
652642 }
653643 Ok ( new_aspace)
0 commit comments