Changeset 629


Ignore:
Timestamp:
May 17, 2019, 9:27:04 AM (2 months ago)
Author:
alain
Message:

Remove the "giant" rwlock protecting the GPT, and
use the GPT_LOCKED attribute in each PTE to prevent
concurrent modifications of one GPT entry.
The version number has been incremented to 2.1.

Location:
trunk
Files:
30 edited

Legend:

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

    r625 r629  
    6161#define GPT_COW         0x0400       /*! PTE must be copied on write                   */
    6262#define GPT_SWAP        0x0800       /*! PTE swapped on disk (not implemented yet)     */
    63 #define GPT_LOCKED      0x1000       /*! PTE is protected against concurrent access    */
     63#define GPT_LOCKED      0x1000       /*! PTE is currently accessed by a thread         */
    6464
    6565/****************************************************************************************
     
    7676
    7777/****************************************************************************************
    78  * This function allocates physical memory for first level page table (PT1),
     78 * This function allocates physical memory for a local GPT,
    7979 * and initializes the GPT descriptor, creating an empty GPT.
    8080 ****************************************************************************************
     
    8787 * This function releases all memory dynamically allocated for a generic page table.
    8888 * For a multi-levels radix tree implementation, it includes all nodes in the tree.
    89  * If the calling thread is running in the reference cluster, it checks that user PTE
    90  * entries are unmapped, and releases the mapped physical pages.
    91  * The kernel pages are not released.
    9289 ****************************************************************************************
    9390 * @ gpt     : pointer on generic page table descriptor.
     
    9693
    9794/****************************************************************************************
    98  * This function prints on the kernel terminal the content of a generic page table.
    99  ****************************************************************************************
    100  * @ process : pointer on local process descriptor.
    101  ***************************************************************************************/
    102 void hal_gpt_display( struct process_s * process );
    103 
    104 /****************************************************************************************
    105  * This blocking function gets a lock on a PTE (Page Table Entry) identified
    106  * by its VPN, and returns only when the PTE has been successfully locked.
    107  * If the target PTE is not present, it allocates and maps a physical page.
    108  * A big page cannot be locked.
    109  ****************************************************************************************
    110  * @ gpt     : pointer on the generic page table
     95 * This blocking function atomically set the GPT_LOCKED attribute in a target PTE
     96 * of a remote GPT identified by the <gpt_xp> and <vpn> arguments, after checking
     97 * (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.
     101 * WARNING : Only small pages can be locked.
     102 ****************************************************************************************
     103 * @ gpt_xp  : [in]  extended pointer on the generic page table.
     104 * @ vpn     : [in]  virtual page number of the target PTE.
     105 * @ attr    : [out] local buffer for GPT attributes.
     106 * @ ppn     : [out] local buffer for physical page number.
     107 * @ returns 0 if success / return -1 if error (no memory or big page).
     108 ***************************************************************************************/
     109error_t hal_gpt_lock_pte( xptr_t     gpt_xp,
     110                          vpn_t      vpn,
     111                          uint32_t * attr,
     112                          ppn_t    * ppn );
     113
     114/****************************************************************************************
     115 * This function atomically reset the GPT_LOCKED attribute in a target PTE in a
     116 * remote GPT identified by the <gpt_xp> and <vpn> arguments.
     117 ****************************************************************************************
     118 * @ gpt_xp  : pointer on the generic page table
    111119 * @ vpn     : virtual page number of the target PTE.
    112  * @ returns 0 if success / return ENOMEM or EINVAL if error.
    113  ***************************************************************************************/
    114 error_t hal_gpt_lock_pte( gpt_t * gpt,
    115                           vpn_t   vpn );
    116 
    117 /****************************************************************************************
    118  * This function releases the lock on a PTE identified by its VPN.
    119  ****************************************************************************************
    120  * @ gpt     : pointer on the generic page table
    121  * @ vpn     : virtual page number of the target PTE.
    122  * @ returns 0 if success / returns EINVAL if error.
    123  ***************************************************************************************/
    124 error_t hal_gpt_unlock_pte( gpt_t * gpt,
    125                             vpn_t   vpn );
    126 
    127 /****************************************************************************************
    128  * This function maps in a - local or remote - GPT identified by the <gpt_xp> argument
    129  * an entry identified by the <vpn> argument, as defined by <ppn> and <attr> arguments.
    130  * It allocates physical memory for the GPT PT2, using a RPC_PMEM_GET_PAGES if required.
    131  ****************************************************************************************
    132  * @ gpt_xp    : [in] pointer on the page table
     120 ***************************************************************************************/
     121void hal_gpt_unlock_pte( xptr_t  gpt_xp,
     122                         vpn_t   vpn );
     123
     124/****************************************************************************************
     125 * This low level function maps a new PTE or modifies an existing PTE in a remote GPT
     126 * identified by the <gpt_xp> and <vpn> arguments, as defined by <ppn> and <attr> args.
     127 * This function can be used for both a small page (PTE2), and a big page (PTE1).
     128 *
     129 * WARNING : For a small page, it checks that the GPT_LOCKED attribute has been
     130 *           previously set, to prevent concurrent accesses.
     131 ****************************************************************************************
     132 * @ gpt_xp    : [in] extended pointer on the page table
    133133 * @ vpn       : [in] virtual page number
    134  * @ attr      : [in] generic attributes
     134 * @ attr      : [in] GPT attributes
    135135 * @ ppn       : [in] physical page number
    136  * @ returns 0 if success / returns ENOMEM if error
    137  ***************************************************************************************/
    138 error_t hal_gpt_set_pte( xptr_t     gpt_xp,
    139                          vpn_t      vpn,
    140                          uint32_t   attr,
    141                          ppn_t      ppn );
    142 
    143 /****************************************************************************************
    144  * This function unmaps all pages identified by the <vpn> argument from the local GPT
    145  * identified by the <gpt> argument.
    146  * It does NOT release the physical memory allocated for the unmapped pages.
    147  ****************************************************************************************
    148  * @ gpt      : [in] pointer on the local page table
    149  * @ vpn      : [in] page index in virtual space
    150  ***************************************************************************************/
    151 void hal_gpt_reset_pte( gpt_t * gpt,
     136 ***************************************************************************************/
     137void hal_gpt_set_pte( xptr_t     gpt_xp,
     138                      vpn_t      vpn,
     139                      uint32_t   attr,
     140                      ppn_t      ppn );
     141
     142/****************************************************************************************
     143 * This low level function unmaps and unlocks a PTE from a remote GPT identified by the
     144 * <gpt_xp> and <vpn> arguments. It does NOT release the allocated physical memory.
     145 * This function can be used for both a small page (PTE2), and a big page (PTE1).
     146 ****************************************************************************************
     147 * @ gpt_xp   : [in] extended pointer on the page table
     148 * @ vpn      : [in] virtual page number.
     149 ***************************************************************************************/
     150void hal_gpt_reset_pte( xptr_t  gpt_xp,
    152151                        vpn_t   vpn );
    153152
    154153/****************************************************************************************
    155  * This function returns in the <attr> and <ppn> arguments the current values stored
    156  * in a - local or remote - GPT entry, identified by the <gpt> and <vpn> arguments.
    157  ****************************************************************************************
    158  * @ gpt_xp    : [in]  extended pointer on the page table
    159  * @ vpn       : [in]  virtual page number
    160  * @ attr      : [out] generic attributes
    161  * @ ppn       : [out] physical page number
     154 * This low level function returns in the <attr> and <ppn> arguments the current values
     155 * of a PTE in a a remote GPT, identified by the <gpt> and <vpn> arguments.
     156 * This function can be used for both a small page (PTE2), and a big page (PTE1).
     157 ****************************************************************************************
     158 * @ gpt_xp    : [in]  extended pointer on the page table.
     159 * @ vpn       : [in]  virtual page number.
     160 * @ attr      : [out] local buffer for generic attributes.
     161 * @ ppn       : [out] local buffer for physical page number.
    162162 ***************************************************************************************/
    163163void hal_gpt_get_pte( xptr_t     gpt_xp,
     
    195195
    196196/****************************************************************************************
    197  * This function returns true if the MAPPED and SMALL flags are both set
    198  * for a PTE defined by <gpt> and <vpn> arguments.
    199  ****************************************************************************************
    200  * @ gpt       : [in]  pointer on the page table
    201  * @ vpn       : [in]  virtual page number
    202  * @ returns true if MAPPED is set.
    203  ***************************************************************************************/
    204 bool_t hal_gpt_pte_is_mapped( gpt_t * gpt,
    205                               vpn_t   vpn );
    206 
    207 /****************************************************************************************
    208  * This function returns true if the MAPPED, SMALL, and COW flags are all set
    209  * for a PTE defined by <gpt> and <vpn> arguments.
    210  ****************************************************************************************
    211  * @ gpt       : [in]  pointer on the page table
    212  * @ vpn       : [in]  virtual page number
    213  * @ returns true if COW is set.
    214  ***************************************************************************************/
    215 bool_t hal_gpt_pte_is_cow( gpt_t * gpt,
    216                            vpn_t   vpn );
    217 
    218 /****************************************************************************************
    219197 * This function atomically set the COW flag and reset the WRITABLE flag for all PTEs
    220198 * of a remote GPT identified by the <gpt_xp>, <vpn_base>, and <vpn_size arguments.
    221  * It does nothing if the remote PTE is not MAPPED and SMALL.
     199 * It does NOT require the GPT_LOCKED attribute to be set in the target PTE.
     200 * It does nothing if the PTE is not MAPPED and SMALL.
    222201 ****************************************************************************************
    223202 * @ gpt_xp    : [in]  extended pointer on the remote GPT.
     
    233212 * It modifies an existing entry identified by the <vpn> argument in a remote GPT
    234213 * 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.
    235215 * It cannot fail, because only MAPPED & SMALL entries are modified.
    236216 ****************************************************************************************
  • trunk/hal/generic/hal_remote.h

    r619 r629  
    22 * hal_remote.h - Generic Remote Access API definition.
    33 *
    4  * Authors   Mohamed Karaoui  (2015)
    5  *           Alain Greiner    (2016)
     4 * Authors    Alain Greiner (2016,2017,2018,2019)
    65 *
    76 * Copyright (c)  UPMC Sorbonne Universites
  • trunk/hal/tsar_mips32/core/hal_gpt.c

    r625 r629  
    3838////////////////////////////////////////////////////////////////////////////////////////
    3939
    40 #define TSAR_MMU_MAPPED         0x80000000
    41 #define TSAR_MMU_SMALL          0x40000000
    42 #define TSAR_MMU_LOCAL          0x20000000
    43 #define TSAR_MMU_REMOTE         0x10000000
    44 #define TSAR_MMU_CACHABLE       0x08000000
    45 #define TSAR_MMU_WRITABLE       0x04000000
    46 #define TSAR_MMU_EXECUTABLE     0x02000000
    47 #define TSAR_MMU_USER           0x01000000
    48 #define TSAR_MMU_GLOBAL         0x00800000
    49 #define TSAR_MMU_DIRTY          0x00400000
    50 
    51 #define TSAR_MMU_COW            0x00000001       // only for small pages
    52 #define TSAR_MMU_SWAP           0x00000004       // only for small pages
    53 #define TSAR_MMU_LOCKED         0x00000008       // only for small pages
     40#define TSAR_PTE_MAPPED         0x80000000
     41#define TSAR_PTE_SMALL          0x40000000
     42#define TSAR_PTE_LOCAL          0x20000000
     43#define TSAR_PTE_REMOTE         0x10000000
     44#define TSAR_PTE_CACHABLE       0x08000000
     45#define TSAR_PTE_WRITABLE       0x04000000
     46#define TSAR_PTE_EXECUTABLE     0x02000000
     47#define TSAR_PTE_USER           0x01000000
     48#define TSAR_PTE_GLOBAL         0x00800000
     49#define TSAR_PTE_DIRTY          0x00400000
     50
     51#define TSAR_PTE_COW            0x00000001       // only for small pages
     52#define TSAR_PTE_SWAP           0x00000004       // only for small pages
     53#define TSAR_PTE_LOCKED         0x00000008       // only for small pages
    5454
    5555////////////////////////////////////////////////////////////////////////////////////////
     
    8585    uint32_t tsar_attr = 0;
    8686
    87     if( gpt_attr & GPT_MAPPED     ) tsar_attr |= TSAR_MMU_MAPPED;
    88     if( gpt_attr & GPT_SMALL      ) tsar_attr |= TSAR_MMU_SMALL;
    89     if( gpt_attr & GPT_WRITABLE   ) tsar_attr |= TSAR_MMU_WRITABLE;
    90     if( gpt_attr & GPT_EXECUTABLE ) tsar_attr |= TSAR_MMU_EXECUTABLE;
    91     if( gpt_attr & GPT_CACHABLE   ) tsar_attr |= TSAR_MMU_CACHABLE;
    92     if( gpt_attr & GPT_USER       ) tsar_attr |= TSAR_MMU_USER;
    93     if( gpt_attr & GPT_DIRTY      ) tsar_attr |= TSAR_MMU_DIRTY;
    94     if( gpt_attr & GPT_ACCESSED   ) tsar_attr |= TSAR_MMU_LOCAL;
    95     if( gpt_attr & GPT_GLOBAL     ) tsar_attr |= TSAR_MMU_GLOBAL;
    96     if( gpt_attr & GPT_COW        ) tsar_attr |= TSAR_MMU_COW;
    97     if( gpt_attr & GPT_SWAP       ) tsar_attr |= TSAR_MMU_SWAP;
    98     if( gpt_attr & GPT_LOCKED     ) tsar_attr |= TSAR_MMU_LOCKED;
     87    if( gpt_attr & GPT_MAPPED     ) tsar_attr |= TSAR_PTE_MAPPED;
     88    if( gpt_attr & GPT_SMALL      ) tsar_attr |= TSAR_PTE_SMALL;
     89    if( gpt_attr & GPT_WRITABLE   ) tsar_attr |= TSAR_PTE_WRITABLE;
     90    if( gpt_attr & GPT_EXECUTABLE ) tsar_attr |= TSAR_PTE_EXECUTABLE;
     91    if( gpt_attr & GPT_CACHABLE   ) tsar_attr |= TSAR_PTE_CACHABLE;
     92    if( gpt_attr & GPT_USER       ) tsar_attr |= TSAR_PTE_USER;
     93    if( gpt_attr & GPT_DIRTY      ) tsar_attr |= TSAR_PTE_DIRTY;
     94    if( gpt_attr & GPT_ACCESSED   ) tsar_attr |= TSAR_PTE_LOCAL;
     95    if( gpt_attr & GPT_GLOBAL     ) tsar_attr |= TSAR_PTE_GLOBAL;
     96    if( gpt_attr & GPT_COW        ) tsar_attr |= TSAR_PTE_COW;
     97    if( gpt_attr & GPT_SWAP       ) tsar_attr |= TSAR_PTE_SWAP;
     98    if( gpt_attr & GPT_LOCKED     ) tsar_attr |= TSAR_PTE_LOCKED;
    9999
    100100    return tsar_attr;
     
    108108    uint32_t gpt_attr = 0;
    109109
    110     if( tsar_attr & TSAR_MMU_MAPPED     ) gpt_attr |= GPT_MAPPED;
    111     if( tsar_attr & TSAR_MMU_MAPPED     ) gpt_attr |= GPT_READABLE;
    112     if( tsar_attr & TSAR_MMU_SMALL      ) gpt_attr |= GPT_SMALL;
    113     if( tsar_attr & TSAR_MMU_WRITABLE   ) gpt_attr |= GPT_WRITABLE;
    114     if( tsar_attr & TSAR_MMU_EXECUTABLE ) gpt_attr |= GPT_EXECUTABLE;
    115     if( tsar_attr & TSAR_MMU_CACHABLE   ) gpt_attr |= GPT_CACHABLE;
    116     if( tsar_attr & TSAR_MMU_USER       ) gpt_attr |= GPT_USER;
    117     if( tsar_attr & TSAR_MMU_DIRTY      ) gpt_attr |= GPT_DIRTY;
    118     if( tsar_attr & TSAR_MMU_LOCAL      ) gpt_attr |= GPT_ACCESSED;
    119     if( tsar_attr & TSAR_MMU_REMOTE     ) gpt_attr |= GPT_ACCESSED;
    120     if( tsar_attr & TSAR_MMU_GLOBAL     ) gpt_attr |= GPT_GLOBAL;
    121     if( tsar_attr & TSAR_MMU_COW        ) gpt_attr |= GPT_COW;
    122     if( tsar_attr & TSAR_MMU_SWAP       ) gpt_attr |= GPT_SWAP;
    123     if( tsar_attr & TSAR_MMU_LOCKED     ) gpt_attr |= GPT_LOCKED;
     110    if( tsar_attr & TSAR_PTE_MAPPED     ) gpt_attr |= GPT_MAPPED;
     111    if( tsar_attr & TSAR_PTE_MAPPED     ) gpt_attr |= GPT_READABLE;
     112    if( tsar_attr & TSAR_PTE_SMALL      ) gpt_attr |= GPT_SMALL;
     113    if( tsar_attr & TSAR_PTE_WRITABLE   ) gpt_attr |= GPT_WRITABLE;
     114    if( tsar_attr & TSAR_PTE_EXECUTABLE ) gpt_attr |= GPT_EXECUTABLE;
     115    if( tsar_attr & TSAR_PTE_CACHABLE   ) gpt_attr |= GPT_CACHABLE;
     116    if( tsar_attr & TSAR_PTE_USER       ) gpt_attr |= GPT_USER;
     117    if( tsar_attr & TSAR_PTE_DIRTY      ) gpt_attr |= GPT_DIRTY;
     118    if( tsar_attr & TSAR_PTE_LOCAL      ) gpt_attr |= GPT_ACCESSED;
     119    if( tsar_attr & TSAR_PTE_REMOTE     ) gpt_attr |= GPT_ACCESSED;
     120    if( tsar_attr & TSAR_PTE_GLOBAL     ) gpt_attr |= GPT_GLOBAL;
     121    if( tsar_attr & TSAR_PTE_COW        ) gpt_attr |= GPT_COW;
     122    if( tsar_attr & TSAR_PTE_SWAP       ) gpt_attr |= GPT_SWAP;
     123    if( tsar_attr & TSAR_PTE_LOCKED     ) gpt_attr |= GPT_LOCKED;
    124124
    125125    return gpt_attr;
     
    184184    uint32_t   * pt2;
    185185    uint32_t     attr;
    186     vpn_t        vpn;     
    187186        kmem_req_t   req;
    188     bool_t       is_ref;
    189187
    190188#if DEBUG_HAL_GPT_DESTROY
     
    196194#endif
    197195
    198     // get pointer on calling process
    199     process_t  * process = CURRENT_THREAD->process;
    200 
    201     // compute is_ref
    202     is_ref = ( GET_CXY( process->ref_xp ) == local_cxy );
    203 
    204196    // get pointer on PT1
    205197    pt1 = (uint32_t *)gpt->ptr;
     
    209201        {
    210202        pte1 = pt1[ix1];
    211                 if( (pte1 & TSAR_MMU_MAPPED) != 0 )  // PTE1 valid
     203
     204                if( (pte1 & TSAR_PTE_MAPPED) != 0 )  // PTE1 mapped
    212205        {
    213             if( (pte1 & TSAR_MMU_SMALL) == 0 )   // BIG page
     206            if( (pte1 & TSAR_PTE_SMALL) == 0 )   // BIG page
    214207            {
    215                 if( (pte1 & TSAR_MMU_USER) != 0 )
    216                 {
    217                     // warning message
    218                     printk("\n[WARNING] in %s : found an USER BIG page / ix1 = %d\n",
    219                     __FUNCTION__ , ix1 );
    220 
    221                     // release the big physical page if reference cluster
    222                     if( is_ref )
    223                     {
    224                         vpn = (vpn_t)(ix1 << TSAR_MMU_IX2_WIDTH);
    225                         hal_gpt_reset_pte( gpt , vpn );
    226                     }
    227                 }
     208                printk("\n[WARNING] in %s : mapped big page / ix1 %x\n",
     209                __FUNCTION__ , ix1 );
    228210            }
    229             else                              // SMALL page
     211            else                             // PT2 exist
    230212            {
    231213                // get local pointer on PT2
     
    234216                pt2     = GET_PTR( base_xp );
    235217
    236                 // scan the PT2 to release all entries VALID and USER if reference cluster
    237                     if( is_ref )
     218                // scan the PT2
     219                for( ix2 = 0 ; ix2 < 512 ; ix2++ )
    238220                {
    239                     for( ix2 = 0 ; ix2 < 512 ; ix2++ )
     221                    attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
     222
     223                    if( (attr & TSAR_PTE_MAPPED) != 0 )  // PTE2 mapped
    240224                    {
    241                         attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
    242                                 if( ((attr & TSAR_MMU_MAPPED) != 0 ) && ((attr & TSAR_MMU_USER) != 0) ) 
    243                         {
    244                             // release the physical page
    245                             vpn = (vpn_t)((ix1 << TSAR_MMU_IX2_WIDTH) | ix2);
    246                             hal_gpt_reset_pte( gpt , vpn );
    247                         }
     225                        printk("\n[WARNING] in %s : mapped small page / ix1 %x / ix2 %x\n",
     226                        __FUNCTION__ , ix1, ix2 );
    248227                    }
    249228                }
    250229
    251                 // release the PT2
     230                // release the page allocated for the PT2
    252231                req.type = KMEM_PAGE;
    253232                req.ptr  = GET_PTR( ppm_base2page( XPTR(local_cxy , pt2 ) ) );
     
    271250} // end hal_gpt_destroy()
    272251
    273 ///////////////////////////////////////////
    274 void hal_gpt_display( process_t * process )
     252/*
     253
     254/////////////////////////////////////////////////////////////////////////////////////
     255// This static function can be used for debug.
     256/////////////////////////////////////////////////////////////////////////////////////
     257static void hal_gpt_display( process_t * process )
    275258{
    276259    gpt_t    * gpt;
     
    301284        {
    302285        pte1 = pt1[ix1];
    303                 if( (pte1 & TSAR_MMU_MAPPED) != 0 )
     286                if( (pte1 & TSAR_PTE_MAPPED) != 0 )
    304287        {
    305             if( (pte1 & TSAR_MMU_SMALL) == 0 )  // BIG page
     288            if( (pte1 & TSAR_PTE_SMALL) == 0 )  // BIG page
    306289            {
    307290                vpn = ix1 << 9;
     
    320303                    pte2_ppn  = TSAR_MMU_PPN_FROM_PTE2( pt2[2 * ix2 + 1] );
    321304
    322                             if( (pte2_attr & TSAR_MMU_MAPPED) != 0 )
     305                            if( (pte2_attr & TSAR_PTE_MAPPED) != 0 )
    323306                    {
    324307                        vpn = (ix1 << 9) | ix2;
     
    332315} // end hal_gpt_display()
    333316
    334 
    335 //////////////////////////////////////////
    336 error_t hal_gpt_set_pte( xptr_t    gpt_xp,
    337                          vpn_t     vpn,
    338                          uint32_t  attr,     // GPT attributes
    339                          ppn_t     ppn )
    340 {
    341     cxy_t               gpt_cxy;             // target GPT cluster
    342     gpt_t             * gpt_ptr;             // target GPT local pointer
    343     uint32_t          * pt1_ptr;             // local pointer on PT1
    344         xptr_t              pte1_xp;             // extended pointer on PT1 entry
    345         uint32_t            pte1;                // PT1 entry value if PTE1
    346 
    347         ppn_t               pt2_ppn;             // PPN of PT2
    348         uint32_t          * pt2_ptr;             // PT2 base address
    349 
    350         uint32_t            small;               // requested PTE is for a small page
    351 
    352         page_t            * page;                // pointer on new physical page descriptor
    353     xptr_t              page_xp;             // extended pointer on new page descriptor
    354 
    355     uint32_t            ix1;                 // index in PT1
    356     uint32_t            ix2;                 // index in PT2
    357 
    358     uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
    359 
    360     thread_t * this = CURRENT_THREAD;
    361 
    362     // get cluster and local pointer on GPT
    363     gpt_cxy = GET_CXY( gpt_xp );
    364     gpt_ptr = GET_PTR( gpt_xp );
    365 
    366 #if DEBUG_HAL_GPT_SET_PTE
    367 uint32_t cycle = (uint32_t)hal_get_cycles();
    368 if( DEBUG_HAL_GPT_SET_PTE < cycle )
    369 printk("\n[%s] : thread[%x,%x] enter / vpn %x / attr %x / ppn %x / cluster %x / cycle %d\n",
    370 __FUNCTION__, this->process->pid, this->trdid, vpn, attr, ppn, gpt_cxy, cycle );
    371 #endif
    372 
    373     // compute indexes in PT1 and PT2
    374     ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    375     ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    376 
    377     pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    378         small   = attr & GPT_SMALL;
    379 
    380     // compute tsar attributes from generic attributes
    381     tsar_attr = gpt2tsar( attr );
    382 
    383     // build extended pointer on PTE1 = PT1[ix1]
    384         pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     317*/
     318
     319/////////////////////////////////////////////////////////////////////////////////////////
     320// This static function check that a PTE1 entry, in the PT1 of a possibly remote GPT,
     321// identified by the <pte1_xp> argument is mapped. If this entry is not mapped,
     322// it allocates a - local or remote - PT2, updates the PTE1 value in PT1, and
     323// returns the PTE1 value in the <pte1> buffer.
     324// It uses the TSR_MMU_LOCKED attribute in PTE1 to handle possible concurrent
     325// mappings of the missing PTE1:
     326// - If the PTE1 is unmapped and unlocked => it tries to atomically lock this PTE1,
     327//   and map it if lock is successful.
     328// - If the PTE1 is unmapped but locked => it poll the PTE1 value, unti the mapping
     329//   is done by the other thread.
     330// - If the PTE1 is already mapped => it does nothing
     331// It returns an error if it cannot allocate memory fot a new PT2.
     332/////////////////////////////////////////////////////////////////////////////////////////
     333static error_t hal_gpt_allocate_pt2( xptr_t     pte1_xp,
     334                                   uint32_t * pte1_value )
     335{
     336    cxy_t      gpt_cxy;     // target GPT cluster = GET_CXY( pte1_xp );
     337    uint32_t   pte1;        // PTE1 value
     338    ppn_t      pt2_ppn;     // PPN of page containing the new PT2
     339    bool_t     atomic;
     340    page_t   * page;
     341    xptr_t     page_xp;
     342
     343    // get GPT cluster identifier
     344    gpt_cxy = GET_CXY( pte1_xp );
    385345
    386346    // get current pte1 value
    387347    pte1 = hal_remote_l32( pte1_xp );
    388348
    389         if( small == 0 )     // map a big page in PT1
    390     {
    391 
    392 // check PT1 entry not mapped
    393 assert( (pte1 == 0) , "try to set a big page in a mapped PT1 entry\n" );
    394 
    395 // check VPN aligned
    396 assert( (ix2 == 0) , "illegal vpn for a big page\n" );
    397 
    398 // check PPN aligned
    399 assert( ((ppn & 0x1FF) == 0) , "illegal ppn for a big page\n" );
    400 
    401         // set the PTE1 value in PT1
    402         pte1 = (tsar_attr  & TSAR_MMU_PTE1_ATTR_MASK) | ((ppn >> 9) & TSAR_MMU_PTE1_PPN_MASK);
    403         hal_remote_s32( pte1_xp , pte1 );
    404                 hal_fence();
    405 
    406 #if DEBUG_HAL_GPT_SET_PTE
    407 if( DEBUG_HAL_GPT_SET_PTE < cycle )
    408 printk("\n[%s] : thread[%x,%x] map PTE1 / cxy %x / ix1 %x / pt1 %x / pte1 %x\n",
    409 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
    410 #endif
    411 
    412                 return 0;
    413         }
    414     else                 // map a small page in PT1 & PT2
    415     {
    416         if( (pte1 & TSAR_MMU_MAPPED) == 0 )    // PT1 entry unmapped => map it
    417         {
     349    if( ((pte1 & TSAR_PTE_MAPPED) == 0) &&   // PTE1 unmapped and unlocked
     350        ((pte1 & TSAR_PTE_LOCKED) == 0) )    // try to allocate a new PT2
     351        {
     352        // atomically lock the PTE1 to prevent concurrent PTE1 mappings
     353        atomic = hal_remote_atomic_cas( pte1_xp,
     354                                        pte1,
     355                                        pte1 | TSAR_PTE_LOCKED );
     356
     357        if( atomic )  // PTE1 successfully locked
     358                {
    418359            // allocate one physical page for PT2
    419360            if( gpt_cxy == local_cxy )
     
    430371            }
    431372
    432             if( page == NULL )
    433             {
    434                 printk("\n[PANIC] in %s : no memory for GPT PT2 / process %x / cluster %x\n",
    435                 __FUNCTION__, this->process->pid, gpt_cxy );
    436                 return ENOMEM;
    437             }
     373            if( page == NULL ) return -1;
    438374
    439375            // get the PT2 PPN
     
    441377            pt2_ppn = ppm_page2ppn( page_xp );
    442378
    443             // build PTD1 value
    444             pte1 = TSAR_MMU_MAPPED | TSAR_MMU_SMALL | pt2_ppn;
     379            // build  PTE1 value
     380            pte1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
    445381
    446382            // set the PTD1 value in PT1
    447383            hal_remote_s32( pte1_xp , pte1 );
     384            hal_fence();
     385
     386#if DEBUG_HAL_GPT_ALLOCATE_PT2
     387thread_t * this  = CURRENT_THREAD;
     388uint32_t   cycle = (uint32_t)hal_get_cycles();
     389if( DEBUG_HAL_GPT_ALLOCATE_PT2 < cycle )
     390printk("\n[%s] : thread[%x,%x] map PTE1 / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
     391__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
     392#endif
     393        }
     394        else
     395        {
     396            // poll PTE1 until mapped by another thread
     397            while( (pte1 & TSAR_PTE_MAPPED) == 0 )  pte1 = hal_remote_l32( pte1_xp );
     398        }
     399    }
     400    else if( ((pte1 & TSAR_PTE_MAPPED) == 0) &&
     401             ((pte1 & TSAR_PTE_LOCKED) != 0) ) 
     402    {
     403        // poll PTE1 until mapped by another thread
     404        while( (pte1 & TSAR_PTE_MAPPED) == 0 )  pte1 = hal_remote_l32( pte1_xp );
     405        }
     406    else                                   // PTE1 mapped => just use it
     407    {
     408
     409#if DEBUG_HAL_GPT_ALLOCATE_PT2
     410thread_t * this  = CURRENT_THREAD;
     411uint32_t   cycle = (uint32_t)hal_get_cycles();
     412if( DEBUG_HAL_GPT_ALLOCATE_PT2 < cycle )
     413printk("\n[%s] : thread[%x,%x] PTE1 mapped / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
     414__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
     415#endif
     416
     417    }
     418
     419    *pte1_value = pte1;
     420    return 0;
     421
     422}  // end hal_gpt_allocate_pt2
     423
     424
     425
     426
     427////////////////////////////////////////////
     428error_t hal_gpt_lock_pte( xptr_t     gpt_xp,
     429                          vpn_t      vpn,
     430                          uint32_t * attr,
     431                          ppn_t    * ppn )
     432{
     433    error_t             error;
     434    uint32_t          * pt1_ptr;         // local pointer on PT1 base
     435    xptr_t              pte1_xp;         // extended pointer on PT1[x1] entry
     436        uint32_t            pte1;            // value of PT1[x1] entry
     437
     438        ppn_t               pt2_ppn;         // PPN of page containing PT2
     439    uint32_t          * pt2_ptr;         // local pointer on PT2 base
     440        xptr_t              pte2_attr_xp;    // extended pointer on PT2[ix2].attr
     441    uint32_t            pte2_attr;       // PT2[ix2].attr current value   
     442        xptr_t              pte2_ppn_xp;     // extended pointer on PT2[ix2].ppn
     443    uint32_t            pte2_ppn;        // PT2[ix2].ppn current value   
     444        bool_t              atomic;
     445
     446    // get cluster and local pointer on GPT
     447    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
     448    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
     449
     450    // get indexes in PTI & PT2
     451    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
     452    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
     453
     454    // get local pointer on PT1
     455    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     456
     457    // build extended pointer on PTE1 == PT1[ix1]
     458        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     459
     460    // get PTE1 value from PT1
     461    // allocate a new PT2 for this PTE1 if required
     462    error = hal_gpt_allocate_pt2( pte1_xp , &pte1 );
     463
     464    if( error )
     465    {
     466        printk("\n[ERROR] in %s : cannot allocate memory for PT2\n", __FUNCTION__ );
     467        return -1;
     468    }
     469
     470    if( (pte1 & TSAR_PTE_SMALL) == 0 )
     471    {
     472        printk("\n[ERROR] in %s : cannot lock a small page\n", __FUNCTION__ );
     473        return -1;
     474    }
     475
     476    // get pointer on PT2 base from PTE1
     477        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     478        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     479
     480    // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
     481    pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     482    pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
     483 
     484    // wait until PTE2 unlocked, get PTE2.attr and set lock
     485    do
     486    {
     487        // busy waiting until TSAR_MMU_LOCK == 0
     488        do
     489                {
     490                        pte2_attr = hal_remote_l32( pte2_attr_xp );
     491                }
     492        while( (pte2_attr & TSAR_PTE_LOCKED) != 0 );
     493
     494        // try to atomically set the TSAR_MMU_LOCK attribute   
     495                atomic = hal_remote_atomic_cas( pte2_attr_xp,
     496                                        pte2_attr,
     497                                        (pte2_attr | TSAR_PTE_LOCKED) );
     498        }
     499    while( atomic == 0 );
     500
     501    // get PTE2.ppn
     502    pte2_ppn = hal_remote_l32( pte2_ppn_xp );
     503
     504#if DEBUG_HAL_GPT_LOCK_PTE
     505thread_t * this  = CURRENT_THREAD;
     506uint32_t   cycle = (uint32_t)hal_get_cycles();
     507if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     508printk("\n[%s] : thread[%x,%x] locks vpn %x / attr %x / ppn %x / cluster %x / cycle %d\n",
     509__FUNCTION__, this->process->pid, this->trdid, vpn, attr, ppn, gpt_cxy, cycle );
     510#endif
     511   
     512    // return PPN and GPT attributes
     513    *ppn  = hal_remote_l32( pte2_ppn_xp ) & ((1<<TSAR_MMU_PPN_WIDTH)-1);
     514    *attr = tsar2gpt( pte2_attr );
     515        return 0;
     516
     517}  // end hal_gpt_lock_pte()
     518
     519////////////////////////////////////////
     520void hal_gpt_unlock_pte( xptr_t  gpt_xp,
     521                         vpn_t   vpn )
     522{
     523    uint32_t * pt1_ptr;         // local pointer on PT1 base
     524    xptr_t     pte1_xp;         // extended pointer on PT1[ix1]
     525        uint32_t   pte1;            // value of PT1[ix1] entry
     526
     527        ppn_t      pt2_ppn;         // PPN of page containing PT2
     528    uint32_t * pt2_ptr;         // PT2 base address
     529        uint32_t   pte2_attr_xp;    // extended pointer on PT2[ix2].attr
     530
     531        uint32_t   attr;            // PTE2 attribute
     532
     533    // get cluster and local pointer on GPT
     534    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
     535    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
     536
     537    // compute indexes in P1 and PT2
     538    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
     539    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
     540
     541    // get local pointer on PT1
     542    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     543
     544    // build extended pointer on PTE1 == PT1[ix1]
     545        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     546
     547    // get current pte1 value
     548    pte1 = hal_remote_l32( pte1_xp );
     549
     550// check PTE1 attributes
     551assert( (((pte1 & TSAR_PTE_MAPPED) != 0) && ((pte1 & TSAR_PTE_SMALL) != 0)),
     552"try to unlock a big or unmapped PTE1\n");
     553
     554    // get pointer on PT2 base from PTE1
     555        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     556        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     557
     558    // build extended pointers on PT2[ix2].attr 
     559    pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     560
     561    // get PT2[ix2].attr
     562    attr = hal_remote_l32( pte2_attr_xp );
     563
     564    // reset TSAR_MMU_LOCK attribute
     565    hal_remote_s32( pte2_attr_xp , attr & ~TSAR_PTE_LOCKED );
     566
     567#if DEBUG_HAL_GPT_LOCK_PTE
     568thread_t * this  = CURRENT_THREAD;
     569uint32_t   cycle = (uint32_t)hal_get_cycles();
     570if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
     571printk("\n[%s] : thread[%x,%x] unlocks vpn %x / attr %x / ppn %x / cluster %x / cycle %d\n",
     572__FUNCTION__, this->process->pid, this->trdid, vpn, attr, ppn, gpt_cxy, cycle );
     573#endif
     574 
     575}  // end hal_gpt_unlock_pte()
     576
     577///////////////////////////////////////
     578void hal_gpt_set_pte( xptr_t    gpt_xp,
     579                      vpn_t     vpn,
     580                      uint32_t  attr, 
     581                      ppn_t     ppn )
     582{
     583    cxy_t               gpt_cxy;             // target GPT cluster
     584    gpt_t             * gpt_ptr;             // target GPT local pointer
     585
     586    uint32_t          * pt1_ptr;             // local pointer on PT1 base
     587        xptr_t              pte1_xp;             // extended pointer on PT1 entry
     588        uint32_t            pte1;                // PT1 entry value if PTE1
     589
     590        ppn_t               pt2_ppn;             // PPN of PT2
     591        uint32_t          * pt2_ptr;             // local pointer on PT2 base
     592    xptr_t              pte2_attr_xp;        // extended pointer on PT2[ix2].attr
     593    xptr_t              pte2_ppn_xp;         // extended pointer on PT2[ix2].ppn
     594    uint32_t            pte2_attr;           // current value of PT2[ix2].attr
     595
     596    uint32_t            ix1;                 // index in PT1
     597    uint32_t            ix2;                 // index in PT2
     598
     599    uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
     600        uint32_t            small;               // requested PTE is for a small page
     601
     602    // get cluster and local pointer on GPT
     603    gpt_cxy = GET_CXY( gpt_xp );
     604    gpt_ptr = GET_PTR( gpt_xp );
     605
     606    // compute indexes in PT1 and PT2
     607    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     608    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
     609
     610    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     611        small   = attr & GPT_SMALL;
     612
     613    // compute tsar attributes from generic attributes
     614    tsar_attr = gpt2tsar( attr );
     615
     616    // build extended pointer on PTE1 = PT1[ix1]
     617        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     618
     619    // get current pte1 value
     620    pte1 = hal_remote_l32( pte1_xp );
     621
     622        if( small == 0 )  ///////////////// map a big page in PT1
     623    {
     624
     625// check PT1 entry not mapped
     626assert( (pte1 == 0) , "try to set a big page in an already mapped PTE1\n" );
     627
     628// check VPN aligned
     629assert( (ix2 == 0) , "illegal vpn for a big page\n" );
     630
     631// check PPN aligned
     632assert( ((ppn & 0x1FF) == 0) , "illegal ppn for a big page\n" );
     633
     634        // set the PTE1 value in PT1
     635        pte1 = (tsar_attr  & TSAR_MMU_PTE1_ATTR_MASK) | ((ppn >> 9) & TSAR_MMU_PTE1_PPN_MASK);
     636        hal_remote_s32( pte1_xp , pte1 );
     637                hal_fence();
    448638
    449639#if DEBUG_HAL_GPT_SET_PTE
     640thread_t * this  = CURRENT_THREAD;
     641uint32_t   cycle = (uint32_t)hal_get_cycles();
    450642if( DEBUG_HAL_GPT_SET_PTE < cycle )
    451 printk("\n[%s] : thread[%x,%x] map PTD1 / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
     643printk("\n[%s] : thread[%x,%x] map PTE1 / cxy %x / ix1 %x / pt1 %x / pte1 %x\n",
    452644__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
    453645#endif
    454         }
    455         else                                   // pt1 entry mapped => use it
    456         {
    457 
    458 #if DEBUG_HAL_GPT_SET_PTE
    459 if( DEBUG_HAL_GPT_SET_PTE < cycle )
    460 printk("\n[%s] : thread[%x,%x] get PTD1 / cxy %x / ix1 %d / pt1 %x / ptd1 %x\n",
    461 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
    462 #endif
    463 
    464         }
    465 
    466         // get PT2 base from pte1
     646
     647        }
     648    else      ///////////////// map a small page in PT2
     649    {
     650
     651// PTE1 must be mapped because PTE2 must be locked
     652assert( (pte1 & TSAR_PTE_MAPPED), "PTE1 must be mapped\n" );
     653
     654        // get PT2 base from PTE1
    467655            pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    468656            pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    469657
     658        // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
     659        pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     660        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
     661
     662        // get current value of PTE2.attr
     663        pte2_attr = hal_remote_l32( pte2_attr_xp );
     664
     665// PTE2 must be locked
     666assert( (pte2_attr & TSAR_PTE_LOCKED), "PTE2 must be locked\n" );
     667 
    470668        // set PTE2 in PT2 (in this order)
    471             hal_remote_s32( XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] ) , ppn );
     669            hal_remote_s32( pte2_ppn_xp , ppn );
    472670            hal_fence();
    473             hal_remote_s32( XPTR( gpt_cxy , &pt2_ptr[2 * ix2] ) , tsar_attr );
     671            hal_remote_s32( pte2_attr_xp , tsar_attr );
    474672            hal_fence();
    475673
    476674#if DEBUG_HAL_GPT_SET_PTE
     675thread_t * this  = CURRENT_THREAD;
     676uint32_t   cycle = (uint32_t)hal_get_cycles();
    477677if( DEBUG_HAL_GPT_SET_PTE < cycle )
    478678printk("\n[%s] : thread[%x,%x] map PTE2 / cxy %x / ix2 %x / pt2 %x / attr %x / ppn %x\n",
     
    480680#endif
    481681
    482             return 0;
    483682    }
    484683} // end of hal_gpt_set_pte()
     684
     685///////////////////////////////////////
     686void hal_gpt_reset_pte( xptr_t  gpt_xp,
     687                        vpn_t   vpn )
     688{
     689    cxy_t      gpt_cxy;        // target GPT cluster
     690    gpt_t    * gpt_ptr;        // target GPT local pointer
     691
     692    uint32_t   ix1;            // index in PT1
     693    uint32_t   ix2;            // index in PT2
     694
     695    uint32_t * pt1_ptr;        // PT1 base address
     696    xptr_t     pte1_xp;        // extended pointer on PT1[ix1]
     697    uint32_t   pte1;           // PT1 entry value
     698
     699    ppn_t      pt2_ppn;        // PPN of PT2
     700    uint32_t * pt2_ptr;        // PT2 base address
     701    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
     702    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
     703    uint32_t   pte2_attr;      // current value of PT2[ix2].attr
     704
     705    // get cluster and local pointer on GPT
     706    gpt_cxy = GET_CXY( gpt_xp );
     707    gpt_ptr = GET_PTR( gpt_xp );
     708
     709    // get ix1 & ix2 indexes
     710    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     711    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
     712
     713    // get local pointer on PT1 base
     714    pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     715
     716    // build extended pointer on PTE1 = PT1[ix1]
     717        pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     718
     719    // get current PTE1 value
     720    pte1 = hal_remote_l32( pte1_xp );
     721
     722        if( (pte1 & TSAR_PTE_MAPPED) == 0 )     // PTE1 unmapped => do nothing
     723        {
     724                return;
     725        }
     726
     727        if( (pte1 & TSAR_PTE_SMALL) == 0 )      // it's a PTE1 => unmap it from PT1
     728        {
     729        hal_remote_s32( pte1_xp , 0 );
     730            hal_fence();
     731
     732#if DEBUG_HAL_GPT_RESET_PTE
     733thread_t * this  = CURRENT_THREAD;
     734uint32_t   cycle = (uint32_t)hal_get_cycles();
     735if( DEBUG_HAL_GPT_RESET_PTE < cycle )
     736printk("\n[%s] : thread[%x,%x] unmap PTE1 / cxy %x / vpn %x / ix1 %x\n",
     737__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix1 );
     738#endif
     739
     740        return;
     741        }
     742    else                                    // it's a PTE2 => unmap it from PT2
     743    {
     744        // compute PT2 base address
     745        pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     746        pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     747       
     748        // build extended pointer on PT2[ix2].attr and PT2[ix2].ppn
     749        pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     750        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
     751
     752        // unmap the PTE2
     753        hal_remote_s32( pte2_attr_xp , 0 );
     754            hal_fence();       
     755        hal_remote_s32( pte2_ppn_xp  , 0 );
     756            hal_fence();       
     757
     758#if DEBUG_HAL_GPT_RESET_PTE
     759thread_t * this  = CURRENT_THREAD;
     760uint32_t   cycle = (uint32_t)hal_get_cycles();
     761if( DEBUG_HAL_GPT_RESET_PTE < cycle )
     762printk("\n[%s] : thread[%x,%x] unmap PTE2 / cxy %x / vpn %x / ix2 %x\n",
     763__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix2 );
     764#endif
     765
     766        return;
     767    }
     768}  // end hal_gpt_reset_pte()
    485769
    486770////////////////////////////////////////
     
    490774                      ppn_t    * ppn )
    491775{
    492     uint32_t * pt1;
    493     uint32_t   pte1;
    494 
    495     uint32_t * pt2;
    496     ppn_t      pt2_ppn;
     776    uint32_t * pt1;            // local pointer on PT1 base
     777    uint32_t   pte1;           // PTE1 value
     778
     779    uint32_t * pt2;            // local pointer on PT2 base
     780    ppn_t      pt2_ppn;        // PPN of page containing the PT2
     781    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
     782    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
     783    uint32_t   pte2_attr;      // current value of PT2[ix2].attr
     784    ppn_t      pte2_ppn;       // current value of PT2[ix2].ppn
    497785
    498786    // get cluster and local pointer on GPT
     
    505793
    506794    // get PT1 base
    507     pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     795    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    508796   
    509797    // get pte1
     
    511799
    512800    // check PTE1 mapped
    513         if( (pte1 & TSAR_MMU_MAPPED) == 0 )   // PT1 entry not present
     801        if( (pte1 & TSAR_PTE_MAPPED) == 0 )   // PTE1 unmapped
    514802        {
    515803                *attr = 0;
     
    519807
    520808    // access GPT
    521         if( (pte1 & TSAR_MMU_SMALL) == 0 )     // it's a PTE1
     809        if( (pte1 & TSAR_PTE_SMALL) == 0 )     // it's a PTE1
    522810        {
    523811        // get PPN & ATTR from PT1
     
    525813        *ppn  = TSAR_MMU_PPN_FROM_PTE1( pte1 ) | (vpn & ((1<<TSAR_MMU_IX2_WIDTH)-1));
    526814        }
    527     else                                  // it's a PTD1
     815    else                                  // it's a PTE2
    528816    {
    529817        // compute PT2 base address
     
    531819        pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    532820
    533         // get PPN & ATTR from PT2
    534         *ppn  = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2+1] ) ) & ((1<<TSAR_MMU_PPN_WIDTH)-1);
    535         *attr = tsar2gpt( hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) ) );
     821        // build extended pointer on PT2[ix2].attr and PT2[ix2].ppn
     822        pte2_attr_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
     823        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2[2 * ix2 + 1] );
     824
     825        // get current value of PTE2.attr & PTE2.ppn
     826        pte2_attr = hal_remote_l32( pte2_attr_xp );
     827        pte2_ppn  = hal_remote_l32( pte2_ppn_xp );
     828
     829        // return PPN & GPT attributes
     830        *ppn  = pte2_ppn & ((1<<TSAR_MMU_PPN_WIDTH)-1);
     831        *attr = tsar2gpt( pte2_attr );
    536832    }
    537833} // end hal_gpt_get_pte()
    538834
    539 ////////////////////////////////////
    540 void hal_gpt_reset_pte( gpt_t * gpt,
    541                         vpn_t   vpn )
    542 {
    543     uint32_t * pt1;         // PT1 base address
    544     uint32_t   pte1;        // PT1 entry value
    545 
    546     ppn_t      pt2_ppn;     // PPN of PT2
    547     uint32_t * pt2;         // PT2 base address
    548 
    549     // get ix1 & ix2 indexes
    550     uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    551     uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    552 
    553     // get PTE1 value
    554         pt1      = gpt->ptr;
    555     pte1     = pt1[ix1];
    556 
    557         if( (pte1 & TSAR_MMU_MAPPED) == 0 )   // PT1 entry not present
    558         {
    559                 return;
    560         }
    561 
    562         if( (pte1 & TSAR_MMU_SMALL) == 0 )      // it's a PTE1
    563         {
    564         // unmap the big page
    565         pt1[ix1] = 0;
    566             hal_fence();
    567 
    568         return;
    569         }
    570     else                                   // it's a PTD1
    571     {
    572         // compute PT2 base address
    573         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    574         pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     835
     836///////////////////////////////////////////
     837error_t hal_gpt_pte_copy( gpt_t  * dst_gpt,
     838                          vpn_t    dst_vpn,
     839                          xptr_t   src_gpt_xp,
     840                          vpn_t    src_vpn,
     841                          bool_t   cow,
     842                          ppn_t  * ppn,
     843                          bool_t * mapped )
     844{
     845    uint32_t     src_ix1;   // index in SRC PT1
     846    uint32_t     src_ix2;   // index in SRC PT2
     847
     848    uint32_t     dst_ix1;   // index in DST PT1
     849    uint32_t     dst_ix2;   // index in DST PT2
     850
     851    cxy_t        src_cxy;   // SRC GPT cluster
     852    gpt_t      * src_gpt;   // SRC GPT local pointer
     853
     854        uint32_t   * src_pt1;   // local pointer on SRC PT1
     855        uint32_t   * dst_pt1;   // local pointer on DST PT1
     856    uint32_t   * src_pt2;   // local pointer on SRC PT2
     857    uint32_t   * dst_pt2;   // local pointer on DST PT2
     858
     859        kmem_req_t   req;       // for PT2 allocation
     860
     861    uint32_t     src_pte1;
     862    uint32_t     dst_pte1;
     863
     864    uint32_t     src_pte2_attr;
     865    uint32_t     src_pte2_ppn;
     866
     867    page_t     * page;
     868    xptr_t       page_xp;
     869
     870    ppn_t        src_pt2_ppn;
     871    ppn_t        dst_pt2_ppn;
     872
     873    // get remote src_gpt cluster and local pointer
     874    src_cxy = GET_CXY( src_gpt_xp );
     875    src_gpt = GET_PTR( src_gpt_xp );
     876
     877#if DEBUG_HAL_GPT_COPY
     878uint32_t   cycle = (uint32_t)hal_get_cycles();
     879thread_t * this  = CURRENT_THREAD;
     880if( DEBUG_HAL_GPT_COPY < cycle )
     881printk("\n[%s] : thread[%x,%x] enter / src_cxy %x / dst_cxy %x / cycle %d\n",
     882__FUNCTION__, this->process->pid, this->trdid, src_cxy, local_cxy, cycle );
     883#endif
     884
     885    // get remote src_gpt cluster and local pointer
     886    src_cxy = GET_CXY( src_gpt_xp );
     887    src_gpt = GET_PTR( src_gpt_xp );
     888
     889    // get remote src_pt1 and local dst_pt1
     890    src_pt1 = (uint32_t *)hal_remote_lpt( XPTR( src_cxy , &src_gpt->ptr ) );
     891    dst_pt1 = (uint32_t *)dst_gpt->ptr;
     892
     893    // check src_pt1 and dst_pt1 existence
     894    assert( (src_pt1 != NULL) , "src_pt1 does not exist\n");
     895    assert( (dst_pt1 != NULL) , "dst_pt1 does not exist\n");
     896
     897    // compute SRC indexes
     898    src_ix1 = TSAR_MMU_IX1_FROM_VPN( src_vpn );
     899    src_ix2 = TSAR_MMU_IX2_FROM_VPN( src_vpn );
     900
     901    // compute DST indexes
     902    dst_ix1 = TSAR_MMU_IX1_FROM_VPN( dst_vpn );
     903    dst_ix2 = TSAR_MMU_IX2_FROM_VPN( dst_vpn );
     904
     905    // get src_pte1
     906    src_pte1 = hal_remote_l32( XPTR( src_cxy , &src_pt1[src_ix1] ) );
     907
     908    // do nothing if src_pte1 not MAPPED or not SMALL
     909        if( (src_pte1 & TSAR_PTE_MAPPED) && (src_pte1 & TSAR_PTE_SMALL) )   
     910    {
     911        // get dst_pt1 entry
     912        dst_pte1 = dst_pt1[dst_ix1];
     913
     914        // map dst_pte1 if required
     915        if( (dst_pte1 & TSAR_PTE_MAPPED) == 0 )
     916        {
     917            // allocate one physical page for a new PT2
     918                req.type  = KMEM_PAGE;
     919                req.size  = 0;                     // 1 small page
     920                req.flags = AF_KERNEL | AF_ZERO;
     921                page = (page_t *)kmem_alloc( &req );
     922
     923            if( page == NULL )
     924            {
     925                        printk("\n[ERROR] in %s : cannot allocate PT2\n", __FUNCTION__ );
     926                return -1;
     927            }
     928
     929            // build extended pointer on page descriptor
     930            page_xp = XPTR( local_cxy , page );
     931
     932            // get PPN for this new PT2
     933            dst_pt2_ppn = (ppn_t)ppm_page2ppn( page_xp );
     934
     935            // build the new dst_pte1
     936            dst_pte1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | dst_pt2_ppn;
     937
     938            // register it in DST_GPT
     939            dst_pt1[dst_ix1] = dst_pte1;
     940        }
     941
     942        // get pointer on src_pt2
     943        src_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( src_pte1 );
     944        src_pt2     = GET_PTR( ppm_ppn2base( src_pt2_ppn ) );
     945
     946        // get pointer on dst_pt2
     947        dst_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( dst_pte1 );
     948        dst_pt2     = GET_PTR( ppm_ppn2base( dst_pt2_ppn ) );
     949
     950        // get attr and ppn from SRC_PT2
     951        src_pte2_attr = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2]     ) );
     952        src_pte2_ppn  = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2 + 1] ) );
     953
     954        // do nothing if src_pte2 not MAPPED
     955        if( (src_pte2_attr & TSAR_PTE_MAPPED) != 0 ) 
     956        {
     957            // set PPN in DST PTE2
     958            dst_pt2[2 * dst_ix2 + 1] = src_pte2_ppn;
     959                       
     960            // set attributes in DST PTE2         
     961            if( cow && (src_pte2_attr & TSAR_PTE_WRITABLE) )
     962            {
     963                dst_pt2[2 * dst_ix2] = (src_pte2_attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
     964            }
     965            else
     966            {
     967                dst_pt2[2 * dst_ix2] = src_pte2_attr;
     968            }
     969
     970            // return "successfully copied"
     971            *mapped = true;
     972            *ppn    = src_pte2_ppn;
    575973       
    576         // unmap the small page
    577             pt2[2*ix2]   = 0;         
    578             hal_fence();       
    579 
    580         return;
    581     }
    582 }  // end hal_gpt_reset_pte()
     974#if DEBUG_HAL_GPT_COPY
     975cycle = (uint32_t)hal_get_cycles;
     976if( DEBUG_HAL_GPT_COPY < cycle )
     977printk("\n[%s] : thread[%x,%x] exit / copy done for src_vpn %x / dst_vpn %x / cycle %d\n",
     978__FUNCTION__, this->process->pid, this->trdid, src_vpn, dst_vpn, cycle );
     979#endif
     980
     981            hal_fence();
     982
     983            return 0;
     984        }   // end if PTE2 mapped
     985    }   // end if PTE1 mapped
     986
     987    // return "nothing done"
     988    *mapped = false;
     989    *ppn    = 0;
     990   
     991#if DEBUG_HAL_GPT_COPY
     992cycle = (uint32_t)hal_get_cycles;
     993if( DEBUG_HAL_GPT_COPY < cycle )
     994printk("\n[%s] : thread[%x,%x] exit / nothing done / cycle %d\n",
     995__FUNCTION__, this->process->pid, this->trdid, cycle );
     996#endif
     997
     998    hal_fence();
     999
     1000    return 0;
     1001
     1002}  // end hal_gpt_pte_copy()
     1003
     1004/////////////////////////////////////////
     1005void hal_gpt_set_cow( xptr_t  gpt_xp,
     1006                      vpn_t   vpn_base,
     1007                      vpn_t   vpn_size )
     1008{
     1009    cxy_t      gpt_cxy;
     1010    gpt_t    * gpt_ptr;
     1011
     1012    vpn_t      vpn;
     1013
     1014    uint32_t   ix1;
     1015    uint32_t   ix2;
     1016
     1017    uint32_t * pt1;
     1018    uint32_t   pte1;
     1019
     1020    uint32_t * pt2;
     1021    ppn_t      pt2_ppn;
     1022    uint32_t   attr;
     1023
     1024    // get GPT cluster and local pointer
     1025    gpt_cxy = GET_CXY( gpt_xp );
     1026    gpt_ptr = GET_PTR( gpt_xp );
     1027
     1028    // get local PT1 pointer
     1029    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     1030
     1031    // loop on pages
     1032    for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     1033    {
     1034        ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     1035        ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
     1036
     1037        // get PTE1 value
     1038        pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
     1039
     1040        // only MAPPED & SMALL PTEs are modified
     1041            if( (pte1 & TSAR_PTE_MAPPED) && (pte1 & TSAR_PTE_SMALL) )
     1042        {
     1043            // compute PT2 base address
     1044            pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     1045            pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     1046
     1047            assert( (GET_CXY( ppm_ppn2base( pt2_ppn ) ) == gpt_cxy ),
     1048            "PT2 and PT1 must be in the same cluster\n");
     1049 
     1050            // get current PTE2 attributes
     1051            attr = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) );
     1052
     1053            // only MAPPED PTEs are modified       
     1054            if( attr & TSAR_PTE_MAPPED )
     1055            {
     1056                attr = (attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
     1057                hal_remote_s32( XPTR( gpt_cxy , &pt2[2*ix2] ) , attr );
     1058            }
     1059        }
     1060    }   // end loop on pages
     1061
     1062}  // end hal_gpt_set_cow()
     1063
     1064//////////////////////////////////////////
     1065void hal_gpt_update_pte( xptr_t    gpt_xp,
     1066                         vpn_t     vpn,
     1067                         uint32_t  attr,     // generic GPT attributes
     1068                         ppn_t     ppn )
     1069{
     1070    uint32_t          * pt1;                 // PT1 base addres
     1071        uint32_t            pte1;                // PT1 entry value
     1072
     1073        ppn_t               pt2_ppn;             // PPN of PT2
     1074        uint32_t          * pt2;                 // PT2 base address
     1075
     1076    uint32_t            ix1;                 // index in PT1
     1077    uint32_t            ix2;                 // index in PT2
     1078
     1079    uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
     1080
     1081    // check attr argument MAPPED and SMALL
     1082    if( (attr & GPT_MAPPED) == 0 )  return;
     1083    if( (attr & GPT_SMALL ) == 0 )  return;
     1084
     1085    // get cluster and local pointer on remote GPT
     1086    cxy_t   gpt_cxy = GET_CXY( gpt_xp );
     1087    gpt_t * gpt_ptr = GET_PTR( gpt_xp );
     1088
     1089    // compute indexes in PT1 and PT2
     1090    ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     1091    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
     1092
     1093    // get PT1 base
     1094    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     1095
     1096    // compute tsar_attr from generic attributes
     1097    tsar_attr = gpt2tsar( attr );
     1098
     1099    // get PTE1 value
     1100    pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
     1101
     1102    if( (pte1 & TSAR_PTE_MAPPED) == 0 ) return;
     1103    if( (pte1 & TSAR_PTE_SMALL ) == 0 ) return;
     1104
     1105    // get PT2 base from PTE1
     1106    pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     1107    pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     1108
     1109    // set PTE2 in this order
     1110        hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2 + 1] ) , ppn );
     1111        hal_fence();
     1112        hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2]     ) , tsar_attr );
     1113        hal_fence();
     1114
     1115} // end hal_gpt_update_pte()
     1116
     1117
    5831118
    5841119
     
    6161151        pte1 = pt1[ix1]
    6171152
    618             if( (pte1 & TSAR_MMU_MAPPED) == 0 )     // PT1[ix1] unmapped
     1153            if( (pte1 & TSAR_PTE_MAPPED) == 0 )     // PT1[ix1] unmapped
    6191154        {
    6201155            // update vpn (next big page)
    6211156            (vpn = ix1 + 1) << 9;
    6221157        }
    623             if( (pte1 & TSAR_MMU_SMALL) == 0 )      // it's a PTE1 (big page)
     1158            if( (pte1 & TSAR_PTE_SMALL) == 0 )      // it's a PTE1 (big page)
    6241159            {
    6251160            // unmap the big page
     
    6501185*/
    6511186
    652 //////////////////////////////////////
    653 error_t hal_gpt_lock_pte( gpt_t * gpt,
    654                           vpn_t   vpn )
    655 {
    656     uint32_t          * pt1;             // PT1 base address
    657         volatile uint32_t * pte1_ptr;        // address of PT1 entry
    658         uint32_t            pte1;            // value of PT1 entry
    659 
    660     uint32_t          * pt2;             // PT2 base address
    661         ppn_t               pt2_ppn;         // PPN of PT2 page if missing PT2
    662         volatile uint32_t * pte2_ptr;        // address of PT2 entry
    663 
    664         uint32_t            attr;
    665         bool_t              atomic;
    666     page_t            * page;
    667     xptr_t              page_xp;
    668 
    669     uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
    670     uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
    671 
    672     // get the PTE1 value
    673     pt1       = gpt->ptr;
    674         pte1_ptr  = &pt1[ix1];
    675         pte1      = *pte1_ptr;
    676 
    677     // If present, the page must be small
    678         if( ((pte1 & TSAR_MMU_MAPPED) != 0) && ((pte1 & TSAR_MMU_SMALL) == 0) )
    679     {
    680         printk("\n[ERROR] in %s : try to lock a big page / PT1[%d] = %x\n",
    681                __FUNCTION__ , ix1 , pte1 );
    682                 return EINVAL;
    683     }
    684 
    685         if( (pte1 & TSAR_MMU_MAPPED) == 0 )  // missing PT1 entry   
    686         {
    687         // allocate one physical page for PT2
    688             kmem_req_t req;
    689             req.type  = KMEM_PAGE;
    690             req.size  = 0;                     // 1 small page
    691             req.flags = AF_KERNEL | AF_ZERO;
    692             page = (page_t *)kmem_alloc( &req );
    693 
    694         if( page == NULL )
    695         {
    696                         printk("\n[ERROR] in %s : try to set a small page but cannot allocate PT2\n",
    697                       __FUNCTION__ );
    698             return ENOMEM;
    699         }
    700 
    701         page_xp = XPTR( local_cxy , page );
    702         pt2_ppn = ppm_page2ppn( page_xp );
    703         pt2     = GET_PTR( ppm_page2base( page_xp ) );
    704 
    705         // try to set the PT1 entry
    706                 do
    707                 {
    708                         atomic = hal_atomic_cas( (void*)pte1_ptr , 0 ,
    709                                      TSAR_MMU_MAPPED | TSAR_MMU_SMALL | pt2_ppn );
    710                 }
    711         while( (atomic == false) && (*pte1_ptr == 0) );
    712 
    713                 if( atomic == false )  // missing PT2 has been allocate by another core
    714                 {
    715             // release the allocated page
    716                         ppm_free_pages( page );
    717 
    718             // read again the PTE1     
    719                         pte1 = *pte1_ptr;
    720 
    721             // get the PT2 base address
    722                         pt2_ppn = TSAR_MMU_PPN_FROM_PTE1( pte1 );
    723                         pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    724                 }
    725         }
    726     else
    727     {
    728         // This valid entry must be a PTD1
    729         if( (pte1 & TSAR_MMU_SMALL) == 0 )
    730         {
    731                         printk("\n[ERROR] in %s : set a small page in a big PT1 entry / PT1[%d] = %x\n",
    732                     __FUNCTION__ , ix1 , pte1 );
    733             return EINVAL;
    734         }
    735 
    736         // compute PPN of PT2 base
    737                 pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    738 
    739         // compute pointer on PT2 base
    740             pt2 = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    741     }
    742    
    743     // from here we have the PT2 pointer
    744    
    745     // compute pointer on PTE2
    746     pte2_ptr = &pt2[2 * ix2];
    747 
    748     // try to atomically lock the PTE2 until success
    749         do
    750     {
    751         // busy waiting until TSAR_MMU_LOCK == 0
    752         do
    753                 {
    754                         attr = *pte2_ptr;
    755                         hal_rdbar();
    756                 }
    757         while( (attr & TSAR_MMU_LOCKED) != 0 );
    758 
    759                 atomic = hal_atomic_cas( (void*)pte2_ptr, attr , (attr | TSAR_MMU_LOCKED) );
    760         }
    761     while( atomic == 0 );
    762 
    763         return 0;
    764 
    765 }  // end hal_gpt_lock_pte()
    766 
    767 ////////////////////////////////////////
    768 error_t hal_gpt_unlock_pte( gpt_t * gpt,
    769                             vpn_t   vpn )
    770 {
    771     uint32_t * pt1;             // PT1 base address
    772         uint32_t   pte1;            // value of PT1 entry
    773 
    774     uint32_t * pt2;             // PT2 base address
    775         ppn_t      pt2_ppn;         // PPN of PT2 page if missing PT2
    776         uint32_t * pte2_ptr;        // address of PT2 entry
    777 
    778         uint32_t   attr;            // PTE2 attribute
    779 
    780     // compute indexes in P1 and PT2
    781     uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
    782     uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
    783 
    784     // get pointer on PT1 base
    785     pt1  = (uint32_t*)gpt->ptr;
    786 
    787     // get PTE1
    788     pte1 = pt1[ix1];
    789 
    790     // check PTE1 present and small page
    791     if( ((pte1 & TSAR_MMU_MAPPED) == 0) || ((pte1 & TSAR_MMU_SMALL) == 0) )
    792     {
    793         printk("\n[ERROR] in %s : try to unlock a big or undefined page / PT1[%d] = %x\n",
    794                  __FUNCTION__ , ix1 , pte1 );
    795         return EINVAL;
    796     }
    797 
    798     // get pointer on PT2 base
    799     pt2_ppn = TSAR_MMU_PPN_FROM_PTE1( pte1 );
    800     pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    801  
    802     // get pointer on PTE2
    803         pte2_ptr = &pt2[2 * ix2];
    804 
    805     // get PTE2_ATTR
    806         attr = *pte2_ptr;
    807 
    808     // check PTE2 present and locked
    809     if( ((attr & TSAR_MMU_MAPPED) == 0) || ((attr & TSAR_MMU_LOCKED) == 0) )
    810     {
    811         printk("\n[ERROR] in %s : unlock an unlocked/unmapped page / PT1[%d] = %x\n",
    812                  __FUNCTION__ , ix1 , pte1 );
    813         return EINVAL;
    814     }
    815 
    816     // reset GPT_LOCK
    817         *pte2_ptr = attr & ~TSAR_MMU_LOCKED;
    818 
    819         return 0;
    820 
    821 }  // end hal_gpt_unlock_pte()
    822 
    823 ///////////////////////////////////////////
    824 error_t hal_gpt_pte_copy( gpt_t  * dst_gpt,
    825                           vpn_t    dst_vpn,
    826                           xptr_t   src_gpt_xp,
    827                           vpn_t    src_vpn,
    828                           bool_t   cow,
    829                           ppn_t  * ppn,
    830                           bool_t * mapped )
    831 {
    832     uint32_t     src_ix1;   // index in SRC PT1
    833     uint32_t     src_ix2;   // index in SRC PT2
    834 
    835     uint32_t     dst_ix1;   // index in DST PT1
    836     uint32_t     dst_ix2;   // index in DST PT2
    837 
    838     cxy_t        src_cxy;   // SRC GPT cluster
    839     gpt_t      * src_gpt;   // SRC GPT local pointer
    840 
    841         uint32_t   * src_pt1;   // local pointer on SRC PT1
    842         uint32_t   * dst_pt1;   // local pointer on DST PT1
    843     uint32_t   * src_pt2;   // local pointer on SRC PT2
    844     uint32_t   * dst_pt2;   // local pointer on DST PT2
    845 
    846         kmem_req_t   req;       // for PT2 allocation
    847 
    848     uint32_t     src_pte1;
    849     uint32_t     dst_pte1;
    850 
    851     uint32_t     src_pte2_attr;
    852     uint32_t     src_pte2_ppn;
    853 
    854     page_t     * page;
    855     xptr_t       page_xp;
    856 
    857     ppn_t        src_pt2_ppn;
    858     ppn_t        dst_pt2_ppn;
    859 
    860     // get remote src_gpt cluster and local pointer
    861     src_cxy = GET_CXY( src_gpt_xp );
    862     src_gpt = GET_PTR( src_gpt_xp );
    863 
    864 #if DEBUG_HAL_GPT_COPY
    865 uint32_t   cycle = (uint32_t)hal_get_cycles();
    866 thread_t * this  = CURRENT_THREAD;
    867 if( DEBUG_HAL_GPT_COPY < cycle )
    868 printk("\n[%s] : thread[%x,%x] enter / src_cxy %x / dst_cxy %x / cycle %d\n",
    869 __FUNCTION__, this->process->pid, this->trdid, src_cxy, local_cxy, cycle );
    870 #endif
    871 
    872     // get remote src_gpt cluster and local pointer
    873     src_cxy = GET_CXY( src_gpt_xp );
    874     src_gpt = GET_PTR( src_gpt_xp );
    875 
    876     // get remote src_pt1 and local dst_pt1
    877     src_pt1 = (uint32_t *)hal_remote_lpt( XPTR( src_cxy , &src_gpt->ptr ) );
    878     dst_pt1 = (uint32_t *)dst_gpt->ptr;
    879 
    880     // check src_pt1 and dst_pt1 existence
    881     assert( (src_pt1 != NULL) , "src_pt1 does not exist\n");
    882     assert( (dst_pt1 != NULL) , "dst_pt1 does not exist\n");
    883 
    884     // compute SRC indexes
    885     src_ix1 = TSAR_MMU_IX1_FROM_VPN( src_vpn );
    886     src_ix2 = TSAR_MMU_IX2_FROM_VPN( src_vpn );
    887 
    888     // compute DST indexes
    889     dst_ix1 = TSAR_MMU_IX1_FROM_VPN( dst_vpn );
    890     dst_ix2 = TSAR_MMU_IX2_FROM_VPN( dst_vpn );
    891 
    892     // get src_pte1
    893     src_pte1 = hal_remote_l32( XPTR( src_cxy , &src_pt1[src_ix1] ) );
    894 
    895     // do nothing if src_pte1 not MAPPED or not SMALL
    896         if( (src_pte1 & TSAR_MMU_MAPPED) && (src_pte1 & TSAR_MMU_SMALL) )   
    897     {
    898         // get dst_pt1 entry
    899         dst_pte1 = dst_pt1[dst_ix1];
    900 
    901         // map dst_pte1 if required
    902         if( (dst_pte1 & TSAR_MMU_MAPPED) == 0 )
    903         {
    904             // allocate one physical page for a new PT2
    905                 req.type  = KMEM_PAGE;
    906                 req.size  = 0;                     // 1 small page
    907                 req.flags = AF_KERNEL | AF_ZERO;
    908                 page = (page_t *)kmem_alloc( &req );
    909 
    910             if( page == NULL )
    911             {
    912                         printk("\n[ERROR] in %s : cannot allocate PT2\n", __FUNCTION__ );
    913                 return -1;
    914             }
    915 
    916             // build extended pointer on page descriptor
    917             page_xp = XPTR( local_cxy , page );
    918 
    919             // get PPN for this new PT2
    920             dst_pt2_ppn = (ppn_t)ppm_page2ppn( page_xp );
    921 
    922             // build the new dst_pte1
    923             dst_pte1 = TSAR_MMU_MAPPED | TSAR_MMU_SMALL | dst_pt2_ppn;
    924 
    925             // register it in DST_GPT
    926             dst_pt1[dst_ix1] = dst_pte1;
    927         }
    928 
    929         // get pointer on src_pt2
    930         src_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( src_pte1 );
    931         src_pt2     = GET_PTR( ppm_ppn2base( src_pt2_ppn ) );
    932 
    933         // get pointer on dst_pt2
    934         dst_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( dst_pte1 );
    935         dst_pt2     = GET_PTR( ppm_ppn2base( dst_pt2_ppn ) );
    936 
    937         // get attr and ppn from SRC_PT2
    938         src_pte2_attr = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2]     ) );
    939         src_pte2_ppn  = hal_remote_l32( XPTR( src_cxy , &src_pt2[2 * src_ix2 + 1] ) );
    940 
    941         // do nothing if src_pte2 not MAPPED
    942         if( (src_pte2_attr & TSAR_MMU_MAPPED) != 0 ) 
    943         {
    944             // set PPN in DST PTE2
    945             dst_pt2[2 * dst_ix2 + 1] = src_pte2_ppn;
    946                        
    947             // set attributes in DST PTE2         
    948             if( cow && (src_pte2_attr & TSAR_MMU_WRITABLE) )
    949             {
    950                 dst_pt2[2 * dst_ix2] = (src_pte2_attr | TSAR_MMU_COW) & (~TSAR_MMU_WRITABLE);
    951             }
    952             else
    953             {
    954                 dst_pt2[2 * dst_ix2] = src_pte2_attr;
    955             }
    956 
    957             // return "successfully copied"
    958             *mapped = true;
    959             *ppn    = src_pte2_ppn;
    960        
    961 #if DEBUG_HAL_GPT_COPY
    962 cycle = (uint32_t)hal_get_cycles;
    963 if( DEBUG_HAL_GPT_COPY < cycle )
    964 printk("\n[%s] : thread[%x,%x] exit / copy done for src_vpn %x / dst_vpn %x / cycle %d\n",
    965 __FUNCTION__, this->process->pid, this->trdid, src_vpn, dst_vpn, cycle );
    966 #endif
    967 
    968             hal_fence();
    969 
    970             return 0;
    971         }   // end if PTE2 mapped
    972     }   // end if PTE1 mapped
    973 
    974     // return "nothing done"
    975     *mapped = false;
    976     *ppn    = 0;
    977    
    978 #if DEBUG_HAL_GPT_COPY
    979 cycle = (uint32_t)hal_get_cycles;
    980 if( DEBUG_HAL_GPT_COPY < cycle )
    981 printk("\n[%s] : thread[%x,%x] exit / nothing done / cycle %d\n",
    982 __FUNCTION__, this->process->pid, this->trdid, cycle );
    983 #endif
    984 
    985     hal_fence();
    986 
    987     return 0;
    988 
    989 }  // end hal_gpt_pte_copy()
    990 
    991 //////////////////////////////////////////
    992 bool_t hal_gpt_pte_is_mapped( gpt_t * gpt,
    993                               vpn_t   vpn )
    994 {
    995     uint32_t * pt1;
    996     uint32_t   pte1;
    997     uint32_t   pte2_attr;
    998 
    999     uint32_t * pt2;
    1000     ppn_t      pt2_ppn;
    1001 
    1002     uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1003     uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1004 
    1005     // get PTE1 value
    1006         pt1  = gpt->ptr;
    1007     pte1 = pt1[ix1];
    1008 
    1009         if( (pte1 & TSAR_MMU_MAPPED) == 0 ) return false;
    1010 
    1011         if( (pte1 & TSAR_MMU_SMALL) == 0 ) return false;
    1012 
    1013     // compute PT2 base address
    1014     pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    1015     pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    1016 
    1017     // get pte2_attr
    1018     pte2_attr = pt2[2*ix2];
    1019 
    1020     if( (pte2_attr & TSAR_MMU_MAPPED) == 0 ) return false;
    1021     else                                     return true;
    1022 
    1023 }   // end hal_gpt_pte_is_mapped()
    1024 
    1025 ///////////////////////////////////////
    1026 bool_t hal_gpt_pte_is_cow( gpt_t * gpt,
    1027                            vpn_t   vpn )
    1028 {
    1029     uint32_t * pt1;
    1030     uint32_t   pte1;
    1031     uint32_t   pte2_attr;
    1032 
    1033     uint32_t * pt2;
    1034     ppn_t      pt2_ppn;
    1035 
    1036     uint32_t   ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1037     uint32_t   ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1038 
    1039     // get PTE1 value
    1040         pt1  = gpt->ptr;
    1041     pte1 = pt1[ix1];
    1042 
    1043         if( (pte1 & TSAR_MMU_MAPPED) == 0 ) return false;
    1044 
    1045         if( (pte1 & TSAR_MMU_SMALL) == 0 ) return false;
    1046 
    1047     // compute PT2 base address
    1048     pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    1049     pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    1050 
    1051     // get pte2_attr
    1052     pte2_attr = pt2[2*ix2];
    1053 
    1054     if( (pte2_attr & TSAR_MMU_MAPPED) == 0 ) return false;
    1055 
    1056     if( (pte2_attr & TSAR_MMU_COW)    == 0 ) return false;
    1057     else                                     return true;
    1058 
    1059 }   // end hal_gpt_pte_is_cow()
    1060 
    1061 /////////////////////////////////////////
    1062 void hal_gpt_set_cow( xptr_t  gpt_xp,
    1063                       vpn_t   vpn_base,
    1064                       vpn_t   vpn_size )
    1065 {
    1066     cxy_t      gpt_cxy;
    1067     gpt_t    * gpt_ptr;
    1068 
    1069     vpn_t      vpn;
    1070 
    1071     uint32_t   ix1;
    1072     uint32_t   ix2;
    1073 
    1074     uint32_t * pt1;
    1075     uint32_t   pte1;
    1076 
    1077     uint32_t * pt2;
    1078     ppn_t      pt2_ppn;
    1079     uint32_t   attr;
    1080 
    1081     // get GPT cluster and local pointer
    1082     gpt_cxy = GET_CXY( gpt_xp );
    1083     gpt_ptr = GET_PTR( gpt_xp );
    1084 
    1085     // get local PT1 pointer
    1086     pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    1087 
    1088     // loop on pages
    1089     for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
    1090     {
    1091         ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1092         ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1093 
    1094         // get PTE1 value
    1095         pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
    1096 
    1097         // only MAPPED & SMALL PTEs are modified
    1098             if( (pte1 & TSAR_MMU_MAPPED) && (pte1 & TSAR_MMU_SMALL) )
    1099         {
    1100             // compute PT2 base address
    1101             pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    1102             pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    1103 
    1104             assert( (GET_CXY( ppm_ppn2base( pt2_ppn ) ) == gpt_cxy ),
    1105             "PT2 and PT1 must be in the same cluster\n");
    1106  
    1107             // get current PTE2 attributes
    1108             attr = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) );
    1109 
    1110             // only MAPPED PTEs are modified       
    1111             if( attr & TSAR_MMU_MAPPED )
    1112             {
    1113                 attr = (attr | TSAR_MMU_COW) & (~TSAR_MMU_WRITABLE);
    1114                 hal_remote_s32( XPTR( gpt_cxy , &pt2[2*ix2] ) , attr );
    1115             }
    1116         }
    1117     }   // end loop on pages
    1118 
    1119 }  // end hal_gpt_set_cow()
    1120 
    1121 //////////////////////////////////////////
    1122 void hal_gpt_update_pte( xptr_t    gpt_xp,
    1123                          vpn_t     vpn,
    1124                          uint32_t  attr,     // generic GPT attributes
    1125                          ppn_t     ppn )
    1126 {
    1127     uint32_t          * pt1;                 // PT1 base addres
    1128         uint32_t            pte1;                // PT1 entry value
    1129 
    1130         ppn_t               pt2_ppn;             // PPN of PT2
    1131         uint32_t          * pt2;                 // PT2 base address
    1132 
    1133     uint32_t            ix1;                 // index in PT1
    1134     uint32_t            ix2;                 // index in PT2
    1135 
    1136     uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
    1137 
    1138     // check attr argument MAPPED and SMALL
    1139     if( (attr & GPT_MAPPED) == 0 )  return;
    1140     if( (attr & GPT_SMALL ) == 0 )  return;
    1141 
    1142     // get cluster and local pointer on remote GPT
    1143     cxy_t   gpt_cxy = GET_CXY( gpt_xp );
    1144     gpt_t * gpt_ptr = GET_PTR( gpt_xp );
    1145 
    1146     // compute indexes in PT1 and PT2
    1147     ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1148     ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1149 
    1150     // get PT1 base
    1151     pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    1152 
    1153     // compute tsar_attr from generic attributes
    1154     tsar_attr = gpt2tsar( attr );
    1155 
    1156     // get PTE1 value
    1157     pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
    1158 
    1159     if( (pte1 & TSAR_MMU_MAPPED) == 0 ) return;
    1160     if( (pte1 & TSAR_MMU_SMALL ) == 0 ) return;
    1161 
    1162     // get PT2 base from PTE1
    1163     pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    1164     pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    1165 
    1166     // set PTE2 in this order
    1167         hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2 + 1] ) , ppn );
    1168         hal_fence();
    1169         hal_remote_s32( XPTR( gpt_cxy, &pt2[2 * ix2]     ) , tsar_attr );
    1170         hal_fence();
    1171 
    1172 } // end hal_gpt_update_pte()
    1173 
     1187
  • trunk/hal/tsar_mips32/core/hal_vmm.c

    r625 r629  
    8181    uint32_t ppn  = cxy << 20;   
    8282
    83     // register PTE1  in slot[0] of kernel GPT
    84     error = hal_gpt_set_pte( XPTR( cxy , gpt ) , 0 , attr , ppn );
    85 
    86     if( error )
    87     {
    88         printk("\n[PANIC] in %s : cannot initialize kernel GPT in cluster %x\n",
    89         __FUNCTION__ , cxy );
    90         hal_core_sleep();
    91     }
     83    // set PT1[0]
     84    hal_gpt_set_pte( XPTR( cxy , gpt ) , 0 , attr , ppn );
    9285
    9386#if DEBUG_HAL_VMM
     
    159152
    160153    // update user GPT : set PTE1 in slot[0]
    161     error = hal_gpt_set_pte( u_gpt_xp , 0 , attr , ppn );
    162 
    163     if( error )
    164     {
    165         printk("\n[ERROR] in %s : cannot update user GPT in cluster %x\n",
    166         __FUNCTION__ , cxy );
    167         return -1;
    168     }
     154    hal_gpt_set_pte( u_gpt_xp , 0 , attr , ppn );
    169155
    170156#if DEBUG_HAL_VMM
     
    220206    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
    221207
    222     // build extended pointers on TXT0 lock, GPT lock and VSL lock
     208    // build extended pointer on TXT0 lock and VSL lock
    223209    xptr_t  txt_lock_xp = XPTR( txt0_cxy  , &txt0_ptr->wait_lock );
    224210    xptr_t  vsl_lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
    225     xptr_t  gpt_lock_xp = XPTR( local_cxy , &vmm->gpt_lock );
    226211
    227212    // get root of vsegs list
     
    230215    // get the locks protecting TXT0, VSL, and GPT
    231216    remote_rwlock_rd_acquire( vsl_lock_xp );
    232     remote_rwlock_rd_acquire( gpt_lock_xp );
    233217    remote_busylock_acquire( txt_lock_xp );
    234218
     
    291275    // release locks
    292276    remote_busylock_release( txt_lock_xp );
    293     remote_rwlock_rd_release( gpt_lock_xp );
    294277    remote_rwlock_rd_release( vsl_lock_xp );
    295278
  • trunk/hal/tsar_mips32/drivers/soclib_pic.c

    r570 r629  
    156156
    157157            // check RPC FIFO,  and activate or create a RPC thread
    158             // (condition is always true, but we use the ack value to avoid a GCC warning)
     158            // condition is always true, but we use the ack value
     159            // to avoid a GCC warning
    159160            if( ack + 1 ) sched_yield("IPI received");
    160161        }
     
    200201
    201202                if( src_chdev == NULL )        // strange, but not fatal
    202                 {
     203                {
    203204            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
    204205                   __FUNCTION__ , index , core->lid , local_cxy );
  • trunk/kernel/fs/fatfs.h

    r628 r629  
    181181 *
    182182 * WARNING 2 : Most fields are constant values, but the <free_cluster_hint>,
    183  * <free_clusters>, <dirty_page_min>, <dirty_page_max>, <lock>, and the <fs_info_buffer>
    184  * are shared variables, that can be modified by any thread running in any cluster.
    185  * The <fs_info_buffer> contains a copy of the FS_INFO sector, and is only allocated in
    186  * the FAT cluster (i.e. in cluster 0). It is used by all to synchronously update the
    187  * free clusters info on IOC device.
     183 * <free_clusters>, <lock>, and the <fs_info_buffer> are shared variables,
     184 * that can be modified by any thread running in any cluster. The <fs_info_buffer>
     185 * contains a copy of the FS_INFO sector, and is only allocated in the FAT cluster
     186 * (cluster 0). It is used to synchronously update the free clusters info on IOC device.
    188187 *  => For all these variables, only the values stored in the FAT cluster must be used.
    189188 ****************************************************************************************/
     
    202201
    203202    /* shared variables (only the copy in FAT cluster must be used)                     */
    204     uint32_t            dirty_page_min;        /*! min dirty page index in FAT mapper   */
    205     uint32_t            dirty_page_max;        /*! max dirty page index in FAT mapper   */
    206203    uint32_t            free_cluster_hint;     /*! cluster[hint+1] is the first free    */
    207204    uint32_t            free_clusters;         /*! free clusters number                 */
  • trunk/kernel/fs/vfs.c

    r628 r629  
    26082608#if (DEBUG_VFS_LOOKUP & 1)
    26092609if( DEBUG_VFS_LOOKUP < cycle )
    2610 printk("\n[%s] thread[%x,%x] created missing inode <%s> in cluster %x\n",
     2610printk("\n[%s] thread[%x,%x] created missing inode for <%s> in cluster %x\n",
    26112611__FUNCTION__, process->pid, this->trdid, name, child_cxy );
    26122612#endif
     
    26292629
    26302630                // when the missing dentry is not in the parent mapper,
    2631                 // it is a new dentry that must be registered in parent directory mapper
     2631                // a new dentry must be registered in parent directory mapper
    26322632                if ( error )
    26332633                {
     
    28142814
    28152815    // 1. allocate one free cluster in file system to child inode,
    2816     // and update the File Allocation Table in both the TAF mapper and IOC device.
     2816    // and update the File Allocation Table in both the FAT mapper and IOC device.
    28172817    // It depends on the child inode FS type.
    28182818    vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) );
  • trunk/kernel/kern/kernel_init.c

    r628 r629  
    171171    "VFS_FILE",              // 33
    172172    "VMM_VSL",               // 34
    173     "VMM_GPT",               // 35
    174     "VFS_MAIN",              // 36
    175     "FATFS_FAT",             // 37
     173    "VFS_MAIN",              // 35
     174    "FATFS_FAT",             // 36
    176175};       
    177176
  • trunk/kernel/kern/process.c

    r626 r629  
    166166#endif
    167167
    168     // initialize GPT and VSL locks
    169     remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
     168    // initialize VSL locks
    170169        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    171170
     
    426425
    427426    // initialize GPT and VSL locks
    428     remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
    429427        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    430428
     
    14821480
    14831481    // set COW flag in DATA, ANON, REMOTE vsegs for parent process VMM
    1484     // this includes all parnet process copies in all clusters
     1482    // this includes all parent process copies in all clusters
    14851483    if( parent_process_cxy == local_cxy )   // reference is local
    14861484    {
     
    17071705
    17081706    // initialize VSL and GPT locks
    1709         remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    1710     remote_rwlock_init( XPTR( local_cxy , &vmm->gpt_lock ) , LOCK_VMM_GPT );
     1707    remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    17111708   
    17121709    // create kernel vsegs in GPT and VSL, as required by the hardware architecture
  • trunk/kernel/kern/rpc.c

    r628 r629  
    104104    "VFS_FILE_CREATE",           // 14
    105105    "VFS_FILE_DESTROY",          // 15
    106     "VFS_FS_GET_DENTRY",         // 16
     106    "VFS_FS_NEW_DENTRY",         // 16
    107107    "VFS_FS_ADD_DENTRY",         // 17
    108108    "VFS_FS_REMOVE_DENTRY",      // 18
  • trunk/kernel/kern/scheduler.c

    r625 r629  
    6363// @ returns pointer on selected thread descriptor
    6464////////////////////////////////////////////////////////////////////////////////////////////
    65 thread_t * sched_select( scheduler_t * sched )
     65static thread_t * sched_select( scheduler_t * sched )
    6666{
    6767    thread_t     * thread;
     
    248248uint32_t cycle = (uint32_t)hal_get_cycles();
    249249if( DEBUG_SCHED_HANDLE_SIGNALS < cycle )
    250 printk("\n[%s] thread[%x,%x] on core[%x,%d] deleted / %d threads / cycle %d\n",
     250printk("\n[%s] thread[%x,%x] on core[%x,%d] deleted (still %d threads) / cycle %d\n",
    251251__FUNCTION__, process->pid, thread->trdid, local_cxy, thread->core->lid, count, cycle );
     252#endif
     253
     254#if CONFIG_INSTRUMENTATION_PGFAULTS
     255uint32_t local_nr    = thread->info.local_pgfault_nr;
     256uint32_t local_cost  = (local_nr == 0)  ? 0 : (thread->info.local_pgfault_cost / local_nr);
     257uint32_t global_nr   = thread->info.global_pgfault_nr;
     258uint32_t global_cost = (global_nr == 0) ? 0 : (thread->info.global_pgfault_cost / global_nr);
     259uint32_t false_nr    = thread->info.false_pgfault_nr;
     260uint32_t false_cost  = (false_nr == 0)  ? 0 : (thread->info.false_pgfault_cost / false_nr);
     261printk("***** page faults for thread[%x,%x]\n"
     262       "  - %d local  : %d cycles\n"
     263       "  - %d global : %d cycles\n"
     264       "  - %d false  : %d cycles\n",
     265       process->pid, thread->trdid,
     266       local_nr,  local_cost,
     267       global_nr, global_cost,
     268       false_nr,  false_cost );
    252269#endif
    253270            // destroy process descriptor if last thread
     
    481498 
    482499#if (DEBUG_SCHED_YIELD & 0x1)
    483 // if( sched->trace )
    484 if( (uint32_t)hal_get_cycles() > DEBUG_SCHED_YIELD )
     500if( sched->trace )
    485501sched_display( lid );
    486502#endif
     
    535551
    536552#if DEBUG_SCHED_YIELD
    537 // if( sched->trace )
    538 if( (uint32_t)hal_get_cycles() > DEBUG_SCHED_YIELD )
     553if( sched->trace )
    539554printk("\n[%s] core[%x,%d] / cause = %s\n"
    540555"      thread %x (%s) (%x,%x) => thread %x (%s) (%x,%x) / cycle %d\n",
     
    553568
    554569#if (DEBUG_SCHED_YIELD & 1)
    555 // if( sched->trace )
    556 if( (uint32_t)hal_get_cycles() > DEBUG_SCHED_YIELD )
     570if( sched->trace )
    557571printk("\n[%s] core[%x,%d] / cause = %s\n"
    558572"      thread %x (%s) (%x,%x) continue / cycle %d\n",
  • trunk/kernel/kern/thread.c

    r625 r629  
    907907
    908908    // update target process instrumentation counter
    909         process->vmm.pgfault_nr += thread->info.pgfault_nr;
     909        // process->vmm.pgfault_nr += thread->info.pgfault_nr;
    910910
    911911    // remove thread from process th_tbl[]
  • trunk/kernel/kern/thread.h

    r625 r629  
    100100typedef struct thread_info_s
    101101{
    102         uint32_t              pgfault_nr;    /*! cumulated number of page fault           */
    103         cycle_t               last_cycle;    /*! last cycle counter value (date)          */
    104         cycle_t               usr_cycles;    /*! user execution duration (cycles)         */
    105         cycle_t               sys_cycles;    /*! system execution duration (cycles)       */
     102        uint32_t     false_pgfault_nr;       /*! number of local page fault               */
     103    uint32_t     false_pgfault_cost;     /*! cumulated cost                           */
     104        uint32_t     local_pgfault_nr;       /*! number of local page fault               */
     105    uint32_t     local_pgfault_cost;     /*! cumulated cost                           */
     106        uint32_t     global_pgfault_nr;      /*! number of global page fault              */
     107    uint32_t     global_pgfault_cost;    /*! cumulated cost                           */
     108
     109        cycle_t      last_cycle;             /*! last cycle counter value (date)          */
     110        cycle_t      usr_cycles;             /*! user execution duration (cycles)         */
     111        cycle_t      sys_cycles;             /*! system execution duration (cycles)       */
    106112}
    107113thread_info_t;
  • trunk/kernel/kernel_config.h

    r628 r629  
    2626#define _KERNEL_CONFIG_H_
    2727
    28 #define CONFIG_ALMOS_VERSION           "Version 2.0 / April 2019"
     28#define CONFIG_ALMOS_VERSION           "Version 2.1 / May 2019"
    2929
    3030////////////////////////////////////////////////////////////////////////////////////////////
     
    4040
    4141#define DEBUG_BUSYLOCK                    0
    42 #define DEBUG_BUSYLOCK_PID                0x10001    // for busylock detailed debug
    43 #define DEBUG_BUSYLOCK_TRDID              0x10000    // for busylock detailed debug
     42#define DEBUG_BUSYLOCK_PID                0          // for busylock detailed debug
     43#define DEBUG_BUSYLOCK_TRDID              0          // for busylock detailed debug
    4444                 
    4545#define DEBUG_CHDEV_CMD_RX                0
     
    136136#define DEBUG_PROCESS_ZERO_CREATE         0
    137137
    138 #define DEBUG_QUEUELOCK_TYPE              0    // lock type (0 : undefined / 1000 : all types)
     138#define DEBUG_QUEUELOCK_TYPE              0       // lock type 0 is undefined => no debug
     139#define DEBUG_QUEUELOCK_PTR               0
     140#define DEBUG_QUEUELOCK_CXY               0
    139141
    140142#define DEBUG_RPC_CLIENT_GENERIC          0
     
    165167#define DEBUG_RPC_VMM_DELETE_VSEG         0
    166168
    167 #define DEBUG_RWLOCK_TYPE                 0    // lock type (0 : undefined / 1000 : all types)
     169#define DEBUG_RWLOCK_TYPE                 35       // lock type 0 is undefined => no debug
     170#define DEBUG_RWLOCK_PTR                  0xb1650
     171#define DEBUG_RWLOCK_CXY                  0x11
    168172
    169173#define DEBUG_SCHED_HANDLE_SIGNALS        2
     
    309313#define LOCK_VFS_FILE         33   // remote (RW) protect file descriptor state
    310314#define LOCK_VMM_VSL          34   // remote (RW) protect VSL (local list of vsegs)
    311 #define LOCK_VMM_GPT          35   // remote (RW) protect GPT (local page table)
    312 #define LOCK_VFS_MAIN         36   // remote (RW) protect vfs traversal (in root inode)
    313 #define LOCK_FATFS_FAT        37   // remote (RW) protect exclusive access to the FATFS FAT
     315#define LOCK_VFS_MAIN         35   // remote (RW) protect vfs traversal (in root inode)
     316#define LOCK_FATFS_FAT        36   // remote (RW) protect exclusive access to the FATFS FAT
    314317
    315318
     
    451454////////////////////////////////////////////////////////////////////////////////////////////
    452455
    453 #define CONFIG_INTRUMENTATION_SYSCALLS  0
     456#define CONFIG_INSTRUMENTATION_SYSCALLS  0
     457#define CONFIG_INSTRUMENTATION_PGFAULTS  1
    454458
    455459
  • trunk/kernel/libk/queuelock.c

    r623 r629  
    22 * queuelock.c - local kernel lock with waiting queue implementation.
    33 *
    4  * Authors   Alain Greiner     (2016,2017,2018)
     4 * Authors   Alain Greiner     (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    4747#if DEBUG_QUEUELOCK_TYPE
    4848thread_t * this = CURRENT_THREAD;
    49 if( DEBUG_QUEUELOCK_TYPE == type )
     49if( (type      == DEBUG_QUEUELOCK_TYPE) &&
     50    (lock      == DEBUG_QUEUELOCK_PTR ) &&
     51    (local_cxy == DEBUG_QUEUELOCK_CXY ) )
    5052printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
    5153__FUNCTION__, this->process->pid, this->trdid,
     
    7577
    7678#if DEBUG_QUEUELOCK_TYPE
    77 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     79if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     80    (lock      == DEBUG_QUEUELOCK_PTR ) &&
     81    (local_cxy == DEBUG_QUEUELOCK_CXY ) )
    7882printk("\n[%s ] thread[%x,%x] BLOCK on q_lock %s [%x,%x]\n",
    7983__FUNCTION__, this->process->pid, this->trdid,
     
    100104
    101105#if DEBUG_QUEUELOCK_TYPE
    102 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     106if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     107    (lock      == DEBUG_QUEUELOCK_PTR ) &&
     108    (local_cxy == DEBUG_QUEUELOCK_CXY ) )
    103109printk("\n[%s] thread[%x,%x] ACQUIRE q_lock %s [%x,%x]\n",
    104110__FUNCTION__, this->process->pid, this->trdid,
     
    126132uint32_t   lock_type = lock->lock.type;
    127133thread_t * this      = CURRENT_THREAD;
    128 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     134if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     135    (lock      == DEBUG_QUEUELOCK_PTR ) &&
     136    (local_cxy == DEBUG_QUEUELOCK_CXY ) )
    129137printk("\n[%s] thread[%x,%x] RELEASE q_lock %s [%x,%x]\n",
    130138__FUNCTION__, this->process->pid, this->trdid,
     
    142150
    143151#if DEBUG_QUEUELOCK_TYPE
    144 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     152if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     153    (lock      == DEBUG_QUEUELOCK_PTR ) &&
     154    (local_cxy == DEBUG_QUEUELOCK_CXY ) )
    145155printk("\n[%s] thread[%x,%x] UNBLOCK thread [%x,%x] / q_lock %s [%x,%x]\n",
    146156__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
  • trunk/kernel/libk/remote_barrier.c

    r623 r629  
    467467if( cycle > DEBUG_BARRIER_WAIT )
    468468printk("\n[%s] thread[%x,%x] exit / barrier (%x,%x) / cycle %d\n",
    469 __FUNCTION__, this->trdid, this->process->pid, barrier_cxy, barrier_ptr, cycle );
     469__FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle );
    470470#endif
    471471
  • trunk/kernel/libk/remote_queuelock.c

    r623 r629  
    22 * remote_queuelock.c - remote kernel lock with waiting queue implementation.
    33 *
    4  * Authors   Alain Greiner     (2016,2017,2018)
     4 * Authors   Alain Greiner     (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    5656#if DEBUG_QUEUELOCK_TYPE
    5757thread_t * this = CURRENT_THREAD;
    58 if( DEBUG_QUEUELOCK_TYPE == type )
     58if( (type     == DEBUG_QUEUELOCK_TYPE) &&
     59    (lock_ptr == DEBUG_QUEUELOCK_PTR ) &&
     60    (lock_cxy == DEBUG_QUEUELOCK_CXY ) )
    5961printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
    6062__FUNCTION__, this->process->pid, this->trdid,
     
    9193
    9294#if DEBUG_QUEUELOCK_TYPE
    93 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     95if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     96    (lock_ptr  == DEBUG_QUEUELOCK_PTR ) &&
     97    (lock_cxy  == DEBUG_QUEUELOCK_CXY ) )
    9498printk("\n[%s] thread[%x,%x] BLOCK on q_lock %s [%x,%x]\n",
    9599__FUNCTION__, this->process->pid, this->trdid,
     
    117121
    118122#if DEBUG_QUEUELOCK_TYPE
    119 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     123if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     124    (lock_ptr  == DEBUG_QUEUELOCK_PTR ) &&
     125    (lock_cxy  == DEBUG_QUEUELOCK_CXY ) )
    120126printk("\n[%s] thread[%x,%x] ACQUIRE q_lock %s [%x,%x]\n",
    121127__FUNCTION__, this->process->pid, this->trdid,
     
    152158thread_t * this      = CURRENT_THREAD;
    153159uint32_t   lock_type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
    154 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     160if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     161    (lock_ptr  == DEBUG_QUEUELOCK_PTR ) &&
     162    (lock_cxy  == DEBUG_QUEUELOCK_CXY ) )
    155163printk("\n[%s] thread[%x,%x] RELEASE q_lock %s (%x,%x)\n",
    156164__FUNCTION__, this->process->pid, this->trdid,
     
    171179
    172180#if DEBUG_QUEUELOCK_TYPE
    173 if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
     181if( (lock_type == DEBUG_QUEUELOCK_TYPE) &&
     182    (lock_ptr  == DEBUG_QUEUELOCK_PTR ) &&
     183    (lock_cxy  == DEBUG_QUEUELOCK_CXY ) )
    174184{
    175185    trdid_t     trdid   = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
  • trunk/kernel/libk/remote_rwlock.c

    r627 r629  
    5555#if DEBUG_RWLOCK_TYPE
    5656thread_t * this = CURRENT_THREAD;
    57 if( DEBUG_RWLOCK_TYPE == type )
     57if( (type               == DEBUG_RWLOCK_TYPE) &&
     58    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     59    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    5860printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
    5961__FUNCTION__, this->process->pid, this->trdid,
     
    9395
    9496#if DEBUG_RWLOCK_TYPE
    95 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     97if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     98    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     99    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    96100printk("\n[%s] thread[%x,%x] READ BLOCK on rwlock %s [%x,%x] / taken %d / count %d\n",
    97101__FUNCTION__, this->process->pid, this->trdid,
     
    124128
    125129#if DEBUG_RWLOCK_TYPE
    126 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
    127 printk("\n[%s] thread[%x,%x] READ ACQUIRE rwlock %s [%x,%x] / taken = %d / count = %d\n",
     130if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     131    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     132    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
     133printk("\n[%s] thread[%x,%x] READ ACQUIRE rwlock %s [%x,%x] / taken %d / count %d\n",
    128134__FUNCTION__, this->process->pid, this->trdid,
    129135lock_type_str[lock_type], lock_cxy, lock_ptr,
     
    166172
    167173#if DEBUG_RWLOCK_TYPE
    168 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     174if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     175    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     176    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    169177printk("\n[%s] thread[%x,%x] WRITE BLOCK on rwlock %s [%x,%x] / taken %d / count %d\n",
    170178__FUNCTION__, this->process->pid, this->trdid,
     
    196204
    197205#if DEBUG_RWLOCK_TYPE
    198 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     206if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     207    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     208    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    199209printk("\n[%s] thread[%x,%x] WRITE ACQUIRE rwlock %s [%x,%x] / taken %d / count %d\n",
    200210__FUNCTION__, this->process->pid, this->trdid,
     
    235245uint32_t   lock_type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
    236246xptr_t     taken_xp  = XPTR( lock_cxy , &lock_ptr->taken );
    237 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     247if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     248    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     249    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    238250printk("\n[%s] thread[%x,%x] READ RELEASE rwlock %s [%x,%x] / taken %d / count %d\n",
    239251__FUNCTION__, this->process->pid, this->trdid,
     
    258270
    259271#if DEBUG_RWLOCK_TYPE
    260 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     272if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     273    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     274    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    261275{
    262276    trdid_t     trdid     = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
     
    289303
    290304#if DEBUG_RWLOCK_TYPE
    291 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     305if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     306    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     307    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    292308{
    293309    trdid_t     trdid     = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
     
    334350uint32_t   lock_type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
    335351xptr_t     count_xp  = XPTR( lock_cxy , &lock_ptr->count );
    336 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     352if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     353    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     354    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    337355printk("\n[%s] thread[%x,%x] WRITE RELEASE rwlock %s [%x,%x] / taken %d / count %d\n",
    338356__FUNCTION__, this->process->pid, this->trdid,
     
    356374
    357375#if DEBUG_RWLOCK_TYPE
    358 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     376if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     377    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     378    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    359379{
    360380    trdid_t     trdid     = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
     
    386406
    387407#if DEBUG_RWLOCK_TYPE
    388 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     408if( (lock_type          == DEBUG_RWLOCK_TYPE) &&
     409    ((intptr_t)lock_ptr == DEBUG_RWLOCK_PTR ) &&
     410    (lock_cxy           == DEBUG_RWLOCK_CXY ) )
    389411{
    390412    trdid_t     trdid     = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
  • trunk/kernel/libk/remote_rwlock.h

    r627 r629  
    4242 *   taken, or if the number of readers is non zero, it registers in the "wr_root" waiting
    4343 *   queue, blocks, and deschedules. It set "taken" otherwise.
    44  * - when a reader completes its access, it decrement the readers "count", unblock the
     44 * - when a reader completes its access, it decrement the readers "count", unblock
    4545 *   the first waiting writer if there is no other readers, and unblock all waiting
    4646 *   readers if there no write request.
  • trunk/kernel/libk/rwlock.c

    r623 r629  
    22 * rwlock.c - kernel local read/write lock implementation.
    33 *
    4  * Author  Alain Greiner     (2016,2017,2018)
     4 * Author  Alain Greiner     (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    5252#if DEBUG_RWLOCK_TYPE
    5353thread_t * this = CURRENT_THREAD;
    54 if( DEBUG_RWLOCK_TYPE == type )
     54if( (type           == DEBUG_RWLOCK_TYPE) &&
     55    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     56    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    5557printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
    5658__FUNCTION__, this->process->pid, this->trdid,
     
    8082
    8183#if DEBUG_RWLOCK_TYPE
    82 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     84if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     85    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     86    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    8387printk("\n[%s] thread[%x,%x] READ BLOCK on rwlock %s [%x,%x] / taken %d / count %d\n",
    8488__FUNCTION__, this->process->pid, this->trdid,
     
    105109
    106110#if DEBUG_RWLOCK_TYPE
    107 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     111if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     112    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     113    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    108114printk("\n[%s] thread[%x,%x] READ ACQUIRE rwlock %s [%x,%x] / taken %d / count %d\n",
    109115__FUNCTION__, this->process->pid, this->trdid,
     
    136142
    137143#if DEBUG_RWLOCK_TYPE
    138 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     144if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     145    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     146    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    139147printk("\n[%s] thread[%x,%x] WRITE BLOCK on rwlock %s [%x,%x] / taken %d / count %d\n",
    140148__FUNCTION__, this->process->pid, this->trdid,
     
    161169
    162170#if DEBUG_RWLOCK_TYPE
    163 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     171if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     172    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     173    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    164174printk("\n[%s] thread[%x,%x] WRITE ACQUIRE rwlock %s [%x,%x] / taken %d / count %d\n",
    165175__FUNCTION__, this->process->pid, this->trdid,
     
    187197thread_t * this = CURRENT_THREAD;
    188198uint32_t lock_type = lock->lock.type;
    189 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     199if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     200    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     201    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    190202printk("\n[%s] thread[%x,%x] READ RELEASE rwlock %s [%x,%x] / taken %d / count %d\n",
    191203__FUNCTION__, this->process->pid, this->trdid,
     
    201213
    202214#if DEBUG_RWLOCK_TYPE
    203 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     215if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     216    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     217    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    204218printk("\n[%s] thread[%x,%x] UNBLOCK thread[%x,%x] / rwlock %s [%x,%x]\n",
    205219__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
     
    223237
    224238#if DEBUG_RWLOCK_TYPE
    225 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     239if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     240    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     241    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    226242printk("\n[%s] thread[%x,%x] UNBLOCK thread[%x,%x] / rwlock %s [%x,%x]\n",
    227243__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
     
    257273thread_t * this = CURRENT_THREAD;
    258274uint32_t lock_type = lock->lock.type;
    259 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     275if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     276    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     277    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    260278printk("\n[%s] thread[%x,%x] WRITE RELEASE rwlock %s [%x,%x] / taken %d / count %d\n",
    261279__FUNCTION__, this->process->pid, this->trdid,
     
    270288
    271289#if DEBUG_RWLOCK_TYPE
    272 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     290if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     291    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     292    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    273293printk("\n[%s] thread[%x,%x] UNBLOCK thread[%x,%x] / rwlock %s [%x,%x]\n",
    274294__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
     
    291311
    292312#if DEBUG_RWLOCK_TYPE
    293 if( (DEBUG_RWLOCK_TYPE == lock_type) || (DEBUG_RWLOCK_TYPE == 1000) )
     313if( (lock_type      == DEBUG_RWLOCK_TYPE) &&
     314    ((intptr_t)lock == DEBUG_RWLOCK_PTR ) &&
     315    (local_cxy      == DEBUG_RWLOCK_CXY ) )
    294316printk("\n[%s] thread[%x,%x] UNBLOCK thread[%x,%x] / rwlock %s [%x,%x]\n",
    295317__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
  • trunk/kernel/libk/user_dir.c

    r619 r629  
    22 * user_dir.c - kernel DIR related operations implementation.
    33 *
    4  * Authors   Alain   Greiner (2016,2017,2018)
     4 * Authors   Alain   Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    9191    pid_t           ref_pid;           // reference process PID
    9292    xptr_t          gpt_xp;            // extended pointer on reference process GPT
    93     uint32_t        gpt_attributes;    // attributes for all mapped gpt entries
     93    uint32_t        attr;              // attributes for all GPT entries
    9494    uint32_t        dirents_per_page;  // number of dirent descriptors per page
    9595    xptr_t          page_xp;           // extended pointer on page descriptor 
     
    9999    uint32_t        total_dirents;     // total number of dirents in dirent array
    100100    uint32_t        total_pages;       // total number of pages for dirent array
    101     vpn_t           vpn;               // first page in dirent array vseg
     101    vpn_t           vpn_base;          // first page in dirent array vseg
     102    vpn_t           vpn;               // current page in dirent array vseg
    102103    ppn_t           ppn;               // ppn of currently allocated physical page
    103104    uint32_t        entries;           // number of dirent actually comied in one page
     
    107108    uint32_t        page_id;           // page index in list of physical pages
    108109    kmem_req_t      req;               // kmem request descriptor
     110    ppn_t           fake_ppn;          // unused, but required by hal_gptlock_pte()
     111    uint32_t        fake_attr;         // unused, but required by hal_gptlock_pte()
    109112    error_t         error;
    110113
    111     // get cluster, local pointer, and pid of reference user process
     114    // get cluster, local pointer, and pid of reference process
    112115    ref_cxy = GET_CXY( ref_xp );
    113116    ref_ptr = GET_PTR( ref_xp );
     
    256259"unconsistent vseg size for dirent array" );
    257260
    258     // build extended pointer on reference process GPT, PTE attributes and ppn
     261    // build extended pointer on reference process GPT
    259262    gpt_xp         = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
    260     gpt_attributes = GPT_MAPPED   |
    261                      GPT_SMALL    |
    262                      GPT_READABLE |
    263                      GPT_CACHABLE |
    264                      GPT_USER     ;
     263
     264    // build PTE attributes
     265    attr = GPT_MAPPED   |
     266           GPT_SMALL    |
     267           GPT_READABLE |
     268           GPT_CACHABLE |
     269           GPT_USER     ;
    265270
    266271    // get first vpn from vseg descriptor
    267     vpn = hal_remote_l32( XPTR( ref_cxy , &vseg->vpn_base ) );
     272    vpn_base = hal_remote_l32( XPTR( ref_cxy , &vseg->vpn_base ) );
    268273
    269274    // scan the list of allocated physical pages to map
    270     // all physical pages in the in the reference process GPT
     275    // all physical pages in the reference process GPT
    271276    page_id = 0;
    272277    while( list_is_empty( &root ) == false )
     
    277282        // compute ppn
    278283        ppn = ppm_page2ppn( XPTR( local_cxy , page ) );
     284
     285        // compute vpn
     286        vpn = vpn_base + page_id;
    279287       
    280         error = hal_gpt_set_pte( gpt_xp,
    281                                  vpn + page_id,
    282                                  gpt_attributes,
    283                                  ppn );
     288        // lock the PTE (and create PT2 if required)
     289        error = hal_gpt_lock_pte( gpt_xp,
     290                                  vpn,
     291                                  &fake_attr,
     292                                  &fake_ppn );
    284293        if( error )
    285294        {
    286295            printk("\n[ERROR] in %s : cannot map vpn %x in GPT\n",
    287             __FUNCTION__, (vpn + page_id) );
     296            __FUNCTION__, vpn );
    288297
    289298            // delete the vseg
    290             if( ref_cxy == local_cxy) vmm_delete_vseg( ref_pid, vpn<<CONFIG_PPM_PAGE_SHIFT );
    291             else rpc_vmm_delete_vseg_client( ref_cxy, ref_pid, vpn<<CONFIG_PPM_PAGE_SHIFT );
     299            if( ref_cxy == local_cxy)
     300                vmm_delete_vseg( ref_pid, vpn_base << CONFIG_PPM_PAGE_SHIFT );
     301            else
     302                rpc_vmm_delete_vseg_client( ref_cxy, ref_pid, vpn_base << CONFIG_PPM_PAGE_SHIFT );
    292303
    293304            // release the user_dir descriptor
     
    298309        }
    299310
     311        // set PTE in GPT                         
     312        hal_gpt_set_pte( gpt_xp,
     313                         vpn,
     314                         attr,
     315                         ppn );
     316
    300317#if DEBUG_USER_DIR
    301318if( cycle > DEBUG_USER_DIR )
     
    317334    dir->current = 0;
    318335    dir->entries = total_dirents;
    319     dir->ident   = (intptr_t)(vpn << CONFIG_PPM_PAGE_SHIFT);
     336    dir->ident   = (intptr_t)(vpn_base << CONFIG_PPM_PAGE_SHIFT);
    320337
    321338    // build extended pointers on root and lock of user_dir xlist in ref process
  • trunk/kernel/libk/user_dir.h

    r623 r629  
    22 * user_dir.h -  DIR related operations definition.
    33 *
    4  * Authors   Alain Greiner   (2016,2017,2018)
     4 * Authors   Alain Greiner   (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
  • trunk/kernel/mm/vmm.c

    r625 r629  
    741741    child_vmm  = &child_process->vmm;
    742742
    743     // initialize the locks protecting the child VSL and GPT
    744     remote_rwlock_init( XPTR( local_cxy , &child_vmm->gpt_lock ) , LOCK_VMM_GPT );
     743    // initialize the lock protecting the child VSL
    745744        remote_rwlock_init( XPTR( local_cxy , &child_vmm->vsl_lock ) , LOCK_VMM_VSL );
    746745
     
    952951    xptr_t   vsl_root_xp = XPTR( local_cxy , &vmm->vsegs_root );
    953952    xptr_t   vsl_lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
    954     xptr_t   gpt_lock_xp = XPTR( local_cxy , &vmm->gpt_lock );
    955953
    956954    // take the VSL lock
     
    10221020    }
    10231021
    1024     // take the GPT lock
    1025     remote_rwlock_wr_acquire( gpt_lock_xp );
    1026 
    10271022    // release memory allocated to the GPT itself
    10281023    hal_gpt_destroy( &vmm->gpt );
    1029 
    1030     // release the GPT lock
    1031     remote_rwlock_wr_release( gpt_lock_xp );
    10321024
    10331025#if DEBUG_VMM_DESTROY
     
    12261218{
    12271219    vmm_t     * vmm;        // local pointer on process VMM
     1220    xptr_t      gpt_xp;     // extended pointer on GPT
    12281221    bool_t      is_ref;     // local process is reference process
    12291222    uint32_t    vseg_type;  // vseg type
     
    12501243    vmm = &process->vmm;
    12511244
     1245    // build extended pointer on GPT
     1246    gpt_xp = XPTR( local_cxy , &vmm->gpt );
     1247
    12521248    // get relevant vseg infos
    12531249    vseg_type = vseg->type;
     
    12681264    {
    12691265        // get ppn and attr
    1270         hal_gpt_get_pte( XPTR( local_cxy , &vmm->gpt ) , vpn , &attr , &ppn );
     1266        hal_gpt_get_pte( gpt_xp , vpn , &attr , &ppn );
    12711267
    12721268        if( attr & GPT_MAPPED )  // PTE is mapped
     
    12781274#endif
    12791275            // unmap GPT entry in local GPT
    1280             hal_gpt_reset_pte( &vmm->gpt , vpn );
     1276            hal_gpt_reset_pte( gpt_xp , vpn );
    12811277
    12821278            // get pointers on physical page descriptor
     
    19151911{
    19161912    vseg_t         * vseg;            // vseg containing vpn
    1917     uint32_t         new_attr;        // new PTE_ATTR value
    1918     ppn_t            new_ppn;         // new PTE_PPN value
     1913    uint32_t         attr;            // PTE_ATTR value
     1914    ppn_t            ppn;             // PTE_PPN value
    19191915    uint32_t         ref_attr;        // PTE_ATTR value in reference GPT
    19201916    ppn_t            ref_ppn;         // PTE_PPN value in reference GPT
     
    19221918    process_t      * ref_ptr;         // reference process for missing vpn
    19231919    xptr_t           local_gpt_xp;    // extended pointer on local GPT
    1924     xptr_t           local_lock_xp;   // extended pointer on local GPT lock
    19251920    xptr_t           ref_gpt_xp;      // extended pointer on reference GPT
    1926     xptr_t           ref_lock_xp;     // extended pointer on reference GPT lock
    19271921    error_t          error;           // value returned by called functions
    19281922
     1923    thread_t * this  = CURRENT_THREAD;
     1924
     1925#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
     1926uint32_t start_cycle = (uint32_t)hal_get_cycles();
     1927#endif
     1928
    19291929#if DEBUG_VMM_HANDLE_PAGE_FAULT
    1930 uint32_t   cycle = (uint32_t)hal_get_cycles();
    1931 thread_t * this  = CURRENT_THREAD;
    1932 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
     1930if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
    19331931printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
    1934 __FUNCTION__, this->process->pid, this->trdid, vpn, cycle );
    1935 hal_vmm_display( process , true );
     1932__FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle );
     1933#endif
     1934
     1935#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     1936hal_vmm_display( this->process , false );
    19361937#endif
    19371938
     
    19421943    if( error )
    19431944    {
    1944         printk("\n[ERROR] in %s : vpn %x in process %x not in registered vseg / cycle %d\n",
    1945         __FUNCTION__ , vpn , process->pid, (uint32_t)hal_get_cycles() );
     1945        printk("\n[ERROR] in %s : vpn %x in thread[%x,%x] not in registered vseg\n",
     1946        __FUNCTION__ , vpn , process->pid, this->trdid );
    19461947       
    19471948        return EXCP_USER_ERROR;
     
    19491950
    19501951#if DEBUG_VMM_HANDLE_PAGE_FAULT
    1951 cycle = (uint32_t)hal_get_cycles();
    1952 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
    1953 printk("\n[%s] threadr[%x,%x] found vseg %s / cycle %d\n",
    1954 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type), cycle );
    1955 #endif
    1956 
    1957     //////////////// private vseg => access only the local GPT
    1958     if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) )
    1959     {
    1960         // build extended pointer on local GPT and local GPT lock
    1961         local_gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
    1962         local_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock );
    1963 
    1964         // take local GPT lock in write mode
    1965         remote_rwlock_wr_acquire( local_lock_xp );
    1966 
    1967         // check VPN still unmapped in local GPT
    1968 
    1969         // do nothing if VPN has been mapped by a a concurrent page_fault
    1970         hal_gpt_get_pte( local_gpt_xp,
    1971                          vpn,
    1972                          &new_attr,
    1973                          &new_ppn );
    1974 
    1975         if( (new_attr & GPT_MAPPED) == 0 )       // VPN still unmapped
    1976         {
    1977             // allocate and initialise a physical page depending on the vseg type
    1978             error = vmm_get_one_ppn( vseg , vpn , &new_ppn );
    1979 
    1980             if( error )
    1981             {
    1982                 printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n",
    1983                 __FUNCTION__ , process->pid , vpn );
    1984 
    1985                 // release local GPT lock in write mode
    1986                 remote_rwlock_wr_release( local_lock_xp );
    1987 
    1988                 return EXCP_KERNEL_PANIC;
    1989             }
    1990 
    1991             // define new_attr from vseg flags
    1992             new_attr = GPT_MAPPED | GPT_SMALL;
    1993             if( vseg->flags & VSEG_USER  ) new_attr |= GPT_USER;
    1994             if( vseg->flags & VSEG_WRITE ) new_attr |= GPT_WRITABLE;
    1995             if( vseg->flags & VSEG_EXEC  ) new_attr |= GPT_EXECUTABLE;
    1996             if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE;
    1997 
    1998             // set PTE (PPN & attribute) to local GPT
    1999             error = hal_gpt_set_pte( local_gpt_xp,
    2000                                      vpn,
    2001                                      new_attr,
    2002                                      new_ppn );
    2003             if ( error )
    2004             {
    2005                 printk("\n[ERROR] in %s : cannot update local GPT / process %x / vpn = %x\n",
    2006                 __FUNCTION__ , process->pid , vpn );
    2007 
    2008                 // release local GPT lock in write mode
    2009                 remote_rwlock_wr_release( local_lock_xp );
    2010 
    2011                 return EXCP_KERNEL_PANIC;
    2012             }
    2013         }
    2014 
    2015         // release local GPT lock in write mode
    2016         remote_rwlock_wr_release( local_lock_xp );
    2017 
    2018 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2019 cycle = (uint32_t)hal_get_cycles();
    2020 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
    2021 printk("\n[%s] private page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2022 __FUNCTION__, vpn, new_ppn, new_attr, cycle );
    2023 #endif
    2024         return EXCP_NON_FATAL;
    2025 
    2026     }   // end local GPT access
    2027 
    2028     //////////// public vseg => access reference GPT
    2029     else                               
     1952if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
     1953printk("\n[%s] thread[%x,%x] found vseg %s\n",
     1954__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
     1955#endif
     1956
     1957    // build extended pointer on local GPT
     1958    local_gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
     1959
     1960    // lock target PTE in local GPT and get current PPN and attributes
     1961    error = hal_gpt_lock_pte( local_gpt_xp,
     1962                              vpn,
     1963                              &attr,
     1964                              &ppn );
     1965    if( error )
     1966    {
     1967        printk("\n[PANIC] in %s : cannot lock PTE in local GPT / vpn %x / process %x\n",
     1968        __FUNCTION__ , vpn , process->pid );
     1969       
     1970        return EXCP_KERNEL_PANIC;
     1971    }
     1972
     1973    // handle page fault only if PTE still unmapped after lock
     1974    if( (attr & GPT_MAPPED) == 0 )
    20301975    {
    20311976        // get reference process cluster and local pointer
     
    20331978        ref_ptr = GET_PTR( process->ref_xp );
    20341979
    2035         // build extended pointer on reference GPT and reference GPT lock
    2036         ref_gpt_xp  = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
    2037         ref_lock_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt_lock );
    2038 
    2039         // build extended pointer on local GPT and local GPT lock
    2040         local_gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
    2041         local_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock );
    2042 
    2043         // take reference GPT lock in read mode
    2044         remote_rwlock_rd_acquire( ref_lock_xp );
    2045 
    2046         // get directly PPN & attributes from reference GPT
    2047         // this can avoids a costly RPC for a false page fault
    2048         hal_gpt_get_pte( ref_gpt_xp,
    2049                          vpn,
    2050                          &ref_attr,
    2051                          &ref_ppn );
    2052 
    2053         // release reference GPT lock in read mode
    2054         remote_rwlock_rd_release( ref_lock_xp );
    2055 
    2056         if( ref_attr & GPT_MAPPED )        // false page fault => update local GPT
     1980        // private vseg or (local == reference) => access only the local GPT
     1981        if( (vseg->type == VSEG_TYPE_STACK) ||
     1982            (vseg->type == VSEG_TYPE_CODE)  ||
     1983            (ref_cxy    == local_cxy ) )
    20571984        {
    2058             // take local GPT lock in write mode
    2059             remote_rwlock_wr_acquire( local_lock_xp );
    2060            
    2061             // check VPN still unmapped in local GPT
    2062             hal_gpt_get_pte( local_gpt_xp,
     1985            // allocate and initialise a physical page depending on the vseg type
     1986            error = vmm_get_one_ppn( vseg , vpn , &ppn );
     1987
     1988            if( error )
     1989            {
     1990                printk("\n[ERROR] in %s : no physical page / process = %x / vpn = %x\n",
     1991                __FUNCTION__ , process->pid , vpn );
     1992
     1993                // unlock PTE in local GPT
     1994                hal_gpt_unlock_pte( local_gpt_xp , vpn );
     1995
     1996                return EXCP_KERNEL_PANIC;
     1997            }
     1998
     1999            // define attr from vseg flags
     2000            attr = GPT_MAPPED | GPT_SMALL;
     2001            if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
     2002            if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
     2003            if( vseg->flags & VSEG_EXEC  ) attr |= GPT_EXECUTABLE;
     2004            if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
     2005
     2006            // set PTE to local GPT
     2007            hal_gpt_set_pte( local_gpt_xp,
    20632008                             vpn,
    2064                              &new_attr,
    2065                              &new_ppn );
    2066 
    2067             if( (new_attr & GPT_MAPPED) == 0 )       // VPN still unmapped
    2068             {
    2069                 // update local GPT from reference GPT
    2070                 error = hal_gpt_set_pte( local_gpt_xp,
    2071                                          vpn,
    2072                                          ref_attr,
    2073                                          ref_ppn );
    2074                 if( error )
    2075                 {
    2076                     printk("\n[ERROR] in %s : cannot update local GPT / process %x / vpn %x\n",
    2077                     __FUNCTION__ , process->pid , vpn );
    2078 
    2079                     // release local GPT lock in write mode
    2080                     remote_rwlock_wr_release( local_lock_xp );
    2081            
    2082                     return EXCP_KERNEL_PANIC;
    2083                 }
    2084             }
    2085             else    // VPN has been mapped by a a concurrent page_fault
    2086             {
    2087                 // keep PTE from local GPT
    2088                 ref_attr = new_attr;
    2089                 ref_ppn  = new_ppn;
    2090             }
    2091 
    2092             // release local GPT lock in write mode
    2093             remote_rwlock_wr_release( local_lock_xp );
    2094            
     2009                             attr,
     2010                             ppn );
     2011
     2012#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
     2013uint32_t end_cycle = (uint32_t)hal_get_cycles();
     2014#endif
     2015
    20952016#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2096 cycle = (uint32_t)hal_get_cycles();
    2097 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
    2098 printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2099 __FUNCTION__, vpn, ref_ppn, ref_attr, cycle );
     2017if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
     2018printk("\n[%s] local page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
     2019__FUNCTION__, vpn, ppn, attr, end_cycle );
     2020#endif
     2021
     2022#if CONFIG_INSTRUMENTATION_PGFAULTS
     2023this->info.local_pgfault_nr++;
     2024this->info.local_pgfault_cost += (end_cycle - start_cycle);
    21002025#endif
    21012026            return EXCP_NON_FATAL;
    2102         }
    2103         else                            // true page fault => update reference GPT
     2027
     2028        }   // end local GPT access
     2029
     2030        // public vseg and (local != reference) => access ref GPT to update local GPT
     2031        else                               
    21042032        {
    2105             // take reference GPT lock in write mode
    2106             remote_rwlock_wr_acquire( ref_lock_xp );
    2107            
    2108             // check VPN still unmapped in reference GPT
    2109             // do nothing if VPN has been mapped by a a concurrent page_fault
     2033            // build extended pointer on reference GPT
     2034            ref_gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
     2035
     2036            // get current PPN and attributes from reference GPT
    21102037            hal_gpt_get_pte( ref_gpt_xp,
    21112038                             vpn,
     
    21132040                             &ref_ppn );
    21142041
    2115             if( (ref_attr & GPT_MAPPED) == 0 )       // VPN actually unmapped
    2116             {
     2042            if( ref_attr & GPT_MAPPED )        // false page fault => update local GPT
     2043            {
     2044                // update local GPT from reference GPT values
     2045                hal_gpt_set_pte( local_gpt_xp,
     2046                                 vpn,
     2047                                 ref_attr,
     2048                                 ref_ppn );
     2049
     2050#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
     2051uint32_t end_cycle = (uint32_t)hal_get_cycles();
     2052#endif
     2053
     2054#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2055if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
     2056printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
     2057__FUNCTION__, vpn, ref_ppn, ref_attr, end_cycle );
     2058#endif
     2059
     2060#if CONFIG_INSTRUMENTATION_PGFAULTS
     2061this->info.false_pgfault_nr++;
     2062this->info.false_pgfault_cost += (end_cycle - start_cycle);
     2063#endif
     2064                return EXCP_NON_FATAL;
     2065            }
     2066            else                            // true page fault => update both GPTs
     2067            {
    21172068                // allocate and initialise a physical page depending on the vseg type
    2118                 error = vmm_get_one_ppn( vseg , vpn , &new_ppn );
     2069                error = vmm_get_one_ppn( vseg , vpn , &ppn );
    21192070
    21202071                if( error )
     
    21232074                    __FUNCTION__ , process->pid , vpn );
    21242075
    2125                    // release reference GPT lock in write mode
    2126                    remote_rwlock_wr_release( ref_lock_xp );
     2076                    // unlock PTE in local GPT
     2077                    hal_gpt_unlock_pte( local_gpt_xp , vpn );
    21272078                   
    2128                    return EXCP_KERNEL_PANIC;
     2079                    return EXCP_KERNEL_PANIC;
    21292080                }
    21302081
    2131                 // define new_attr from vseg flags
    2132                 new_attr = GPT_MAPPED | GPT_SMALL;
    2133                 if( vseg->flags & VSEG_USER  ) new_attr |= GPT_USER;
    2134                 if( vseg->flags & VSEG_WRITE ) new_attr |= GPT_WRITABLE;
    2135                 if( vseg->flags & VSEG_EXEC  ) new_attr |= GPT_EXECUTABLE;
    2136                 if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE;
    2137 
    2138                 // update reference GPT
    2139                 error = hal_gpt_set_pte( ref_gpt_xp,
    2140                                          vpn,
    2141                                          new_attr,
    2142                                          new_ppn );
    2143 
    2144                 // update local GPT (protected by reference GPT lock)
    2145                 error |= hal_gpt_set_pte( local_gpt_xp,
     2082                // lock PTE in reference GPT
     2083                error = hal_gpt_lock_pte( ref_gpt_xp,
    21462084                                          vpn,
    2147                                           new_attr,
    2148                                           new_ppn );
    2149 
     2085                                          &ref_attr,
     2086                                          &ref_ppn );
    21502087                if( error )
    21512088                {
    2152                     printk("\n[ERROR] in %s : cannot update GPT / process %x / vpn = %x\n",
    2153                     __FUNCTION__ , process->pid , vpn );
    2154 
    2155                     // release reference GPT lock in write mode
    2156                     remote_rwlock_wr_release( ref_lock_xp );
    2157 
     2089                    printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n",
     2090                    __FUNCTION__ , vpn , process->pid );
     2091       
     2092                    // unlock PTE in local GPT
     2093                    hal_gpt_unlock_pte( local_gpt_xp , vpn );
     2094                   
    21582095                    return EXCP_KERNEL_PANIC;
    21592096                }
     2097
     2098                // define attr from vseg flags
     2099                attr = GPT_MAPPED | GPT_SMALL;
     2100                if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
     2101                if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
     2102                if( vseg->flags & VSEG_EXEC  ) attr |= GPT_EXECUTABLE;
     2103                if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
     2104
     2105                // set PTE in reference GPT
     2106                hal_gpt_set_pte( ref_gpt_xp,
     2107                                 vpn,
     2108                                 attr,
     2109                                 ppn );
     2110
     2111                // set PTE in local GPT
     2112                hal_gpt_set_pte( local_gpt_xp,
     2113                                 vpn,
     2114                                 attr,
     2115                                 ppn );
     2116
     2117#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
     2118uint32_t end_cycle = (uint32_t)hal_get_cycles();
     2119#endif
     2120
     2121#if DEBUG_VMM_HANDLE_PAGE_FAULT
     2122if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
     2123printk("\n[%s] global page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
     2124__FUNCTION__, vpn, ppn, attr, end_cycle );
     2125#endif
     2126
     2127#if CONFIG_INSTRUMENTATION_PGFAULTS
     2128this->info.global_pgfault_nr++;
     2129this->info.global_pgfault_cost += (end_cycle - start_cycle);
     2130#endif
     2131                return EXCP_NON_FATAL;
    21602132            }
    2161 
    2162             // release reference GPT lock in write mode
    2163             remote_rwlock_wr_release( ref_lock_xp );
    2164 
    2165 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2166 cycle = (uint32_t)hal_get_cycles();
    2167 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
    2168 printk("\n[%s] true page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
    2169 __FUNCTION__, vpn, new_ppn, new_attr, cycle );
    2170 #endif
    2171             return EXCP_NON_FATAL;
    21722133        }
    21732134    }
     2135    else   // page has been locally mapped by another concurrent thread
     2136    {
     2137        // unlock PTE in local GPT
     2138        hal_gpt_unlock_pte( local_gpt_xp , vpn );
     2139
     2140        return EXCP_NON_FATAL;
     2141    }
     2142
    21742143}   // end vmm_handle_page_fault()
    21752144
     
    21792148{
    21802149    vseg_t         * vseg;            // vseg containing vpn
    2181     cxy_t            ref_cxy;         // reference cluster for missing vpn
    2182     process_t      * ref_ptr;         // reference process for missing vpn
    2183     xptr_t           gpt_xp;          // extended pointer on GPT
    2184     xptr_t           gpt_lock_xp;     // extended pointer on GPT lock
     2150    xptr_t           gpt_xp;          // extended pointer on GPT (local or reference)
     2151    gpt_t          * gpt_ptr;         // local pointer on GPT (local or reference)
     2152    cxy_t            gpt_cxy;         // GPT cluster identifier
    21852153    uint32_t         old_attr;        // current PTE_ATTR value
    21862154    ppn_t            old_ppn;         // current PTE_PPN value
    21872155    uint32_t         new_attr;        // new PTE_ATTR value
    21882156    ppn_t            new_ppn;         // new PTE_PPN value
     2157    cxy_t            ref_cxy;         // reference process cluster
     2158    process_t      * ref_ptr;         // local pointer on reference process
    21892159    error_t          error;
    21902160
    2191     thread_t * this = CURRENT_THREAD;
     2161    thread_t * this  = CURRENT_THREAD;
    21922162
    21932163#if DEBUG_VMM_HANDLE_COW
    2194 uint32_t   cycle   = (uint32_t)hal_get_cycles();
     2164uint32_t   cycle = (uint32_t)hal_get_cycles();
    21952165if( DEBUG_VMM_HANDLE_COW < cycle )
    21962166printk("\n[%s] thread[%x,%x] enter for vpn %x / core[%x,%d] / cycle %d\n",
    21972167__FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle );
     2168#endif
     2169
     2170#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
    21982171hal_vmm_display( process , true );
    21992172#endif
    2200 
    2201     // access local GPT to get GPT_COW flag
    2202     bool_t cow = hal_gpt_pte_is_cow( &(process->vmm.gpt), vpn );
    2203 
    2204     if( cow == false ) return EXCP_USER_ERROR;
    22052173
    22062174    // get local vseg
     
    22102178    if( error )
    22112179    {
    2212         printk("\n[PANIC] in %s vpn %x in thread[%x,%x] not in a registered vseg\n",
     2180        printk("\n[ERROR] in %s : vpn %x in thread[%x,%x] not in a registered vseg\n",
    22132181        __FUNCTION__, vpn, process->pid, this->trdid );
    22142182
    2215         return EXCP_KERNEL_PANIC;
    2216     }
    2217 
    2218 #if( DEBUG_VMM_HANDLE_COW & 1)
     2183        return EXCP_USER_ERROR;
     2184    }
     2185
     2186#if DEBUG_VMM_HANDLE_COW
    22192187if( DEBUG_VMM_HANDLE_COW < cycle )
    2220 printk("\n[%s] thread[%x,%x] get vseg for vpn %x\n",
    2221 __FUNCTION__, this->process->pid, this->trdid, vpn );
    2222 #endif
    2223 
    2224     // get reference GPT cluster and local pointer
     2188printk("\n[%s] thread[%x,%x] get vseg %s\n",
     2189__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
     2190#endif
     2191
     2192    // get reference process cluster and local pointer
    22252193    ref_cxy = GET_CXY( process->ref_xp );
    22262194    ref_ptr = GET_PTR( process->ref_xp );
    22272195
    2228     // build relevant extended pointers on  relevant GPT and  GPT lock
    2229     // - access local GPT for a private vseg 
    2230     // - access reference GPT for a public vseg
     2196    // build pointers on relevant GPT
     2197    // - access only local GPT for a private vseg 
     2198    // - access reference GPT and all copies for a public vseg
    22312199    if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) )
    22322200    {
    2233         gpt_xp      = XPTR( local_cxy , &process->vmm.gpt );
    2234         gpt_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock );
     2201        gpt_cxy = local_cxy;
     2202        gpt_ptr = &process->vmm.gpt;
     2203        gpt_xp  = XPTR( gpt_cxy , gpt_ptr );
    22352204    }
    22362205    else
    22372206    {
    2238         gpt_xp      = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
    2239         gpt_lock_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt_lock );
    2240     }
    2241 
    2242     // take GPT lock in write mode
    2243     remote_rwlock_wr_acquire( gpt_lock_xp );
    2244 
    2245     // get current PTE from reference GPT
    2246     hal_gpt_get_pte( gpt_xp,
    2247                      vpn,
    2248                      &old_attr,
    2249                      &old_ppn );
    2250 
    2251 #if( DEBUG_VMM_HANDLE_COW & 1)
     2207        gpt_cxy = ref_cxy;
     2208        gpt_ptr = &ref_ptr->vmm.gpt;
     2209        gpt_xp  = XPTR( gpt_cxy , gpt_ptr );
     2210    }
     2211
     2212    // lock target PTE in relevant GPT (local or reference)
     2213    error = hal_gpt_lock_pte( gpt_xp,
     2214                              vpn,
     2215                              &old_attr,
     2216                              &old_ppn );
     2217    if( error )
     2218    {
     2219        printk("\n[PANIC] in %s : cannot lock PTE in GPT / cxy %x / vpn %x / process %x\n",
     2220        __FUNCTION__ , gpt_cxy, vpn , process->pid );
     2221       
     2222        return EXCP_KERNEL_PANIC;
     2223    }
     2224
     2225#if DEBUG_VMM_HANDLE_COW
    22522226if( DEBUG_VMM_HANDLE_COW < cycle )
    22532227printk("\n[%s] thread[%x,%x] get pte for vpn %x : ppn %x / attr %x\n",
     
    22552229#endif
    22562230
    2257     // the PTE must be mapped for a COW
    2258     if( (old_attr & GPT_MAPPED) == 0 )
    2259     {
    2260         printk("\n[PANIC] in %s : VPN %x in process %x unmapped\n",
    2261         __FUNCTION__, vpn, process->pid );
    2262 
    2263         // release GPT lock in write mode
    2264         remote_rwlock_wr_release( gpt_lock_xp );
    2265 
    2266         return EXCP_KERNEL_PANIC;
     2231    // return user error if COW attribute not set or PTE2 unmapped
     2232    if( ((old_attr & GPT_COW) == 0) || ((old_attr & GPT_MAPPED) == 0) )
     2233    {
     2234        hal_gpt_unlock_pte( gpt_xp , vpn );
     2235
     2236        return EXCP_USER_ERROR;
    22672237    }
    22682238
     
    22822252    uint32_t forks = hal_remote_l32( forks_xp );
    22832253
    2284 #if( DEBUG_VMM_HANDLE_COW & 1)
     2254#if DEBUG_VMM_HANDLE_COW
    22852255if( DEBUG_VMM_HANDLE_COW < cycle )
    22862256printk("\n[%s] thread[%x,%x] get forks = %d for vpn %x\n",
     
    22962266        remote_busylock_release( forks_lock_xp );
    22972267
    2298         // allocate a new page
     2268        // allocate a new physical page depending on vseg type
    22992269        page_xp = vmm_page_allocate( vseg , vpn );
    23002270
     
    23042274            __FUNCTION__ , vpn, process->pid );
    23052275
    2306             // release GPT lock in write mode
    2307             remote_rwlock_wr_acquire( gpt_lock_xp );
     2276            hal_gpt_unlock_pte( gpt_xp , vpn );
    23082277
    23092278            return EXCP_KERNEL_PANIC;
     
    23132282        new_ppn = ppm_page2ppn( page_xp );
    23142283
    2315 #if( DEBUG_VMM_HANDLE_COW & 1)
     2284#if DEBUG_VMM_HANDLE_COW
    23162285if( DEBUG_VMM_HANDLE_COW < cycle )
    23172286printk("\n[%s] thread[%x,%x] get new ppn %x for vpn %x\n",
     
    23242293                           CONFIG_PPM_PAGE_SIZE );
    23252294
    2326 #if(DEBUG_VMM_HANDLE_COW & 1)
     2295#if DEBUG_VMM_HANDLE_COW
    23272296if( DEBUG_VMM_HANDLE_COW < cycle )
    23282297printk("\n[%s] thread[%x,%x] copied old page to new page\n",
     
    23442313    }
    23452314
    2346     // build new_attr : reset COW and set WRITABLE,
    2347     new_attr = (old_attr | GPT_WRITABLE) & (~GPT_COW);
    2348 
    2349     // update the relevant GPT
    2350     // - private vseg => update local GPT
    2351     // - public vseg => update all GPT copies
     2315    // build new_attr : set WRITABLE, reset COW, reset LOCKED
     2316    new_attr = (((old_attr | GPT_WRITABLE) & (~GPT_COW)) & (~GPT_LOCKED));
     2317
     2318    // update the relevant GPT(s)
     2319    // - private vseg => update only the local GPT
     2320    // - public vseg => update the reference GPT AND all the GPT copies
    23522321    if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) )
    23532322    {
     2323        // set the new PTE2
    23542324        hal_gpt_set_pte( gpt_xp,
    23552325                         vpn,
     
    23762346    }
    23772347
    2378     // release GPT lock in write mode
    2379     remote_rwlock_wr_release( gpt_lock_xp );
    2380 
    23812348#if DEBUG_VMM_HANDLE_COW
    23822349cycle = (uint32_t)hal_get_cycles();
  • trunk/kernel/mm/vmm.h

    r625 r629  
    106106 * 3. The GPT in the reference cluster can be directly accessed by remote threads to handle
    107107 *    false page-fault (page is mapped in the reference GPT, but the PTE copy is missing
    108  *    in the local GPT). It is also protected by a remote_rwlock.
     108 *    in the local GPT). As each PTE can be protected by a specific GPT_LOCKED attribute
     109 *    for exclusive access, it is NOT protected by a global lock.
    109110 ********************************************************************************************/
    110111
     
    115116        uint32_t         vsegs_nr;           /*! total number of local vsegs                    */
    116117
    117     remote_rwlock_t  gpt_lock;           /*! lock protecting the local GPT                  */
    118118    gpt_t            gpt;                /*! Generic Page Table (complete in reference)     */
    119119
     
    165165 * This function is called by the process_make_fork() function. It partially copies
    166166 * the content of a remote parent process VMM to the local child process VMM:
    167  * - All DATA, ANON, REMOTE vsegs registered in the parent VSL are registered in the
     167 * - The DATA, ANON, REMOTE vsegs registered in the parent VSL are registered in the
    168168 *   child VSL. All valid PTEs in parent GPT are copied to the child GPT, but the
    169169 *   WRITABLE flag is reset and the COW flag is set.
    170  * - All CODE vsegs registered in the parent VSL are registered in the child VSL, but the
     170 * - The CODE vsegs registered in the parent VSL are registered in the child VSL, but the
    171171 *   GPT entries are not copied in the child GPT, and will be dynamically updated from
    172172 *   the .elf file when a page fault is reported.
    173  * - All FILE vsegs registered in the parent VSL are registered in the child VSL, and all
     173 * - The FILE vsegs registered in the parent VSL are registered in the child VSL, and all
    174174 *   valid GPT entries in parent GPT are copied to the child GPT. The COW flag is not set.
    175175 * - No STACK vseg is copied from  parent VMM to child VMM, because the child stack vseg
     
    186186
    187187/*********************************************************************************************
    188  * This function is called by the process_make_fork() function executing the fork syscall.
    189  * It set the COW flag, and reset the WRITABLE flag of all GPT entries of the DATA, MMAP,
    190  * and REMOTE vsegs of a process identified by the <process> argument.
     188 * This function is called by the process_make_fork() function to update the COW attribute
     189 * in the parent parent process vsegs. It set the COW flag, and reset the WRITABLE flag of
     190 * all GPT entries of the DATA, MMAP, and REMOTE vsegs of the <process> argument.
    191191 * It must be called by a thread running in the reference cluster, that contains the complete
    192192 * VSL and GPT (use the rpc_vmm_set_cow_client() when the calling thread client is remote).
     
    201201
    202202/*********************************************************************************************
    203  * This function modifies a GPT entry identified by the <process> and <vpn> arguments
     203 * This function modifies one GPT entry identified by the <process> and <vpn> arguments
    204204 * in all clusters containing a process copy.
    205  * It must be called by a thread running in the reference cluster.
    206  * It updates all copies of the process in all clusters, to maintain coherence in GPT copies,
    207  * using the list of copies stored in the owner process, and using remote_write accesses to
    208  * update the remote GPTs. It cannot fail, as only mapped entries in GPT copies are updated.
     205 * 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.
     208 * It cannot fail, as only mapped PTE2 in GPT copies are updated.
    209209 *********************************************************************************************
    210210 * @ process   : local pointer on local process descriptor.
     
    373373 *    is mapped in the reference GPT, but not in the local GPT. For this false page-fault,
    374374 *    the local GPT is simply updated from the reference GPT.
    375  * 3) if the missing VPN is public, and unmapped in the reference GPT, it's a true page fault.
     375 * 3) if the missing VPN is public, and unmapped in the ref GPT, it is a true page fault.
    376376 *    The calling thread  allocates a new physical page, computes the attributes, depending
    377377 *    on vseg type, and updates directly (without RPC) the local GPT and the reference GPT.
    378378 *    Other GPT copies  will updated on demand.
    379  * Concurrent accesses to the GPT are handled, thanks to the
    380  * remote_rwlock protecting each GPT copy.
     379 * Concurrent accesses to the GPT(s) are handled, by locking the target PTE before accessing
     380 * the local and/or reference GPT(s).
    381381 *********************************************************************************************
    382382 * @ process  : local pointer on local process.
     
    392392 * It returns a kernel panic if VPN is not in a registered vseg or is not mapped.
    393393 * For a legal mapped vseg there is two cases:
    394  * 1) If the missing VPN belongs to a private vseg (STACK or CODE segment types, non
    395  *    replicated in all clusters), it access the local GPT to get the current PPN and ATTR.
     394 * 1) If the missing VPN belongs to a private vseg (STACK), it access only the local GPT.
    396395 *    It access the forks counter in the current physical page descriptor.
    397396 *    If there is a pending fork, it allocates a new physical page from the cluster defined
     
    399398 *    and decrements the pending_fork counter in old physical page descriptor.
    400399 *    Finally, it reset the COW flag and set the WRITE flag in local GPT.
    401  * 2) If the missing VPN is public, it access the reference GPT to get the current PPN and
    402  *    ATTR. It access the forks counter in the current physical page descriptor.
     400 * 2) If the missing VPN is public, it access only the reference GPT.
     401 *    It access the forks counter in the current physical page descriptor.
    403402 *    If there is a pending fork, it allocates a new physical page from the cluster defined
    404403 *    by the vseg type, copies the old physical page content to the new physical page,
     
    406405 *    Finally it calls the vmm_global_update_pte() function to reset the COW flag and set
    407406 *    the WRITE flag in all the GPT copies, using a RPC if the reference cluster is remote.
    408  * In both cases, concurrent accesses to the GPT are protected by the remote_rwlock
    409  * atached to the GPT copy in VMM.
     407 * In both cases, concurrent accesses to the GPT are handled by locking the target PTE
     408 * before accessing the GPT.
    410409 *********************************************************************************************
    411410 * @ process   : pointer on local process descriptor copy.
  • trunk/kernel/syscalls/sys_barrier.c

    r626 r629  
    184184        }
    185185        ////////
    186         default: {
     186        default:
     187        {
    187188            assert ( false, "illegal operation type <%x>", operation );
    188189        }
  • trunk/libs/libalmosmkh/almosmkh.h

    r626 r629  
    267267 * This syscall implements an user-level interactive debugger that can be
    268268 * introduced in any user application to display various kernel distributed structures.
    269  * The supported commands are:
    270  * - p (cxy)     : display all processes descriptors in a given cluster.
    271  * - s (cxy,lid) : display all threads attached to a given core in a given cluster.
    272  * - v (cxy)     : display the calling process VMM in a given cluster.
    273  * - t (tid)     : display all owner process descriptors attached to a TXT terminal.
    274  * - x           : force the calling process to exit.
    275  * - c           : continue calling process execution.
    276  * - h           : list the supported commands
    277269 ***************************************************************************************/
    278270void idbg( void );
  • trunk/params-hard.mk

    r628 r629  
    22
    33ARCH      = /users/alain/soc/tsar-trunk-svn-2013/platforms/tsar_generic_iob
    4 X_SIZE    = 2
    5 Y_SIZE    = 2
    6 NB_PROCS  = 4
    7 NB_TTYS   = 3
     4X_SIZE    = 4
     5Y_SIZE    = 4
     6NB_PROCS  = 1
     7NB_TTYS   = 2
    88IOC_TYPE  = IOC_BDV
    99TXT_TYPE  = TXT_TTY
  • trunk/user/fft/fft.c

    r628 r629  
    538538        exit(0);
    539539    }
    540     printf("\n[sort] file <%s> closed\n", path );
     540    printf("\n[fft] file <%s> closed\n", path );
    541541
    542542    exit( 0 );
     
    570570
    571571#if DEBUG_SLAVE
    572 printf("\n[fft] %s : thread %x enter / cycle %d\n",
     572printf("\n[fft] %s : thread %d enter / cycle %d\n",
    573573__FUNCTION__, MyNum, (unsigned int)parallel_start );
    574574#endif
     575
     576    // BARRIER
     577    get_cycle( &barrier_start );
     578    pthread_barrier_wait( &barrier );
     579    get_cycle( &barrier_stop );
     580    sync_time[MyNum] += (barrier_stop - barrier_start);
     581
     582// printf("\n[@@@] %s : thread %d exit first barrier / cycle %d\n",
     583// __FUNCTION__, MyNum, (unsigned int)barrier_stop );
    575584
    576585    // allocate and initialise local array upriv[]
     
    592601    FFT1D( 1 , data , trans , upriv , twid , MyNum , MyFirst , MyLast );
    593602
    594     // BARRIER
    595     get_cycle( &barrier_start );
    596     pthread_barrier_wait( &barrier );
    597     get_cycle( &barrier_stop );
    598 
    599     sync_time[MyNum] += (barrier_stop - barrier_start);
    600 
    601603#if CHECK
    602604get_cycle( &barrier_start );
    603605pthread_barrier_wait( &barrier );
    604606get_cycle( &barrier_stop );
    605 
    606607sync_time[MyNum] += (long)(barrier_stop - barrier_start);
    607 
    608608FFT1D( -1 , data , trans , upriv , twid , MyNum , MyFirst , MyLast );
    609609#endif
     
    688688{
    689689    unsigned int         i , j;
    690     double       cks;
    691690    unsigned int         c_id;
    692691    unsigned int         c_offset;
     692    double               cks;
    693693
    694694    cks = 0.0;
     
    849849unsigned long long cycle;
    850850get_cycle( &cycle );
    851 printf("\n[fft] %s : thread %x enter / first %d / last %d / cycle %d\n",
     851printf("\n[fft] %s : thread %d enter / first %d / last %d / cycle %d\n",
    852852__FUNCTION__, MyNum, MyFirst, MyLast, (unsigned int)cycle );
    853853#endif
     
    858858#if( DEBUG_FFT1D & 1 )
    859859get_cycle( &cycle );
    860 printf("\n[fft] %s : thread %x after first transpose / cycle %d\n",
     860printf("\n[fft] %s : thread %d after first transpose / cycle %d\n",
    861861__FUNCTION__, MyNum, (unsigned int)cycle );
    862862if( PRINT_ARRAY ) PrintArray( tmp , N );
     
    871871#if( DEBUG_FFT1D & 1 )
    872872get_cycle( &cycle );
    873 printf("\n[fft] %s : thread %x exit barrier after first transpose / cycle %d\n",
     873printf("\n[fft] %s : thread %d exit barrier after first transpose / cycle %d\n",
    874874__FUNCTION__, MyNum, (unsigned int)cycle );
    875875#endif
     
    884884
    885885#if( DEBUG_FFT1D & 1 )
    886 printf("\n[fft] %s : thread %x after first twiddle\n", __FUNCTION__, MyNum);
     886printf("\n[fft] %s : thread %d after first twiddle\n", __FUNCTION__, MyNum);
    887887if( PRINT_ARRAY ) PrintArray( tmp , N );
    888888#endif
     
    894894
    895895#if( DEBUG_FFT1D & 1 )
    896 printf("\n[fft] %s : thread %x exit barrier after first twiddle\n", __FUNCTION__, MyNum);
     896printf("\n[fft] %s : thread %d exit barrier after first twiddle\n", __FUNCTION__, MyNum);
    897897#endif
    898898
     
    903903
    904904#if( DEBUG_FFT1D & 1 )
    905 printf("\n[fft] %s : thread %x after second transpose\n", __FUNCTION__, MyNum);
     905printf("\n[fft] %s : thread %d after second transpose\n", __FUNCTION__, MyNum);
    906906if( PRINT_ARRAY ) PrintArray( x , N );
    907907#endif
     
    913913
    914914#if( DEBUG_FFT1D & 1 )
    915 printf("\n[fft] %s : thread %x exit barrier after second transpose\n", __FUNCTION__, MyNum);
     915printf("\n[fft] %s : thread %d exit barrier after second transpose\n", __FUNCTION__, MyNum);
    916916#endif
    917917
     
    926926
    927927#if( DEBUG_FFT1D & 1 )
    928 printf("\n[fft] %s : thread %x after FFT on rows\n", __FUNCTION__, MyNum);
     928printf("\n[fft] %s : thread %d after FFT on rows\n", __FUNCTION__, MyNum);
    929929if( PRINT_ARRAY ) PrintArray( x , N );
    930930#endif
     
    936936
    937937#if( DEBUG_FFT1D & 1 )
    938 printf("\n[fft] %s : thread %x exit barrier after FFT on rows\n", __FUNCTION__, MyNum);
     938printf("\n[fft] %s : thread %d exit barrier after FFT on rows\n", __FUNCTION__, MyNum);
    939939#endif
    940940    sync_time[MyNum] += (long)(barrier_stop - barrier_start);
     
    954954
    955955#if( DEBUG_FFT1D & 1 )
    956 printf("\n[fft] %s : thread %x exit barrier after third transpose\n", __FUNCTION__, MyNum);
     956printf("\n[fft] %s : thread %d exit barrier after third transpose\n", __FUNCTION__, MyNum);
    957957#endif
    958958
     
    964964
    965965#if DEBUG_FFT1D
    966 printf("\n[fft] %s : thread %x completed\n", __FUNCTION__, MyNum);
     966printf("\n[fft] %s : thread %d completed\n", __FUNCTION__, MyNum);
    967967if( PRINT_ARRAY ) PrintArray( x , N );
    968968#endif
  • trunk/user/ksh/ksh.c

    r628 r629  
    11871187else
    11881188{
    1189     printf("\n[ksh] load bin/user/sort.elf\n");
     1189    printf("\n[ksh] load bin/user/fft.elf\n");
    11901190}
    11911191
    1192 strcpy( cmd , "load bin/user/sort.elf" );
     1192strcpy( cmd , "load bin/user/fft.elf" );
    11931193execute( cmd );
    11941194*/
  • trunk/user/sort/sort.c

    r628 r629  
    2929#include <hal_macros.h>
    3030
    31 #define ARRAY_LENGTH        1024       // number of items
     31#define ARRAY_LENGTH        4096       // number of items
    3232#define MAX_THREADS         1024       // 16 * 16 * 4
    3333
     
    423423
    424424#if CHECK_RESULT
    425    
    426425    int    success = 1;
    427426    int *  res_array = ( (total_threads ==   2) ||
     
    444443    if ( success ) printf("\n[sort] success\n");
    445444    else           printf("\n[sort] failure\n");
    446 
    447445#endif
    448446
    449447#if INSTRUMENTATION
    450 
    451448    char               name[64];
    452449    char               path[128];
    453450    unsigned long long instru_cycle;
    454451
    455     // build a file name from n_items / n_clusters / n_cores
    456     if( USE_DQT_BARRIER ) snprintf( name , 64 , "sort_dqt_%d_%d_%d",
    457                           ARRAY_LENGTH, x_size * y_size, ncores );
    458     else                  snprintf( name , 64 , "sort_smp_%d_%d_%d",
    459                           ARRAY_LENGTH, x_size * y_size, ncores );
     452    // build file name
     453    if( USE_DQT_BARRIER )
     454    snprintf( name , 64 , "sort_dqt_%d_%d_%d", ARRAY_LENGTH, x_size * y_size, ncores );
     455    else
     456    snprintf( name , 64 , "sort_smp_%d_%d_%d", ARRAY_LENGTH, x_size * y_size, ncores );
    460457
    461458    // build file pathname
     
    471468           " - parallel   : %d cycles\n",
    472469           name, sequencial, parallel );
    473 
    474 #if IDBG
    475 idbg();
    476 #endif
    477470
    478471    // open file
Note: See TracChangeset for help on using the changeset viewer.