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


Ignore:
Timestamp:
Nov 7, 2017, 3:08:12 PM (6 years ago)
Author:
alain
Message:

First implementation of fork/exec.

File:
1 edited

Legend:

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

    r406 r407  
    5858    vseg_t  * vseg_args;
    5959    vseg_t  * vseg_envs;
    60     vseg_t  * vseg_heap;
    6160    intptr_t  base;
    6261    intptr_t  size;
    6362
    64     vmm_dmsg("\n[DMSG] %s : enter for process %x\n", __FUNCTION__ , process->pid );
     63vmm_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
     64__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
    6565
    6666    // get pointer on VMM
    6767    vmm_t   * vmm = &process->vmm;
     68
     69    // initialize local list of vsegs
     70    vmm->vsegs_nr = 0;
     71        list_root_init( &vmm->vsegs_root );
     72        rwlock_init( &vmm->vsegs_lock );
    6873
    6974    assert( ((CONFIG_VMM_KENTRY_SIZE + CONFIG_VMM_ARGS_SIZE + CONFIG_VMM_ENVS_SIZE)
     
    7782             "STACK zone too small\n");
    7883
    79     // initialize the rwlock protecting the vsegs list
    80         rwlock_init( &vmm->vsegs_lock );
    81 
    82     // initialize local list of vsegs and radix-tree
    83     vmm->vsegs_nr = 0;
    84         list_root_init( &vmm->vsegs_root );
    85 
    8684    // register kentry vseg in VMM
    8785    base = CONFIG_VMM_KENTRY_BASE << CONFIG_PPM_PAGE_SHIFT;
    8886    size = CONFIG_VMM_KENTRY_SIZE << CONFIG_PPM_PAGE_SHIFT;
    8987
    90     vseg_kentry = vmm_create_vseg( process , base , size , VSEG_TYPE_CODE );
     88    vseg_kentry = vmm_create_vseg( process,
     89                                   VSEG_TYPE_CODE,
     90                                   base,
     91                                   size,
     92                                   0,             // file_offset unused
     93                                   0,             // file_size unused
     94                                   XPTR_NULL,     // mapper_xp unused
     95                                   local_cxy );
    9196
    9297    assert( (vseg_kentry != NULL) , __FUNCTION__ , "cannot register kentry vseg\n" );
     
    99104    size = CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_SHIFT;
    100105
    101     vseg_args = vmm_create_vseg( process , base , size , VSEG_TYPE_DATA );
    102 
    103     assert( (vseg_args != NULL) , __FUNCTION__ , "cannot register args vseg\n" );
     106    vseg_args = vmm_create_vseg( process,
     107                                 VSEG_TYPE_DATA,
     108                                 base,
     109                                 size,
     110                                 0,             // file_offset unused
     111                                 0,             // file_size unused
     112                                 XPTR_NULL,     // mapper_xp unused
     113                                 local_cxy );
     114
     115    assert( (vseg_args != NULL) , __FUNCTION__ , "cannot create args vseg\n" );
    104116
    105117    vmm->args_vpn_base = base;
     
    111123    size = CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_SHIFT;
    112124
    113     vseg_envs = vmm_create_vseg( process , base , size , VSEG_TYPE_DATA );
    114 
    115     assert( (vseg_envs != NULL) , __FUNCTION__ , "cannot register envs vseg\n" );
     125    vseg_envs = vmm_create_vseg( process,
     126                                 VSEG_TYPE_DATA,
     127                                 base,
     128                                 size,
     129                                 0,             // file_offset unused
     130                                 0,             // file_size unused
     131                                 XPTR_NULL,     // mapper_xp unused
     132                                 local_cxy );
     133
     134    assert( (vseg_envs != NULL) , __FUNCTION__ , "cannot create envs vseg\n" );
    116135
    117136    vmm->envs_vpn_base = base;
    118 
    119     // register the heap vseg in VMM
    120     base = CONFIG_VMM_HEAP_BASE << CONFIG_PPM_PAGE_SHIFT;
    121     size = (CONFIG_VMM_MMAP_BASE-CONFIG_VMM_HEAP_BASE) << CONFIG_PPM_PAGE_SHIFT;
    122 
    123     vseg_heap = vmm_create_vseg( process , base , size , VSEG_TYPE_HEAP );
    124 
    125     assert( (vseg_heap != NULL) , __FUNCTION__ , "cannot register heap vseg\n" );
    126 
    127     vmm->heap_vpn_base = base;
    128137
    129138    // initialize generic page table
     
    137146
    138147    // initialize MMAP allocator
    139     vmm->mmap_mgr.vpn_base        = CONFIG_VMM_MMAP_BASE;
    140     vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_MMAP_BASE;
    141     vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_MMAP_BASE;
     148    vmm->mmap_mgr.vpn_base        = CONFIG_VMM_HEAP_BASE;
     149    vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
     150    vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_HEAP_BASE;
    142151    uint32_t i;
    143152    for( i = 0 ; i < 32 ; i++ ) list_root_init( &vmm->mmap_mgr.zombi_list[i] );
     
    150159    hal_fence();
    151160
    152     vmm_dmsg("\n[DMSG] %s : exit for process %x / entry_point = %x\n",
    153     __FUNCTION__ , process->pid , process->vmm.entry_point );
     161vmm_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x / entry_point = %x\n",
     162__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid ,
     163process->pid , process->vmm.entry_point );
    154164
    155165}  // end vmm_init()
     166
     167//////////////////////////////////////
     168void vmm_display( process_t * process,
     169                  bool_t      mapping )
     170{
     171    vmm_t * vmm = &process->vmm;
     172    gpt_t * gpt = &vmm->gpt;
     173
     174    printk("\n***** VSL and GPT for process %x\n\n",
     175    process->pid );
     176
     177    // get lock protecting the vseg list
     178    rwlock_rd_lock( &vmm->vsegs_lock );
     179
     180    // scan the list of vsegs
     181    list_entry_t * iter;
     182    vseg_t       * vseg;
     183    LIST_FOREACH( &vmm->vsegs_root , iter )
     184    {
     185        vseg = LIST_ELEMENT( iter , vseg_t , list );
     186        printk(" - %s : base = %X / size = %X / npages = %d\n",
     187        vseg_type_str( vseg->type ) , vseg->min , vseg->max - vseg->min , vseg->vpn_size );
     188
     189        if( mapping )
     190        {
     191            vpn_t    vpn;
     192            ppn_t    ppn;
     193            uint32_t attr;
     194            vpn_t    base = vseg->vpn_base;
     195            vpn_t    size = vseg->vpn_size;
     196            for( vpn = base ; vpn < (base+size) ; vpn++ )
     197            {
     198                hal_gpt_get_pte( gpt , vpn , &attr , &ppn );
     199                if( attr & GPT_MAPPED )
     200                {
     201                    printk("    . vpn = %X / attr = %X / ppn = %X\n", vpn , attr , ppn );
     202                }
     203            }
     204        }
     205    }
     206
     207    // release the lock
     208    rwlock_rd_unlock( &vmm->vsegs_lock );
     209}
    156210
    157211//////////////////////////////////////////
     
    170224    rwlock_init( &dst_vmm->vsegs_lock );
    171225
    172     // initialize the dst_vmm vsegs list and the radix tree
     226    // initialize the dst_vmm vsegs list
    173227    dst_vmm->vsegs_nr = 0;
    174228    list_root_init( &dst_vmm->vsegs_root );
    175229
    176     // loop on src_vmm list of vsegs to create
    177     // and register vsegs copies in dst_vmm
     230    // initialize generic page table
     231    error = hal_gpt_create( &dst_vmm->gpt );
     232
     233    if( error )
     234    {
     235        printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ );
     236        return ENOMEM;
     237    }
     238
     239    // loop on SRC VSL to register vsegs copies in DST VSL
     240    // and copy valid PTEs from SRC GPT to DST GPT
    178241    list_entry_t * iter;
    179242    vseg_t       * src_vseg;
     
    201264        vseg_init_from_ref( dst_vseg , XPTR( local_cxy , src_vseg ) );
    202265
    203         // register dst_vseg in dst_vmm
     266        // register dst_vseg in DST VSL
    204267        vseg_attach( dst_vmm , dst_vseg );
     268
     269        // copy SRC GPT to DST GPT / set COW for all writable vsegs, but the FILE type
     270        bool_t cow = (src_vseg->type != VSEG_TYPE_FILE) && (src_vseg->flags & VSEG_WRITE);
     271        error = hal_gpt_copy( &dst_vmm->gpt,
     272                              &src_vmm->gpt,
     273                              src_vseg->vpn_base,
     274                              src_vseg->vpn_size,
     275                              cow );
     276        if( error )
     277        {
     278            printk("\n[ERROR] in %s : cannot copy page GPT\n", __FUNCTION__ );
     279            hal_gpt_destroy( &dst_vmm->gpt );
     280            return ENOMEM;
     281        }
    205282    }
    206283
    207284    // release the src_vmm vsegs_lock
    208285    rwlock_wr_unlock( &src_vmm->vsegs_lock );
    209 
    210     // initialize generic page table
    211     error = hal_gpt_create( &dst_vmm->gpt );
    212 
    213     if( error )
    214     {
    215         printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ );
    216         return ENOMEM;
    217     }
    218286
    219287    // initialize STACK allocator
     
    222290
    223291    // initialize MMAP allocator
    224     dst_vmm->mmap_mgr.vpn_base        = CONFIG_VMM_MMAP_BASE;
    225     dst_vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_MMAP_BASE;
    226     dst_vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_MMAP_BASE;
     292    dst_vmm->mmap_mgr.vpn_base        = CONFIG_VMM_HEAP_BASE;
     293    dst_vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
     294    dst_vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_HEAP_BASE;
    227295    uint32_t i;
    228296    for( i = 0 ; i < 32 ; i++ ) list_root_init( &dst_vmm->mmap_mgr.zombi_list[i] );
     
    242310
    243311    dst_vmm->entry_point   = src_vmm->entry_point;
    244 
    245     // HEAP TODO : new heap for child ???
    246     dst_vmm->heap_vseg     = src_vmm->heap_vseg;
    247 
    248     // initialize generic page table
    249     error = hal_gpt_create( &dst_vmm->gpt );
    250 
    251     if( error )
    252     {
    253         printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ );
    254         return ENOMEM;
    255     }
    256 
    257     // copy GPT content from src_vmm to dst_vmm, activating "Copy-On-Write"
    258     // TODO register Copy-On_Write in page descriptors
    259     bool_t cow = true;
    260     hal_gpt_copy( &dst_vmm->gpt , &src_vmm->gpt , cow );
    261312
    262313    hal_fence();
     
    431482}  // end vmm_mmap_alloc()
    432483
    433 //////////////////////////////////////////////
    434 vseg_t * vmm_create_vseg( process_t * process,
    435                           intptr_t    base,
    436                               intptr_t    size,
    437                               uint32_t    type )
     484////////////////////////////////////////////////
     485vseg_t * vmm_create_vseg( process_t   * process,
     486                              vseg_type_t   type,
     487                          intptr_t      base,
     488                              uint32_t      size,
     489                          uint32_t      file_offset,
     490                          uint32_t      file_size,
     491                          xptr_t        mapper_xp,
     492                          cxy_t         cxy )
    438493{
    439494    vseg_t     * vseg;          // created vseg pointer
     
    442497        error_t      error;
    443498
    444     // get pointer on VMM
    445         vmm_t * vmm = &process->vmm;
    446 
    447         vmm_dmsg("\n[DMSG] %s : enter for process %x / base = %x / size = %x / type = %s\n",
    448                      __FUNCTION__ , process->pid , base , size , vseg_type_str(type) );
     499vmm_dmsg("\n[DBG] %s : core[%x,%d] enters / process %x / base %x / size %x / %s / cxy = %x\n",
     500__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid ,
     501process->pid , base , size , vseg_type_str(type) , cxy );
     502
     503    // get pointer on VMM
     504        vmm_t * vmm    = &process->vmm;
    449505
    450506    // compute base, size, vpn_base, vpn_size, depending on vseg type
    451     // we use the VMM specific allocators for STACK and MMAP vsegs
     507    // we use the VMM specific allocators for "stack", "file", "anon", & "remote" vsegs
    452508    if( type == VSEG_TYPE_STACK )
    453509    {
     
    456512        if( error )
    457513        {
    458             printk("\n[ERROR] in %s : no vspace for stack vseg / process %x in cluster %x\n",
    459                    __FUNCTION__ , process->pid , local_cxy );
     514            printk("\n[ERROR] in %s : no space for stack vseg / process %x in cluster %x\n",
     515            __FUNCTION__ , process->pid , local_cxy );
    460516            return NULL;
    461517        }
     
    498554        printk("\n[ERROR] in %s for process %x : new vseg [vpn_base = %x / vpn_size = %x]\n"
    499555               "  overlap existing vseg [vpn_base = %x / vpn_size = %x]\n",
    500                __FUNCTION__ , process->pid, vpn_base, vpn_size,
    501                vseg->vpn_base, vseg->vpn_size );
     556        __FUNCTION__ , process->pid, vpn_base, vpn_size, vseg->vpn_base, vseg->vpn_size );
    502557        return NULL;
    503558    }
     
    508563        {
    509564            printk("\n[ERROR] in %s for process %x : cannot allocate memory for vseg\n",
    510              __FUNCTION__ , process->pid );
     565        __FUNCTION__ , process->pid );
    511566        return NULL;
    512567        }
    513568
    514569    // initialize vseg descriptor
    515         vseg_init( vseg , base, size , vpn_base , vpn_size , type , local_cxy );
    516 
    517     // update "heap_vseg" in VMM
    518         if( type == VSEG_TYPE_HEAP ) process->vmm.heap_vseg = vseg;
     570        vseg_init( vseg,
     571               type,
     572               base,
     573               size,
     574               vpn_base,
     575               vpn_size,
     576               file_offset,
     577               file_size,
     578               mapper_xp,
     579               cxy );
    519580
    520581    // attach vseg to vmm
     
    523584        rwlock_wr_unlock( &vmm->vsegs_lock );
    524585
    525         vmm_dmsg("\n[DMSG] %s : exit for process %x / vseg [%x, %x] registered\n",
    526                      __FUNCTION__ , process->pid , vseg->min , vseg->max );
     586vmm_dmsg("\n[DBG] %s : core[%x,%d] exit / process %x / base %x / size %x / type %s\n",
     587__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid ,
     588process->pid , base , size , vseg_type_str(type) );
    527589
    528590        return vseg;
     
    579641        vseg_free( vseg );
    580642    }
    581 }
     643}  // end vmm_remove_vseg()
    582644
    583645//////////////////////////////////////////////
     
    655717}
    656718
    657 ///////////////////////////////////////////////////////////////////////////////////////
     719//////////////////////////////////////////////////////////////////////////////////////////
    658720// This low-level static function is called by the vmm_get_vseg() and vmm_resize_vseg()
    659721// functions.  It scan the list of registered vsegs to find the unique vseg containing
    660722// a given virtual address.
    661 ///////////////////////////////////////////////////////////////////////////////////////
     723//////////////////////////////////////////////////////////////////////////////////////////
    662724// @ vmm     : pointer on the process VMM.
    663725// @ vaddr   : virtual address.
    664726// @ return vseg pointer if success / return NULL if not found.
    665 ///////////////////////////////////////////////////////////////////////////////////////
     727//////////////////////////////////////////////////////////////////////////////////////////
    666728static vseg_t * vseg_from_vaddr( vmm_t    * vmm,
    667729                                 intptr_t   vaddr )
     
    755817
    756818        // create new vseg
    757         new = vmm_create_vseg( process , addr_min , (vseg->max - addr_max) , vseg->type );
     819        new = vmm_create_vseg( process,
     820                               vseg->type,
     821                               addr_min,
     822                               (vseg->max - addr_max),
     823                               vseg->file_offset,
     824                               vseg->file_size,
     825                               vseg->mapper_xp,
     826                               vseg->cxy );
     827
    758828        if( new == NULL ) error = EINVAL;
    759829        else              error = 0;
     
    814884}  // end vmm_get_vseg()
    815885
     886//////////////////////////////////////////////////////////////////////////////////////
     887// This static function compute the target cluster to allocate a physical page
     888// for a given <vpn> in a given <vseg>, allocates the page (with an RPC if required)
     889// and returns an extended pointer on the allocated page descriptor.
     890// The vseg cannot have the FILE type.
     891//////////////////////////////////////////////////////////////////////////////////////
     892static xptr_t vmm_page_allocate( vseg_t * vseg,
     893                                 vpn_t    vpn )
     894{
     895    // compute target cluster
     896    page_t     * page_ptr;
     897    cxy_t        page_cxy;
     898    kmem_req_t   req;
     899
     900    uint32_t     type  = vseg->type;
     901    uint32_t     flags = vseg->flags;
     902
     903    assert( ( type != VSEG_TYPE_FILE ) , __FUNCTION__ , "illegal vseg type\n" );
     904
     905    if( flags & VSEG_DISTRIB )    // distributed => cxy depends on vpn LSB
     906    {
     907        uint32_t x_size  = LOCAL_CLUSTER->x_size;
     908        uint32_t y_size  = LOCAL_CLUSTER->y_size;
     909        uint32_t y_width = LOCAL_CLUSTER->y_width;
     910        uint32_t index   = vpn & ((x_size * y_size) - 1);
     911        uint32_t x       = index / y_size;
     912        uint32_t y       = index % y_size;
     913        page_cxy         = (x<<y_width) + y;
     914    }
     915    else                          // other cases => cxy specified in vseg
     916    {
     917        page_cxy         = vseg->cxy;
     918    }
     919
     920    // allocate a physical page from target cluster
     921    if( page_cxy == local_cxy )  // target cluster is the local cluster
     922    {
     923        req.type  = KMEM_PAGE;
     924        req.size  = 0;
     925        req.flags = AF_NONE;
     926        page_ptr  = (page_t *)kmem_alloc( &req );
     927    }
     928    else                           // target cluster is not the local cluster
     929    {
     930        rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr );
     931    }
     932
     933    if( page_ptr == NULL ) return XPTR_NULL;
     934    else                   return XPTR( page_cxy , page_ptr );
     935
     936}  // end vmm_page_allocate() 
     937
    816938////////////////////////////////////////
    817939error_t vmm_get_one_ppn( vseg_t * vseg,
     
    820942{
    821943    error_t    error;
    822     cxy_t      page_cxy;          // physical page cluster
     944    xptr_t     page_xp;           // extended pointer on physical page descriptor
    823945    page_t   * page_ptr;          // local pointer on physical page descriptor
    824946    uint32_t   index;             // missing page index in vseg mapper
     
    828950    index     = vpn - vseg->vpn_base;
    829951
    830     vmm_dmsg("\n[DMSG] %s : core[%x,%d] enter for vpn = %x / type = %s / index = %d\n",
    831     __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn, vseg_type_str(type), index );
     952vmm_dmsg("\n[DBG] %s : core[%x,%d] enter for vpn = %x / type = %s / index = %d\n",
     953__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn, vseg_type_str(type), index );
    832954
    833955    // FILE type : get the physical page from the file mapper
     
    835957    {
    836958        // get extended pointer on mapper
    837         xptr_t     mapper_xp = vseg->mapper_xp;
     959        xptr_t mapper_xp = vseg->mapper_xp;
    838960
    839961        assert( (mapper_xp != XPTR_NULL), __FUNCTION__,
     
    856978        if ( page_ptr == NULL ) return EINVAL;
    857979
    858         page_cxy = mapper_cxy;
     980        page_xp = XPTR( mapper_cxy , page_ptr );
    859981    }
    860982
    861983    // Other types : allocate a physical page from target cluster,
     984    // as defined by vseg type and vpn value
    862985    else
    863986    {
    864         uint32_t flags = vseg->flags;
    865 
    866         // get target cluster for physical page
    867         if( flags & VSEG_DISTRIB ) // depends on VPN LSB
    868         {
    869             uint32_t x_size = LOCAL_CLUSTER->x_size;
    870             uint32_t y_size = LOCAL_CLUSTER->y_size;
    871             page_cxy = vpn & ((x_size * y_size) - 1);
    872         }
    873         else                       // defined in vseg descriptor
    874         {
    875             page_cxy = vseg->cxy;
    876         }
    877 
    878         // allocate a physical page in target cluster
    879         kmem_req_t   req;
    880         if( page_cxy == local_cxy )  // target cluster is the local cluster
    881         {
    882             req.type  = KMEM_PAGE;
    883             req.size  = 0;
    884             req.flags = AF_NONE;
    885             page_ptr  = (page_t *)kmem_alloc( &req );
    886         }
    887         else                           // target cluster is not the local cluster
    888         {
    889             rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr );
    890         }
    891 
    892         if( page_ptr == NULL ) return ENOMEM;
     987        // allocate physical page
     988        page_xp = vmm_page_allocate( vseg , vpn );
     989
     990        if( page_xp == XPTR_NULL ) return ENOMEM;
    893991
    894992        // initialise missing page from .elf file mapper for DATA and CODE types
     
    9121010            uint32_t elf_offset = vseg->file_offset + offset;
    9131011
    914             vmm_dmsg("\n[DMSG] %s : core[%x,%d] for vpn = %x / elf_offset = %x\n",
    915             __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn, elf_offset );
     1012vmm_dmsg("\n[DBG] %s : core[%x,%d] for vpn = %x / elf_offset = %x\n",
     1013__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn, elf_offset );
    9161014
    9171015            // compute extended pointer on page base
    918             xptr_t base_xp  = ppm_page2base( XPTR( page_cxy , page_ptr ) );
     1016            xptr_t base_xp  = ppm_page2base( page_xp );
    9191017
    9201018            // file_size (in .elf mapper) can be smaller than vseg_size (BSS)
     
    9231021            if( file_size < offset )                 // missing page fully in  BSS
    9241022            {
    925                 vmm_dmsg("\n[DMSG] %s : core[%x,%d] for vpn = %x / fully in BSS\n",
    926                 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn );
    927 
    928                 if( page_cxy == local_cxy )
     1023vmm_dmsg("\n[DBG] %s : core[%x,%d] for vpn = %x / fully in BSS\n",
     1024__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn );
     1025
     1026                if( GET_CXY( page_xp ) == local_cxy )
    9291027                {
    9301028                    memset( GET_PTR( base_xp ) , 0 , CONFIG_PPM_PAGE_SIZE );
     
    9371035            else if( file_size >= (offset + CONFIG_PPM_PAGE_SIZE) )  // fully in  mapper
    9381036            {
    939                 vmm_dmsg("\n[DMSG] %s : core[%x,%d] for vpn = %x / fully in mapper\n",
    940                 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn );
     1037
     1038vmm_dmsg("\n[DBG] %s : core[%x,%d] for vpn = %x / fully in mapper\n",
     1039__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn );
    9411040
    9421041                if( mapper_cxy == local_cxy )
     
    9651064                  // - (page_size + offset - file_size) bytes from BSS
    9661065            {
    967                 vmm_dmsg("\n[DMSG] %s : core[%x,%d] for vpn = %x / both mapper & BSS\n"
    968                          "      %d bytes from mapper / %d bytes from BSS\n",
    969                 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn,
    970                 file_size - offset , offset + CONFIG_PPM_PAGE_SIZE - file_size  );
     1066
     1067vmm_dmsg("\n[DBG] %s : core[%x,%d] for vpn = %x / both mapper & BSS\n"
     1068         "      %d bytes from mapper / %d bytes from BSS\n",
     1069__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vpn,
     1070file_size - offset , offset + CONFIG_PPM_PAGE_SIZE - file_size  );
    9711071
    9721072                // initialize mapper part
     
    9931093
    9941094                // initialize BSS part
    995                 if( page_cxy == local_cxy )
     1095                if( GET_CXY( page_xp ) == local_cxy )
    9961096                {
    9971097                    memset( GET_PTR( base_xp ) + file_size - offset , 0 ,
     
    10081108
    10091109    // return ppn
    1010     *ppn = ppm_page2ppn( XPTR( page_cxy , page_ptr ) );
    1011 
    1012     vmm_dmsg("\n[DMSG] %s : core[%x,%d] exit for vpn = %x / ppn = %x\n",
    1013     __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , *ppn );
     1110    *ppn = ppm_page2ppn( page_xp );
     1111
     1112vmm_dmsg("\n[DBG] %s : core[%x,%d] exit for vpn = %x / ppn = %x\n",
     1113__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , *ppn );
    10141114
    10151115    return 0;
     
    10201120error_t vmm_get_pte( process_t * process,
    10211121                     vpn_t       vpn,
    1022                      uint32_t  * ret_attr,
    1023                      ppn_t     * ret_ppn )
    1024 {
    1025     vseg_t  * vseg;   // pointer on vseg containing VPN
    1026     ppn_t     ppn;    // physical page number
    1027     uint32_t  attr;   // attributes from GPT entry
     1122                     bool_t      cow,
     1123                     uint32_t  * attr,
     1124                     ppn_t     * ppn )
     1125{
     1126    vseg_t  * vseg;       // pointer on vseg containing VPN
     1127    ppn_t     old_ppn;    // current PTE_PPN
     1128    uint32_t  old_attr;   // current PTE_ATTR
     1129    ppn_t     new_ppn;    // new PTE_PPN
     1130    uint32_t  new_attr;   // new PTE_ATTR
     1131    xptr_t    page_xp;    // extended pointer on allocated page descriptor
    10281132    error_t   error;
    10291133
     
    10321136    "not called in the reference cluster\n" );
    10331137
    1034     vmm_dmsg("\n[DMSG] %s : core[%x,%d] enter for vpn = %x in process %x\n",
    1035     __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , process->pid );
     1138vmm_dmsg("\n[DBG] %s : core[%x,%d] enter for vpn = %x in process %x / cow = %d\n",
     1139__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , process->pid , %d);
    10361140
    10371141    // get VMM pointer
    10381142    vmm_t * vmm = &process->vmm;
    10391143
    1040     // access GPT to get PTE attributes and PPN
    1041     hal_gpt_get_pte( &vmm->gpt , vpn , &attr , &ppn );
    1042 
    1043     // if PTE is unmapped
    1044     // 1) get VSEG containing the missing VPN
    1045     // 2) get & initialize physical page (depending on vseg type),
    1046     // 3) register the PTE in reference GPT
    1047     if( (attr & GPT_MAPPED) == 0 )
    1048     {
    1049         vmm_dmsg("\n[DMSG] %s : core[%x,%d] page %x unmapped => try to map it\n",
    1050         __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
    1051 
    1052         // 1. get vseg pointer
    1053         error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg );
     1144    // get vseg pointer from ref VSL
     1145    error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg );
     1146
     1147    if( error )
     1148    {
     1149        printk("\n[ERROR] in %s : out of segment / process = %x / vpn = %x\n",
     1150        __FUNCTION__ , process->pid , vpn );
     1151        return error;
     1152    }
     1153
     1154vmm_dmsg("\n[DBG] %s : core[%x,%d] found vseg %s / vpn_base = %x / vpn_size = %x\n",
     1155__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid ,
     1156vseg_type_str(vseg->type) , vseg->vpn_base , vseg->vpn_size );
     1157
     1158    // access GPT to get current PTE attributes and PPN
     1159    hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn );
     1160
     1161    // for both copy_on_write and page_fault events, we allocate a physical page,
     1162    // initialize it, register it in the GPT, and return the new_ppn and new_attr
     1163
     1164    if( cow )               ////////////// copy_on_write request ///////////
     1165    {
     1166        assert( (*attr & GPT_MAPPED) , __FUNCTION__ ,
     1167        "PTE must be mapped for a copy-on-write\n" );
     1168
     1169vmm_dmsg("\n[DBG] %s : core[%x,%d] page %x must be copied => do it\n",
     1170__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
     1171
     1172        // allocate a physical page depending on vseg type
     1173        page_xp = vmm_page_allocate( vseg , vpn );
     1174
     1175        if( page_xp == XPTR_NULL )
     1176        {
     1177            printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
     1178            __FUNCTION__ , process->pid , vpn );
     1179            return ENOMEM;
     1180        }
     1181
     1182        // compute allocated page PPN
     1183        new_ppn = ppm_page2ppn( page_xp );
     1184
     1185        // copy old page content to new page
     1186        xptr_t  old_base_xp = ppm_ppn2base( old_ppn );
     1187        xptr_t  new_base_xp = ppm_ppn2base( new_ppn );
     1188        memcpy( GET_PTR( new_base_xp ),
     1189                GET_PTR( old_base_xp ),
     1190                CONFIG_PPM_PAGE_SIZE );
     1191
     1192        // update attributes: reset COW and set WRITABLE
     1193        new_attr = old_attr & ~GPT_COW; 
     1194        new_attr = new_attr | GPT_WRITABLE;
     1195
     1196        // register PTE in GPT
     1197        error = hal_gpt_set_pte( &vmm->gpt , vpn , new_ppn , new_attr );
    10541198
    10551199        if( error )
    10561200        {
    1057             printk("\n[ERROR] in %s : out of segment / process = %x / vpn = %x\n",
    1058                    __FUNCTION__ , process->pid , vpn );
     1201            printk("\n[ERROR] in %s : cannot update GPT / process = %x / vpn = %x\n",
     1202            __FUNCTION__ , process->pid , vpn );
    10591203            return error;
    10601204        }
    1061 
    1062         vmm_dmsg("\n[DMSG] %s : core[%x,%d] found vseg %s / vpn_base = %x / vpn_size = %x\n",
    1063         __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid ,
    1064         vseg_type_str(vseg->type) , vseg->vpn_base , vseg->vpn_size );
    1065 
    1066         // 2. get physical page number, depending on vseg type
    1067         error = vmm_get_one_ppn( vseg , vpn , &ppn );
    1068 
    1069         if( error )
     1205    }
     1206    else                    //////////////////// page_fault request ///////////
     1207    { 
     1208        if( (old_attr & GPT_MAPPED) == 0 )    // PTE unmapped in ref GPT
    10701209        {
    1071             printk("\n[ERROR] in %s : cannot allocate memory / process = %x / vpn = %x\n",
    1072                    __FUNCTION__ , process->pid , vpn );
    1073             return error;
     1210
     1211vmm_dmsg("\n[DBG] %s : core[%x,%d] page %x unmapped => try to map it\n",
     1212__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
     1213
     1214            // allocate one physical page, depending on vseg type
     1215            error = vmm_get_one_ppn( vseg , vpn , &new_ppn );
     1216
     1217            if( error )
     1218            {
     1219                printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
     1220                __FUNCTION__ , process->pid , vpn );
     1221                return error;
     1222            }
     1223
     1224            // define attributes from vseg flags
     1225            new_attr = GPT_MAPPED | GPT_SMALL;
     1226            if( vseg->flags & VSEG_USER  ) new_attr |= GPT_USER;
     1227            if( vseg->flags & VSEG_WRITE ) new_attr |= GPT_WRITABLE;
     1228            if( vseg->flags & VSEG_EXEC  ) new_attr |= GPT_EXECUTABLE;
     1229            if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE;
     1230
     1231            // register PTE in GPT
     1232            error = hal_gpt_set_pte( &vmm->gpt , vpn , new_ppn , new_attr );
     1233
     1234            if( error )
     1235            {
     1236                printk("\n[ERROR] in %s : cannot update GPT / process = %x / vpn = %x\n",
     1237                __FUNCTION__ , process->pid , vpn );
     1238                return error;
     1239            }
    10741240        }
    1075 
    1076         // 3. define attributes from vseg flags and register in GPT
    1077         attr = GPT_MAPPED | GPT_SMALL;
    1078         if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
    1079         if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
    1080         if( vseg->flags & VSEG_EXEC  ) attr |= GPT_EXECUTABLE;
    1081         if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
    1082 
    1083         error = hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
    1084 
    1085         if( error )
     1241        else
    10861242        {
    1087             printk("\n[ERROR] in %s : cannot register PTE / process = %x / vpn = %x\n",
    1088                    __FUNCTION__ , process->pid , vpn );
    1089             return error;
     1243            new_attr = old_attr;
     1244            new_ppn  = old_ppn;
    10901245        }
    1091     }  // end new PTE
    1092 
    1093     vmm_dmsg("\n[DMSG] %s : core[%x,%d] exit for vpn = %x / ppn = %x\n",
    1094     __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , ppn );
    1095 
    1096     *ret_ppn  = ppn;
    1097     *ret_attr = attr;
     1246    }
     1247
     1248vmm_dmsg("\n[DBG] %s : core[%x,%d] exit for vpn = %x / ppn = %x / attr = %x\n",
     1249__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , new_ppn , new_attr );
     1250
     1251    *ppn  = new_ppn;
     1252    *attr = new_attr;
    10981253    return 0;
    10991254
     
    11061261    uint32_t         attr;          // missing page attributes
    11071262    ppn_t            ppn;           // missing page PPN
    1108     error_t          error;         // return value
     1263    error_t          error;
    11091264
    11101265    // get reference process cluster and local pointer
     
    11131268
    11141269    // get missing PTE attributes and PPN from reference cluster
    1115     if( local_cxy != ref_cxy )   // local cluster is not the reference cluster
    1116     {
    1117         rpc_vmm_get_pte_client( ref_cxy , ref_ptr , vpn , &attr , &ppn , &error );
    1118     }
    1119     else                              // local cluster is the reference cluster
    1120     {
    1121         error = vmm_get_pte( process , vpn , &attr , &ppn );
     1270    if( local_cxy != ref_cxy ) 
     1271    {
     1272        rpc_vmm_get_pte_client( ref_cxy,
     1273                                ref_ptr,
     1274                                vpn,
     1275                                false,    // page_fault
     1276                                &attr,
     1277                                &ppn,
     1278                                &error );
     1279
     1280        // get local VMM pointer
     1281        vmm_t * vmm = &process->vmm;
     1282
     1283        // update local GPT
     1284        error |= hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
     1285    }
     1286    else   // local cluster is the reference cluster
     1287    {
     1288        error = vmm_get_pte( process,
     1289                             vpn,
     1290                             false,      // page-fault
     1291                             &attr,
     1292                             &ppn );
    11221293    }
    11231294
     
    11261297}  // end vmm_handle_page_fault()
    11271298
     1299///////////////////////////////////////////////
     1300error_t vmm_copy_on_write( process_t * process,
     1301                           vpn_t       vpn )
     1302{
     1303    uint32_t         attr;          // missing page attributes
     1304    ppn_t            ppn;           // missing page PPN
     1305    error_t          error;
     1306
     1307    // get reference process cluster and local pointer
     1308    cxy_t       ref_cxy = GET_CXY( process->ref_xp );
     1309    process_t * ref_ptr = (process_t *)GET_PTR( process->ref_xp );
     1310
     1311    // get new PTE attributes and PPN from reference cluster
     1312    if( local_cxy != ref_cxy )
     1313    {
     1314        rpc_vmm_get_pte_client( ref_cxy,
     1315                                ref_ptr,
     1316                                vpn,
     1317                                true,     // copy-on-write
     1318                                &attr,
     1319                                &ppn,
     1320                                &error );
     1321
     1322        // get local VMM pointer
     1323        vmm_t * vmm = &process->vmm;
     1324
     1325        // update local GPT
     1326        error |= hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
     1327    }
     1328    else   // local cluster is the reference cluster
     1329    {
     1330        error = vmm_get_pte( process,
     1331                             vpn,
     1332                             true,      // copy-on-write
     1333                             &attr,
     1334                             &ppn );
     1335    }
     1336
     1337    return error;
     1338
     1339}  // end vmm_copy_on_write()
    11281340
    11291341///////////////////////////////////////////
     
    11521364    if( local_cxy == GET_CXY( process->ref_xp) ) // calling process is reference process
    11531365    {
    1154         error = vmm_get_pte( process, vpn , &attr , &ppn );
     1366        error = vmm_get_pte( process, vpn , false , &attr , &ppn );
    11551367    }
    11561368    else                                         // calling process is not reference process
     
    11581370        cxy_t       ref_cxy = GET_CXY( process->ref_xp );
    11591371        process_t * ref_ptr = (process_t *)GET_PTR( process->ref_xp );
    1160         rpc_vmm_get_pte_client( ref_cxy , ref_ptr , vpn , &attr , &ppn , &error );
     1372        rpc_vmm_get_pte_client( ref_cxy , ref_ptr , vpn , false , &attr , &ppn , &error );
    11611373    }
    11621374
Note: See TracChangeset for help on using the changeset viewer.