Changeset 629 for trunk/hal


Ignore:
Timestamp:
May 17, 2019, 9:27:04 AM (5 years 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/hal
Files:
5 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 );
Note: See TracChangeset for help on using the changeset viewer.