Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 635)
+++ trunk/kernel/mm/vmm.c	(revision 640)
@@ -32,5 +32,4 @@
 #include <printk.h>
 #include <memcpy.h>
-#include <remote_rwlock.h>
 #include <remote_queuelock.h>
 #include <list.h>
@@ -313,5 +312,5 @@
 
     // initialize the lock protecting the VSL 
-	remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
+	remote_queuelock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
 
 
@@ -425,5 +424,5 @@
 
     // take the VSL lock
-	remote_rwlock_wr_acquire( lock_xp );
+	remote_queuelock_acquire( lock_xp );
 
     // scan the VSL to delete all non kernel vsegs
@@ -474,5 +473,5 @@
 
     // release the VSL lock
-	remote_rwlock_wr_release( lock_xp );
+	remote_queuelock_release( lock_xp );
 
 // FIXME il faut gérer les process copies...
@@ -491,4 +490,225 @@
 
 }  // end vmm_user_reset()
+
+/////////////////////////////////////////////////
+void vmm_global_delete_vseg( process_t * process,
+                             intptr_t    base )
+{
+    pid_t           pid;
+    cxy_t           owner_cxy;
+    lpid_t          owner_lpid;
+
+    xlist_entry_t * process_root_ptr;
+    xptr_t          process_root_xp;
+    xptr_t          process_iter_xp;
+
+    xptr_t          remote_process_xp;
+    cxy_t           remote_process_cxy;
+    process_t     * remote_process_ptr;
+
+    xptr_t          vsl_root_xp;
+    xptr_t          vsl_lock_xp;
+    xptr_t          vsl_iter_xp;
+
+#if DEBUG_VMM_GLOBAL_DELETE_VSEG
+uint32_t cycle = (uint32_t)hal_get_cycles();
+thread_t * this = CURRENT_THREAD;
+#endif
+
+#if (DEBUG_VMM_GLOBAL_DELETE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_DELETE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] : process %x / base %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, process->pid, base, cycle );
+#endif
+
+    // get owner process cluster and local index 
+    pid              = process->pid;
+    owner_cxy        = CXY_FROM_PID( pid );
+    owner_lpid       = LPID_FROM_PID( pid );
+
+    // get extended pointer on root of process copies xlist in owner cluster
+    process_root_ptr = &LOCAL_CLUSTER->pmgr.copies_root[owner_lpid];
+    process_root_xp  = XPTR( owner_cxy , process_root_ptr );
+
+    // loop on process copies
+    XLIST_FOREACH( process_root_xp , process_iter_xp )
+    {
+        // get cluster and local pointer on remote process
+        remote_process_xp  = XLIST_ELEMENT( process_iter_xp , process_t , copies_list );
+        remote_process_ptr = GET_PTR( remote_process_xp );
+        remote_process_cxy = GET_CXY( remote_process_xp );
+
+        // build extended pointers on remote VSL root and lock
+        vsl_root_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.vsegs_root );
+        vsl_lock_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.vsl_lock );
+
+        // get lock on remote VSL
+        remote_queuelock_acquire( vsl_lock_xp );
+
+        // loop on vsegs in remote process VSL
+        XLIST_FOREACH( vsl_root_xp , vsl_iter_xp )
+        {
+            // get pointers on current vseg 
+            xptr_t   vseg_xp  = XLIST_ELEMENT( vsl_iter_xp , vseg_t , xlist );
+            vseg_t * vseg_ptr = GET_PTR( vseg_xp );
+
+            // get current vseg base address
+            intptr_t vseg_base = (intptr_t)hal_remote_lpt( XPTR( remote_process_cxy,
+                                                                 &vseg_ptr->min ) );
+
+            if( vseg_base == base )   // found searched vseg
+            {
+                if( remote_process_cxy == local_cxy )
+                {
+                    vmm_remove_vseg( process,
+                                     vseg_ptr );
+                }
+                else
+                {
+                    rpc_vmm_remove_vseg_client( remote_process_cxy,
+                                                remote_process_ptr,
+                                                vseg_ptr );
+                }
+
+#if (DEBUG_VMM_GLOBAL_DELETE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_DELETE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] deleted vseg %x for process %x in cluster %x\n",
+__FUNCTION__, this->process->pid, this->trdid, base, process->pid, remote_process_cxy );
+#endif
+
+            }
+        }  // end of loop on vsegs
+
+#if (DEBUG_VMM_GLOBAL_DELETE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_DELETE_VSEG < cycle )
+hal_vmm_display( remote_process_xp , false );
+#endif
+
+        // release lock on remote VSL
+        remote_queuelock_release( vsl_lock_xp );
+
+    }  // end of loop on process copies
+
+#if DEBUG_VMM_GLOBAL_DELETE_VSEG
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_VMM_GLOBAL_DELETE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] exit for process %x / base %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, process->pid , base, cycle );
+#endif
+
+}  // end vmm_global_delete_vseg()
+
+////////////////////////////////////////////////
+void vmm_global_resize_vseg( process_t * process,
+                             intptr_t    base,
+                             intptr_t    new_base,
+                             intptr_t    new_size )
+{
+    pid_t           pid;
+    cxy_t           owner_cxy;
+    lpid_t          owner_lpid;
+
+    xlist_entry_t * process_root_ptr;
+    xptr_t          process_root_xp;
+    xptr_t          process_iter_xp;
+
+    xptr_t          remote_process_xp;
+    cxy_t           remote_process_cxy;
+    process_t     * remote_process_ptr;
+
+    xptr_t          vsl_root_xp;
+    xptr_t          vsl_lock_xp;
+    xptr_t          vsl_iter_xp;
+
+#if DEBUG_VMM_GLOBAL_RESIZE_VSEG
+uint32_t cycle = (uint32_t)hal_get_cycles();
+thread_t * this = CURRENT_THREAD;
+#endif
+
+#if (DEBUG_VMM_GLOBAL_RESIZE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_RESIZE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] : process %x / base %x / new_base %x / new_size %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, process->pid, base, new_base, new_size, cycle );
+#endif
+
+    // get owner process cluster and local index 
+    pid              = process->pid;
+    owner_cxy        = CXY_FROM_PID( pid );
+    owner_lpid       = LPID_FROM_PID( pid );
+
+    // get extended pointer on root of process copies xlist in owner cluster
+    process_root_ptr = &LOCAL_CLUSTER->pmgr.copies_root[owner_lpid];
+    process_root_xp  = XPTR( owner_cxy , process_root_ptr );
+
+    // loop on process copies
+    XLIST_FOREACH( process_root_xp , process_iter_xp )
+    {
+        // get cluster and local pointer on remote process
+        remote_process_xp  = XLIST_ELEMENT( process_iter_xp , process_t , copies_list );
+        remote_process_ptr = GET_PTR( remote_process_xp );
+        remote_process_cxy = GET_CXY( remote_process_xp );
+
+        // build extended pointers on remote VSL root and lock
+        vsl_root_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.vsegs_root );
+        vsl_lock_xp = XPTR( remote_process_cxy , &remote_process_ptr->vmm.vsl_lock );
+
+        // get lock on remote VSL
+        remote_queuelock_acquire( vsl_lock_xp );
+
+        // loop on vsegs in remote process VSL
+        XLIST_FOREACH( vsl_root_xp , vsl_iter_xp )
+        {
+            // get pointers on current vseg 
+            xptr_t   vseg_xp  = XLIST_ELEMENT( vsl_iter_xp , vseg_t , xlist );
+            vseg_t * vseg_ptr = GET_PTR( vseg_xp );
+
+            // get current vseg base address
+            intptr_t vseg_base = (intptr_t)hal_remote_lpt( XPTR( remote_process_cxy,
+                                                                 &vseg_ptr->min ) );
+
+            if( vseg_base == base )   // found searched vseg
+            {
+                if( remote_process_cxy == local_cxy )
+                {
+                    vmm_resize_vseg( remote_process_ptr,
+                                     vseg_ptr,
+                                     new_base,
+                                     new_size );
+                }
+                else
+                {
+                    rpc_vmm_resize_vseg_client( remote_process_cxy,
+                                                remote_process_ptr,
+                                                vseg_ptr,
+                                                new_base,
+                                                new_size );
+                }
+ 
+#if (DEBUG_VMM_GLOBAL_RESIZE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_RESIZE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] resized vseg %x for process %x in cluster %x\n",
+__FUNCTION__, this->process->pid, this->trdid, base, process->pid, remote_process_cxy );
+#endif
+
+            }
+        }  // end of loop on vsegs
+
+#if (DEBUG_VMM_GLOBAL_RESIZE_VSEG & 1)
+if( DEBUG_VMM_GLOBAL_RESIZE_VSEG < cycle )
+hal_vmm_display( remote_process_xp , false );
+#endif
+
+        // release lock on remote VSL
+        remote_queuelock_release( vsl_lock_xp );
+    }  // end of loop on process copies
+
+#if DEBUG_VMM_GLOBAL_RESIZE_VSEG
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_VMM_GLOBAL_RESIZE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] exit for process %x / base %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, process->pid , base, cycle );
+#endif
+
+}  // end vmm_global_resize_vseg()
 
 ////////////////////////////////////////////////
@@ -498,4 +718,8 @@
                             ppn_t       ppn )
 {
+    pid_t           pid;
+    cxy_t           owner_cxy;
+    lpid_t          owner_lpid;
+
     xlist_entry_t * process_root_ptr;
     xptr_t          process_root_xp;
@@ -507,27 +731,26 @@
     xptr_t          remote_gpt_xp;
 
-    pid_t           pid;
-    cxy_t           owner_cxy;
-    lpid_t          owner_lpid;
-
-#if DEBUG_VMM_UPDATE_PTE
+#if DEBUG_VMM_GLOBAL_UPDATE_PTE
 uint32_t cycle = (uint32_t)hal_get_cycles();
 thread_t * this = CURRENT_THREAD;
-if( DEBUG_VMM_UPDATE_PTE < cycle )
+#endif
+
+
+#if (DEBUG_VMM_GLOBAL_UPDATE_PTE & 1)
+if( DEBUG_VMM_GLOBAL_UPDATE_PTE < cycle )
 printk("\n[%s] thread[%x,%x] enter for process %x / vpn %x / attr %x / ppn %x / ycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, process->pid, vpn, attr, ppn, cycle );
 #endif
 
-    // get extended pointer on root of process copies xlist in owner cluster
+    // get owner process cluster and local index
     pid              = process->pid;
     owner_cxy        = CXY_FROM_PID( pid );
     owner_lpid       = LPID_FROM_PID( pid );
+
+    // get extended pointer on root of process copies xlist in owner cluster
     process_root_ptr = &LOCAL_CLUSTER->pmgr.copies_root[owner_lpid];
     process_root_xp  = XPTR( owner_cxy , process_root_ptr );
 
-// check local cluster is owner cluster
-assert( (owner_cxy == local_cxy) , "must be called in owner cluster\n");
-
-    // loop on destination process copies
+    // loop on process copies
     XLIST_FOREACH( process_root_xp , process_iter_xp )
     {
@@ -537,6 +760,6 @@
         remote_process_cxy = GET_CXY( remote_process_xp );
 
-#if (DEBUG_VMM_UPDATE_PTE & 1)
-if( DEBUG_VMM_UPDATE_PTE < cycle )
+#if (DEBUG_VMM_GLOBAL_UPDATE_PTE & 1)
+if( DEBUG_VMM_GLOBAL_UPDATE_PTE < cycle )
 printk("\n[%s] thread[%x,%x] handling vpn %x for process %x in cluster %x\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, process->pid, remote_process_cxy );
@@ -550,12 +773,12 @@
     }  
 
-#if DEBUG_VMM_UPDATE_PTE
+#if DEBUG_VMM_GLOBAL_UPDATE_PTE
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_UPDATE_PTE < cycle )
+if( DEBUG_VMM_GLOBAL_UPDATE_PTE < cycle )
 printk("\n[%s] thread[%x,%x] exit for process %x / vpn %x / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, process->pid , vpn , cycle );
 #endif
 
-#if (DEBUG_VMM_UPDATE_PTE & 1)
+#if (DEBUG_VMM_GLOBAL_UPDATE_PTE & 1)
 hal_vmm_display( process , true );
 #endif
@@ -772,6 +995,6 @@
     parent_lock_xp = XPTR( parent_cxy , &parent_vmm->vsl_lock );
 
-    // take the lock protecting the parent VSL in read mode
-    remote_rwlock_rd_acquire( parent_lock_xp );
+    // take the lock protecting the parent VSL 
+    remote_queuelock_acquire( parent_lock_xp );
 
     // loop on parent VSL xlist
@@ -809,15 +1032,15 @@
             vseg_init_from_ref( child_vseg , parent_vseg_xp );
 
-            // build extended pointer on VSL lock
-            xptr_t lock_xp = XPTR( local_cxy , &child_vmm->vsl_lock );
+            // build extended pointer on child VSL lock
+            xptr_t child_lock_xp = XPTR( local_cxy , &child_vmm->vsl_lock );
  
-            // take the VSL lock in write mode
-            remote_rwlock_wr_acquire( lock_xp );
+            // take the child VSL lock 
+            remote_queuelock_acquire( child_lock_xp );
 
             // register child vseg in child VSL
             vmm_attach_vseg_to_vsl( child_vmm , child_vseg );
 
-            // release the VSL lock
-            remote_rwlock_wr_release( lock_xp );
+            // release the child VSL lock
+            remote_queuelock_release( child_lock_xp );
 
 #if DEBUG_VMM_FORK_COPY
@@ -866,5 +1089,5 @@
 
     // release the parent VSL lock in read mode
-    remote_rwlock_rd_release( parent_lock_xp );
+    remote_queuelock_release( parent_lock_xp );
 
     // initialize the child VMM STACK allocator
@@ -939,5 +1162,5 @@
 
     // take the VSL lock
-    remote_rwlock_wr_acquire( vsl_lock_xp );
+    remote_queuelock_acquire( vsl_lock_xp );
 
     // scan the VSL to delete all registered vsegs
@@ -968,5 +1191,5 @@
 
     // release the VSL lock
-    remote_rwlock_wr_release( vsl_lock_xp );
+    remote_queuelock_release( vsl_lock_xp );
 
     // remove all registered MMAP vsegs
@@ -1042,6 +1265,4 @@
 
 }  // end vmm_check_conflict()
-
-
 
 ////////////////////////////////////////////////
@@ -1060,7 +1281,11 @@
 	error_t      error;
 
+#if DEBUG_VMM_CREATE_VSEG
+thread_t * this  = CURRENT_THREAD;
+uint32_t   cycle;
+#endif
+
 #if (DEBUG_VMM_CREATE_VSEG & 1)
-thread_t * this  = CURRENT_THREAD;
-uint32_t   cycle = (uint32_t)hal_get_cycles();
+cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VMM_CREATE_VSEG < cycle )
 printk("\n[%s] thread[%x,%x] enter / process %x / %s / base %x / cxy %x / cycle %d\n",
@@ -1180,5 +1405,5 @@
  
     // take the VSL lock in write mode
-    remote_rwlock_wr_acquire( lock_xp );
+    remote_queuelock_acquire( lock_xp );
 
     // attach vseg to VSL
@@ -1186,9 +1411,10 @@
 
     // release the VSL lock
-    remote_rwlock_wr_release( lock_xp );
+    remote_queuelock_release( lock_xp );
 
 #if DEBUG_VMM_CREATE_VSEG
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_CREATE_VSEG < cycle )
+// if( DEBUG_VMM_CREATE_VSEG < cycle )
+if( type == VSEG_TYPE_REMOTE )
 printk("\n[%s] thread[%x,%x] exit / process %x / %s / base %x / cxy %x / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, 
@@ -1200,4 +1426,96 @@
 }  // vmm_create_vseg()
 
+////////////////////////////////////////////////////////////////////////////////////////////
+// This static function is called by the vmm_remove_vseg() and vmm_resize_vseg() functions.
+// Depending on the vseg <type>, it decrements the physical page refcount, and
+// conditionnally release to the relevant kmem the physical page identified by <ppn>.
+////////////////////////////////////////////////////////////////////////////////////////////
+// @ process  : local pointer on process.
+// @ vseg     : local pointer on vseg.
+// @ ppn      : released pysical page index. 
+////////////////////////////////////////////////////////////////////////////////////////////
+static void vmm_ppn_release( process_t * process,
+                             vseg_t    * vseg,
+                             ppn_t       ppn )
+{
+    bool_t do_release;
+
+    // get vseg type
+    vseg_type_t type = vseg->type;
+
+    // compute is_ref
+    bool_t is_ref = (GET_CXY( process->ref_xp ) == local_cxy);
+
+    // get pointers on physical page descriptor
+    xptr_t   page_xp  = ppm_ppn2page( ppn );
+    cxy_t    page_cxy = GET_CXY( page_xp );
+    page_t * page_ptr = GET_PTR( page_xp );
+
+    // decrement page refcount
+    xptr_t count_xp = XPTR( page_cxy , &page_ptr->refcount );
+    hal_remote_atomic_add( count_xp , -1 );
+
+    // compute the do_release condition depending on vseg type
+    if( (type == VSEG_TYPE_FILE)  ||
+        (type == VSEG_TYPE_KCODE) || 
+        (type == VSEG_TYPE_KDATA) || 
+        (type == VSEG_TYPE_KDEV) )            
+    {
+        // no physical page release for FILE and KERNEL 
+        do_release = false;
+    }
+    else if( (type == VSEG_TYPE_CODE)  ||
+             (type == VSEG_TYPE_STACK) ) 
+    {
+        // always release physical page for private vsegs
+        do_release = true;
+    }
+    else if( (type == VSEG_TYPE_ANON)  ||
+             (type == VSEG_TYPE_REMOTE) )
+    {
+        // release physical page if reference cluster
+        do_release = is_ref;
+    }
+    else if( is_ref )  // vseg_type == DATA in reference cluster
+    {
+        // get extended pointers on forks and lock field in page descriptor
+        xptr_t forks_xp = XPTR( page_cxy , &page_ptr->forks );
+        xptr_t lock_xp  = XPTR( page_cxy , &page_ptr->lock );
+
+        // take lock protecting "forks" counter
+        remote_busylock_acquire( lock_xp );
+
+        // get number of pending forks from page descriptor
+        uint32_t forks = hal_remote_l32( forks_xp );
+
+        // decrement pending forks counter if required
+        if( forks )  hal_remote_atomic_add( forks_xp , -1 );
+
+        // release lock protecting "forks" counter
+        remote_busylock_release( lock_xp );
+
+        // release physical page if forks == 0
+        do_release = (forks == 0); 
+    }
+    else              // vseg_type == DATA not in reference cluster
+    {
+        // no physical page release if not in reference cluster 
+        do_release = false;
+    }
+
+    // release physical page to relevant kmem when required
+    if( do_release )
+    {
+        ppm_remote_free_pages( page_cxy , page_ptr );
+
+#if DEBUG_VMM_PPN_RELEASE
+thread_t * this = CURRENT_THREAD;
+if( DEBUG_VMM_PPN_RELEASE < cycle )
+printk("\n[%s] thread[%x,%x] released ppn %x to kmem\n",
+__FUNCTION__, this->process->pid, this->trdid, ppn );
+#endif
+
+    }
+} // end vmm_ppn_release()
 
 //////////////////////////////////////////
@@ -1205,7 +1523,4 @@
                       vseg_t    * vseg )
 {
-    vmm_t     * vmm;        // local pointer on process VMM
-    xptr_t      gpt_xp;     // extended pointer on GPT
-    bool_t      is_ref;     // local process is reference process
     uint32_t    vseg_type;  // vseg type
     vpn_t       vpn;        // VPN of current PTE
@@ -1214,8 +1529,4 @@
     ppn_t       ppn;        // current PTE ppn value
     uint32_t    attr;       // current PTE attributes
-    xptr_t      page_xp;    // extended pointer on page descriptor
-    cxy_t       page_cxy;   // page descriptor cluster
-    page_t    * page_ptr;   // page descriptor pointer
-    xptr_t      count_xp;   // extended pointer on page refcount
 
 // check arguments
@@ -1223,12 +1534,9 @@
 assert( (vseg    != NULL), "vseg argument is NULL" );
 
-    // compute is_ref
-    is_ref = (GET_CXY( process->ref_xp ) == local_cxy);
-
     // get pointers on local process VMM 
-    vmm = &process->vmm;
+    vmm_t * vmm = &process->vmm;
 
     // build extended pointer on GPT
-    gpt_xp = XPTR( local_cxy , &vmm->gpt );
+    xptr_t gpt_xp = XPTR( local_cxy , &vmm->gpt );
 
     // get relevant vseg infos
@@ -1240,4 +1548,7 @@
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
+#endif
+
+#if (DEBUG_VMM_REMOVE_VSEG & 1 )
 if( DEBUG_VMM_REMOVE_VSEG < cycle )
 printk("\n[%s] thread[%x,%x] enter / process %x / %s / base %x / cycle %d\n",
@@ -1246,5 +1557,5 @@
 #endif
 
-    // loop on PTEs in GPT
+    // loop on PTEs in GPT to unmap all mapped PTE
 	for( vpn = vpn_min ; vpn < vpn_max ; vpn++ )
     {
@@ -1257,77 +1568,12 @@
 #if( DEBUG_VMM_REMOVE_VSEG & 1 )
 if( DEBUG_VMM_REMOVE_VSEG < cycle )
-printk("- unmap vpn %x / ppn %x / %s" , vpn , ppn, vseg_type_str(vseg_type) );
+printk("\n[%s] thread[%x,%x] unmap vpn %x / ppn %x / %s",
+__FUNCTION__, this->process->pid, this->trdid, vpn , ppn, vseg_type_str(vseg_type) );
 #endif
             // unmap GPT entry in local GPT
             hal_gpt_reset_pte( gpt_xp , vpn );
 
-            // get pointers on physical page descriptor
-            page_xp  = ppm_ppn2page( ppn );
-            page_cxy = GET_CXY( page_xp );
-            page_ptr = GET_PTR( page_xp );
-
-            // decrement page refcount
-            count_xp = XPTR( page_cxy , &page_ptr->refcount );
-            hal_remote_atomic_add( count_xp , -1 );
-
-            // compute the ppn_release condition depending on vseg type
-            bool_t ppn_release;
-            if( (vseg_type == VSEG_TYPE_FILE)  ||
-                (vseg_type == VSEG_TYPE_KCODE) || 
-                (vseg_type == VSEG_TYPE_KDATA) || 
-                (vseg_type == VSEG_TYPE_KDEV) )            
-            {
-                // no physical page release for FILE and KERNEL 
-                ppn_release = false;
-            }
-            else if( (vseg_type == VSEG_TYPE_CODE)  ||
-                     (vseg_type == VSEG_TYPE_STACK) ) 
-            {
-                // always release physical page for private vsegs
-                ppn_release = true;
-            }
-            else if( (vseg_type == VSEG_TYPE_ANON)  ||
-                     (vseg_type == VSEG_TYPE_REMOTE) )
-            {
-                // release physical page if reference cluster
-                ppn_release = is_ref;
-            }
-            else if( is_ref )  // vseg_type == DATA in reference cluster
-            {
-                // get extended pointers on forks and lock field in page descriptor
-                xptr_t forks_xp = XPTR( page_cxy , &page_ptr->forks );
-                xptr_t lock_xp  = XPTR( page_cxy , &page_ptr->lock );
-
-                // take lock protecting "forks" counter
-                remote_busylock_acquire( lock_xp );
-
-                // get number of pending forks from page descriptor
-                uint32_t forks = hal_remote_l32( forks_xp );
-
-                // decrement pending forks counter if required
-                if( forks )  hal_remote_atomic_add( forks_xp , -1 );
-
-                // release lock protecting "forks" counter
-                remote_busylock_release( lock_xp );
-
-                // release physical page if forks == 0
-                ppn_release = (forks == 0); 
-            }
-            else              // vseg_type == DATA not in reference cluster
-            {
-                // no physical page release if not in reference cluster 
-                ppn_release = false;
-            }
-
-            // release physical page to relevant kmem when required
-            if( ppn_release ) ppm_remote_free_pages( page_cxy , page_ptr );
-
-#if( DEBUG_VMM_REMOVE_VSEG & 1 )
-if( DEBUG_VMM_REMOVE_VSEG < cycle )
-{
-    if( ppn_release ) printk(" / released to kmem\n" );
-    else              printk("\n");
-}
-#endif
+            // release physical page when required
+            vmm_ppn_release( process , vseg , ppn );
         }
     }
@@ -1368,229 +1614,146 @@
 }  // end vmm_remove_vseg()
 
-
-///////////////////////////////////
-void vmm_delete_vseg( pid_t    pid,
-                      intptr_t vaddr )
+/////////////////////////////////////////////
+void vmm_resize_vseg( process_t * process,
+                      vseg_t    * vseg,
+                      intptr_t    new_base,
+                      intptr_t    new_size )
 {
-    process_t * process;    // local pointer on local process 
-    vseg_t    * vseg;       // local pointer on local vseg containing vaddr
-
-    // get local pointer on local process descriptor
-    process = cluster_get_local_process_from_pid( pid );
-
-    if( process == NULL )
-    {
-        printk("\n[WARNING] in %s : cannot get local process descriptor\n",
-        __FUNCTION__ );
-        return;
-    }
-
-    // get local pointer on local vseg containing vaddr
-    vseg = vmm_vseg_from_vaddr( &process->vmm , vaddr );
-
-    if( vseg == NULL )
-    {
-        printk("\n[WARNING] in %s : cannot get vseg descriptor\n",
-        __FUNCTION__ );
-        return;
-    }
-
-    // call relevant function
-    vmm_remove_vseg( process , vseg );
-
-}  // end vmm_delete_vseg
-
-
-/////////////////////////////////////////////
-vseg_t * vmm_vseg_from_vaddr( vmm_t    * vmm,
-                              intptr_t   vaddr )
-{
-    xptr_t   vseg_xp;
-    vseg_t * vseg;
-    xptr_t   iter_xp;
-
-    // get extended pointers on VSL lock and root
-    xptr_t lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
-    xptr_t root_xp = XPTR( local_cxy , &vmm->vsegs_root );
-
-    // get lock protecting the VSL
-    remote_rwlock_rd_acquire( lock_xp );
-
-    // scan the list of vsegs in VSL
-    XLIST_FOREACH( root_xp , iter_xp )
-    {
-        // get pointers on vseg
-        vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
-        vseg    = GET_PTR( vseg_xp );
-
-        // return success when match
-        if( (vaddr >= vseg->min) && (vaddr < vseg->max) )
-        { 
-            // return success
-            remote_rwlock_rd_release( lock_xp );
-            return vseg;
-        }
-    }
-
-    // return failure
-    remote_rwlock_rd_release( lock_xp );
-    return NULL;
-
-}  // end vmm_vseg_from_vaddr()
-
-/////////////////////////////////////////////
-error_t vmm_resize_vseg( process_t * process,
-                         intptr_t    base,
-                         intptr_t    size )
-{
-    error_t   error;
-    vseg_t  * new;
-    vpn_t     vpn_min;
-    vpn_t     vpn_max;
+    vpn_t     vpn;
+    ppn_t     ppn;
+    uint32_t  attr;
+
+// check arguments
+assert( (process != NULL), "process argument is NULL" );
+assert( (vseg    != NULL), "vseg argument is NULL" );
 
 #if DEBUG_VMM_RESIZE_VSEG
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
+#endif
+
+#if (DEBUG_VMM_RESIZE_VSEG & 1)
 if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] enter / process %x / base %x / size %d / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, process->pid, base, size, cycle );
-#endif
-
-    // get pointer on process VMM
-    vmm_t * vmm = &process->vmm;
-
-    intptr_t addr_min = base;
-	intptr_t addr_max = base + size;
-
-    // get pointer on vseg
-	vseg_t * vseg = vmm_vseg_from_vaddr( vmm , base );
-
-	if( vseg == NULL)
-    {
-        printk("\n[ERROR] in %s : vseg(%x,%d) not found\n",
-        __FUNCTION__, base , size );
-        return -1;
-    }
-
-    // resize depends on unmapped region base and size
-	if( (vseg->min > addr_min) || (vseg->max < addr_max) )        // not included in vseg
-    {
-        printk("\n[ERROR] in %s : unmapped region[%x->%x[ not included in vseg[%x->%x[\n",
-        __FUNCTION__, addr_min, addr_max, vseg->min, vseg->max );
-
-        error = -1;
-    }
-	else if( (vseg->min == addr_min) && (vseg->max == addr_max) )  // vseg must be deleted
-    {
+printk("\n[%s] thread[%x,%x] enter / process %x / %s / base %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, 
+process->pid, vseg_type_str(vseg->type), old_base, cycle );
+#endif
+
+    // get existing vseg vpn_min and vpn_max
+    vpn_t     old_vpn_min = vseg->vpn_base;
+    vpn_t     old_vpn_max = old_vpn_min + vseg->vpn_size - 1;
+
+    // compute new vseg vpn_min & vpn_max  
+    intptr_t min          = new_base;
+    intptr_t max          = new_base + new_size;
+    vpn_t    new_vpn_min  = min >> CONFIG_PPM_PAGE_SHIFT;
+    vpn_t    new_vpn_max  = (max - 1) >> CONFIG_PPM_PAGE_SHIFT;
+
+    // build extended pointer on GPT
+    xptr_t gpt_xp = XPTR( local_cxy , &process->vmm.gpt );
+
+    // loop on PTEs in GPT to unmap PTE if (oldd_vpn_min <= vpn < new_vpn_min)
+	for( vpn = old_vpn_min ; vpn < new_vpn_min ; vpn++ )
+    {
+        // get ppn and attr
+        hal_gpt_get_pte( gpt_xp , vpn , &attr , &ppn );
+
+        if( attr & GPT_MAPPED )  // PTE is mapped
+        { 
 
 #if( DEBUG_VMM_RESIZE_VSEG & 1 )
 if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] unmapped region[%x->%x[ equal vseg[%x->%x[\n",
-__FUNCTION__, addr_min, addr_max, vseg->min, vseg->max );
-#endif
-        vmm_delete_vseg( process->pid , vseg->min );
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
+printk("\n[%s] thread[%x,%x] unmap vpn %x / ppn %x / %s",
+__FUNCTION__, this->process->pid, this->trdid, vpn , ppn, vseg_type_str(vseg_type) );
+#endif
+            // unmap GPT entry 
+            hal_gpt_reset_pte( gpt_xp , vpn );
+
+            // release physical page when required
+            vmm_ppn_release( process , vseg , ppn );
+        }
+    }
+
+    // loop on PTEs in GPT to unmap PTE if (new vpn_max <= vpn < old_vpn_max)
+	for( vpn = new_vpn_max ; vpn < old_vpn_max ; vpn++ )
+    {
+        // get ppn and attr
+        hal_gpt_get_pte( gpt_xp , vpn , &attr , &ppn );
+
+        if( attr & GPT_MAPPED )  // PTE is mapped
+        { 
+
+#if( DEBUG_VMM_REMOVE_VSEG & 1 )
 if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] deleted vseg\n",
-__FUNCTION__, this->process->pid, this->trdid );
-#endif
-        error = 0;
-    }
-	else if( vseg->min == addr_min )                               // vseg must be resized
-    {
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
+printk("\n[%s] thread[%x,%x] unmap vpn %x / ppn %x / %s",
+__FUNCTION__, this->process->pid, this->trdid, vpn , ppn, vseg_type_str(vseg_type) );
+#endif
+            // unmap GPT entry in local GPT
+            hal_gpt_reset_pte( gpt_xp , vpn );
+
+            // release physical page when required
+            vmm_ppn_release( process , vseg , ppn );
+        }
+    }
+
+    // resize vseg in VSL
+    vseg->min      = min;
+    vseg->max      = max;
+    vseg->vpn_base = new_vpn_min;
+    vseg->vpn_size = new_vpn_max - new_vpn_min + 1;
+
+#if DEBUG_VMM_RESIZE_VSEG
+cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] unmapped region[%x->%x[ included in vseg[%x->%x[\n",
-__FUNCTION__, addr_min, addr_max, vseg->min, vseg->max );
-#endif
-        // update vseg min address
-        vseg->min = addr_max;
-
-        // update vpn_base and vpn_size
-        vpn_min        = vseg->min >> CONFIG_PPM_PAGE_SHIFT;
-        vpn_max        = (vseg->max - 1) >> CONFIG_PPM_PAGE_SHIFT;
-        vseg->vpn_base = vpn_min;
-        vseg->vpn_size = vpn_max - vpn_min + 1;
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] changed vseg_min\n",
-__FUNCTION__, this->process->pid, this->trdid );
-#endif
-        error = 0;
-    }
-	else if( vseg->max == addr_max )                              // vseg must be resized
-    {
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] unmapped region[%x->%x[ included in vseg[%x->%x[\n",
-__FUNCTION__, addr_min, addr_max, vseg->min, vseg->max );
-#endif
-        // update vseg max address
-        vseg->max = addr_min;
-
-        // update vpn_base and vpn_size
-        vpn_min        = vseg->min >> CONFIG_PPM_PAGE_SHIFT;
-        vpn_max        = (vseg->max - 1) >> CONFIG_PPM_PAGE_SHIFT;
-        vseg->vpn_base = vpn_min;
-        vseg->vpn_size = vpn_max - vpn_min + 1;
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] changed vseg_max\n",
-__FUNCTION__, this->process->pid, this->trdid );
-#endif
-        error = 0;
-
-    }
-    else                                                          // vseg cut in three regions 
-    {
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] unmapped region[%x->%x[ included in vseg[%x->%x[\n",
-__FUNCTION__, addr_min, addr_max, vseg->min, vseg->max );
-#endif
-        // resize existing vseg
-        vseg->max = addr_min;
-
-        // update vpn_base and vpn_size
-        vpn_min        = vseg->min >> CONFIG_PPM_PAGE_SHIFT;
-        vpn_max        = (vseg->max - 1) >> CONFIG_PPM_PAGE_SHIFT;
-        vseg->vpn_base = vpn_min;
-        vseg->vpn_size = vpn_max - vpn_min + 1;
-
-        // create new vseg
-        new = vmm_create_vseg( process, 
-                               vseg->type,
-                               addr_min, 
-                               (vseg->max - addr_max),
-                               vseg->file_offset,
-                               vseg->file_size,
-                               vseg->mapper_xp,
-                               vseg->cxy ); 
-
-#if( DEBUG_VMM_RESIZE_VSEG & 1 )
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] replaced vseg by two smal vsegs\n",
-__FUNCTION__, this->process->pid, this->trdid );
-#endif
-
-        if( new == NULL ) error = -1;
-        else              error = 0;
-    }
-
-#if DEBUG_VMM_RESIZE_VSEG
-if( DEBUG_VMM_RESIZE_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] exit / process %x / base %x / size %d / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, process->pid, base, size, cycle );
-#endif
-
-	return error;
-
-}  // vmm_resize_vseg()
+printk("[%s] thread[%x,%x] exit / process %x / %s / base %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, 
+process->pid, vseg_type_str(vseg->type), vseg->min, cycle );
+#endif
+
+}  // end vmm_resize_vseg
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// This static function is called twice by the vmm_get_vseg() function.
+// It scan the - possibly remote - VSL defined by the <vmm_xp> argument to find the vseg
+// containing a given virtual address <vaddr>. It uses remote accesses to access the remote
+// VSL if required. The VSL lock protecting the VSL must be taken by the caller.
+/////////////////////////////////////////////////////////////////////////////////////////////
+// @ vmm_xp  : extended pointer on the process VMM.
+// @ vaddr   : virtual address.
+// @ return local pointer on remote vseg if success / return NULL if not found.
+/////////////////////////////////////////////////////////////////////////////////////////////
+static vseg_t * vmm_vseg_from_vaddr( xptr_t     vmm_xp,
+                                     intptr_t   vaddr )
+{
+    xptr_t   iter_xp;
+    xptr_t   vseg_xp;
+    vseg_t * vseg;
+    intptr_t min;
+    intptr_t max;
+
+    // get cluster and local pointer on target VMM
+    vmm_t * vmm_ptr = GET_PTR( vmm_xp );
+    cxy_t   vmm_cxy = GET_CXY( vmm_xp );
+
+    // build extended pointer on VSL root
+    xptr_t root_xp = XPTR( vmm_cxy , &vmm_ptr->vsegs_root );
+
+    // scan the list of vsegs in VSL
+    XLIST_FOREACH( root_xp , iter_xp )
+    {
+        vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
+        vseg    = GET_PTR( vseg_xp );
+
+        min = hal_remote_l32( XPTR( vmm_cxy , &vseg->min ) );
+        max = hal_remote_l32( XPTR( vmm_cxy , &vseg->max ) );
+
+        // return success when match
+        if( (vaddr >= min) && (vaddr < max) ) return vseg;
+    }
+
+    // return failure
+    return NULL;
+
+}  // end vmm_vseg_from_vaddr()
 
 ///////////////////////////////////////////
@@ -1599,56 +1762,87 @@
                        vseg_t   ** found_vseg )
 {
-    xptr_t    vseg_xp;
-    vseg_t  * vseg;
-    vmm_t   * vmm;
-    error_t   error;
-
-    // get pointer on local VMM
-    vmm = &process->vmm;
+    xptr_t    loc_lock_xp;     // extended pointer on local VSL lock
+    xptr_t    ref_lock_xp;     // extended pointer on reference VSL lock
+    vseg_t  * loc_vseg;        // local pointer on local vseg
+    vseg_t  * ref_vseg;        // local pointer on reference vseg
+
+    // build extended pointer on local VSL lock
+    loc_lock_xp = XPTR( local_cxy , &process->vmm.vsl_lock );
+     
+    // get local VSL lock 
+    remote_queuelock_acquire( loc_lock_xp );
 
     // try to get vseg from local VMM
-    vseg = vmm_vseg_from_vaddr( vmm , vaddr );
-
-    if( vseg == NULL )   // vseg not found in local cluster => try to get it from ref
-	{
+    loc_vseg = vmm_vseg_from_vaddr( XPTR( local_cxy, &process->vmm ) , vaddr );
+
+    if (loc_vseg == NULL)   // vseg not found => access reference VSL
+    {
         // get extended pointer on reference process
         xptr_t ref_xp = process->ref_xp;
 
-        // get cluster and local pointer on reference process 
+        // get cluster and local pointer on reference process
         cxy_t       ref_cxy = GET_CXY( ref_xp );
         process_t * ref_ptr = GET_PTR( ref_xp );
 
-        if( local_cxy == ref_cxy )  return -1;   // local cluster is the reference
-
-        // get extended pointer on reference vseg
-        rpc_vmm_get_vseg_client( ref_cxy , ref_ptr , vaddr , &vseg_xp , &error );
-            
-        if( error )   return -1;                // vseg not found => illegal user vaddr 
-        
-        // allocate a vseg in local cluster
-        vseg = vseg_alloc();
-
-        if( vseg == NULL ) return -1;           // cannot allocate a local vseg
-
-        // initialise local vseg from reference
-        vseg_init_from_ref( vseg , vseg_xp );
-
-        // build extended pointer on VSL lock
-        xptr_t lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
- 
-        // take the VSL lock in write mode
-        remote_rwlock_wr_acquire( lock_xp );
-
-        // register local vseg in local VSL
-        vmm_attach_vseg_to_vsl( vmm , vseg );
- 
-        // release the VSL lock
-        remote_rwlock_wr_release( lock_xp );
-    }   
-
-    // success
-    *found_vseg = vseg;
-    return 0;
-
+        // build extended pointer on reference VSL lock
+        ref_lock_xp = XPTR( ref_cxy , &ref_ptr->vmm.vsl_lock );
+     
+        // get reference VSL lock 
+        remote_queuelock_acquire( ref_lock_xp );
+
+        // try to get vseg from reference VMM
+        ref_vseg = vmm_vseg_from_vaddr( XPTR( ref_cxy , &ref_ptr->vmm ) , vaddr );
+
+        if( ref_vseg == NULL )  // vseg not found => return error
+        {
+            printk("\n[ERROR] in %s : vaddr %x in process %x out of segment\n",
+            __FUNCTION__, vaddr, process->pid );
+
+            // release reference VSL lock 
+            remote_queuelock_release( ref_lock_xp );
+
+            return -1;
+        }
+        else                    // vseg found => try to update local VSL 
+        {
+            // allocate a local vseg descriptor
+            loc_vseg = vseg_alloc();
+
+            if( loc_vseg == NULL )   // no memory => return error
+            {
+                printk("\n[ERROR] in %s : vaddr %x in process %x / no memory for local vseg\n",
+                __FUNCTION__, vaddr, process->pid );
+
+                // release reference VSL & local VSL locks
+                remote_queuelock_release( ref_lock_xp );
+                remote_queuelock_release( loc_lock_xp );
+
+                return -1;
+            }
+            else                     // update local VSL and return success
+            {
+                // initialize local vseg
+                vseg_init_from_ref( loc_vseg , XPTR( ref_cxy , ref_vseg ) );
+
+                // register local vseg in local VSL
+                vmm_attach_vseg_to_vsl( &process->vmm , loc_vseg );
+
+                // release reference VSL & local VSL locks
+                remote_queuelock_release( ref_lock_xp );
+                remote_queuelock_release( loc_lock_xp );
+
+                *found_vseg = loc_vseg;
+                return 0;
+            }
+        }
+    }
+    else                        // vseg found in local VSL => return success
+    {
+        // release local VSL lock 
+        remote_queuelock_release( loc_lock_xp );
+
+        *found_vseg = loc_vseg;
+        return 0;
+    }
 }  // end vmm_get_vseg()
 
@@ -1658,4 +1852,8 @@
 // pointer on the allocated page descriptor.
 // The vseg cannot have the FILE type.
+//////////////////////////////////////////////////////////////////////////////////////
+// @ vseg   : local pointer on vseg.
+// @ vpn    : unmapped vpn.
+// @ return an extended pointer on the allocated page
 //////////////////////////////////////////////////////////////////////////////////////
 static xptr_t vmm_page_allocate( vseg_t * vseg,
@@ -2194,5 +2392,5 @@
 #if DEBUG_VMM_HANDLE_COW
 uint32_t   cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] enter for vpn %x / core[%x,%d] / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle );
@@ -2200,5 +2398,5 @@
 
 #if ((DEBUG_VMM_HANDLE_COW & 3) == 3 )
-hal_vmm_display( process , true );
+hal_vmm_display( XPTR( local_cxy , process ) , true );
 #endif
 
@@ -2216,5 +2414,5 @@
 
 #if DEBUG_VMM_HANDLE_COW 
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] get vseg %s\n",
 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
@@ -2256,5 +2454,5 @@
 
 #if DEBUG_VMM_HANDLE_COW 
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] get pte for vpn %x : ppn %x / attr %x\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, old_ppn, old_attr );
@@ -2285,5 +2483,5 @@
 
 #if DEBUG_VMM_HANDLE_COW 
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] get forks = %d for vpn %x\n",
 __FUNCTION__, this->process->pid, this->trdid, forks, vpn );
@@ -2315,5 +2513,5 @@
 
 #if DEBUG_VMM_HANDLE_COW 
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] get new ppn %x for vpn %x\n",
 __FUNCTION__, this->process->pid, this->trdid, new_ppn, vpn );
@@ -2326,5 +2524,5 @@
 
 #if DEBUG_VMM_HANDLE_COW
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] copied old page to new page\n",
 __FUNCTION__, this->process->pid, this->trdid );
@@ -2338,5 +2536,5 @@
 
 #if(DEBUG_VMM_HANDLE_COW & 1)
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] no pending forks / keep existing PPN %x\n",
 __FUNCTION__, this->process->pid, this->trdid, old_ppn );
@@ -2349,5 +2547,5 @@
 
 #if(DEBUG_VMM_HANDLE_COW & 1)
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] new_attr %x / new_ppn %x\n",
 __FUNCTION__, this->process->pid, this->trdid, new_attr, new_ppn );
@@ -2367,24 +2565,14 @@
     else
     {
-        if( ref_cxy == local_cxy )                  // reference cluster is local
-        {
-            vmm_global_update_pte( process,
-                                   vpn,
-                                   new_attr,
-                                   new_ppn );
-        }
-        else                                        // reference cluster is remote
-        {
-            rpc_vmm_global_update_pte_client( ref_cxy,
-                                              ref_ptr,
-                                              vpn,
-                                              new_attr,
-                                              new_ppn );
-        }
+        // set new PTE in all GPT copies
+        vmm_global_update_pte( process,
+                               vpn,
+                               new_attr,
+                               new_ppn );
     }
 
 #if DEBUG_VMM_HANDLE_COW
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_HANDLE_COW < cycle )
+if( (DEBUG_VMM_HANDLE_COW < cycle) && (vpn > 0) )
 printk("\n[%s] thread[%x,%x] exit for vpn %x / core[%x,%d] / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle );
@@ -2392,5 +2580,5 @@
 
 #if ((DEBUG_VMM_HANDLE_COW & 3) == 3)
-hal_vmm_display( process , true );
+hal_vmm_display( XPTR( local_cxy , process ) , true );
 #endif
 
