Changeset 313 for trunk/kernel/mm/vmm.c


Ignore:
Timestamp:
Aug 2, 2017, 3:24:57 PM (5 years ago)
Author:
alain
Message:

RSeveral modifs in the page-fault handling.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/mm/vmm.c

    r286 r313  
    741741}
    742742
     743////////////////////////////////////////
     744error_t vmm_get_one_ppn( vseg_t * vseg,
     745                         vpn_t    vpn,
     746                         ppn_t  * ppn )
     747{
     748    error_t    error;
     749    cxy_t      page_cxy;          // physical page cluster
     750    page_t   * page_ptr;          // local pointer on physical page descriptor
     751
     752    uint32_t   type      = vseg->type;
     753    xptr_t     mapper_xp = vseg->mapper_xp;
     754
     755    // get mapper cluster and local pointer
     756    cxy_t      mapper_cxy = GET_CXY( mapper_xp );
     757    mapper_t * mapper_ptr = (mapper_t *)GET_PTR( mapper_xp );
     758
     759    // FILE type : simply get the physical page from the file mapper
     760    if( type == VSEG_TYPE_FILE )
     761    {
     762        // compute index in file mapper
     763        uint32_t index = vpn - vseg->vpn_base;
     764
     765        // get page descriptor from mapper
     766        if( mapper_cxy == local_cxy )             // mapper is local
     767        {
     768            page_ptr = mapper_get_page( mapper_ptr , index );
     769        }
     770        else                                      // mapper is remote
     771        {
     772            rpc_mapper_get_page_client( mapper_cxy , mapper_ptr , index , &page_ptr );
     773        }
     774
     775        if ( page_ptr == NULL ) return EINVAL;
     776
     777        page_cxy = mapper_cxy;
     778    }
     779
     780    // all other types : allocate a physical page from target cluster,
     781    else
     782    {
     783        // get target cluster for physical page
     784        if( flags & VSEG_DISTRIB ) // depends on VPN LSB
     785        {
     786            uint32_t x_width = LOCAL_CLUSTER->x_width;
     787            uint32_t y_width = LOCAL_CLUSTER->y_width;
     788            page_cxy = vpn & ((1<<(x_width + y_width)) - 1);
     789        }
     790        else                       // defined in vseg descriptor
     791        {
     792            page_cxy = vseg->cxy;
     793        }
     794
     795        // allocate a physical page in target cluster
     796        kmem_req_t   req;
     797        if( page_cxy == local_cxy )    // target cluster is the local cluster
     798        {
     799            req.type  = KMEM_PAGE;
     800            req.size  = 0;
     801            req.flags = AF_NONE;
     802            page_ptr  = (page_t *)kmem_alloc( &req );
     803        }
     804        else                           // target cluster is not the local cluster
     805        {
     806            rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr );
     807        }
     808
     809        if( page_ptr == NULL ) return ENOMEM;
     810
     811        // initialise page from .elf file mapper for DATA and CODE types
     812        if( (type == VSEG_TYPE_CODE) || (type == VSEG_TYPE_DATA) )
     813        {
     814            // compute missing page index in vseg
     815            vpn_t page_index = vpn - vseg->vpn_base;
     816
     817            // compute missing page offset in .elf file
     818            intptr_t page_offset = vseg->file_offset + (page_index << PPM_PAGE_SHIFT);
     819
     820            // compute both local and extended pointer on page first byte
     821            // WARNING : the pages_offset must have the same value in all clusters !!!
     822            //           to use this ppm_page2vaddr() function for a remote cluster
     823            uint8_t * base_ptr = (uint8_t *)ppm_page2vaddr( page_ptr );
     824            xptr_t    base_xp  = XPTR( page_cxy , base_ptr );
     825
     826            // file_size can be smaller than vseg_size for BSS
     827            file_size = vseg->file_size;
     828
     829            if( file_size < page_offset )                          // page fully in  BSS
     830            {
     831                if( page_cxy == local_cxy )
     832                {
     833                    memset( base_ptr , 0 , PPM_PAGE_SIZE );
     834                }
     835                else
     836                {
     837                   hal_remote_memset( base_xp , 0 , PPM_PAGE_SIZE );       
     838                }
     839            }
     840            else if( file size >= (page_offset + PPM_PAGE_SIZE) )  // page fully in  mapper
     841   
     842                if( mapper_cxy == local_cxy )
     843                {
     844                    error = mapper_move_kernel( mapper_ptr,
     845                                                true,             // to_buffer
     846                                                page_offset,
     847                                                base_xp,
     848                                                PPM_PAGE_SIZE );
     849                }
     850                else
     851                {
     852                    rpc_mapper_move_buffer_client( mapper_cxy,
     853                                                   mapper_ptr,
     854                                                   true,         // to buffer
     855                                                   false,        // kernel buffer
     856                                                   page_offset,
     857                                                   (uint64_t)base_xp,
     858                                                   PPM_PAGE_SIZE,
     859                                                   &error );
     860                }
     861                if( error ) return EINVAL;
     862            }
     863            else  // in mapper : from page_offset -> (file_size - page_offset)
     864                  // in BSS    : from file_size   -> (page_offset + page_size)
     865            {
     866                // initialize mapper part
     867                if( mapper_cxy == local_cxy )                    // mapper is local
     868                {
     869                    error = mapper_move_kernel( mapper_ptr,
     870                                                true,         // to_buffer
     871                                                page_offset,
     872                                                base_xp,
     873                                                file_size - page_offset );
     874                }
     875                else                                             // mapper is remote
     876                {
     877                    rpc_mapper_move_buffer_client( mapper_cxy,
     878                                                   mapper_ptr,
     879                                                   true,
     880                                                   false,        // kernel buffer
     881                                                   page_offset,
     882                                                   (uint64_t)base_xp,
     883                                                   file_size - page_offset,
     884                                                   &error );
     885                }
     886                if( error ) return EINVAL;
     887
     888                // initialize BSS part
     889                if( page_cxy == local_cxy )
     890                {
     891                    memset( base_ptr + file_size - page_offset , 0 ,
     892                            page_offset + PPM_PAGE_SIZE - file_size );
     893                }
     894                else
     895                {
     896                   hal_remote_memset( base_xp + file_size - page_offset , 0 ,
     897                                      page_offset + PPM_PAGE_SIZE - file_size );
     898                }
     899            }   
     900        }  // end initialisation for CODE or DATA types   
     901    }
     902
     903    // return ppn
     904    *ppn = hal_page2ppn( XPTR( page_cxy , page_ptr ) );
     905    return 0;
     906
     907}  // end vmm_get_one_ppn()
     908
    743909/////////////////////////////////////////
    744910error_t vmm_get_pte( process_t * process,
     
    748914{
    749915    vseg_t  * vseg;   // pointer on vseg containing VPN
    750     ppn_t     ppn;    // PPN from GPT entry
     916    ppn_t     ppn;    // physical page number
    751917    uint32_t  attr;   // attributes from GPT entry
    752918    error_t   error;
     
    762928    hal_gpt_get_pte( &vmm->gpt , vpn , &attr , &ppn );
    763929
    764     // if PTE unmapped => allocate one small physical page to map it
     930    // if PTE is unmapped
     931    // 1) get VSEG containing the missing VPN
     932    // 2) get & initialize physical page (depending on vseg type),
     933    // 3) register the PTE in reference GPT
    765934    if( (attr & GPT_MAPPED) == 0 )
    766935    {
    767         // get vseg pointer
     936        // 1. get vseg pointer
    768937        vseg = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT );
    769938
     
    775944        }
    776945
    777         // select the target cluster for physical mapping
    778         uint32_t target_cxy;
    779         if( vseg->flags & VSEG_DISTRIB ) // depends on VPN LSB
    780         {
    781             uint32_t x_width = LOCAL_CLUSTER->x_width;
    782             uint32_t y_width = LOCAL_CLUSTER->y_width;
    783             target_cxy = vpn & ((1<<(x_width + y_width)) - 1);
    784         }
    785         else                             // defined in vseg descriptor
    786         {
    787             target_cxy = vseg->cxy;
    788         }
    789 
    790         // allocate memory for page fault
    791         kmem_req_t   req;
    792         page_t     * page;
    793         if( target_cxy == local_cxy )        // target cluster is the local cluster
    794         {
    795             req.type  = KMEM_PAGE;
    796             req.size  = 0;
    797             req.flags = AF_NONE;
    798             page      = (page_t *)kmem_alloc( &req );
    799 
    800             error = ( page == NULL ) ? 1 : 0;
    801             ppn   = ppm_page2ppn( page );
    802         }
    803         else                                 // target cluster is not the local cluster
    804         {
    805             rpc_pmem_get_pages_client( target_cxy , 0 , &error , &ppn );
    806         }
     946        // 2. get physical page number, depending on vseg type
     947        error = vmm_get_one_ppn( vseg , vpn , &ppn );
    807948
    808949        if( error )
     
    810951            printk("\n[ERROR] in %s : cannot allocate memory / process = %x / vpn = %x\n",
    811952                   __FUNCTION__ , process->pid , vpn );
    812             return ENOMEM;
     953            return error;
    813954        }
    814955
    815         // define GPT attributes from vseg flags
     956        // 3. define attributes from vseg flags and register in GPT
    816957        attr = GPT_MAPPED | GPT_SMALL;
    817958        if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
     
    820961        if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
    821962
    822         // set the missing PTE in local VMM
    823963        error = hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
     964
    824965        if( error )
    825966        {
     
    828969            return ENOMEM;
    829970        }
    830     }
     971    }  // end new PTE
    831972
    832973    *ret_ppn  = ppn;
    833974    *ret_attr = attr;
    834975    return 0;
    835 }
     976
     977}  // end vmm_get_pte()
    836978
    837979///////////////////////////////////////////////////
     
    851993    process_t * ref_ptr = (process_t *)GET_PTR( process->ref_xp );
    852994
    853     // get missing PTE attributes and PPN
     995    // get missing PTE attributes and PPN from reference cluster
    854996    if( local_cxy != ref_cxy )   // local cluster is not the reference cluster
    855997    {
     
    8791021
    8801022    return 0;
    881 }
     1023
     1024}  // end vmm_handle_page_fault()
     1025
    8821026
    8831027///////////////////////////////////////////
     
    9191063
    9201064    return error;
     1065
    9211066}
    922 
    9231067/*
    9241068
Note: See TracChangeset for help on using the changeset viewer.