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


Ignore:
Timestamp:
Dec 5, 2017, 4:20:07 PM (7 years ago)
Author:
alain
Message:

Fix several bugs in the fork() syscall.

File:
1 edited

Legend:

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

    r407 r408  
    3232#include <rwlock.h>
    3333#include <list.h>
     34#include <xlist.h>
    3435#include <bits.h>
    3536#include <process.h>
     
    6970    // initialize local list of vsegs
    7071    vmm->vsegs_nr = 0;
    71         list_root_init( &vmm->vsegs_root );
    72         rwlock_init( &vmm->vsegs_lock );
     72        xlist_root_init( XPTR( local_cxy , &vmm->vsegs_root ) );
     73        remote_rwlock_init( XPTR( local_cxy , &vmm->vsegs_lock ) );
    7374
    7475    assert( ((CONFIG_VMM_KENTRY_SIZE + CONFIG_VMM_ARGS_SIZE + CONFIG_VMM_ENVS_SIZE)
     
    154155    // initialize instrumentation counters
    155156        vmm->pgfault_nr          = 0;
    156         vmm->u_err_nr            = 0;
    157         vmm->m_err_nr            = 0;
    158157
    159158    hal_fence();
     
    176175
    177176    // get lock protecting the vseg list
    178     rwlock_rd_lock( &vmm->vsegs_lock );
     177    remote_rwlock_rd_lock( XPTR( local_cxy , &vmm->vsegs_lock ) );
    179178
    180179    // scan the list of vsegs
    181     list_entry_t * iter;
     180    xptr_t         root_xp = XPTR( local_cxy , &vmm->vsegs_root );
     181    xptr_t         iter_xp;
     182    xptr_t         vseg_xp;
    182183    vseg_t       * vseg;
    183     LIST_FOREACH( &vmm->vsegs_root , iter )
    184     {
    185         vseg = LIST_ELEMENT( iter , vseg_t , list );
     184    XLIST_FOREACH( root_xp , iter_xp )
     185    {
     186        vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     187        vseg    = (vseg_t *)GET_PTR( vseg_xp );
     188
    186189        printk(" - %s : base = %X / size = %X / npages = %d\n",
    187190        vseg_type_str( vseg->type ) , vseg->min , vseg->max - vseg->min , vseg->vpn_size );
     
    206209
    207210    // release the lock
    208     rwlock_rd_unlock( &vmm->vsegs_lock );
    209 }
    210 
    211 //////////////////////////////////////////
    212 error_t vmm_copy( process_t * dst_process,
    213                   process_t * src_process )
    214 {
    215     error_t error;
    216 
    217     vmm_t * src_vmm = &src_process->vmm;
    218     vmm_t * dst_vmm = &dst_process->vmm;
    219 
    220     // take the src_vmm vsegs_lock
    221     rwlock_wr_lock( &src_vmm->vsegs_lock );
    222 
    223     // initialize dst_vmm vsegs_lock
    224     rwlock_init( &dst_vmm->vsegs_lock );
    225 
    226     // initialize the dst_vmm vsegs list
    227     dst_vmm->vsegs_nr = 0;
    228     list_root_init( &dst_vmm->vsegs_root );
    229 
    230     // initialize generic page table
    231     error = hal_gpt_create( &dst_vmm->gpt );
    232 
     211    remote_rwlock_rd_unlock( XPTR( local_cxy , &vmm->vsegs_lock ) );
     212
     213}  // vmm_display()
     214
     215/////////////////////i////////////////////
     216void vmm_update_pte( process_t * process,
     217                     vpn_t       vpn,
     218                     uint32_t    attr,
     219                     ppn_t       ppn )
     220{
     221
     222    xlist_entry_t * process_root_ptr;
     223    xptr_t          process_root_xp;
     224    xptr_t          process_iter_xp;
     225
     226    xptr_t          remote_process_xp;
     227    cxy_t           remote_process_cxy;
     228    process_t     * remote_process_ptr;
     229    xptr_t          remote_gpt_xp;
     230
     231    pid_t           pid;
     232    cxy_t           owner_cxy;
     233    lpid_t          owner_lpid;
     234
     235    // get extended pointer on root of process copies xlist in owner cluster
     236    pid              = process->pid;
     237    owner_cxy        = CXY_FROM_PID( pid );
     238    owner_lpid       = LPID_FROM_PID( pid );
     239    process_root_ptr = &LOCAL_CLUSTER->pmgr.copies_root[owner_lpid];
     240    process_root_xp  = XPTR( owner_cxy , process_root_ptr );
     241
     242    // loop on destination process copies
     243    XLIST_FOREACH( process_root_xp , process_iter_xp )
     244    {
     245        // get cluster and local pointer on remote process
     246        remote_process_xp  = XLIST_ELEMENT( process_iter_xp , process_t , copies_list );
     247        remote_process_ptr = (process_t *)GET_PTR( remote_process_xp );
     248        remote_process_cxy = GET_CXY( remote_process_xp );
     249
     250        // get extended pointer on remote gpt
     251        remote_gpt_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.gpt );
     252
     253        hal_gpt_update_pte( remote_gpt_xp,
     254                            vpn,
     255                            attr,
     256                            ppn );
     257    } 
     258}  // end vmm_update_pte()
     259
     260///////////////////////////////////////
     261void vmm_set_cow( process_t * process )
     262{
     263    vmm_t         * vmm;
     264
     265    xlist_entry_t * process_root_ptr;
     266    xptr_t          process_root_xp;
     267    xptr_t          process_iter_xp;
     268
     269    xptr_t          remote_process_xp;
     270    cxy_t           remote_process_cxy;
     271    process_t     * remote_process_ptr;
     272    xptr_t          remote_gpt_xp;
     273
     274    xptr_t          vseg_root_xp;
     275    xptr_t          vseg_iter_xp;
     276
     277    xptr_t          vseg_xp;
     278    vseg_t        * vseg;
     279
     280    pid_t           pid;
     281    cxy_t           owner_cxy;
     282    lpid_t          owner_lpid;
     283
     284vmm_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
     285__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
     286
     287    // check cluster is reference
     288    assert( (GET_CXY( process->ref_xp ) == local_cxy) , __FUNCTION__,
     289    "local cluster is not process reference cluster\n");
     290
     291    // get pointer on reference VMM
     292    vmm = &process->vmm;
     293
     294    // get extended pointer on root of process copies xlist in owner cluster
     295    pid              = process->pid;
     296    owner_cxy        = CXY_FROM_PID( pid );
     297    owner_lpid       = LPID_FROM_PID( pid );
     298    process_root_ptr = &LOCAL_CLUSTER->pmgr.copies_root[owner_lpid];
     299    process_root_xp  = XPTR( owner_cxy , process_root_ptr );
     300
     301    // get extended pointer on root of vsegs xlist from reference VMM
     302    vseg_root_xp  = XPTR( local_cxy , &vmm->vsegs_root );
     303
     304    // loop on destination process copies
     305    XLIST_FOREACH( process_root_xp , process_iter_xp )
     306    {
     307        // get cluster and local pointer on remote process
     308        remote_process_xp  = XLIST_ELEMENT( process_iter_xp , process_t , copies_list );
     309        remote_process_ptr = (process_t *)GET_PTR( remote_process_xp );
     310        remote_process_cxy = GET_CXY( remote_process_xp );
     311
     312vmm_dmsg("\n[DBG] %s : core[%x,%d] handling process %x in cluster %x\n",
     313__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid , remote_process_cxy );
     314
     315        // get extended pointer on remote gpt
     316        remote_gpt_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.gpt );
     317
     318        // loop on vsegs in (local) reference process VSL
     319        XLIST_FOREACH( vseg_root_xp , vseg_iter_xp )
     320        {
     321            // get pointer on vseg
     322            vseg_xp  = XLIST_ELEMENT( vseg_iter_xp , vseg_t , xlist );
     323            vseg     = (vseg_t *)GET_PTR( vseg_xp );
     324
     325            assert( (GET_CXY( vseg_xp ) == local_cxy) , __FUNCTION__,
     326            "all vsegs in reference VSL must be local\n" );
     327
     328            // get vseg type, base and size
     329            uint32_t type     = vseg->type;
     330            vpn_t    vpn_base = vseg->vpn_base;
     331            vpn_t    vpn_size = vseg->vpn_size;
     332
     333vmm_dmsg("\n[DBG] %s : core[%x,%d] handling vseg %s / vpn_base = %x / vpn_size = %x\n",
     334__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, vseg_type_str(type), vpn_base, vpn_size );
     335
     336            // set COW flag on the remote GPT depending on vseg type
     337            if( (type == VSEG_TYPE_DATA)  ||
     338                (type == VSEG_TYPE_ANON)  ||
     339                (type == VSEG_TYPE_REMOTE) )
     340            {
     341                hal_gpt_flip_cow( true,             // set_cow
     342                                  remote_gpt_xp,
     343                                  vpn_base,
     344                                  vpn_size );
     345            }
     346        }    // en loop on vsegs
     347    }   // end loop on process copies
     348 
     349vmm_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
     350__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , process->pid );
     351
     352}  // end vmm_set-cow()
     353
     354/////////////////////////////////////////////////
     355error_t vmm_fork_copy( process_t * child_process,
     356                       xptr_t      parent_process_xp )
     357{
     358    error_t     error;
     359    cxy_t       parent_cxy;
     360    process_t * parent_process;
     361    vmm_t     * parent_vmm;
     362    xptr_t      parent_lock_xp;
     363    vmm_t     * child_vmm;
     364    xptr_t      iter_xp;
     365    xptr_t      parent_vseg_xp;
     366    vseg_t    * parent_vseg;
     367    vseg_t    * child_vseg;
     368    uint32_t    type;
     369    bool_t      cow;
     370    vpn_t       vpn;           
     371    vpn_t       vpn_base;
     372    vpn_t       vpn_size;
     373    xptr_t      page_xp;
     374    page_t    * page_ptr;
     375    cxy_t       page_cxy;
     376    xptr_t      parent_root_xp;
     377    bool_t      mapped;
     378    ppn_t       ppn;
     379
     380vmm_dmsg("\n[DBG] %s : core[%x,%d] enter\n",
     381__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid );
     382
     383    // get parent process cluster and local pointer
     384    parent_cxy     = GET_CXY( parent_process_xp );
     385    parent_process = (process_t *)GET_PTR( parent_process_xp );
     386
     387    // get local pointers on parent and child VMM
     388    parent_vmm = &parent_process->vmm;
     389    child_vmm  = &child_process->vmm;
     390
     391    // get extended pointer on lock protecting the parent VSL
     392    parent_lock_xp = XPTR( parent_cxy , &parent_vmm->vsegs_lock );
     393
     394    // take the lock protecting the parent VSL
     395    remote_rwlock_rd_lock( parent_lock_xp );
     396
     397    // initialize the lock protecting the child VSL
     398    remote_rwlock_init( XPTR( local_cxy , &child_vmm->vsegs_lock ) );
     399
     400    // initialize the child VSL as empty
     401    xlist_root_init( XPTR( local_cxy, &child_vmm->vsegs_root ) );
     402    child_vmm->vsegs_nr = 0;
     403
     404    // create & initialize the child GPT as empty
     405    error = hal_gpt_create( &child_vmm->gpt );
    233406    if( error )
    234407    {
    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
    241     list_entry_t * iter;
    242     vseg_t       * src_vseg;
    243     vseg_t       * dst_vseg;
    244     LIST_FOREACH( &src_vmm->vsegs_root , iter )
    245     {
    246         // get pointer on current src_vseg
    247         src_vseg = LIST_ELEMENT( iter , vseg_t , list );
    248 
    249         // allocate memory for a new dst_vseg
    250         dst_vseg = vseg_alloc();
    251 
    252         if( dst_vseg == NULL )
     408        printk("\n[ERROR] in %s : cannot create GPT\n", __FUNCTION__ );
     409        return -1;
     410    }
     411
     412    // build extended pointer on parent VSL
     413    parent_root_xp = XPTR( parent_cxy , &parent_vmm->vsegs_root );
     414
     415    // loop on parent VSL xlist
     416    XLIST_FOREACH( parent_root_xp , iter_xp )
     417    {
     418        // get local and extended pointers on current parent vseg
     419        parent_vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     420        parent_vseg    = (vseg_t *)GET_PTR( parent_vseg_xp );
     421
     422        // get vseg type
     423        type = hal_remote_lw( XPTR( parent_cxy , &parent_vseg->type ) );
     424       
     425
     426vmm_dmsg("\n[DBG] %s : core[%x,%d] found parent vseg %s / vpn_base = %x\n",
     427__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vseg_type_str(type),
     428hal_remote_lw( XPTR( parent_cxy , &parent_vseg->vpn_base ) ) );
     429
     430        // all parent vsegs - but STACK - must be copied in child VSL
     431        if( type != VSEG_TYPE_STACK )
    253432        {
    254             // release all allocated vsegs
    255             LIST_FOREACH( &dst_vmm->vsegs_root , iter )
     433            // allocate memory for a new child vseg
     434            child_vseg = vseg_alloc();
     435            if( child_vseg == NULL )   // release all allocated vsegs
    256436            {
    257                 dst_vseg = LIST_ELEMENT( iter , vseg_t , list );
    258                 vseg_free( dst_vseg );
     437                vmm_destroy( child_process );
     438                printk("\n[ERROR] in %s : cannot create vseg for child\n", __FUNCTION__ );
     439                return -1;
    259440            }
    260             return ENOMEM;
    261         }
    262 
    263         // copy src_vseg to dst_vseg
    264         vseg_init_from_ref( dst_vseg , XPTR( local_cxy , src_vseg ) );
    265 
    266         // register dst_vseg in DST VSL
    267         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         }
    282     }
    283 
    284     // release the src_vmm vsegs_lock
    285     rwlock_wr_unlock( &src_vmm->vsegs_lock );
    286 
    287     // initialize STACK allocator
    288     dst_vmm->stack_mgr.bitmap   = 0;
    289     dst_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;
    290 
    291     // initialize MMAP allocator
    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;
     441
     442            // copy parent vseg to child vseg
     443            vseg_init_from_ref( child_vseg , parent_vseg_xp );
     444
     445            // register child vseg in child VSL
     446            vseg_attach( child_vmm , child_vseg );
     447
     448vmm_dmsg("\n[DBG] %s : core[%x,%d] copied to child VSL : vseg %s / vpn_base = %x\n",
     449__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vseg_type_str(type),
     450hal_remote_lw( XPTR( parent_cxy , &parent_vseg->vpn_base ) ) );
     451
     452            // copy DATA, MMAP, REMOTE, FILE parent GPT entries to child GPT
     453            if( type != VSEG_TYPE_CODE )
     454            {
     455                // activate the COW for DATA, MMAP, REMOTE vsegs only
     456                cow = ( type != VSEG_TYPE_FILE );
     457
     458                vpn_base = child_vseg->vpn_base;
     459                vpn_size = child_vseg->vpn_size;
     460
     461                // scan pages in parent vseg
     462                for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     463                {
     464                    error = hal_gpt_pte_copy( &child_vmm->gpt,
     465                                              XPTR( parent_cxy , &parent_vmm->gpt ),
     466                                              vpn,
     467                                              cow,
     468                                              &ppn,
     469                                              &mapped );
     470                    if( error )
     471                    {
     472                        vmm_destroy( child_process );
     473                        printk("\n[ERROR] in %s : cannot copy GPT\n", __FUNCTION__ );
     474                        return -1;
     475                    }
     476
     477                    // increment page descriptor fork_nr for the referenced page if mapped
     478                    if( mapped )
     479                    {
     480                        page_xp = ppm_ppn2page( ppn );
     481                        page_cxy = GET_CXY( page_xp );
     482                        page_ptr = (page_t *)GET_PTR( page_xp );
     483                        hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->fork_nr ) , 1 );
     484
     485vmm_dmsg("\n[DBG] %s : core[%x,%d] copied to child GPT : vpn %x\n",
     486__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
     487
     488                    }
     489                }
     490            }   // end if no code & no stack
     491        }   // end if no stack
     492    }   // end loop on vsegs
     493
     494    // release the parent vsegs lock
     495    remote_rwlock_rd_unlock( parent_lock_xp );
     496
     497    // initialize the child VMM STACK allocator
     498    child_vmm->stack_mgr.bitmap   = 0;
     499    child_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;
     500
     501    // initialize the child VMM MMAP allocator
    295502    uint32_t i;
    296     for( i = 0 ; i < 32 ; i++ ) list_root_init( &dst_vmm->mmap_mgr.zombi_list[i] );
     503    child_vmm->mmap_mgr.vpn_base        = CONFIG_VMM_HEAP_BASE;
     504    child_vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_HEAP_BASE;
     505    child_vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_HEAP_BASE;
     506    for( i = 0 ; i < 32 ; i++ ) list_root_init( &child_vmm->mmap_mgr.zombi_list[i] );
    297507
    298508    // initialize instrumentation counters
    299         dst_vmm->pgfault_nr    = 0;
    300         dst_vmm->u_err_nr      = 0;
    301         dst_vmm->m_err_nr      = 0;
    302 
    303     // copy base addresses
    304     dst_vmm->kent_vpn_base = src_vmm->kent_vpn_base;
    305     dst_vmm->args_vpn_base = src_vmm->args_vpn_base;
    306     dst_vmm->envs_vpn_base = src_vmm->envs_vpn_base;
    307     dst_vmm->heap_vpn_base = src_vmm->heap_vpn_base;
    308     dst_vmm->code_vpn_base = src_vmm->code_vpn_base;
    309     dst_vmm->data_vpn_base = src_vmm->data_vpn_base;
    310 
    311     dst_vmm->entry_point   = src_vmm->entry_point;
     509        child_vmm->pgfault_nr    = 0;
     510
     511    // copy base addresses from parent VMM to child VMM
     512    child_vmm->kent_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->kent_vpn_base));
     513    child_vmm->args_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->args_vpn_base));
     514    child_vmm->envs_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->envs_vpn_base));
     515    child_vmm->heap_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->heap_vpn_base));
     516    child_vmm->code_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->code_vpn_base));
     517    child_vmm->data_vpn_base = (vpn_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->data_vpn_base));
     518
     519    child_vmm->entry_point = (intptr_t)hal_remote_lpt(XPTR(parent_cxy, &parent_vmm->entry_point));
    312520
    313521    hal_fence();
     
    315523    return 0;
    316524
    317 }  // vmm_copy()
     525}  // vmm_fork_copy()
    318526
    319527///////////////////////////////////////
    320528void vmm_destroy( process_t * process )
    321529{
     530    xptr_t   vseg_xp;
    322531        vseg_t * vseg;
    323532
     
    325534    vmm_t  * vmm = &process->vmm;
    326535
     536    // get extended pointer on VSL root and VSL lock
     537    xptr_t   root_xp = XPTR( local_cxy , &vmm->vsegs_root );
     538        xptr_t   lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
     539
    327540    // get lock protecting vseg list
    328         rwlock_wr_lock( &vmm->vsegs_lock );
    329 
    330     // remove all vsegs registered in vmm
    331         while( !list_is_empty( &vmm->vsegs_root ) )
     541        remote_rwlock_wr_lock( lock_xp );
     542
     543    // remove all vsegs registered in VSL
     544        while( !xlist_is_empty( root_xp ) )
    332545        {
    333                 vseg = LIST_FIRST( &vmm->vsegs_root ,  vseg_t , list );
     546                vseg_xp = XLIST_FIRST_ELEMENT( root_xp , vseg_t , xlist );
     547        vseg = (vseg_t *)GET_PTR( vseg_xp );
    334548                vseg_detach( vmm , vseg );
    335549        vseg_free( vseg );
     
    337551
    338552    // release lock
    339         rwlock_wr_unlock(&vmm->vsegs_lock);
     553        remote_rwlock_wr_unlock( lock_xp );
    340554
    341555    // remove all vsegs from zombi_lists in MMAP allocator
     
    345559            while( !list_is_empty( &vmm->mmap_mgr.zombi_list[i] ) )
    346560            {
    347                     vseg = LIST_FIRST( &vmm->mmap_mgr.zombi_list[i] , vseg_t , list );
     561                    vseg = LIST_FIRST( &vmm->mmap_mgr.zombi_list[i] , vseg_t , zlist );
    348562                    vseg_detach( vmm , vseg );
    349563            vseg_free( vseg );
     
    362576{
    363577    vmm_t        * vmm = &process->vmm;
     578
     579    // scan the VSL
    364580        vseg_t       * vseg;
    365     list_entry_t * iter;
    366 
    367     // scan the list of registered vsegs
    368         LIST_FOREACH( &vmm->vsegs_root , iter )
     581    xptr_t         iter_xp;
     582    xptr_t         vseg_xp;
     583    xptr_t         root_xp = XPTR( local_cxy , &vmm->vsegs_root );
     584
     585        XLIST_FOREACH( root_xp , iter_xp )
    369586        {
    370                 vseg = LIST_ELEMENT( iter , vseg_t , list );
     587                vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     588        vseg    = (vseg_t *)GET_PTR( vseg_xp );
    371589
    372590                if( ((vpn_base + vpn_size) > vseg->vpn_base) &&
     
    463681    {
    464682        // get pointer on zombi vseg from zombi_list
    465         vseg = LIST_FIRST( &mgr->zombi_list[index] , vseg_t , list );
     683        vseg = LIST_FIRST( &mgr->zombi_list[index] , vseg_t , zlist );
    466684
    467685        // remove vseg from free-list
    468         list_unlink( &vseg->list );
     686        list_unlink( &vseg->zlist );
    469687
    470688        // compute base
     
    579797               cxy );
    580798
    581     // attach vseg to vmm
    582         rwlock_wr_lock( &vmm->vsegs_lock );
     799    // attach vseg to VSL
     800    xptr_t lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
     801        remote_rwlock_wr_lock( lock_xp );
    583802        vseg_attach( vmm , vseg );
    584         rwlock_wr_unlock( &vmm->vsegs_lock );
     803        remote_rwlock_wr_unlock( lock_xp );
    585804
    586805vmm_dmsg("\n[DBG] %s : core[%x,%d] exit / process %x / base %x / size %x / type %s\n",
     
    601820    uint32_t     type    = vseg->type;
    602821
    603     // detach vseg from VMM
    604         rwlock_wr_lock( &vmm->vsegs_lock );
    605     vseg_detach( &process->vmm , vseg );
    606         rwlock_wr_unlock( &vmm->vsegs_lock );
     822    // detach vseg from VSL
     823    xptr_t lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
     824        remote_rwlock_wr_lock( lock_xp );
     825        vseg_detach( &process->vmm , vseg );
     826        remote_rwlock_wr_unlock( lock_xp );
    607827
    608828    // release the stack slot to VMM stack allocator if STACK type
     
    632852        // update zombi_list
    633853        spinlock_lock( &mgr->lock );
    634         list_add_first( &mgr->zombi_list[index] , &vseg->list );
     854        list_add_first( &mgr->zombi_list[index] , &vseg->zlist );
    635855        spinlock_unlock( &mgr->lock );
    636856    }
     
    686906        // set page table entry
    687907        ppn = ppm_page2ppn( XPTR( local_cxy , page ) );
    688         error = hal_gpt_set_pte( gpt , vpn , ppn , attr );
     908        error = hal_gpt_set_pte( gpt,
     909                                 vpn,
     910                                 attr,
     911                                 ppn );
    689912                if( error )
    690913        {
     
    695918
    696919        return 0;
    697 }
     920
     921}  // end vmm_map_kernel_vseg()
    698922
    699923/////////////////////////////////////////
     
    729953                                 intptr_t   vaddr )
    730954{
    731     list_entry_t * iter;
    732     vseg_t       * vseg = NULL;
    733 
    734     // get lock protecting the vseg list
    735     rwlock_rd_lock( &vmm->vsegs_lock );
    736 
    737     // scan the list of vsegs
    738     LIST_FOREACH( &vmm->vsegs_root , iter )
    739     {
    740         vseg = LIST_ELEMENT( iter , vseg_t , list );
    741         if( (vaddr >= vseg->min) && (vaddr < vseg->max) ) break;
    742     }
    743 
    744     // release the lock
    745     rwlock_rd_unlock( &vmm->vsegs_lock );
    746 
    747     return vseg;
    748 }
     955    xptr_t   iter_xp;
     956    xptr_t   vseg_xp;
     957    vseg_t * vseg;
     958
     959    // get extended pointers on VSL lock and root
     960    xptr_t lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
     961    xptr_t root_xp = XPTR( local_cxy , &vmm->vsegs_root );
     962
     963    // get lock protecting the VSL
     964    remote_rwlock_rd_lock( lock_xp );
     965
     966    // scan the list of vsegs in VSL
     967    XLIST_FOREACH( root_xp , iter_xp )
     968    {
     969        vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     970        vseg    = (vseg_t *)GET_PTR( vseg_xp );
     971        if( (vaddr >= vseg->min) && (vaddr < vseg->max) )
     972        {
     973            // return success
     974            remote_rwlock_rd_unlock( lock_xp );
     975            return vseg;
     976        }
     977    }
     978
     979    // return failure
     980    remote_rwlock_rd_unlock( lock_xp );
     981    return NULL;
     982
     983}  // end vseg_from_vaddr()
    749984
    750985/////////////////////////////////////////////
     
    7691004        if( vseg == NULL)  return EINVAL;
    7701005
    771     // get VMM lock protecting vsegs list
    772         rwlock_wr_lock( &vmm->vsegs_lock );
     1006    // get extended pointer on VSL lock
     1007    xptr_t lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
     1008
     1009    // get lock protecting VSL
     1010        remote_rwlock_wr_lock( lock_xp );
    7731011
    7741012        if( (vseg->min > addr_min) || (vseg->max < addr_max) )   // region not included in vseg
     
    8311069
    8321070    // release VMM lock
    833         rwlock_wr_unlock( &vmm->vsegs_lock );
     1071        remote_rwlock_wr_unlock( lock_xp );
    8341072
    8351073        return error;
     
    11291367    ppn_t     new_ppn;    // new PTE_PPN
    11301368    uint32_t  new_attr;   // new PTE_ATTR
    1131     xptr_t    page_xp;    // extended pointer on allocated page descriptor
    11321369    error_t   error;
    11331370
     
    11371374
    11381375vmm_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);
     1376__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , process->pid , cow );
    11401377
    11411378    // get VMM pointer
     
    11591396    hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn );
    11601397
    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
     1398    // for both "copy_on_write" and "page_fault" events, allocate a physical page,
     1399    // initialize it, register it in the reference GPT, update GPT copies in all
     1400    // clusters containing a copy, and return the new_ppn and new_attr
    11631401
    11641402    if( cow )               ////////////// copy_on_write request ///////////
    11651403    {
    1166         assert( (*attr & GPT_MAPPED) , __FUNCTION__ ,
    1167         "PTE must be mapped for a copy-on-write\n" );
    1168 
    1169 vmm_dmsg("\n[DBG] %s : core[%x,%d] page %x must be copied => do it\n",
     1404        assert( (old_attr & GPT_MAPPED) , __FUNCTION__ ,
     1405        "PTE must be mapped for a copy-on-write exception\n" );
     1406
     1407excp_dmsg("\n[DBG] %s : core[%x,%d] handling COW for vpn %x\n",
    11701408__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
    11711409
    1172         // allocate a physical page depending on vseg type
    1173         page_xp = vmm_page_allocate( vseg , vpn );
    1174 
    1175         if( page_xp == XPTR_NULL )
     1410        // get extended pointer, cluster and local pointer on page descriptor
     1411        xptr_t   page_xp  = ppm_ppn2page( old_ppn );
     1412        cxy_t    page_cxy = GET_CXY( page_xp );
     1413        page_t * page_ptr = (page_t *)GET_PTR( page_xp );
     1414
     1415        // get number of pending forks in page descriptor
     1416        uint32_t count = hal_remote_lw( XPTR( page_cxy , &page_ptr->fork_nr ) );
     1417
     1418        if( count )        // pending fork => allocate a new page, copy it, reset COW
    11761419        {
    1177             printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
    1178             __FUNCTION__ , process->pid , vpn );
    1179             return ENOMEM;
     1420            // allocate a new physical page
     1421            page_xp = vmm_page_allocate( vseg , vpn );
     1422            if( page_xp == XPTR_NULL )
     1423            {
     1424                printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
     1425                __FUNCTION__ , process->pid , vpn );
     1426                return -1;
     1427            }
     1428
     1429            // compute allocated page PPN
     1430            new_ppn = ppm_page2ppn( page_xp );
     1431
     1432            // copy old page content to new page
     1433            xptr_t  old_base_xp = ppm_ppn2base( old_ppn );
     1434            xptr_t  new_base_xp = ppm_ppn2base( new_ppn );
     1435            memcpy( GET_PTR( new_base_xp ),
     1436                    GET_PTR( old_base_xp ),
     1437                    CONFIG_PPM_PAGE_SIZE );
     1438        }             
     1439        else               // no pending fork => keep the existing page, reset COW
     1440        {
     1441            new_ppn = old_ppn;
    11801442        }
    11811443
    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 );
    1198 
    1199         if( error )
     1444        // build new_attr : reset COW and set WRITABLE,
     1445        new_attr = (old_attr | GPT_WRITABLE) & (~GPT_COW);
     1446
     1447        // update GPT[vpn] for all GPT copies
     1448        // to maintain coherence of copies
     1449        vmm_update_pte( process,
     1450                        vpn,
     1451                        new_attr,
     1452                        new_ppn );
     1453
     1454        // decrement fork_nr in page descriptor
     1455        hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->fork_nr ) , -1 );
     1456    }
     1457    else                         /////////////// page_fault request ///////////
     1458    { 
     1459        if( (old_attr & GPT_MAPPED) == 0 )   // true page_fault => map it
    12001460        {
    1201             printk("\n[ERROR] in %s : cannot update GPT / process = %x / vpn = %x\n",
    1202             __FUNCTION__ , process->pid , vpn );
    1203             return error;
    1204         }
    1205     }
    1206     else                    //////////////////// page_fault request ///////////
    1207     { 
    1208         if( (old_attr & GPT_MAPPED) == 0 )    // PTE unmapped in ref GPT
    1209         {
    1210 
    1211 vmm_dmsg("\n[DBG] %s : core[%x,%d] page %x unmapped => try to map it\n",
     1461
     1462excp_dmsg("\n[DBG] %s : core[%x,%d] handling page fault for vpn %x\n",
    12121463__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
    12131464
    1214             // allocate one physical page, depending on vseg type
     1465            // allocate new_ppn, depending on vseg type
    12151466            error = vmm_get_one_ppn( vseg , vpn , &new_ppn );
    1216 
    12171467            if( error )
    12181468            {
    12191469                printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
    12201470                __FUNCTION__ , process->pid , vpn );
    1221                 return error;
     1471                return -1;
    12221472            }
    12231473
    1224             // define attributes from vseg flags
     1474            // define new_attr from vseg flags
    12251475            new_attr = GPT_MAPPED | GPT_SMALL;
    12261476            if( vseg->flags & VSEG_USER  ) new_attr |= GPT_USER;
     
    12291479            if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE;
    12301480
    1231             // register PTE in GPT
    1232             error = hal_gpt_set_pte( &vmm->gpt , vpn , new_ppn , new_attr );
    1233 
     1481            // register new PTE in reference GPT
     1482            // on demand policy => no update of GPT copies
     1483            error = hal_gpt_set_pte( &vmm->gpt,
     1484                                     vpn,
     1485                                     new_attr,
     1486                                     new_ppn );
    12341487            if( error )
    12351488            {
    12361489                printk("\n[ERROR] in %s : cannot update GPT / process = %x / vpn = %x\n",
    12371490                __FUNCTION__ , process->pid , vpn );
    1238                 return error;
     1491                return -1;
    12391492            }
    12401493        }
    1241         else
     1494        else                                  // mapped in reference GPT => get it
    12421495        {
     1496            new_ppn  = old_ppn;
    12431497            new_attr = old_attr;
    1244             new_ppn  = old_ppn;
    12451498        }
    12461499    }
    12471500
    1248 vmm_dmsg("\n[DBG] %s : core[%x,%d] exit for vpn = %x / ppn = %x / attr = %x\n",
     1501excp_dmsg("\n[DBG] %s : core[%x,%d] update GPT for vpn %x / ppn = %x / attr = %x\n",
    12491502__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , new_ppn , new_attr );
    12501503
     1504    // retur success
    12511505    *ppn  = new_ppn;
    12521506    *attr = new_attr;
     
    12821536
    12831537        // update local GPT
    1284         error |= hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
     1538        error |= hal_gpt_set_pte( &vmm->gpt,
     1539                                  vpn,
     1540                                  attr,
     1541                                  ppn );
    12851542    }
    12861543    else   // local cluster is the reference cluster
     
    12971554}  // end vmm_handle_page_fault()
    12981555
    1299 ///////////////////////////////////////////////
    1300 error_t vmm_copy_on_write( process_t * process,
    1301                            vpn_t       vpn )
     1556////////////////////////////////////////////
     1557error_t vmm_handle_cow( process_t * process,
     1558                        vpn_t       vpn )
    13021559{
    13031560    uint32_t         attr;          // missing page attributes
     
    13241581
    13251582        // update local GPT
    1326         error |= hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
     1583        error |= hal_gpt_set_pte( &vmm->gpt,
     1584                                  vpn,
     1585                                  attr,
     1586                                  ppn );
    13271587    }
    13281588    else   // local cluster is the reference cluster
     
    13371597    return error;
    13381598
    1339 }  // end vmm_copy_on_write()
     1599}  // end vmm_handle_cow()
    13401600
    13411601///////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.