Changeset 632 for trunk


Ignore:
Timestamp:
May 28, 2019, 2:56:04 PM (5 years ago)
Author:
alain
Message:

This version replace the RPC by direct remote memory access
for physical pages allacation/release.
It is commited before being tested.

Location:
trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/generic/hal_gpt.h

    r629 r632  
    9696 * of a remote GPT identified by the <gpt_xp> and <vpn> arguments, after checking
    9797 * (in a busy waiting loop) that this attribute has been reset.
    98  * Then, it returns in the <attr> and <ppn> buffers the current value of the PTE.
    99  * It allocates memory required by the GPT implementation to register this lock
    100  * in the PTE when required.
     98 * It returns in the <attr> and <ppn> buffers the value of the PTE before modification.
     99 * It atomically allocates memory  to register this attribute in the PTE when
     100 * required by a specific GPT implementation (example : allocate a PT2 in the TSAR GPT).
    101101 * WARNING : Only small pages can be locked.
    102102 ****************************************************************************************
     
    128128 *
    129129 * WARNING : For a small page, it checks that the GPT_LOCKED attribute has been
    130  *           previously set, to prevent concurrent accesses.
     130 *           previously set, to prevent concurrent mapping accesses.
    131131 ****************************************************************************************
    132132 * @ gpt_xp    : [in] extended pointer on the page table
     
    212212 * It modifies an existing entry identified by the <vpn> argument in a remote GPT
    213213 * identified by the <gpt_xp> argument, using remote accesses.
    214  * It does NOT require the GPT_LOCKED attribute to be set in the target PTE.
    215  * It cannot fail, because only MAPPED & SMALL entries are modified.
     214 * - The MAPPED and SMALL attributes must be set, and the LOCKED attibute must be reset
     215 *   in the <attr> argument.
     216 * - The MAPPED and SMALL attributes must be set in the target PTE.
    216217 ****************************************************************************************
    217218 * @ gpt_xp    : [in] extended pointer on the page table
  • trunk/hal/tsar_mips32/core/hal_exception.c

    r625 r632  
    165165// in case of illegal virtual address. Finally, it updates the local page table from the
    166166// reference cluster.
     167// WARNING : In order to prevent deadlocks, this function enable IRQs before calling the
     168// vmm_handle_page_fault() and the vmm_handle_cow() functions, because concurrent calls
     169// to these functions can create cross dependencies...
    167170//////////////////////////////////////////////////////////////////////////////////////////
    168171// @ this     : pointer on faulty thread descriptor.
     
    187190
    188191    // check thread type
    189     if( CURRENT_THREAD->type != THREAD_USER )
     192   if( CURRENT_THREAD->type != THREAD_USER )
    190193    {
    191194        printk("\n[PANIC] in %s : illegal thread type %s\n",
  • trunk/hal/tsar_mips32/core/hal_gpt.c

    r630 r632  
    7777#define TSAR_MMU_ATTR_FROM_PTE2( pte2 )    (pte2 & 0xFFC000FF)
    7878
    79 
    8079///////////////////////////////////////////////////////////////////////////////////////
    8180// This static function translates the GPT attributes to the TSAR attributes
     
    125124    return gpt_attr;
    126125}
     126
     127///////////////////////////////////////////////////////////////////////////////////////
     128// The blocking hal_gpt_lock_pte() function implements a busy-waiting policy to get
     129// exclusive access to a specific GPT entry.
     130// - when non zero, the following variable defines the max number of iterations
     131//   in the busy waiting loop.
     132// - when zero, the watchdog mechanism is deactivated.
     133///////////////////////////////////////////////////////////////////////////////////////
     134
     135#define GPT_LOCK_WATCHDOG   100000
    127136
    128137/////////////////////////////////////
     
    317326*/
    318327
    319 /////////////////////////////////////////////////////////////////////////////////////////
    320 // This static function returns in the <ptd1_value> buffer the current value of
    321 // the PT1 entry identified by the <pte1_xp> argument, that must contain a PTD1
    322 // (i.e. a pointer on a PT2). If this PT1 entry is not mapped yet, it allocates a
    323 // new PT2 and updates the PT1 entry, using the TSAR_MMU_LOCKED attribute in PT1
    324 // entry, to handle possible concurrent mappings of the missing PTD1:
    325 // 1) If the PT1 entry is unmapped, it tries to atomically lock this PTD1.
    326 //    - if the atomic lock is successful it allocates a new PT1, and updates the PTD1.
    327 //    - else, it simply waits, in a polling loop, the mapping done by another thread.
    328 //    In both cases, returns the PTD1 value, when the mapping is completed.
    329 // 2) If the PT1 entry is already mapped, it returns the PTD1 value, and does
    330 //    nothing else.
    331 /////////////////////////////////////////////////////////////////////////////////////////
    332 static error_t hal_gpt_allocate_pt2( xptr_t     ptd1_xp,
    333                                      uint32_t * ptd1_value )
    334 {
    335     cxy_t      gpt_cxy;     // target GPT cluster = GET_CXY( ptd1_xp );
    336     uint32_t   ptd1;        // PTD1 value
    337     ppn_t      pt2_ppn;     // PPN of page containing the new PT2
    338     bool_t     atomic;
    339     page_t   * page;
    340     xptr_t     page_xp;
    341 
    342     // get GPT cluster identifier
    343     gpt_cxy = GET_CXY( ptd1_xp );
    344 
    345     // get current ptd1 value
    346     ptd1 = hal_remote_l32( ptd1_xp );
    347 
    348     if( (ptd1 & TSAR_PTE_MAPPED) == 0)    // PTD1 unmapped and unlocked
    349         {
    350         // atomically lock the PTD1 to prevent concurrent PTD1 mappings
    351         atomic = hal_remote_atomic_cas( ptd1_xp,
    352                                         ptd1,
    353                                         ptd1 | TSAR_PTE_LOCKED );
    354 
    355         if( atomic )  // PTD1 successfully locked
    356                 {
    357             // allocate one physical page for PT2
    358             if( gpt_cxy == local_cxy )
    359             {
    360                     kmem_req_t req;
    361                     req.type  = KMEM_PAGE;
    362                     req.size  = 0;                     // 1 small page
    363                     req.flags = AF_KERNEL | AF_ZERO;
    364                     page = (page_t *)kmem_alloc( &req );
    365             }
    366             else
    367             {
    368                 rpc_pmem_get_pages_client( gpt_cxy , 0 , &page );
    369             }
    370 
    371             if( page == NULL ) return -1;
    372 
    373             // get the PT2 PPN
    374             page_xp = XPTR( gpt_cxy , page );       
    375             pt2_ppn = ppm_page2ppn( page_xp );
    376 
    377             // build  PTD1
    378             ptd1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
    379 
    380             // set the PTD1 value in PT1
    381             hal_remote_s32( ptd1_xp , ptd1 );
    382             hal_fence();
    383 
    384 #if DEBUG_HAL_GPT_ALLOCATE_PT2
    385 thread_t * this  = CURRENT_THREAD;
    386 uint32_t   cycle = (uint32_t)hal_get_cycles();
    387 if( DEBUG_HAL_GPT_ALLOCATE_PT2 < cycle )
    388 printk("\n[%s] : thread[%x,%x] map PTD1 / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
    389 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, ptd1 );
    390 #endif
    391         }
    392         else         // PTD1 modified by another thread
    393         {
    394             // poll PTD1 until mapped by another thread
    395             while( (ptd1 & TSAR_PTE_MAPPED) == 0 )  ptd1 = hal_remote_l32( ptd1_xp );
    396         }
    397     }
    398     else                                   // PTD1 mapped => just use it
    399     {
    400 
    401 #if DEBUG_HAL_GPT_ALLOCATE_PT2
    402 thread_t * this  = CURRENT_THREAD;
    403 uint32_t   cycle = (uint32_t)hal_get_cycles();
    404 if( DEBUG_HAL_GPT_ALLOCATE_PT2 < cycle )
    405 printk("\n[%s] : thread[%x,%x] PTD1 mapped / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
    406 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, ptd1 );
    407 #endif
    408 
    409     }
    410 
    411     *ptd1_value = ptd1;
    412     return 0;
    413 
    414 }  // end hal_gpt_allocate_pt2
    415 
    416 
    417 
    418 
    419328////////////////////////////////////////////
    420329error_t hal_gpt_lock_pte( xptr_t     gpt_xp,
     
    423332                          ppn_t    * ppn )
    424333{
    425     error_t             error;
    426334    uint32_t          * pt1_ptr;         // local pointer on PT1 base
    427     xptr_t              pte1_xp;         // extended pointer on PT1[x1] entry
    428         uint32_t            pte1;            // value of PT1[x1] entry
     335    xptr_t              ptd1_xp;         // extended pointer on PT1[x1] entry
     336        uint32_t            ptd1;            // value of PT1[x1] entry
     337
     338    xptr_t              page_xp;
    429339
    430340        ppn_t               pt2_ppn;         // PPN of page containing PT2
    431341    uint32_t          * pt2_ptr;         // local pointer on PT2 base
    432         xptr_t              pte2_attr_xp;    // extended pointer on PT2[ix2].attr
     342        xptr_t              pte2_xp;         // extended pointer on PT2[ix2].attr
    433343    uint32_t            pte2_attr;       // PT2[ix2].attr current value   
    434         xptr_t              pte2_ppn_xp;     // extended pointer on PT2[ix2].ppn
    435344    uint32_t            pte2_ppn;        // PT2[ix2].ppn current value   
    436345        bool_t              atomic;
     346
     347#if GPT_LOCK_WATCHDOG
     348    uint32_t count;
     349#endif
    437350
    438351    // get cluster and local pointer on GPT
     
    440353    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
    441354
    442     // get indexes in PTI & PT2
     355#if DEBUG_HAL_GPT_LOCK_PTE
     356thread_t * this  = CURRENT_THREAD;
     357uint32_t   cycle = (uint32_t)hal_get_cycles();
     358if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     359printk("\n[%s] : thread[%x,%x] enters / vpn %x in cluster %x / cycle %d\n",
     360__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
     361#endif
     362
     363    // get indexes in PTI & PT2 from vpn
    443364    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
    444365    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
     
    447368    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    448369
    449     // build extended pointer on PTE1 == PT1[ix1]
    450         pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
    451 
    452     // get PTE1 value from PT1
    453     // allocate a new PT2 for this PTE1 if required
    454     error = hal_gpt_allocate_pt2( pte1_xp , &pte1 );
    455 
    456     if( error )
     370    // build extended pointer on PTD1 == PT1[ix1]
     371        ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     372
     373    // get current PT1 entry value
     374    ptd1 = hal_remote_l32( ptd1_xp );
     375
     376    // If PTD1 is unmapped and unlocked, try to atomically lock this PT1 entry.
     377    // This PTD1 lock prevent multiple concurrent PT2 allocations
     378    // - only the thread that successfully locked the PTD1 allocates a new PT2
     379    //   and updates the PTD1
     380    // - all other threads simply wait until the missing PTD1 is mapped.
     381
     382    if( ptd1 == 0 ) 
     383        {
     384        // try to atomically lock the PTD1 to prevent concurrent PT2 allocations
     385        atomic = hal_remote_atomic_cas( ptd1_xp,
     386                                        ptd1,
     387                                        ptd1 | TSAR_PTE_LOCKED );
     388        if( atomic ) 
     389                {
     390            // allocate one 4 Kbytes physical page for PT2
     391            page_xp = ppm_remote_alloc_pages( gpt_cxy , 0 );
     392
     393            if( page_xp == NULL )
     394            {
     395                printk("\n[ERROR] in %s : cannot allocate memory for PT2\n", __FUNCTION__ );
     396                return -1;
     397            }
     398
     399            // get the PT2 PPN
     400            pt2_ppn = ppm_page2ppn( page_xp );
     401
     402            // build  PTD1
     403            ptd1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
     404
     405            // set the PTD1 value in PT1
     406            // this unlocks the PTD1
     407            hal_remote_s32( ptd1_xp , ptd1 );
     408            hal_fence();
     409
     410#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
     411if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     412printk("\n[%s] : thread[%x,%x] allocates a new PT2 for vpn %x in cluster %x\n",
     413__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy );
     414#endif
     415
     416        }  // end if atomic
     417    }  // end if (ptd1 == 0)
     418
     419    // wait until PTD1 is mapped by another thread
     420    while( (ptd1 & TSAR_PTE_MAPPED) == 0 )
    457421    {
    458         printk("\n[ERROR] in %s : cannot allocate memory for PT2\n", __FUNCTION__ );
    459         return -1;
     422        ptd1 = hal_remote_l32( ptd1_xp );
     423
     424#if GPT_LOCK_WATCHDOG
     425if( count > GPT_LOCK_WATCHDOG ) 
     426{
     427    thread_t * thread = CURRENT_THREAD;
     428    printk("\n[PANIC] in %s : thread[%x,%x] waiting PTD1 / vpn %x / cxy %x / %d iterations\n",
     429    __FUNCTION__, thread->process->pid, thread->trdid, vpn, gpt_cxy, count );
     430    hal_core_sleep();
     431}
     432count++;
     433#endif
     434
    460435    }
    461436
    462     if( (pte1 & TSAR_PTE_SMALL) == 0 )
    463     {
    464         printk("\n[ERROR] in %s : cannot lock a small page\n", __FUNCTION__ );
    465         return -1;
    466     }
    467 
    468     // get pointer on PT2 base from PTE1
    469         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     437// check ptd1 because only small page can be locked
     438assert( (ptd1 & TSAR_PTE_SMALL), "cannot lock a big page\n");
     439
     440#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
     441if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     442printk("\n[%s] : thread[%x,%x] get ptd1 %x for vpn %x in cluster %x\n",
     443__FUNCTION__, this->process->pid, this->trdid, ptd1, vpn, gpt_cxy );
     444#endif
     445
     446    // get pointer on PT2 base from PTD1
     447        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
    470448        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    471449
    472     // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
    473     pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
    474     pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
    475  
    476     // wait until PTE2 unlocked, get PTE2.attr and set lock
     450    // build extended pointers on PT2[ix2].attr 
     451    pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     452
     453    // wait until PTE2 atomically set using a remote CAS
    477454    do
    478455    {
    479         // busy waiting until TSAR_MMU_LOCK == 0
     456
     457#if GPT_LOCK_WATCHDOG
     458count = 0;
     459#endif
     460
     461        // wait until PTE lock released by the current owner
    480462        do
    481463                {
    482                         pte2_attr = hal_remote_l32( pte2_attr_xp );
     464                        pte2_attr = hal_remote_l32( pte2_xp );
     465
     466#if GPT_LOCK_WATCHDOG
     467if( count > GPT_LOCK_WATCHDOG ) 
     468{
     469    thread_t * thread = CURRENT_THREAD;
     470    printk("\n[PANIC] in %s : thread[%x,%x] waiting PTE2 / vpn %x / cxy %x / %d iterations\n",
     471    __FUNCTION__, thread->process->pid, thread->trdid, vpn, gpt_cxy, count );
     472    hal_core_sleep();
     473}
     474count++;
     475#endif
     476     
    483477                }
    484478        while( (pte2_attr & TSAR_PTE_LOCKED) != 0 );
    485479
    486         // try to atomically set the TSAR_MMU_LOCK attribute   
    487                 atomic = hal_remote_atomic_cas( pte2_attr_xp,
     480        // try to atomically set the TSAR_PTE_LOCKED attribute   
     481                atomic = hal_remote_atomic_cas( pte2_xp,
    488482                                        pte2_attr,
    489483                                        (pte2_attr | TSAR_PTE_LOCKED) );
     
    492486
    493487    // get PTE2.ppn
    494     pte2_ppn = hal_remote_l32( pte2_ppn_xp );
     488    pte2_ppn = hal_remote_l32( pte2_xp + 4 );
     489
     490#if DEBUG_HAL_GPT_LOCK_PTE
     491cycle = (uint32_t)hal_get_cycles();
     492if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     493printk("\n[%s] : thread[%x,%x] exit / vpn %x in cluster %x / attr %x / ppn %x / cycle %d\n",
     494__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, pte2_attr, pte2_ppn, cycle );
     495#endif
     496   
     497    // return PPN and GPT attributes
     498    *ppn  = pte2_ppn & ((1<<TSAR_MMU_PPN_WIDTH)-1);
     499    *attr = tsar2gpt( pte2_attr );
     500        return 0;
     501
     502}  // end hal_gpt_lock_pte()
     503
     504////////////////////////////////////////
     505void hal_gpt_unlock_pte( xptr_t  gpt_xp,
     506                         vpn_t   vpn )
     507{
     508    uint32_t * pt1_ptr;         // local pointer on PT1 base
     509    xptr_t     ptd1_xp;         // extended pointer on PT1[ix1]
     510        uint32_t   ptd1;            // value of PT1[ix1] entry
     511
     512        ppn_t      pt2_ppn;         // PPN of page containing PT2
     513    uint32_t * pt2_ptr;         // PT2 base address
     514        xptr_t     pte2_xp;         // extended pointer on PT2[ix2].attr
     515        uint32_t   pte2_attr;       // PTE2 attribute
     516
     517    // get cluster and local pointer on GPT
     518    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
     519    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
    495520
    496521#if DEBUG_HAL_GPT_LOCK_PTE
     
    498523uint32_t   cycle = (uint32_t)hal_get_cycles();
    499524if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    500 printk("\n[%s] : thread[%x,%x] locks vpn %x / attr %x / ppn %x / cluster %x / cycle %d\n",
    501 __FUNCTION__, this->process->pid, this->trdid, vpn, attr, ppn, gpt_cxy, cycle );
    502 #endif
    503    
    504     // return PPN and GPT attributes
    505     *ppn  = hal_remote_l32( pte2_ppn_xp ) & ((1<<TSAR_MMU_PPN_WIDTH)-1);
    506     *attr = tsar2gpt( pte2_attr );
    507         return 0;
    508 
    509 }  // end hal_gpt_lock_pte()
    510 
    511 ////////////////////////////////////////
    512 void hal_gpt_unlock_pte( xptr_t  gpt_xp,
    513                          vpn_t   vpn )
    514 {
    515     uint32_t * pt1_ptr;         // local pointer on PT1 base
    516     xptr_t     pte1_xp;         // extended pointer on PT1[ix1]
    517         uint32_t   pte1;            // value of PT1[ix1] entry
    518 
    519         ppn_t      pt2_ppn;         // PPN of page containing PT2
    520     uint32_t * pt2_ptr;         // PT2 base address
    521         uint32_t   pte2_attr_xp;    // extended pointer on PT2[ix2].attr
    522 
    523         uint32_t   attr;            // PTE2 attribute
    524 
    525     // get cluster and local pointer on GPT
    526     cxy_t   gpt_cxy = GET_CXY( gpt_xp );
    527     gpt_t * gpt_ptr = GET_PTR( gpt_xp );
     525printk("\n[%s] : thread[%x,%x] enters for vpn %x in cluster %x / cycle %d\n",
     526__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
     527#endif
    528528
    529529    // compute indexes in P1 and PT2
     
    534534    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    535535
    536     // build extended pointer on PTE1 == PT1[ix1]
    537         pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
    538 
    539     // get current pte1 value
    540     pte1 = hal_remote_l32( pte1_xp );
    541 
    542 // check PTE1 attributes
    543 assert( (((pte1 & TSAR_PTE_MAPPED) != 0) && ((pte1 & TSAR_PTE_SMALL) != 0)),
    544 "try to unlock a big or unmapped PTE1\n");
    545 
    546     // get pointer on PT2 base from PTE1
    547         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     536    // build extended pointer on PTD1 == PT1[ix1]
     537        ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     538
     539    // get current ptd1 value
     540    ptd1 = hal_remote_l32( ptd1_xp );
     541
     542// check PTD1 attributes
     543assert( ((ptd1 & TSAR_PTE_MAPPED) != 0), "unmapped PTE1\n");
     544assert( ((ptd1 & TSAR_PTE_SMALL ) != 0), "big page PTE1\n");
     545
     546    // get pointer on PT2 base from PTD1
     547        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
    548548        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    549549
    550550    // build extended pointers on PT2[ix2].attr 
    551     pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     551    pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
    552552
    553553    // get PT2[ix2].attr
    554     attr = hal_remote_l32( pte2_attr_xp );
    555 
    556     // reset TSAR_MMU_LOCK attribute
    557     hal_remote_s32( pte2_attr_xp , attr & ~TSAR_PTE_LOCKED );
     554    pte2_attr = hal_remote_l32( pte2_xp );
     555
     556// check PTE2 attributes
     557assert( ((pte2_attr & TSAR_PTE_MAPPED) != 0), "unmapped PTE2\n");
     558assert( ((pte2_attr & TSAR_PTE_LOCKED) != 0), "unlocked PTE2\n");
     559
     560    // reset TSAR_PTE_LOCKED attribute
     561    hal_remote_s32( pte2_xp , pte2_attr & ~TSAR_PTE_LOCKED );
    558562
    559563#if DEBUG_HAL_GPT_LOCK_PTE
    560 thread_t * this  = CURRENT_THREAD;
    561 uint32_t   cycle = (uint32_t)hal_get_cycles();
     564cycle = (uint32_t)hal_get_cycles();
    562565if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    563 printk("\n[%s] : thread[%x,%x] unlocks vpn %x / attr %x / ppn %x / cluster %x / cycle %d\n",
    564 __FUNCTION__, this->process->pid, this->trdid, vpn, attr, ppn, gpt_cxy, cycle );
    565 #endif
    566  
     566printk("\n[%s] : thread[%x,%x] unlocks vpn %x in cluster %x / cycle %d\n",
     567__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
     568#endif
     569
    567570}  // end hal_gpt_unlock_pte()
     571
    568572
    569573///////////////////////////////////////
     
    693697    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
    694698    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
    695     uint32_t   pte2_attr;      // current value of PT2[ix2].attr
    696699
    697700    // get cluster and local pointer on GPT
     
    10651068        ppn_t               pt2_ppn;             // PPN of PT2
    10661069        uint32_t          * pt2;                 // PT2 base address
     1070    xptr_t              pte2_xp;             // exended pointer on PTE2
    10671071
    10681072    uint32_t            ix1;                 // index in PT1
    10691073    uint32_t            ix2;                 // index in PT2
    10701074
     1075
    10711076    uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
    10721077
    1073     // check attr argument MAPPED and SMALL
    1074     if( (attr & GPT_MAPPED) == 0 )  return;
    1075     if( (attr & GPT_SMALL ) == 0 )  return;
     1078// check MAPPED, SMALL, and not LOCKED in attr argument
     1079assert( ((attr & GPT_MAPPED) != 0), "attribute MAPPED must be set in new attributes\n" );
     1080assert( ((attr & GPT_SMALL ) != 0), "attribute SMALL  must be set in new attributes\n" );
     1081assert( ((attr & GPT_LOCKED) == 0), "attribute LOCKED must not be set in new attributes\n" );
    10761082
    10771083    // get cluster and local pointer on remote GPT
     
    10921098    pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
    10931099
    1094     if( (pte1 & TSAR_PTE_MAPPED) == 0 ) return;
    1095     if( (pte1 & TSAR_PTE_SMALL ) == 0 ) return;
     1100// check MAPPED and SMALL in target PTE1
     1101assert( ((pte1 & GPT_MAPPED) != 0), "attribute MAPPED must be set in target PTE1\n" );
     1102assert( ((pte1 & GPT_SMALL ) != 0), "attribute SMALL  must be set in target PTE1\n" );
    10961103
    10971104    // get PT2 base from PTE1
     
    10991106    pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    11001107
     1108    // get extended pointer on PTE2
     1109    pte2_xp = XPTR( gpt_cxy , &pt2[2*ix2] );
     1110   
     1111// check MAPPED in target PTE2
     1112assert( ((hal_remote_l32(pte2_xp) & GPT_MAPPED) != 0),
     1113"attribute MAPPED must be set in target PTE2\n" );
     1114
    11011115    // set PTE2 in this order
    1102         hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2 + 1] ) , ppn );
     1116        hal_remote_s32( pte2_xp    , ppn );
    11031117        hal_fence();
    1104         hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2]     ) , tsar_attr );
     1118        hal_remote_s32( pte2_xp + 4 , tsar_attr );
    11051119        hal_fence();
    11061120
     
    11101124
    11111125
    1112 /* unused until now (march 2019) [AG]
    1113 
    1114 //////////////////////////////////////
    1115 void hal_gpt_reset_range( gpt   * gpt,
    1116                           vpn_t   vpn_min,
    1117                           vpn_t   vpn_max )
    1118 {
    1119     vpn_t      vpn;         // current vpn
    1120 
    1121     uint32_t * pt1;         // PT1 base address
    1122     uint32_t   pte1;        // PT1 entry value
    1123 
    1124     ppn_t      pt2_ppn;     // PPN of PT2
    1125     uint32_t * pt2;         // PT2 base address
    1126 
    1127     uint32_t   ix1;         // index in PT1
    1128     uint32_t   ix2;         // index in PT2
    1129 
    1130     // get PT1
    1131     pt1 = gpt->ptr;
    1132 
    1133     // initialize current index
    1134     vpn = vpn_min;
    1135 
    1136     // loop on pages
    1137     while( vpn <= vpn_max )
    1138     {
    1139         // get ix1 index from vpn
    1140         ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1141 
    1142         // get PTE1
    1143         pte1 = pt1[ix1]
    1144 
    1145             if( (pte1 & TSAR_PTE_MAPPED) == 0 )     // PT1[ix1] unmapped
    1146         {
    1147             // update vpn (next big page)
    1148             (vpn = ix1 + 1) << 9;
    1149         }
    1150             if( (pte1 & TSAR_PTE_SMALL) == 0 )      // it's a PTE1 (big page)
    1151             {
    1152             // unmap the big page
    1153             pt1[ix1] = 0;
    1154                 hal_fence();
    1155            
    1156             // update vpn (next big page)
    1157             (vpn = ix1 + 1) << 9;
    1158         }
    1159         else                                    // it's a PTD1 (small page)
    1160         {
    1161             // compute PT2 base address
    1162             pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    1163             pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    1164 
    1165             // get ix2 index from vpn
    1166             ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1167 
    1168             // unmap the small page
    1169             pt2[2*ix2]   = 0;         
    1170             hal_fence();       
    1171 
    1172             // update vpn (next small page)
    1173             vpn++;
    1174         }
    1175     }
    1176 }  // hal_gpt_reset_range()
    1177 */
    1178 
    1179 
     1126
  • trunk/hal/tsar_mips32/core/hal_irqmask.c

    r457 r632  
    3333        __asm__ volatile
    3434                (".set noat                          \n"
    35          "mfc0   $1,     $12                 \n"
    36                  "or     %0,     $0,     $1          \n"
     35         "mfc0   $1,     $12                 \n"   /* $1    <= c0_sr        */
     36                 "or     %0,     $0,     $1          \n"   /* old   <= $1           */
    3737                 "srl    $1,     $1,     1           \n"
    38                  "sll    $1,     $1,     1           \n"
    39                  "mtc0   $1,     $12                 \n"
     38                 "sll    $1,     $1,     1           \n"   /* clear IE bit in $1    */
     39                 "mtc0   $1,     $12                 \n"   /* c0_sr <= $1           */
    4040         ".set at                            \n"
    4141                 : "=&r" (sr) );
     
    5151        __asm__ volatile
    5252                (".set noat                          \n"
    53                  "mfc0   $1,     $12                 \n"
    54                  "or     %0,     $0,     $1          \n"
    55                  "ori    $1,     $1,     0xFF01      \n"
    56                  "mtc0   $1,     $12                 \n"
     53                 "mfc0   $1,     $12                 \n"   /* s1    <= c0_sr        */
     54                 "or     %0,     $0,     $1          \n"   /* old   <= $1           */
     55                 "ori    $1,     $1,     0x1         \n"   /* set IE bit in $1      */
     56                 "mtc0   $1,     $12                 \n"   /* c0_sr <= $1           */
    5757         ".set at                            \n"
    5858                 : "=&r" (sr) );
  • trunk/hal/tsar_mips32/core/hal_ppm.c

    r610 r632  
    22 * hal_ppm.c - Generic Physical Page Manager API implementation for TSAR
    33 *
    4  * Authors  Alain Greiner (2016,2017,2018)
     4 * Authors  Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    6060
    6161        // initialize lock protecting the free_pages[] lists
    62         busylock_init( &ppm->free_lock , LOCK_PPM_FREE );
     62        remote_busylock_init( XPTR( local_cxy , &ppm->free_lock ) , LOCK_PPM_FREE );
    6363
    6464        // initialize lock protecting the dirty_pages list
     
    117117
    118118        // check consistency
    119         return ppm_assert_order( ppm );
     119        return  ppm_assert_order();
    120120
    121121}  // end hal_ppm_init()
  • trunk/kernel/kern/dqdt.c

    r583 r632  
    373373// It traverses the quad tree from clusters to root.
    374374///////////////////////////////////////////////////////////////////////////
    375 // @ node       : extended pointer on current node
     375// @ node_xp    : extended pointer on current node
    376376// @ increment  : number of pages variation
    377377///////////////////////////////////////////////////////////////////////////
    378 static void dqdt_propagate_pages( xptr_t  node,
     378static void dqdt_propagate_pages( xptr_t  node_xp,
    379379                                  int32_t increment )
    380380{
    381381    // get current node cluster identifier and local pointer
    382     cxy_t         cxy = GET_CXY( node );
    383     dqdt_node_t * ptr = GET_PTR( node );
     382    cxy_t         node_cxy = GET_CXY( node_xp );
     383    dqdt_node_t * node_ptr = GET_PTR( node_xp );
    384384
    385385    // update current node pages number
    386     hal_remote_atomic_add( XPTR( cxy , &ptr->pages ) , increment );
     386    hal_remote_atomic_add( XPTR( node_cxy , &node_ptr->pages ) , increment );
    387387
    388388    // get extended pointer on parent node
    389     xptr_t parent = (xptr_t)hal_remote_l64( XPTR( cxy , &ptr->parent ) );
     389    xptr_t parent_xp = (xptr_t)hal_remote_l64( XPTR( node_cxy , &node_ptr->parent ) );
    390390
    391391    // propagate if required
    392     if ( parent != XPTR_NULL ) dqdt_propagate_pages( parent, increment );
    393 }
    394 
    395 ///////////////////////////////////////////
    396 void dqdt_increment_pages( uint32_t order )
    397 {
    398         cluster_t   * cluster = LOCAL_CLUSTER;
    399     dqdt_node_t * node    = &cluster->dqdt_tbl[0];
    400 
    401     // update DQDT node level 0
    402     hal_atomic_add( &node->pages , (1 << order) );
    403 
    404     // propagate to DQDT upper levels
    405     if( node->parent != XPTR_NULL ) dqdt_propagate_pages( node->parent , (1 << order) );
     392    if ( parent_xp != XPTR_NULL ) dqdt_propagate_pages( parent_xp, increment );
     393}
     394
     395////////////////////////////////////////
     396void dqdt_increment_pages( cxy_t    cxy,
     397                           uint32_t order )
     398{
     399    // get local pointer on node[0] (same in all clusters)
     400    dqdt_node_t * node_ptr = &LOCAL_CLUSTER->dqdt_tbl[0];
     401
     402    // update DQDT node[0] in remote cluster cxy
     403    hal_remote_atomic_add( XPTR( cxy , &node_ptr->pages ) , (1 << order) );
     404
     405    // get extended pointer on parent node in remote cluster cxy
     406    xptr_t parent_xp = hal_remote_l64( XPTR( cxy , &node_ptr->parent ) );
     407
     408     // propagate to DQDT upper levels
     409    if( parent_xp != XPTR_NULL ) dqdt_propagate_pages( parent_xp , (1 << order) );
    406410
    407411#if DEBUG_DQDT_UPDATE_PAGES
     
    409413if( cycle > DEBUG_DQDT_UPDATE_PAGES )
    410414printk("\n[DBG] %s : thread %x in process %x / %x pages in cluster %x / cycle %d\n",
    411 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->pages, local_cxy, cycle );
    412 #endif
    413 
    414 }
    415 
    416 ///////////////////////////////////////////
    417 void dqdt_decrement_pages( uint32_t order )
    418 {
    419         cluster_t   * cluster = LOCAL_CLUSTER;
    420     dqdt_node_t * node    = &cluster->dqdt_tbl[0];
    421 
    422     // update DQDT node level 0
    423     hal_atomic_add( &node->pages , -(1 << order) );
    424 
    425     // propagate to DQDT upper levels
    426     if( node->parent != XPTR_NULL ) dqdt_propagate_pages( node->parent , -(1 << order) );
     415__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
     416hal_remote_l32( XPTR( cxy , &node_ptr->pages ), cxy, cycle );
     417#endif
     418
     419}
     420
     421////////////////////////////////////////
     422void dqdt_decrement_pages( cxy_t    cxy,
     423                           uint32_t order )
     424{
     425    // get local pointer on node[0] (same in all clusters)
     426    dqdt_node_t * node_ptr = &LOCAL_CLUSTER->dqdt_tbl[0];
     427
     428    // update DQDT node[0] in remote cluster cxy
     429    hal_remote_atomic_add( XPTR( cxy , &node_ptr->pages ) , -(1 << order) );
     430
     431    // get extended pointer on parent node in remote cluster cxy
     432    xptr_t parent_xp = hal_remote_l64( XPTR( cxy , &node_ptr->parent ) );
     433
     434     // propagate to DQDT upper levels
     435    if( parent_xp != XPTR_NULL ) dqdt_propagate_pages( parent_xp , -(1 << order) );
    427436
    428437#if DEBUG_DQDT_UPDATE_PAGES
     
    430439if( cycle > DEBUG_DQDT_UPDATE_PAGES )
    431440printk("\n[DBG] %s : thread %x in process %x / %x pages in cluster %x / cycle %d\n",
    432 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->pages, local_cxy, cycle );
     441__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
     442hal_remote_l32( XPTR( cxy , &node_ptr->pages ), cxy, cycle );
    433443#endif
    434444
     
    478488if( cycle > DEBUG_DQDT_UPDATE_THREADS )
    479489printk("\n[DBG] %s : thread %x in process %x / %d threads in cluster %x / cycle %d\n",
    480 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->threads, local_cxy, cycle );
     490__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
     491node->threads, local_cxy, cycle );
    481492#endif
    482493
     
    499510if( cycle > DEBUG_DQDT_UPDATE_THREADS )
    500511printk("\n[DBG] %s : thread %x in process %x / %d threads in cluster %x / cycle %d\n",
    501 __FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, node->threads, local_cxy, cycle );
     512__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid,
     513node->threads, local_cxy, cycle );
    502514#endif
    503515
  • trunk/kernel/kern/dqdt.h

    r583 r632  
    105105
    106106/****************************************************************************************
    107  * This local function updates the total number of pages in level 0 DQDT node,
    108  * and immediately propagates the variation to the DQDT upper levels.
     107 * These two functions can be called by any thread running in any cluster.
     108 * They increment/decrement the total number of 4 Kbytes pages allocated in a cluster
     109 * identified by the <cxy> argument, as specified by the <order> argument. The level 0
     110 * DQDT node is udated, and this change is immediately propagated to upper levels.
    109111 * They are called by PPM on each physical memory page allocation or release.
    110112 ****************************************************************************************
    111  * @ order   : ln2( number of small pages )
     113 * @ cxy     : target cluster identifier.
     114 * @ order   : ln2( number of 4 Kbytes pages )
    112115 ***************************************************************************************/
    113 void dqdt_increment_pages( uint32_t order );
    114 void dqdt_decrement_pages( uint32_t order );
     116void dqdt_increment_pages( cxy_t    cxy ,
     117                           uint32_t order );
     118
     119void dqdt_decrement_pages( cxy_t    cxy,
     120                           uint32_t order );
    115121
    116122/****************************************************************************************
  • trunk/kernel/kern/kernel_init.c

    r630 r632  
    133133
    134134    "CLUSTER_KCM",           //  1
    135     "PPM_FREE",              //  2
    136     "SCHED_STATE",           //  3
    137     "VMM_STACK",             //  4
    138     "VMM_MMAP",              //  5
    139     "VFS_CTX",               //  6
    140     "KCM_STATE",             //  7
    141     "KHM_STATE",             //  8
    142     "HTAB_STATE",            //  9
    143 
     135    "SCHED_STATE",           //  2
     136    "VMM_STACK",             //  3
     137    "VMM_MMAP",              //  4
     138    "VFS_CTX",               //  5
     139    "KCM_STATE",             //  6
     140    "KHM_STATE",             //  7
     141    "HTAB_STATE",            //  8
     142
     143    "PPM_FREE",              //  9
    144144    "THREAD_JOIN",           // 10
    145145    "XHTAB_STATE",           // 11
  • trunk/kernel/kern/rpc.c

    r629 r632  
    5151rpc_server_t * rpc_server[RPC_MAX_INDEX] =
    5252{
    53     &rpc_pmem_get_pages_server,            // 0
    54     &rpc_pmem_release_pages_server,        // 1
    55     &rpc_ppm_display_server,               // 2
     53    &rpc_undefined,                        // 0
     54    &rpc_undefined,                        // 1
     55    &rpc_undefined,                        // 2
    5656    &rpc_process_make_fork_server,         // 3
    5757    &rpc_user_dir_create_server,           // 4
     
    8787char * rpc_str[RPC_MAX_INDEX] =
    8888{
    89     "PMEM_GET_PAGES",            // 0
    90     "PMEM_RELEASE_PAGES",        // 1
    91     "PPM_DISPLAY",               // 2
     89    "undefined_0",               // 0
     90    "undefined_1",               // 1
     91    "undefined_2",               // 2
    9292    "PROCESS_MAKE_FORK",         // 3
    9393    "USER_DIR_CREATE",           // 4
     
    423423
    424424/////////////////////////////////////////////////////////////////////////////////////////
    425 // [0]           Marshaling functions attached to RPC_PMEM_GET_PAGES (blocking)
    426 /////////////////////////////////////////////////////////////////////////////////////////
    427 
     425// [0]       RPC_PMEM_GET_PAGES deprecated [AG] May 2019
     426/////////////////////////////////////////////////////////////////////////////////////////
     427
     428/*
    428429///////////////////////////////////////////////
    429430void rpc_pmem_get_pages_client( cxy_t      cxy,
     
    495496#endif
    496497}
    497 
    498 /////////////////////////////////////////////////////////////////////////////////////////
    499 // [1]       Marshaling functions attached to RPC_PMEM_RELEASE_PAGES
    500 /////////////////////////////////////////////////////////////////////////////////////////
    501 
     498*/
     499
     500/////////////////////////////////////////////////////////////////////////////////////////
     501// [1]       RPC_PMEM_RELEASE_PAGES deprecated [AG] may 2019
     502/////////////////////////////////////////////////////////////////////////////////////////
     503
     504/*
    502505//////////////////////////////////////////////////
    503506void rpc_pmem_release_pages_client( cxy_t     cxy,
     
    565568#endif
    566569}
    567 
    568 /////////////////////////////////////////////////////////////////////////////////////////
    569 // [2]            Marshaling functions attached to RPC_PPM_DISPLAY   
    570 /////////////////////////////////////////////////////////////////////////////////////////
    571 
     570*/
     571
     572/////////////////////////////////////////////////////////////////////////////////////////
     573// [2]          RPC_PPM_DISPLAY deprecated [AG] May 2019   
     574/////////////////////////////////////////////////////////////////////////////////////////
     575
     576/*
    572577/////////////////////////////////////////
    573578void rpc_ppm_display_client( cxy_t  cxy )
     
    621626#endif
    622627}
     628*/
    623629
    624630/////////////////////////////////////////////////////////////////////////////////////////
  • trunk/kernel/kern/rpc.h

    r628 r632  
    6060typedef enum
    6161{
    62     RPC_PMEM_GET_PAGES            = 0,
    63     RPC_PMEM_RELEASE_PAGES        = 1,
    64     RPC_PPM_DISPLAY               = 2,      
     62    RPC_UNDEFINED_0               = 0,   // RPC_PMEM_GET_PAGES     deprecated [AG]
     63    RPC_UNDEFINED_1               = 1,   // RPC_PMEM_RELEASE_PAGES deprecated [AG]
     64    RPC_UNDEFINED_2               = 2,   // RPC_PMEM_DISPLAY       deprecated [AG]     
    6565    RPC_PROCESS_MAKE_FORK         = 3,
    6666    RPC_USER_DIR_CREATE           = 4,
     
    177177 * [0] The RPC_PMEM_GET_PAGES allocates one or several pages in a remote cluster,
    178178 * and returns the local pointer on the page descriptor.
     179 *         deprecated [AG] may 2019
    179180 ***********************************************************************************
    180181 * @ cxy     : server cluster identifier
     
    182183 * @ page    : [out] local pointer on page descriptor / NULL if failure
    183184 **********************************************************************************/
     185
     186/*
    184187void rpc_pmem_get_pages_client( cxy_t             cxy,
    185188                                uint32_t          order,
     
    187190
    188191void rpc_pmem_get_pages_server( xptr_t xp );
     192*/
    189193
    190194/***********************************************************************************
    191195 * [1] The RPC_PMEM_RELEASE_PAGES release one or several pages to a remote cluster.
     196 *         deprecated [AG] may 2019
    192197 ***********************************************************************************
    193198 * @ cxy     : server cluster identifier
    194199 * @ page    : [in] local pointer on page descriptor to release.
    195200 **********************************************************************************/
     201
     202/*
    196203void rpc_pmem_release_pages_client( cxy_t            cxy,
    197204                                    struct page_s  * page );
    198205
    199206void rpc_pmem_release_pages_server( xptr_t xp );
     207*/
    200208
    201209/***********************************************************************************
    202210 * [2] The RPC_PPM_DISPLAY allows any client thread to require any remote cluster
    203211 * identified by the <cxy> argumentto display the physical memory allocator state.
    204  **********************************************************************************/
     212 *         deprecated [AG] may 2019
     213 **********************************************************************************/
     214
     215/*
    205216void rpc_ppm_display_client( cxy_t  cxy );
    206217
    207218void rpc_ppm_display_server( xptr_t xp );
     219*/
    208220
    209221/***********************************************************************************
  • trunk/kernel/kernel_config.h

    r629 r632  
    9595#define DEBUG_HAL_CONTEXT                 0
    9696#define DEBUG_HAL_EXCEPTIONS              0
    97 #define DEBUG_HAL_GPT_SET_PTE             0
    9897#define DEBUG_HAL_GPT_COPY                0
    9998#define DEBUG_HAL_GPT_CREATE              0
    10099#define DEBUG_HAL_GPT_DESTROY             0
     100#define DEBUG_HAL_GPT_LOCK_PTE            0
     101#define DEBUG_HAL_GPT_SET_PTE             0
    101102#define DEBUG_HAL_IOC_RX                  0
    102103#define DEBUG_HAL_IOC_TX                  0
     
    140141#define DEBUG_QUEUELOCK_CXY               0
    141142
    142 #define DEBUG_RPC_CLIENT_GENERIC          0
    143 #define DEBUG_RPC_SERVER_GENERIC          0
     143#define DEBUG_RPC_CLIENT_GENERIC             21000000
     144#define DEBUG_RPC_SERVER_GENERIC             21000000
    144145
    145146#define DEBUG_RPC_KCM_ALLOC               0
     
    147148#define DEBUG_RPC_MAPPER_HANDLE_MISS      0
    148149#define DEBUG_RPC_MAPPER_MOVE_USER        0
    149 #define DEBUG_RPC_PMEM_GET_PAGES          0
     150#define DEBUG_RPC_PMEM_GET_PAGES             21000000
    150151#define DEBUG_RPC_PMEM_RELEASE_PAGES      0
    151152#define DEBUG_RPC_PROCESS_MAKE_FORK       0
     
    254255#define DEBUG_VMM_DESTROY                 0
    255256#define DEBUG_VMM_FORK_COPY               0
    256 #define DEBUG_VMM_GET_ONE_PPN             0
     257#define DEBUG_VMM_GET_ONE_PPN                2
    257258#define DEBUG_VMM_GET_PTE                 0
    258 #define DEBUG_VMM_HANDLE_PAGE_FAULT       0
     259#define DEBUG_VMM_HANDLE_PAGE_FAULT          2
    259260#define DEBUG_VMM_HANDLE_COW              0
    260261#define DEBUG_VMM_MMAP_ALLOC              0
    261 #define DEBUG_VMM_PAGE_ALLOCATE           0
     262#define DEBUG_VMM_PAGE_ALLOCATE              2
    262263#define DEBUG_VMM_REMOVE_VSEG             0
    263264#define DEBUG_VMM_RESIZE_VSEG             0
     
    276277
    277278#define LOCK_CLUSTER_KCM       1   // local  (B)  protect dynamic KCM creation in cluster
    278 #define LOCK_PPM_FREE          2   // local  (B)  protect PPM allocator free_pages lists
    279 #define LOCK_SCHED_STATE       3   // local  (B)  protect scheduler state for given core
    280 #define LOCK_VMM_STACK         4   // local  (B)  protect VMM stack vseg allocator   
    281 #define LOCK_VMM_MMAP          5   // local  (B)  protect VMM mmap vseg allocator
    282 #define LOCK_VFS_CTX           6   // local  (B)  protect vfs context state
    283 #define LOCK_KCM_STATE         7   // local  (B)  protect KCM allocator state
    284 #define LOCK_KHM_STATE         8   // local  (B)  protect KHM allocator state
    285 #define LOCK_HTAB_STATE        9   // local  (B)  protect a local htab state
    286 
     279#define LOCK_SCHED_STATE       2   // local  (B)  protect scheduler state for given core
     280#define LOCK_VMM_STACK         3   // local  (B)  protect VMM stack vseg allocator   
     281#define LOCK_VMM_MMAP          4   // local  (B)  protect VMM mmap vseg allocator
     282#define LOCK_VFS_CTX           5   // local  (B)  protect vfs context state
     283#define LOCK_KCM_STATE         6   // local  (B)  protect KCM allocator state
     284#define LOCK_KHM_STATE         7   // local  (B)  protect KHM allocator state
     285#define LOCK_HTAB_STATE        8   // local  (B)  protect a local htab state
     286
     287#define LOCK_PPM_FREE          9   // remote (B)  protect PPM allocator free_pages lists
    287288#define LOCK_THREAD_JOIN      10   // remote (B)  protect join/exit between two threads
    288289#define LOCK_XHTAB_STATE      11   // remote (B)  protect  a distributed xhtab state
  • trunk/kernel/libk/list.h

    r612 r632  
    11/*
    2  * list.h - Double circular chained lists, inspired from linux
     2 * list.h - Double circular linked list
    33 *
    44 * Authors Ghassan Almaless  (2008,2009,2010,2011,2012)
    5  *         Alain Greiner     (2016,2017,2018)
     5 *         Alain Greiner     (2016,2017,2018i,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    2828#include <kernel_config.h>
    2929#include <hal_kernel_types.h>
     30#include <hal_remote.h>
    3031#include <printk.h>
    3132
     
    3435#endif
    3536
     37
     38////////////////////////////////////////////////////////////////////////////
     39//          Double circular linked list functions & macros
     40//
     41// It defines a generic local list, as all elements are in the same cluster.
     42//
     43// There is two sets of access functions, because these local lists can be
     44// accessed by local threads, using local pointers, but they can also be
     45// accessed by remote threads running in any cluster, with specific access
     46// functions using extended pointers.
     47////////////////////////////////////////////////////////////////////////////
     48
     49/***************************************************************************
     50 * This structure defines a Double Circular Linked List entry.
     51 * Note : The list root is an extra list-entry_t, that is NOT part
     52 *            of the set of linked elements.
     53 **************************************************************************/
     54
     55typedef struct list_entry_s
     56{
     57        struct list_entry_s * next;
     58        struct list_entry_s * pred;
     59}
     60list_entry_t;
    3661
    3762/***************************************************************************
     
    4671#endif
    4772
    48 ////////////////////////////////////////////////////////////////////////////
    49 ////////////////////////////////////////////////////////////////////////////
    50 //          Double circular linked list functions & macros
    51 ////////////////////////////////////////////////////////////////////////////
    52 ////////////////////////////////////////////////////////////////////////////
    53 
    54 /***************************************************************************
    55  * This structure defines a Double Circular Linked List entry.
    56  * Note : The list root is an extra list-entry_t, that is NOT part
    57  *            of the set of linked elements.
    58  **************************************************************************/
    59 
    60 typedef struct list_entry_s
    61 {
    62         struct list_entry_s * next;
    63         struct list_entry_s * pred;
    64 }
    65 list_entry_t;
    66 
    6773/***************************************************************************
    6874 * This macro returns a pointer on a structure containing a list_entry_t.
     
    7783        (container_type *)( (char*)__member_ptr - OFFSETOF( container_type , member_name ));})
    7884
     85
     86////////////////////////////////////////////////////////////////////////////
     87// These functions and macros mus be called by a thread running
     88// in the local cluster to access the local list.
     89////////////////////////////////////////////////////////////////////////////
     90
    7991/***************************************************************************
    8092 * This macro returns t pointer on the first element of a list.
     
    101113/***************************************************************************
    102114 * This macro traverse a rooted double linked list in forward order.
    103  * WARNING : Don't use 2 LIST_FOREACH in the same function, because the
    104  * variable __ptr will be defined twice, wich result in a compilation error.
     115 * WARNING : Don't use this macro when you want to remove one or several
     116 * item(s) from the traversed list.     
    105117 ***************************************************************************
    106118 * @ root      : pointer on the root list_entry
     
    149161
    150162/***************************************************************************
    151  * This function inserts a new entry in first place of a double linked list.
     163 * This function must be called by a thread running in local cluster.
     164 * It inserts a new entry in first place of a double linked list.
    152165 ***************************************************************************
    153166 * @ root    : pointer on the list root
     
    157170                                   list_entry_t * entry )
    158171{
    159     list_entry_t * pred_entry;
    160     list_entry_t * next_entry;
    161  
    162         pred_entry = root;
    163         next_entry = root->next;
    164        
    165         entry->next = next_entry;
    166         entry->pred = pred_entry;
    167  
    168         pred_entry->next = entry;
    169         next_entry->pred = entry;
    170 }
    171 
    172 /***************************************************************************
    173  * This function inserts a new entry in last place of a double linked list.
     172    list_entry_t * next = root->next; 
     173
     174        entry->next = next;
     175        entry->pred = root;
     176 
     177        root->next = entry;
     178        next->pred = entry;
     179}
     180
     181/***************************************************************************
     182 * This function must be called by a thread running in local cluster.
     183 * It inserts a new entry in last place of a double linked list.
    174184 ***************************************************************************
    175185 * @ root    : pointer on the list root
     
    179189                                  list_entry_t * entry )
    180190{
    181     list_entry_t * pred_entry;
    182     list_entry_t * next_entry;
    183 
    184         pred_entry = root->pred;
    185         next_entry = root;
    186        
    187         entry->next = next_entry;
    188         entry->pred = pred_entry;
    189  
    190         pred_entry->next = entry;
    191         next_entry->pred = entry;
    192 }
    193 
    194 /***************************************************************************
    195  * This function returns true if the list is empty.
     191    list_entry_t * pred = root->pred;
     192
     193        entry->next = root;
     194        entry->pred = pred;
     195 
     196        root->pred = entry;
     197        pred->next = entry;
     198}
     199
     200/***************************************************************************
     201 * This function must be called by a thread running in local cluster.
     202 * It returns true if the list is empty.
    196203 ***************************************************************************
    197204 * @ root    : pointer on the list root
     
    202209}
    203210
    204 /***************************************************************************
    205  * This function remove an entry from a rooted double linked list.
     211
     212/***************************************************************************
     213 * This function must be called by a thread running in local cluster.
     214 * It removes an entry from the list.
    206215 ***************************************************************************
    207216 * @ entry : pointer on the entry to be removed.
     
    209218static inline void list_unlink( list_entry_t * entry )
    210219{
    211         list_entry_t * pred_entry;
    212     list_entry_t * next_entry;
    213 
    214         pred_entry = entry->pred;
    215         next_entry = entry->next;
    216 
    217         pred_entry->next = entry->next;
    218         next_entry->pred = entry->pred;
     220        list_entry_t * pred;
     221    list_entry_t * next;
     222
     223        pred = entry->pred;
     224        next = entry->next;
     225
     226        pred->next = next;
     227        next->pred = pred;
    219228}
    220229
     
    278287
    279288
     289
     290////////////////////////////////////////////////////////////////////////////
     291// These functions and macros can be used by any thread running
     292// in any cluster to access a remote local list.
     293////////////////////////////////////////////////////////////////////////////
     294
     295/***************************************************************************
     296 * This macro can be used by a thread running in any cluster to access
     297 * a remote local list. It returns a local pointer on the first element
     298 * of the remote list in the remote cluster.
     299 ***************************************************************************
     300 * @ cxy     : remote list cluster identifier
     301 * @ root    : local pointer on the list root
     302 * @ type    : type of the linked element
     303 * @ member  : name of the list_entry_t field
     304 **************************************************************************/
     305
     306#define LIST_REMOTE_FIRST( cxy , root , type , member )                       \
     307    ({ list_entry_t * __first = hal_remote_lpt( XPTR( cxy , &root->next ) );  \
     308           LIST_ELEMENT( __first , type , member ); })
     309
     310/***************************************************************************
     311 * This macro can be used by a thread running in any cluster to access
     312 * a remote local list. It traverse the list in forward order.
     313 * WARNING : Don't use this macro when you want to remove one or several
     314 * item(s) from the traversed list.     
     315 ***************************************************************************
     316 * @ cxy     : remote list cluster identifier
     317 * @ root    : pointer on the root list_entry
     318 * @ iter    : pointer on the current list_entry
     319 **************************************************************************/
     320
     321#define LIST_REMOTE_FOREACH( cxy , root , iter )               \
     322for( (iter) = hal_remote_lpt( XPTR( cxy , &(root)->next ) ) ;  \
     323     (iter) != (root) ;                         \
     324     (iter) = hal_remote_lpt( XPTR( cxy , &(iter)->next ) ) )
     325       
     326/***************************************************************************
     327 * This function can be called by a thread running in any cluster to access
     328 * a remote local list. It returns true if the list is empty.
     329 ***************************************************************************
     330 * @ cxy     : remote list cluster identifier
     331 * @ root    : local pointer on the remote list root
     332 **************************************************************************/
     333static inline bool_t list_remote_is_empty( cxy_t          cxy,
     334                                           list_entry_t * root )
     335{
     336    list_entry_t * next = hal_remote_lpt( XPTR( cxy , &root->next ) );
     337    return( root == next );
     338}
     339
     340/***************************************************************************
     341 * This function can be called by a thread running in any cluster to access
     342 * a remote local list. It inserts a new entry in first place of the list.
     343 ***************************************************************************
     344 * @ cxy     : remote list cluster identifier
     345 * @ root    : local pointer on the remote list root
     346 * @ entry   : local pointer on the remote entry to be inserted
     347 **************************************************************************/
     348static inline void list_remote_add_first( cxy_t          cxy,
     349                                          list_entry_t * root,
     350                                          list_entry_t * entry )
     351{
     352    list_entry_t * first;    // local pointer on current first entry
     353    list_entry_t * next;     // local pointer on current first->next entry
     354 
     355        first  = hal_remote_lpt( XPTR( cxy , &root->next ) );
     356    next   = hal_remote_lpt( XPTR( cxy , &first->next ) );
     357       
     358        hal_remote_spt( XPTR( cxy , &entry->next ) , first );
     359        hal_remote_spt( XPTR( cxy , &entry->pred ) , root );
     360 
     361        hal_remote_spt( XPTR( cxy , &root->next ) , entry );
     362        hal_remote_spt( XPTR( cxy , &next->pred ) , entry );
     363}
     364
     365/***************************************************************************
     366 * This function can be called by a thread running in any cluster to access
     367 * a remote local list. It inserts a new entry in last place of the list.
     368 ***************************************************************************
     369 * @ cxy     : remote list cluster identifier
     370 * @ root    : local pointer on the remote list root
     371 * @ entry   : local pointer on the remote entry to be inserted
     372 **************************************************************************/
     373static inline void list_remote_add_last( cxy_t          cxy,
     374                                         list_entry_t * root,
     375                                         list_entry_t * entry )
     376{
     377    list_entry_t * last;     // local pointer on current last entry
     378    list_entry_t * pred;     // local pointer on current last->pred entry
     379 
     380        last   = hal_remote_lpt( XPTR( cxy , &root->pred ) );
     381    pred   = hal_remote_lpt( XPTR( cxy , &last->pred ) );
     382       
     383        hal_remote_spt( XPTR( cxy , &entry->next ) , root );
     384        hal_remote_spt( XPTR( cxy , &entry->pred ) , pred );
     385 
     386        hal_remote_spt( XPTR( cxy , &root->pred ) , entry );
     387        hal_remote_spt( XPTR( cxy , &pred->next ) , entry );
     388}
     389
     390/***************************************************************************
     391 * This function can be called by a thread running in any cluster to access
     392 * a remote local list. It removes an entry from the list.
     393 ***************************************************************************
     394 * @ cxy     : remote list cluster identifier
     395 * @ entry   : pointer on the entry to be removed.
     396 **************************************************************************/
     397static inline void list_remote_unlink( cxy_t          cxy,
     398                                       list_entry_t * entry )
     399{
     400        list_entry_t * pred;
     401    list_entry_t * next;
     402
     403        pred = hal_remote_lpt( XPTR( cxy , &entry->pred ) );
     404        next = hal_remote_lpt( XPTR( cxy , &entry->next ) );
     405
     406        hal_remote_spt( XPTR( cxy , &pred->next ) , next );
     407        hal_remote_spt( XPTR( cxy , &next->pred ) , pred );
     408}
     409
     410
     411
    280412#endif  /* _LIST_H_ */
  • trunk/kernel/libk/remote_barrier.c

    r629 r632  
    506506                                    uint32_t    nthreads )
    507507{
    508     page_t        * dqt_page;
    509508    xptr_t          dqt_page_xp;     
    510509    page_t        * rpc_page;
     
    514513    uint32_t        z;             // actual DQT size == max(x_size,y_size)
    515514    uint32_t        levels;        // actual number of DQT levels
    516     kmem_req_t      req;           // kmem request
    517515    xptr_t          rpc_xp;        // extended pointer on RPC descriptors array
    518516    rpc_desc_t    * rpc;           // pointer on RPC descriptors array
     
    522520    uint32_t        y;             // Y coordinate in QDT mesh
    523521    uint32_t        l;             // level coordinate
     522    kmem_req_t      req;           // kmem request
    524523
    525524    // compute size and number of DQT levels
     
    554553    cxy_t          ref_cxy = GET_CXY( ref_xp );
    555554
    556     // 1. allocate memory for DQT barrier descriptor in reference cluster
    557     if( ref_cxy == local_cxy )                   
    558      {
    559         req.type     = KMEM_PAGE;
    560         req.size     = 2;               // 4 pages == 16 Kbytes
    561         req.flags    = AF_ZERO;
    562         dqt_page     = kmem_alloc( &req );
    563         dqt_page_xp  = XPTR( local_cxy , dqt_page );
    564     }
    565     else                                         
    566     {
    567         rpc_pmem_get_pages_client( ref_cxy,
    568                                    2,
    569                                    &dqt_page );
    570         dqt_page_xp  = XPTR( ref_cxy , dqt_page );
    571     }
    572 
    573     if( dqt_page == NULL ) return NULL;
     555    // 1. allocate 4 4 Kbytes pages for DQT barrier descriptor in reference cluster
     556    dqt_page_xp = ppm_remote_alloc_pages( ref_cxy , 2 );
     557
     558    if( dqt_page_xp == XPTR_NULL ) return NULL;
    574559
    575560    // get pointers on DQT barrier descriptor
     
    948933
    949934    // 4. release memory allocated for barrier descriptor
    950     xptr_t   page_xp = ppm_base2page( barrier_xp );
    951     page_t * page    = GET_PTR( page_xp );
    952 
    953     if( barrier_cxy == local_cxy )                   
    954     {
    955         req.type      = KMEM_PAGE;
    956         req.ptr       = page;
    957         kmem_free( &req );
    958     }
    959     else                                         
    960     {
    961         rpc_pmem_release_pages_client( barrier_cxy,
    962                                        page );
    963     }
     935    xptr_t   page_xp  = ppm_base2page( barrier_xp );
     936    cxy_t    page_cxy = GET_CXY( page_xp );
     937    page_t * page_ptr = GET_PTR( page_xp );
     938
     939    ppm_remote_free_pages( page_cxy , page_ptr );
    964940
    965941#if DEBUG_BARRIER_DESTROY
  • trunk/kernel/mm/page.c

    r567 r632  
    9393}
    9494
    95 ////////////////////////////////
    96 void page_print( page_t * page )
     95
     96////////////////////////////////////////////////////
     97inline void page_remote_set_flag( xptr_t    page_xp,
     98                                  uint32_t  value )
    9799{
    98         printk("*** Page %d : base = %x / flags = %x / order = %d / count = %d\n",
    99                 page->index,
    100                 GET_PTR( ppm_page2base( XPTR( local_cxy , page ) ) ),
    101                 page->flags,
    102                 page->order,
    103                 page->refcount );
     100    cxy_t    page_cxy = GET_CXY( page_xp );
     101    page_t * page_ptr = GET_PTR( page_xp );
     102
     103        hal_remote_atomic_or( XPTR( page_cxy , &page_ptr->flags ) , value );
    104104}
    105105
     106//////////////////////////////////////////////////////
     107inline void page_remote_clear_flag( xptr_t    page_xp,
     108                                    uint32_t  value )
     109{
     110    cxy_t    page_cxy = GET_CXY( page_xp );
     111    page_t * page_ptr = GET_PTR( page_xp );
     112
     113        hal_remote_atomic_and( XPTR( page_cxy , &page_ptr->flags ) , value );
     114}
     115
     116/////////////////////////////////////////////////////
     117inline bool_t page_remote_is_flag( xptr_t    page_xp,
     118                                   uint32_t  value )
     119{
     120    cxy_t    page_cxy = GET_CXY( page_xp );
     121    page_t * page_ptr = GET_PTR( page_xp );
     122
     123    uint32_t flags = hal_remote_l32( XPTR( page_cxy , &page_ptr->flags ) );
     124   
     125    return (flags & value) ? 1 : 0;
     126}
     127
     128/////////////////////////////////////////////////////
     129inline void page_remote_refcount_up( xptr_t page_xp )
     130{
     131    cxy_t    page_cxy = GET_CXY( page_xp );
     132    page_t * page_ptr = GET_PTR( page_xp );
     133
     134    hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->refcount ) , 1 );
     135}
     136
     137///////////////////////////////////////////////////////
     138inline void page_remote_refcount_down( xptr_t page_xp )
     139{
     140    cxy_t    page_cxy = GET_CXY( page_xp );
     141    page_t * page_ptr = GET_PTR( page_xp );
     142
     143    hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->refcount ) , -1 );
     144}
     145
     146///////////////////////////////////////////
     147void page_remote_display( xptr_t  page_xp )
     148{
     149    page_t  page;   // local copy of page decriptor
     150
     151    hal_remote_memcpy( XPTR( local_cxy , &page ) , page_xp , sizeof( page_t ) );
     152                     
     153        printk("*** Page %d in cluster %x : ppn %x / flags %x / order %d / refcount %d\n",
     154                page.index,
     155            GET_CXY( page_xp ),
     156                ppm_page2ppn( page_xp ),
     157                page.flags,
     158                page.order,
     159                page.refcount );
     160}
     161
     162
     163
  • trunk/kernel/mm/page.h

    r625 r632  
    33 *
    44 * Authors Ghassan Almalles (2008,2009,2010,2011,2012)
    5  *         Alain Greiner    (2016)
     5 *         Alain Greiner    (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    6868
    6969/*************************************************************************************
    70  * This function initializes one page descriptor.
     70 * This function must be called by a thread running in the local cluster.
     71 * It initializes the page descriptor.
    7172 *************************************************************************************
    7273 * @ page    : pointer to page descriptor
     
    7576
    7677/*************************************************************************************
    77  * This function atomically set one or several flags in page descriptor flags.
     78 * This function must be called by a thread running in the local cluster.
     79 * It atomically set one or several flags in page descriptor flags.
    7880 *************************************************************************************
    7981 * @ page    : pointer to page descriptor.
     
    8486
    8587/*************************************************************************************
    86  * This function atomically reset one or several flags in page descriptor flags.
     88 * This function must be called by a thread running in the local cluster.
     89 * It atomically reset one or several flags in page descriptor flags.
    8790 *************************************************************************************
    8891 * @ page    : pointer to page descriptor.
     
    9396
    9497/*************************************************************************************
    95  * This function tests the value of one or several flags in page descriptor flags.
     98 * This function must be called by a thread running in the local cluster.
     99 * It tests the value of one or several flags in page descriptor flags.
    96100 *************************************************************************************
    97101 * @ page    : pointer to page descriptor.
     
    103107
    104108/*************************************************************************************
    105  * This function resets to 0 all bytes in a given page.
     109 * This function must be called by a thread running in the local cluster.
     110 * It resets to 0 all bytes in a given page.
    106111 *************************************************************************************
    107112 * @ page     : pointer on page descriptor.
     
    110115
    111116/*************************************************************************************
    112  * This blocking function atomically increments the page refcount.
     117 * This function must be called by a thread running in the local cluster.
     118 * It atomically increments the page refcount.
    113119 *************************************************************************************
    114120 * @ page     : pointer on page descriptor.
     
    117123
    118124/*************************************************************************************
    119  * This blocking function atomically decrements the page refcount.
     125 * This function must be called by a thread running in the local cluster.
     126 * It atomically decrements the page refcount.
    120127 *************************************************************************************
    121128 * @ page     : pointer on page descriptor.
     
    123130inline void page_refcount_down( page_t * page );
    124131
    125 /*************************************************************************************
    126  * This function display the values contained in a page descriptor.
    127  *************************************************************************************
    128  * @ page     : pointer on page descriptor.
    129  ************************************************************************************/
    130 void page_print( page_t * page );
    131132
    132133
     134
     135/*************************************************************************************
     136 * This function can be called by any thread running in any cluster.
     137 * It atomically set one or several flags in a remote page descriptor
     138 * identified by the <page_xp> argument.
     139 *************************************************************************************
     140 * @ page_xp : extended pointer to page descriptor.
     141 * @ value   : all non zero bits in value will be set.
     142 ************************************************************************************/
     143inline void page_remote_set_flag( xptr_t    page_xp,
     144                                  uint32_t  value );
     145
     146/*************************************************************************************
     147 * This function can be called by any thread running in any cluster.
     148 * It atomically reset one or several flags in a remote page descriptor
     149 * identified by the <page_xp> argument.
     150 *************************************************************************************
     151 * @ page_xp : extended pointer to page descriptor.
     152 * @ value   : all non zero bits in value will be cleared.
     153 ************************************************************************************/
     154inline void page_remote_clear_flag( xptr_t    page_xp,
     155                                    uint32_t  value );
     156
     157/*************************************************************************************
     158 * This function can be called by any thread running in any cluster.
     159 * It tests the value of one or several flags in a remote page descriptor
     160 * identified by the <page_xp> argument.
     161 *************************************************************************************
     162 * @ page_xp : extended pointer to page descriptor.
     163 * @ value   : all non zero bits will be tested.
     164 * @ returns true if at least one non zero bit in value is set / false otherwise.
     165 ************************************************************************************/
     166inline bool_t page_remote_is_flag( xptr_t    page_xp,
     167                                   uint32_t  value );
     168
     169/*************************************************************************************
     170 * This function can be called by any thread running in any cluster.
     171 * It atomically increments the refcount for the remote page identified by
     172 * the <page_xp> argument.
     173 *************************************************************************************
     174 * @ page_xp   : extended pointer on page descriptor.
     175 ************************************************************************************/
     176inline void page_remote_refcount_up( xptr_t page_xp );
     177
     178/*************************************************************************************
     179 * This function can be called by any thread running in any cluster.
     180 * It atomically decrements the refcount for the remote page identified by
     181 * the <page_xp> argument.
     182 *************************************************************************************
     183 * @ page_xp   : extended pointer on page descriptor.
     184 ************************************************************************************/
     185inline void page_remote_refcount_down( xptr_t  page_xp );
     186
     187/*************************************************************************************
     188 * This debug function can be called by any thread running in any cluster.
     189 * It displays the values contained in a page descriptor.
     190 *************************************************************************************
     191 * @ page_xp     : extended pointer on page descriptor.
     192 ************************************************************************************/
     193void page_remote_display( xptr_t  page_xp );
     194
    133195#endif  /* _PAGE_H_ */
  • trunk/kernel/mm/ppm.c

    r625 r632  
    33 *
    44 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Alain Greiner    (2016,2017,2018)
     5 *          Alain Greiner    (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    4545////////////////////////////////////////////////////////////////////////////////////////
    4646
    47 ////////////////////////////////////////////////
    48 inline bool_t ppm_page_is_valid( page_t * page )
    49 {
    50         ppm_t    * ppm  = &LOCAL_CLUSTER->ppm;
    51         uint32_t   pgnr = (uint32_t)( page - ppm->pages_tbl );
    52         return (pgnr <= ppm->pages_nr);
    53 }
    5447
    5548/////////////////////////////////////////////
     
    151144void ppm_free_pages_nolock( page_t * page )
    152145{
    153         page_t   * buddy;            // searched buddy page descriptor
    154         uint32_t   buddy_index;      // buddy page index
    155         page_t   * current;          // current (merged) page descriptor
    156         uint32_t   current_index;    // current (merged) page index
    157         uint32_t   current_order;    // current (merged) page order
     146        page_t   * buddy;            // searched buddy block page descriptor
     147        uint32_t   buddy_index;      // buddy bloc index in page_tbl[]
     148        page_t   * current;          // current (merged) block page descriptor
     149        uint32_t   current_index;    // current (merged) block index in page_tbl[]
     150        uint32_t   current_order;    // current (merged) block order
    158151
    159152        ppm_t    * ppm         = &LOCAL_CLUSTER->ppm;
    160153        page_t   * pages_tbl   = ppm->pages_tbl;
    161154
    162         assert( !page_is_flag( page , PG_FREE ) ,
    163     "page already released : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
    164 
    165         assert( !page_is_flag( page , PG_RESERVED ) ,
    166     "reserved page : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     155assert( !page_is_flag( page , PG_FREE ) ,
     156"page already released : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     157
     158assert( !page_is_flag( page , PG_RESERVED ) ,
     159"reserved page : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
    167160
    168161        // update released page descriptor flags
     
    172165        // - merge with current page descriptor if found
    173166        // - exit to release the current page descriptor if not found
    174         current       = page ,
     167        current       = page;
    175168        current_index = (uint32_t)(page - ppm->pages_tbl);
    176169        for( current_order = page->order ;
     
    181174                buddy       = pages_tbl + buddy_index;
    182175
    183                 if( !page_is_flag( buddy , PG_FREE ) || (buddy->order != current_order) ) break;
    184 
    185                 // remove buddy from free list
     176        // exit this loop if buddy block not found
     177                if( !page_is_flag( buddy , PG_FREE ) ||
     178            (buddy->order != current_order) ) break;
     179
     180                // remove buddy block from free_list
    186181                list_unlink( &buddy->list );
    187182                ppm->free_pages_nr[current_order] --;
    188183
    189                 // merge buddy with current
     184        // reset order field in buddy block page descriptor
    190185                buddy->order = 0;
     186
     187                // compute merged block index in page_tbl[]
    191188                current_index &= buddy_index;
    192189        }
    193190
    194         // update merged page descriptor order
     191        // update pointer and order field for merged block page descriptor
    195192        current        = pages_tbl + current_index;
    196193        current->order = current_order;
    197194
    198         // insert current in free list
     195        // insert merged block in free list
    199196        list_add_first( &ppm->free_pages_root[current_order] , &current->list );
    200197        ppm->free_pages_nr[current_order] ++;
     
    205202page_t * ppm_alloc_pages( uint32_t   order )
    206203{
     204        page_t   * current_block;
    207205        uint32_t   current_order;
    208         page_t   * remaining_block;
    209206        uint32_t   current_size;
     207        page_t   * found_block; 
    210208
    211209#if DEBUG_PPM_ALLOC_PAGES
     
    213211uint32_t cycle = (uint32_t)hal_get_cycles();
    214212if( DEBUG_PPM_ALLOC_PAGES < cycle )
    215 printk("\n[%s] thread[%x,%x] enter for %d page(s) / cycle %d\n",
    216 __FUNCTION__, this->process->pid, this->trdid, 1<<order, cycle );
     213printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / cycle %d\n",
     214__FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
    217215#endif
    218216
    219217#if(DEBUG_PPM_ALLOC_PAGES & 0x1)
    220218if( DEBUG_PPM_ALLOC_PAGES < cycle )
    221 ppm_print("enter ppm_alloc_pages");
     219ppm_remote_display( local_cxy );
    222220#endif
    223221
     
    227225assert( (order < CONFIG_PPM_MAX_ORDER) , "illegal order argument = %d\n" , order );
    228226
    229         page_t * block = NULL; 
     227    //build extended pointer on lock protecting remote PPM
     228    xptr_t lock_xp = XPTR( local_cxy , &ppm->free_lock );
    230229
    231230        // take lock protecting free lists
    232         busylock_acquire( &ppm->free_lock );
     231        remote_busylock_acquire( lock_xp );
     232
     233        current_block = NULL;
    233234
    234235        // find a free block equal or larger to requested size
     
    237238                if( !list_is_empty( &ppm->free_pages_root[current_order] ) )
    238239                {
    239                         block = LIST_FIRST( &ppm->free_pages_root[current_order] , page_t , list );
    240                         list_unlink( &block->list );
    241                         break;
     240            // get first free block in this free_list
     241                        current_block = LIST_FIRST( &ppm->free_pages_root[current_order] , page_t , list );
     242
     243            // remove this block from this free_list
     244                        list_unlink( &current_block->list );
     245
     246            // register pointer on found block
     247            found_block = current_block;
     248
     249            // update this free-list number of blocks
     250                ppm->free_pages_nr[current_order] --;
     251
     252            // compute found block size
     253                current_size = (1 << current_order);
     254
     255                        break; 
    242256                }
    243257        }
    244258
    245         if( block == NULL ) // return failure
     259        if( current_block == NULL ) // return failure if no free block found
    246260        {
    247261                // release lock protecting free lists
    248                 busylock_release( &ppm->free_lock );
     262                remote_busylock_release( lock_xp );
    249263
    250264#if DEBUG_PPM_ALLOC_PAGES
    251265cycle = (uint32_t)hal_get_cycles();
    252266if( DEBUG_PPM_ALLOC_PAGES < cycle )
    253 printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) / cycle %d\n",
    254 __FUNCTION__, this->process->pid, this->trdid, 1<<order, cycle );
     267printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) in cluster %x / cycle %d\n",
     268__FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
    255269#endif
    256270
     
    258272        }
    259273
    260         // update free-lists after removing a block
    261         ppm->free_pages_nr[current_order] --;
    262         current_size = (1 << current_order);
    263 
    264         // split the removed block in smaller sub-blocks if required
     274
     275        // split the found block in smaller sub-blocks if required
    265276        // and update the free-lists accordingly
    266277        while( current_order > order )
    267278        {
    268279                current_order --;
     280
     281        // update pointer, size, and order fiels for new free block
    269282                current_size >>= 1;
    270 
    271                 remaining_block = block + current_size;
    272                 remaining_block->order = current_order;
    273 
    274                 list_add_first( &ppm->free_pages_root[current_order] , &remaining_block->list );
     283                current_block = found_block + current_size;
     284                current_block->order = current_order;
     285
     286        // insert new free block in relevant free_list
     287                list_add_first( &ppm->free_pages_root[current_order] , &current_block->list );
     288
     289        // update number of blocks in free list
    275290                ppm->free_pages_nr[current_order] ++;
    276291        }
    277292
    278         // update page descriptor
    279         page_clear_flag( block , PG_FREE );
    280         page_refcount_up( block );
    281         block->order = order;
     293        // update found block page descriptor
     294        page_clear_flag( found_block , PG_FREE );
     295        page_refcount_up( found_block );
     296        found_block->order = order;
    282297
    283298        // release lock protecting free lists
    284         busylock_release( &ppm->free_lock );
     299        remote_busylock_release( lock_xp );
    285300
    286301    // update DQDT
    287     dqdt_increment_pages( order );
     302    dqdt_increment_pages( local_cxy , order );
    288303
    289304#if DEBUG_PPM_ALLOC_PAGES
    290305cycle = (uint32_t)hal_get_cycles();
    291306if( DEBUG_PPM_ALLOC_PAGES < cycle )
    292 printk("\n[%s] thread[%x,%x] exit for %d page(s) / ppn = %x / cycle %d\n",
     307printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn = %x / cycle %d\n",
    293308__FUNCTION__, this->process->pid, this->trdid,
    294 1<<order, ppm_page2ppn(XPTR( local_cxy , block )), cycle );
     3091<<order, ppm_page2ppn(XPTR( local_cxy , found_block )), cxy, cycle );
    295310#endif
    296311
    297312#if(DEBUG_PPM_ALLOC_PAGES & 0x1)
    298313if( DEBUG_PPM_ALLOC_PAGES < cycle )
    299 ppm_print("exit ppm_alloc_pages");
    300 #endif
    301 
    302         return block;
     314ppm_remote_display( local_cxy );
     315#endif
     316
     317        return found_block;
    303318
    304319}  // end ppm_alloc_pages()
     
    311326
    312327#if DEBUG_PPM_FREE_PAGES
    313 uint32_t cycle = (uint32_t)hal_get_cycles();
     328thread_t * this  = CURRENT_THREAD;
     329uint32_t   cycle = (uint32_t)hal_get_cycles();
    314330if( DEBUG_PPM_FREE_PAGES < cycle )
    315 printk("\n[%s] thread[%x,%x] enter for %d page(s) / ppn %x / cycle %d\n",
     331printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / ppn %x / cycle %d\n",
    316332__FUNCTION__, this->process->pid, this->trdid,
    317 1<<page->order, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
     3331<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
    318334#endif
    319335
    320336#if(DEBUG_PPM_FREE_PAGES & 0x1)
    321337if( DEBUG_PPM_FREE_PAGES < cycle )
    322 ppm_print("enter ppm_free_pages");
    323 #endif
     338ppm_remote_display( local_cxy );
     339#endif
     340
     341    //build extended pointer on lock protecting free_lists
     342    xptr_t lock_xp = XPTR( local_cxy , &ppm->free_lock );
    324343
    325344        // get lock protecting free_pages[] array
    326         busylock_acquire( &ppm->free_lock );
     345        remote_busylock_acquire( lock_xp );
    327346
    328347        ppm_free_pages_nolock( page );
    329348
    330         // release lock protecting free_pages[] array
    331         busylock_release( &ppm->free_lock );
     349        // release lock protecting free_lists
     350        remote_busylock_release( lock_xp );
    332351
    333352    // update DQDT
    334     dqdt_decrement_pages( page->order );
     353    dqdt_decrement_pages( local_cxy , page->order );
    335354
    336355#if DEBUG_PPM_FREE_PAGES
    337356cycle = (uint32_t)hal_get_cycles();
    338357if( DEBUG_PPM_FREE_PAGES < cycle )
    339 printk("\n[%s] thread[%x,%x] exit for %d page(s) / ppn %x / cycle %d\n",
     358printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn %x / cycle %d\n",
    340359__FUNCTION__, this->process->pid, this->trdid,
    341 1<<page->order, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
     3601<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)) , cycle );
    342361#endif
    343362
    344363#if(DEBUG_PPM_FREE_PAGES & 0x1)
    345364if( DEBUG_PPM_FREE_PAGES < cycle )
    346 ppm_print("exit ppm_free_pages");
     365ppm_remote_display( local_cxy );
    347366#endif
    348367
    349368}  // end ppm_free_pages()
    350369
    351 ////////////////////////
    352 void ppm_display( void )
     370/////////////////////////////////////////////
     371xptr_t ppm_remote_alloc_pages( cxy_t     cxy,
     372                               uint32_t  order )
     373{
     374        uint32_t   current_order;
     375        uint32_t   current_size;
     376    page_t   * current_block;   
     377    page_t   * found_block;
     378
     379#if DEBUG_PPM_ALLOC_PAGES
     380thread_t * this  = CURRENT_THREAD;
     381uint32_t   cycle = (uint32_t)hal_get_cycles();
     382if( DEBUG_PPM_ALLOC_PAGES < cycle )
     383printk("\n[%s] thread[%x,%x] enter for %d small page(s) in cluster %x / cycle %d\n",
     384__FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
     385#endif
     386
     387#if(DEBUG_PPM_ALLOC_PAGES & 0x1)
     388if( DEBUG_PPM_ALLOC_PAGES < cycle )
     389ppm_remote_display( cxy );
     390#endif
     391
     392// check order
     393assert( (order < CONFIG_PPM_MAX_ORDER) , "illegal order argument = %d\n" , order );
     394
     395    // get local pointer on PPM (same in all clusters)
     396        ppm_t * ppm = &LOCAL_CLUSTER->ppm;
     397
     398    //build extended pointer on lock protecting remote PPM
     399    xptr_t lock_xp = XPTR( cxy , &ppm->free_lock );
     400
     401        // take lock protecting free lists in remote cluster
     402        remote_busylock_acquire( lock_xp );
     403
     404    current_block = NULL;   
     405
     406        // find in remote cluster a free block equal or larger to requested size
     407        for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ )
     408        {
     409        // get local pointer on the root of relevant free_list in remote cluster
     410        list_entry_t * root = &ppm->free_pages_root[current_order];
     411
     412                if( !list_remote_is_empty( cxy , root ) )
     413                {
     414            // get local pointer on first free page descriptor in remote cluster
     415                        current_block = LIST_REMOTE_FIRST( cxy, root , page_t , list );
     416
     417            // remove first free page from the free-list in remote cluster
     418                        list_remote_unlink( cxy , &current_block->list );
     419
     420            // register found block
     421            found_block = current_block;
     422
     423                // decrement relevant free-list number of items in remote cluster
     424                hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ), -1 );
     425
     426            // compute found block size
     427                current_size = (1 << current_order);
     428
     429                        break;
     430                }
     431        }
     432
     433        if( current_block == NULL ) // return failure
     434        {
     435                // release lock protecting free lists
     436                remote_busylock_release( lock_xp );
     437
     438#if DEBUG_PPM_ALLOC_PAGES
     439cycle = (uint32_t)hal_get_cycles();
     440if( DEBUG_PPM_ALLOC_PAGES < cycle )
     441printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) in cluster %x / cycle %d\n",
     442__FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
     443#endif
     444
     445                return XPTR_NULL;
     446        }
     447
     448        // split the found block in smaller sub-blocks if required
     449        // and update the free-lists accordingly in remote cluster
     450        while( current_order > order )
     451        {
     452        // update order, size, and local pointer for new free block
     453                current_order --;
     454                current_size >>= 1;
     455                current_block = found_block + current_size;
     456
     457        // update new free block order field in remote cluster
     458                hal_remote_s32( XPTR( cxy , &current_block->order ) , current_order );
     459
     460        // get local pointer on the root of the relevant free_list in remote cluster 
     461        list_entry_t * root = &ppm->free_pages_root[current_order];
     462
     463        // insert new free block in this free_list
     464                list_remote_add_first( cxy , root, &current_block->list );
     465
     466        // update free-list number of items in remote cluster
     467        hal_remote_atomic_add( XPTR(cxy , &ppm->free_pages_nr[current_order]), 1 );
     468        }
     469
     470        // update refcount, flags and order fields in found block remote page descriptor
     471        page_remote_clear_flag( XPTR( cxy , found_block ), PG_FREE );
     472        page_remote_refcount_up( XPTR( cxy , found_block ) );
     473        hal_remote_s32( XPTR( cxy , &found_block->order ) , order );
     474   
     475        // release lock protecting free lists in remote cluster
     476        remote_busylock_release( lock_xp );
     477
     478    // update DQDT page counter in remote cluster
     479    dqdt_increment_pages( cxy , order );
     480
     481#if DEBUG_PPM_ALLOC_PAGES
     482cycle = (uint32_t)hal_get_cycles();
     483if( DEBUG_PPM_ALLOC_PAGES < cycle )
     484printk("\n[%s] thread[%x,%x] exit for %d page(s) / ppn = %x in cluster %x / cycle %d\n",
     485__FUNCTION__, this->process->pid, this->trdid,
     4861<<order, ppm_page2ppn(XPTR( local_cxy , found_block )), cxy, cycle );
     487#endif
     488
     489#if(DEBUG_PPM_ALLOC_PAGES & 0x1)
     490if( DEBUG_PPM_ALLOC_PAGES < cycle )
     491ppm_remote_display( cxy );
     492#endif
     493
     494        return XPTR( cxy , found_block );
     495
     496}  // end ppm_remote_alloc_pages()
     497
     498//////////////////////////////////////////
     499void ppm_remote_free_pages( cxy_t     cxy,
     500                            page_t  * page )
     501{
     502    xptr_t     page_xp;          // extended pointer on released page descriptor
     503    uint32_t   order;            // released block order
     504        page_t   * buddy_ptr;        // searched buddy block page descriptor
     505    uint32_t   buddy_order;      // searched buddy block order
     506        uint32_t   buddy_index;      // buddy block index in page_tbl[]
     507        page_t   * current_ptr;      // current (merged) block page descriptor
     508        uint32_t   current_index;    // current (merged) block index in page_tbl[]
     509        uint32_t   current_order;    // current (merged) block order
     510
     511#if DEBUG_PPM_FREE_PAGES
     512thread_t * this  = CURRENT_THREAD;
     513uint32_t   cycle = (uint32_t)hal_get_cycles();
     514if( DEBUG_PPM_FREE_PAGES < cycle )
     515printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / ppn %x / cycle %d\n",
     516__FUNCTION__, this->process->pid, this->trdid,
     5171<<page->order, cxy, ppm_page2ppn(XPTR(cxy , page)), cycle );
     518#endif
     519
     520#if(DEBUG_PPM_FREE_PAGES & 0x1)
     521if( DEBUG_PPM_FREE_PAGES < cycle )
     522ppm_remote_display( cxy );
     523#endif
     524
     525    // build extended pointer on released page descriptor
     526    page_xp = XPTR( cxy , page );
     527   
     528    // get released page order
     529    order = hal_remote_l32( XPTR( cxy , &page->order ) );
     530
     531    // get local pointer on PPM (same in all clusters)
     532        ppm_t * ppm = &LOCAL_CLUSTER->ppm;
     533
     534    // build extended pointer on lock protecting remote PPM
     535    xptr_t lock_xp = XPTR( cxy , &ppm->free_lock );
     536
     537    // get local pointer on remote PPM page_tbl[] array
     538        page_t * pages_tbl = hal_remote_lpt( XPTR( cxy , &ppm->pages_tbl ) );
     539
     540        // get lock protecting free_pages in remote cluster
     541        remote_busylock_acquire( lock_xp );
     542
     543assert( !page_remote_is_flag( page_xp , PG_FREE ) ,
     544"page already released : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     545
     546assert( !page_remote_is_flag( page_xp , PG_RESERVED ) ,
     547"reserved page : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     548
     549        // update released page descriptor flags
     550        page_remote_set_flag( page_xp , PG_FREE );
     551
     552        // search the buddy page descriptor
     553        // - merge with current page descriptor if found
     554        // - exit to release the current page descriptor if not found
     555        current_ptr   = page;
     556        current_index = (uint32_t)(page - ppm->pages_tbl);
     557        for( current_order = order ;
     558             current_order < CONFIG_PPM_MAX_ORDER ;
     559             current_order++ )
     560        {
     561                buddy_index = current_index ^ (1 << current_order);
     562                buddy_ptr   = pages_tbl + buddy_index;
     563
     564        // get buddy block order
     565        buddy_order = hal_remote_l32( XPTR( cxy , &buddy_ptr->order ) );
     566
     567        // exit loop if buddy block not found
     568                if( !page_remote_is_flag( XPTR( cxy , buddy_ptr ) , PG_FREE ) ||
     569            (buddy_order != current_order) ) break;
     570
     571                // remove buddy from free list in remote cluster
     572                list_remote_unlink( cxy , &buddy_ptr->list );
     573        hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ) , -1 );
     574
     575        // reset order field in buddy block page descriptor
     576        hal_remote_s32( XPTR( cxy , &buddy_ptr->order ) , 0 );
     577
     578                // compute merged block index in page_tbl[] array
     579                current_index &= buddy_index;
     580        }
     581
     582        // update merged page descriptor order field
     583        current_ptr = pages_tbl + current_index;
     584    hal_remote_s32( XPTR( cxy , &current_ptr->order ) , current_order );
     585
     586        // insert merged block into relevant free list in remote cluster
     587        list_remote_add_first( cxy , &ppm->free_pages_root[current_order] , &current_ptr->list );
     588    hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ) , 1 );
     589
     590        // release lock protecting free_pages[] array
     591        remote_busylock_release( lock_xp );
     592
     593    // update DQDT
     594    dqdt_decrement_pages( cxy , page->order );
     595
     596#if DEBUG_PPM_FREE_PAGES
     597cycle = (uint32_t)hal_get_cycles();
     598if( DEBUG_PPM_FREE_PAGES < cycle )
     599printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn %x / cycle %d\n",
     600__FUNCTION__, this->process->pid, this->trdid,
     6011<<page->order, cxy, ppm_page2ppn(XPTR(cxy , page)), cycle );
     602#endif
     603
     604#if(DEBUG_PPM_FREE_PAGES & 0x1)
     605if( DEBUG_PPM_FREE_PAGES < cycle )
     606ppm_remote_display( cxy );
     607#endif
     608
     609}  // end ppm_remote_free_pages()
     610
     611////////////////////////////////////
     612void ppm_remote_display( cxy_t cxy )
    353613{
    354614        uint32_t       order;
     
    358618    ppm_t * ppm = &LOCAL_CLUSTER->ppm;
    359619
    360         // get lock protecting free lists
    361         busylock_acquire( &ppm->free_lock );
     620    // build extended pointer on lock protecting remote PPM
     621    xptr_t lock_xp = XPTR( cxy , &ppm->free_lock );
     622
     623        // get lock protecting free lists in remote cluster
     624        remote_busylock_acquire( lock_xp );
    362625
    363626        printk("\n***** PPM in cluster %x / %d pages\n", local_cxy , ppm->pages_nr );
     
    365628        for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ )
    366629        {
    367                 printk("- order = %d / free_pages = %d\t: ",
    368                        order , ppm->free_pages_nr[order] );
    369 
    370                 LIST_FOREACH( &ppm->free_pages_root[order] , iter )
     630        // get number of free pages for free_list[order] in remote cluster
     631        uint32_t n = hal_remote_l32( XPTR( cxy , &ppm->free_pages_nr[order] ) );
     632                printk("- order = %d / free_pages = %d\t: ", order , n );
     633
     634                LIST_REMOTE_FOREACH( cxy , &ppm->free_pages_root[order] , iter )
    371635                {
    372636                        page = LIST_ELEMENT( iter , page_t , list );
     
    377641        }
    378642
    379         // release lock protecting free lists
    380         busylock_release( &ppm->free_lock );
     643        // release lock protecting free lists in remote cluster
     644        remote_busylock_release( lock_xp );
    381645}
    382646
    383 ///////////////////////////////////////
    384 error_t ppm_assert_order( ppm_t * ppm )
     647////////////////////////////////
     648error_t ppm_assert_order( void )
    385649{
    386650        uint32_t       order;
    387651        list_entry_t * iter;
    388652        page_t       * page;
     653
     654    ppm_t * ppm = &LOCAL_CLUSTER->ppm;
    389655
    390656        for( order=0 ; order < CONFIG_PPM_MAX_ORDER ; order++ )
     
    438704        hal_remote_s32( page_flags_xp , flags | PG_DIRTY );
    439705
    440                 // The PPM dirty list is a LOCAL list !!!
    441         // We must update 4 pointers to insert a new page in this list.
    442         // We can use the standard LIST API when the page is local,
    443         // but we cannot use the standard API if the page is remote...
    444 
    445         if( page_cxy == local_cxy )         // locally update the PPM dirty list
    446         {
    447             list_add_first( &ppm->dirty_root , &page_ptr->list );
    448         }
    449         else                                // remotely update the PPM dirty list
    450         {
    451             // get local and remote pointers on "root" list entry
    452             list_entry_t * root    = &ppm->dirty_root;
    453             xptr_t         root_xp = XPTR( page_cxy , root );
    454 
    455             // get local and remote pointers on "page" list entry
    456             list_entry_t * list    = &page_ptr->list;
    457             xptr_t         list_xp = XPTR( page_cxy , list );
    458 
    459             // get local and remote pointers on first dirty page
    460             list_entry_t * dirt    = hal_remote_lpt( XPTR( page_cxy, &root->next ) );
    461             xptr_t         dirt_xp = XPTR( page_cxy , dirt );
    462 
    463             // set root.next, list.next, list pred, curr.pred in remote cluster
    464             hal_remote_spt( root_xp                    , list );
    465             hal_remote_spt( list_xp                    , dirt );
    466             hal_remote_spt( list_xp + sizeof(intptr_t) , root );
    467             hal_remote_spt( dirt_xp + sizeof(intptr_t) , list );
    468         }
     706                // insert the page in the remote dirty list
     707        list_remote_add_first( page_cxy , &ppm->dirty_root , &page_ptr->list );
    469708
    470709                done = true;
     
    512751        hal_remote_s32( page_flags_xp , flags & (~PG_DIRTY) );
    513752
    514                 // The PPM dirty list is a LOCAL list !!!
    515         // We must update 4 pointers to remove a page from this list.
    516         // we can use the standard LIST API when the page is local,
    517         // but we cannot use the standard API if the page is remote...
    518 
    519         if( page_cxy == local_cxy )         // locally update the PPM dirty list
    520         {
    521             list_unlink( &page_ptr->list );
    522         }
    523         else                                // remotely update the PPM dirty list
    524         {
    525             // get local and remote pointers on "page" list entry
    526             list_entry_t * list    = &page_ptr->list;
    527             xptr_t         list_xp = XPTR( page_cxy , list );
    528 
    529             // get local and remote pointers on "next" page list entry
    530             list_entry_t * next    = hal_remote_lpt( list_xp );
    531             xptr_t         next_xp = XPTR( page_cxy , next );
    532 
    533             // get local and remote pointers on "pred" page list entry
    534             list_entry_t * pred    = hal_remote_lpt( list_xp + sizeof(intptr_t) );
    535             xptr_t         pred_xp = XPTR( page_cxy , pred );
    536 
    537             // set root.next, list.next, list pred, curr.pred in remote cluster
    538             hal_remote_spt( pred_xp                    , next );
    539             hal_remote_spt( list_xp                    , NULL );
    540             hal_remote_spt( list_xp + sizeof(intptr_t) , NULL );
    541             hal_remote_spt( next_xp + sizeof(intptr_t) , pred );
    542         }
     753        // remove the page from remote dirty list
     754        list_remote_unlink( page_cxy , &page_ptr->list );
    543755
    544756                done = true;
  • trunk/kernel/mm/ppm.h

    r625 r632  
    5151 *
    5252 * The main service provided by the PMM is the dynamic allocation of physical pages
    53  * from the "kernel_heap" section. This low-level allocator implements the buddy
     53 * from the "kernel_heap" section. This low-level allocator implements the "buddy"
    5454 * algorithm: an allocated block is an integer number n of small pages, where n
    55  * is a power of 2, and ln(n) is called order.
    56  * This allocator being shared by the local threads, the free_page lists rooted
    57  * in the PPM descriptor are protected by a local busylock, because it is used
    58  * by the idle_thread during kernel_init().
    59  *
    60  * Another service is to register the dirty pages in a specific dirty_list, that is
     55 * is a power of 2, and ln(n) is called order. The free_pages_root[] array contains
     56 * the roots ot the local lists of free pages for different sizes, as required by
     57 * the "buddy" algorithm.
     58 * The local threads can access these free_lists by calling the ppm_alloc_pages() and
     59 * ppm_free_page() functions, but the remote threads can access the same free lists,
     60 * by calling the ppm_remote_alloc_pages() and ppm_remote_free_pages functions.
     61 * Therefore, these free lists are protected by a remote_busy_lock.
     62 *
     63 * Another service is to register the dirty pages in a specific local dirty_list,
    6164 * also rooted in the PPM, in order to be able to synchronize all dirty pages on disk.
    6265 * This dirty list is protected by a specific remote_queuelock, because it can be
    63  * modified by a remote thread, but it contains only local pages.
     66 * modified by a remote thread.
    6467 ****************************************************************************************/
    6568
    6669typedef struct ppm_s
    6770{
    68         busylock_t          free_lock;          /*! lock protecting free_pages[] lists      */
     71        remote_busylock_t   free_lock;          /*! lock protecting free_pages[] lists      */
    6972        list_entry_t        free_pages_root[CONFIG_PPM_MAX_ORDER];  /*! roots of free lists */
    7073        uint32_t            free_pages_nr[CONFIG_PPM_MAX_ORDER];    /*! free pages number   */
     
    8083
    8184/*****************************************************************************************
    82  * This is the low-level physical pages allocation function.
    83  * It allocates N contiguous physical pages. N is a power of 2.
    84  * In normal use, it should not be called directly, as the recommended way to get
    85  * physical pages is to call the generic allocator defined in kmem.h.
    86  *****************************************************************************************
    87  * @ order        : ln2( number of 4 Kbytes pages)
    88  * @ returns a pointer on the page descriptor if success / NULL otherwise
     85 * This local allocator must be called by a thread running in local cluster.
     86 * It allocates n contiguous physical 4 Kbytes pages from the local cluster, where
     87 * n is a power of 2 defined by the <order> argument.
     88 * In normal use, it should not be called directly, as the recommended way to allocate
     89 * physical pages is to call the generic allocator defined in kmem.h.
     90 *****************************************************************************************
     91 * @ order     : ln2( number of 4 Kbytes pages)
     92 * @ returns a local pointer on the page descriptor if success / NULL if error.
    8993 ****************************************************************************************/
    9094page_t * ppm_alloc_pages( uint32_t order );
    9195
    9296/*****************************************************************************************
    93  * This is the low-level physical pages release function. It takes the lock protecting
    94  * the free_list before register the released page in the relevant free_list.
     97 * This function must be called by a thread running in local cluster to release
     98 * physical pages. It takes the lock protecting the free_lists before register the
     99 * released page in the relevant free_list.
    95100 * In normal use, you do not need to call it directly, as the recommended way to free
    96101 * physical pages is to call the generic allocator defined in kmem.h.
    97102 *****************************************************************************************
    98  * @ page         : pointer to the page descriptor to be released
     103 * @ page   : local pointer on the page descriptor to be released
    99104 ****************************************************************************************/
    100105void ppm_free_pages( page_t * page );
     
    105110 * there is no concurrent access issue.
    106111 *****************************************************************************************
    107  * @ page         : pointer to the page descriptor to be released
     112 * @ page   : local pointer on the page descriptor to be released
    108113 ****************************************************************************************/
    109114void ppm_free_pages_nolock( page_t * page );
    110115
    111116/*****************************************************************************************
    112  * This function check if a page descriptor pointer is valid.
    113  *****************************************************************************************
    114  * @ page         : pointer on a page descriptor
    115  * @ returns true if valid / false otherwise.
    116  ****************************************************************************************/
    117 inline bool_t ppm_page_is_valid( page_t * page );
     117 * This remote  allocator can be called by any thread running in any cluster.
     118 * It allocates n contiguous physical 4 Kbytes pages from cluster identified
     119 * by the <cxy> argument, where n is a power of 2 defined by the <order> argument.
     120 * In normal use, it should not be called directly, as the recommended way to allocate
     121 * physical pages is to call the generic allocator defined in kmem.h.
     122 *****************************************************************************************
     123 * @ cxy       : remote cluster identifier.
     124 * @ order     : ln2( number of 4 Kbytes pages)
     125 * @ returns an extended pointer on the page descriptor if success / XPTR_NULL if error.
     126 ****************************************************************************************/
     127xptr_t  ppm_remote_alloc_pages( cxy_t    cxy,
     128                                uint32_t order );
     129
     130/*****************************************************************************************
     131 * This function can be called by any thread running in any cluster to release physical
     132 * pages to a remote cluster. It takes the lock protecting the free_list before register
     133 * the released page in the relevant free_list.
     134 * In normal use, you do not need to call it directly, as the recommended way to free
     135 * physical pages is to call the generic allocator defined in kmem.h.
     136 *****************************************************************************************
     137 * @ cxy       : remote cluster identifier.
     138 * @ page      : local pointer on the page descriptor to be released in remote cluster.
     139 ****************************************************************************************/
     140void ppm_remote_free_pages( cxy_t    cxy,
     141                            page_t * page );
     142
     143/*****************************************************************************************
     144 * This debug function can be called by any thread running in any cluster to display
     145 * the current PPM state of a remote cluster.
     146 *****************************************************************************************
     147 * @ cxy       : remote cluster identifier.
     148 ****************************************************************************************/
     149void ppm_remote_display( cxy_t cxy );
    118150
    119151
     
    172204
    173205/*****************************************************************************************
    174  * This function prints the PPM allocator status in the calling thread cluster.
    175  *****************************************************************************************
    176  * string   : character string printed in header
    177  ****************************************************************************************/
    178 void ppm_display( void );
    179 
    180 /*****************************************************************************************
    181  * This function checks PPM allocator consistency.
    182  *****************************************************************************************
    183  * @ ppm      : pointer on PPM allocator.
     206 * This function can be called by any thread running in any cluster.
     207 * It displays the PPM allocator status in cluster identified by the <cxy> argument.
     208 *****************************************************************************************
     209 * @ cxy   : remote cluster
     210 ****************************************************************************************/
     211void ppm_remote_display( cxy_t cxy );
     212
     213/*****************************************************************************************
     214 * This function must be called by a thread running in local cluster.
     215 * It checks the consistency of the local PPM allocator.
     216 *****************************************************************************************
    184217 * @ return 0 if PPM is OK / return -1 if PPM not consistent.
    185218 ****************************************************************************************/
    186 error_t ppm_assert_order( ppm_t * ppm );
     219error_t ppm_assert_order( void );
    187220
    188221
  • trunk/kernel/mm/vmm.c

    r630 r632  
    12261226    ppn_t       ppn;        // current PTE ppn value
    12271227    uint32_t    attr;       // current PTE attributes
    1228     kmem_req_t  req;        // request to release memory
    12291228    xptr_t      page_xp;    // extended pointer on page descriptor
    12301229    cxy_t       page_cxy;   // page descriptor cluster
     
    13351334
    13361335            // release physical page to relevant kmem when required
    1337             if( ppn_release )
    1338             {
    1339                 if( page_cxy == local_cxy )
    1340                 {
    1341                     req.type = KMEM_PAGE;
    1342                     req.ptr  = page_ptr;
    1343                     kmem_free( &req );
    1344                 }
    1345                 else
    1346                 {
    1347                     rpc_pmem_release_pages_client( page_cxy , page_ptr );
    1348                 }
    1349             }
     1336            if( ppn_release ) ppm_remote_free_pages( page_cxy , page_ptr );
    13501337
    13511338#if( DEBUG_VMM_REMOVE_VSEG & 1 )
     
    16811668//////////////////////////////////////////////////////////////////////////////////////
    16821669// This static function compute the target cluster to allocate a physical page
    1683 // for a given <vpn> in a given <vseg>, allocates the page (with an RPC if required)
    1684 // and returns an extended pointer on the allocated page descriptor.
    1685 // It can be called by a thread running in any cluster.
     1670// for a given <vpn> in a given <vseg>, allocates the page and returns an extended
     1671// pointer on the allocated page descriptor.
    16861672// The vseg cannot have the FILE type.
    16871673//////////////////////////////////////////////////////////////////////////////////////
     
    16901676{
    16911677
    1692 #if DEBUG_VMM_ALLOCATE_PAGE
     1678#if DEBUG_VMM_PAGE_ALLOCATE
    16931679uint32_t   cycle   = (uint32_t)hal_get_cycles();
    16941680thread_t * this    = CURRENT_THREAD;
    1695 if( DEBUG_VMM_ALLOCATE_PAGE < (uint32_t)hal_get_cycles() )
     1681if( DEBUG_VMM_PAGE_ALLOCATE < cycle )
    16961682printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
    16971683__FUNCTION__ , this->process->pid, this->trdid, vpn, cycle );
    16981684#endif
    16991685
    1700     page_t     * page_ptr;
     1686    xptr_t       page_xp;
    17011687    cxy_t        page_cxy;
    1702     kmem_req_t   req;
    17031688    uint32_t     index;
    17041689
     
    17271712    }
    17281713
    1729     // allocate a physical page from target cluster
    1730     if( page_cxy == local_cxy )  // target cluster is the local cluster
    1731     {
    1732         req.type  = KMEM_PAGE;
    1733         req.size  = 0;
    1734         req.flags = AF_NONE;
    1735         page_ptr  = (page_t *)kmem_alloc( &req );
    1736     }
    1737     else                           // target cluster is not the local cluster
    1738     {
    1739         rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr );
    1740     }
    1741 
    1742 #if DEBUG_VMM_ALLOCATE_PAGE
     1714    // allocate a 4 Kbytes physical page from target cluster
     1715    page_xp = ppm_remote_alloc_pages( page_cxy , 0 );
     1716
     1717#if DEBUG_VMM_PAGE_ALLOCATE
    17431718cycle = (uint32_t)hal_get_cycles();
    1744 if( DEBUG_VMM_ALLOCATE_PAGE < (uint32_t)hal_get_cycles() )
    1745 printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle %d\n",
    1746 __FUNCTION__ , this->process->pid, this->trdid, vpn,
    1747 ppm_page2ppn( XPTR( page_cxy , page_ptr ) , cycle );
    1748 #endif
    1749 
    1750     if( page_ptr == NULL ) return XPTR_NULL;
    1751     else                   return XPTR( page_cxy , page_ptr );
     1719if( DEBUG_VMM_PAGE_ALLOCATE < cycle )
     1720printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cluster %x / cycle %d\n",
     1721__FUNCTION__ , this->process->pid, this->trdid, vpn, ppm_page2ppn(page_xp), page_cxy, cycle );
     1722#endif
     1723
     1724    return page_xp;
    17521725
    17531726}  // end vmm_page_allocate() 
     
    17691742uint32_t   cycle = (uint32_t)hal_get_cycles();
    17701743thread_t * this  = CURRENT_THREAD;
    1771 if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1744// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1745if( vpn == 0x40B )
    17721746printk("\n[%s] thread[%x,%x] enter for vpn %x / type %s / page_id  %d / cycle %d\n",
    17731747__FUNCTION__, this->process->pid, this->trdid, vpn, vseg_type_str(type), page_id, cycle );
     
    18151789
    18161790#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1817 if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
     1791// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1792if( vpn == 0x40B )
    18181793printk("\n[%s] thread[%x,%x] for vpn = %x / elf_offset = %x\n",
    18191794__FUNCTION__, this->process->pid, this->trdid, vpn, elf_offset );
     
    18291804
    18301805#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1831 if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
     1806// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1807if( vpn == 0x40B )
    18321808printk("\n[%s] thread[%x,%x] for vpn  %x / fully in BSS\n",
    18331809__FUNCTION__, this->process->pid, this->trdid, vpn );
     
    18461822
    18471823#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1848 if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
     1824// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1825if( vpn == 0x40B )
    18491826printk("\n[%s] thread[%x,%x] for vpn  %x / fully in mapper\n",
    18501827__FUNCTION__, this->process->pid, this->trdid, vpn );
     
    18631840
    18641841#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1865 if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
     1842// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1843if( vpn == 0x40B )
    18661844printk("\n[%s] thread[%x,%x] for vpn  %x / both mapper & BSS\n"
    18671845"      %d bytes from mapper / %d bytes from BSS\n",
     
    18971875#if DEBUG_VMM_GET_ONE_PPN
    18981876cycle = (uint32_t)hal_get_cycles();
    1899 if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1877// if( DEBUG_VMM_GET_ONE_PPN < cycle )
     1878if( vpn == 0x40B )
    19001879printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle\n",
    19011880__FUNCTION__ , this->process->pid, this->trdid , vpn , *ppn, cycle );
     
    19281907
    19291908#if DEBUG_VMM_HANDLE_PAGE_FAULT
    1930 if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
     1909if( vpn == 0x40b )
    19311910printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
    19321911__FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle );
     
    19501929
    19511930#if DEBUG_VMM_HANDLE_PAGE_FAULT
    1952 if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
    1953 printk("\n[%s] thread[%x,%x] found vseg %s\n",
    1954 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
     1931uint32_t cycle = (uint32_t)hal_get_cycles();
     1932if( vpn == 0x40b )
     1933printk("\n[%s] thread[%x,%x] found vseg %s / cycle %d\n",
     1934__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type), cycle );
    19551935#endif
    19561936
     
    19581938    local_gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
    19591939
    1960     // lock target PTE in local GPT and get current PPN and attributes
     1940    // lock PTE in local GPT and get current PPN and attributes
    19611941    error = hal_gpt_lock_pte( local_gpt_xp,
    19621942                              vpn,
     
    19711951    }
    19721952
    1973     // handle page fault only if PTE still unmapped after lock
     1953#if DEBUG_VMM_HANDLE_PAGE_FAULT
     1954cycle = (uint32_t)hal_get_cycles();
     1955if( vpn == 0x40b )
     1956printk("\n[%s] thread[%x,%x] locked vpn %x in cluster %x / cycle %d\n",
     1957__FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, cycle );
     1958#endif
     1959
     1960    // handle page fault only if local PTE still unmapped after lock
    19741961    if( (attr & GPT_MAPPED) == 0 )
    19751962    {
     
    19841971            (ref_cxy    == local_cxy ) )
    19851972        {
    1986             // allocate and initialise a physical page depending on the vseg type
     1973
     1974#if DEBUG_VMM_HANDLE_PAGE_FAULT
     1975if( vpn == 0x40b )
     1976printk("\n[%s] thread[%x,%x] : access local gpt : local_cxy %x / ref_cxy %x / type %s\n",
     1977__FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
     1978#endif
     1979            // allocate and initialise a physical page
    19871980            error = vmm_get_one_ppn( vseg , vpn , &ppn );
    19881981
     
    19991992
    20001993            // define attr from vseg flags
    2001             attr = GPT_MAPPED | GPT_SMALL;
     1994            attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE;
    20021995            if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
    20031996            if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
     
    20061999
    20072000            // set PTE to local GPT
     2001            // it unlocks this PTE
    20082002            hal_gpt_set_pte( local_gpt_xp,
    20092003                             vpn,
     
    20162010
    20172011#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2018 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
    2019 printk("\n[%s] local page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2020 __FUNCTION__, vpn, ppn, attr, end_cycle );
     2012if( vpn == 0x40b )
     2013printk("\n[%s] thread[%x,%x] handled local pgfault / ppn %x / attr %x / cycle %d\n",
     2014__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
    20212015#endif
    20222016
     
    20332027        else                               
    20342028        {
     2029
     2030#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2031if( vpn == 0x40b )
     2032printk("\n[%s] thread[%x,%x] access ref gpt : local_cxy %x / ref_cxy %x / type %s\n",
     2033__FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
     2034#endif
    20352035            // build extended pointer on reference GPT
    20362036            ref_gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
    20372037
    2038             // get current PPN and attributes from reference GPT
    2039             // without locking the PTE (in case of false page fault)
    2040             hal_gpt_get_pte( ref_gpt_xp,
    2041                              vpn,
    2042                              &ref_attr,
    2043                              &ref_ppn );
    2044 
    2045             if( ref_attr & GPT_MAPPED )        // false page fault => update local GPT
     2038            // lock PTE in reference GPT and get current PPN and attributes
     2039            error = hal_gpt_lock_pte( ref_gpt_xp,
     2040                                      vpn,
     2041                                      &ref_attr,
     2042                                      &ref_ppn );
     2043            if( error )
     2044            {
     2045                printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n",
     2046                __FUNCTION__ , vpn , process->pid );
     2047       
     2048                // unlock PTE in local GPT
     2049                hal_gpt_unlock_pte( local_gpt_xp , vpn );
     2050                   
     2051                return EXCP_KERNEL_PANIC;
     2052            }
     2053
     2054#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2055if( vpn == 0x40b )
     2056printk("\n[%s] thread[%x,%x] get pte from ref gpt / attr %x / ppn %x\n",
     2057__FUNCTION__, this->process->pid, this->trdid, ref_attr, ref_ppn );
     2058#endif
     2059
     2060            if( ref_attr & GPT_MAPPED )        // false page fault
    20462061            {
    20472062                // update local GPT from reference GPT values
     2063                // this unlocks the PTE in local GPT
    20482064                hal_gpt_set_pte( local_gpt_xp,
    20492065                                 vpn,
     
    20512067                                 ref_ppn );
    20522068
     2069#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2070if( vpn == 0x40b )
     2071printk("\n[%s] thread[%x,%x] updated local gpt for a false pgfault\n",
     2072__FUNCTION__, this->process->pid, this->trdid );
     2073#endif
     2074
     2075                // unlock the PTE in reference GPT
     2076                hal_gpt_unlock_pte( ref_gpt_xp, vpn );
     2077                             
     2078#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2079if( vpn == 0x40b )
     2080printk("\n[%s] thread[%x,%x] unlock the ref gpt after a false pgfault\n",
     2081__FUNCTION__, this->process->pid, this->trdid );
     2082#endif
     2083
    20532084#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
    20542085uint32_t end_cycle = (uint32_t)hal_get_cycles();
     
    20562087
    20572088#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2058 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
    2059 printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2060 __FUNCTION__, vpn, ref_ppn, ref_attr, end_cycle );
     2089if( vpn == 0x40b )
     2090printk("\n[%s] thread[%x,%x] handled false pgfault / ppn %x / attr %x / cycle %d\n",
     2091__FUNCTION__, this->process->pid, this->trdid, ref_ppn, ref_attr, end_cycle );
    20612092#endif
    20622093
     
    20672098                return EXCP_NON_FATAL;
    20682099            }
    2069             else                            // true page fault => update both GPTs
     2100            else                            // true page fault
    20702101            {
    20712102                // allocate and initialise a physical page depending on the vseg type
     
    20772108                    __FUNCTION__ , process->pid , vpn );
    20782109
    2079                     // unlock PTE in local GPT
     2110                    // unlock PTE in local GPT and in reference GPT
    20802111                    hal_gpt_unlock_pte( local_gpt_xp , vpn );
     2112                    hal_gpt_unlock_pte( ref_gpt_xp   , vpn );
    20812113                   
    20822114                    return EXCP_KERNEL_PANIC;
    20832115                }
    20842116
    2085                 // lock PTE in reference GPT
    2086                 error = hal_gpt_lock_pte( ref_gpt_xp,
    2087                                           vpn,
    2088                                           &ref_attr,
    2089                                           &ref_ppn );
    2090                 if( error )
    2091                 {
    2092                     printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n",
    2093                     __FUNCTION__ , vpn , process->pid );
    2094        
    2095                     // unlock PTE in local GPT
    2096                     hal_gpt_unlock_pte( local_gpt_xp , vpn );
    2097                    
    2098                     return EXCP_KERNEL_PANIC;
    2099                 }
    2100 
    21012117                // define attr from vseg flags
    2102                 attr = GPT_MAPPED | GPT_SMALL;
     2118                attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE;
    21032119                if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
    21042120                if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
     
    21062122                if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
    21072123
     2124#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2125if( vpn == 0x40b )
     2126printk("\n[%s] thread[%x,%x] build a new PTE for a true pgfault\n",
     2127__FUNCTION__, this->process->pid, this->trdid );
     2128#endif
    21082129                // set PTE in reference GPT
     2130                // this unlock the PTE
    21092131                hal_gpt_set_pte( ref_gpt_xp,
    21102132                                 vpn,
     
    21122134                                 ppn );
    21132135
     2136#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2137if( vpn == 0x40b )
     2138printk("\n[%s] thread[%x,%x] set new PTE in ref gpt for a true page fault\n",
     2139__FUNCTION__, this->process->pid, this->trdid );
     2140#endif
     2141
    21142142                // set PTE in local GPT
     2143                // this unlock the PTE
    21152144                hal_gpt_set_pte( local_gpt_xp,
    21162145                                 vpn,
     
    21232152
    21242153#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2125 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
    2126 printk("\n[%s] global page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2127 __FUNCTION__, vpn, ppn, attr, end_cycle );
     2154if( vpn == 0x40b )
     2155printk("\n[%s] thread[%x,%x] handled global pgfault / ppn %x / attr %x / cycle %d\n",
     2156__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
    21282157#endif
    21292158
     
    21382167    else   // page has been locally mapped by another concurrent thread
    21392168    {
    2140         // unlock PTE in local GPT
     2169        // unlock the PTE in local GPT
    21412170        hal_gpt_unlock_pte( local_gpt_xp , vpn );
    21422171
     2172#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
     2173uint32_t end_cycle = (uint32_t)hal_get_cycles();
     2174#endif
     2175
     2176#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2177if( vpn == 0x40b )
     2178printk("\n[%s] handled by another thread / vpn %x / ppn %x / attr %x / cycle %d\n",
     2179__FUNCTION__, vpn, ppn, attr, end_cycle );
     2180#endif
     2181
     2182#if CONFIG_INSTRUMENTATION_PGFAULTS
     2183this->info.false_pgfault_nr++;
     2184this->info.false_pgfault_cost += (end_cycle - start_cycle);
     2185#endif
    21432186        return EXCP_NON_FATAL;
    21442187    }
     
    22142257
    22152258    // lock target PTE in relevant GPT (local or reference)
     2259    // and get current PTE value
    22162260    error = hal_gpt_lock_pte( gpt_xp,
    22172261                              vpn,
  • trunk/kernel/mm/vmm.h

    r629 r632  
    202202/*********************************************************************************************
    203203 * This function modifies one GPT entry identified by the <process> and <vpn> arguments
    204  * in all clusters containing a process copy.
     204 * in all clusters containing a process copy. It is used to maintain coherence in GPT
     205 * copies, using the list of copies stored in the owner process, and remote_write accesses.
    205206 * It must be called by a thread running in the process owner cluster.
    206  * It is used to update to maintain coherence in GPT copies, using the list of copies
    207  * stored in the owner process, and uses remote_write accesses.
     207 * Use the RPC_VMM_GLOBAL_UPDATE_PTE if required.
    208208 * It cannot fail, as only mapped PTE2 in GPT copies are updated.
    209209 *********************************************************************************************
  • trunk/libs/libpthread/pthread.h

    r581 r632  
    3333/*********************************************************************************************
    3434 * This function creates a new user thread. The <user_attr> argument is a pointer
    35  * on a structure containing the thread attributes, defined in thread.h file.
     35 * on a structure containing the thread attributes, defined in the shared_pthread.h file.
    3636 *********************************************************************************************
    3737 * @ trdid       : [out] buffer for created thread identifier in process.
    38  * @ user_attr   : [in]  pointer on thread attributes structure.
     38 * @ attr        : [in]  pointer on user defined attributes structure.
    3939 * @ start_func  : [in]  pointer on start function.
    4040 * @ start_args  : [in]  pointer on start function arguments.
Note: See TracChangeset for help on using the changeset viewer.