Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 630)
+++ trunk/kernel/mm/vmm.c	(revision 632)
@@ -1226,5 +1226,4 @@
     ppn_t       ppn;        // current PTE ppn value
     uint32_t    attr;       // current PTE attributes
-    kmem_req_t  req;        // request to release memory
     xptr_t      page_xp;    // extended pointer on page descriptor
     cxy_t       page_cxy;   // page descriptor cluster
@@ -1335,17 +1334,5 @@
 
             // release physical page to relevant kmem when required
-            if( ppn_release )
-            {
-                if( page_cxy == local_cxy )
-                {
-                    req.type = KMEM_PAGE;
-                    req.ptr  = page_ptr; 
-                    kmem_free( &req );
-                }
-                else
-                {
-                    rpc_pmem_release_pages_client( page_cxy , page_ptr );
-                }
-            }
+            if( ppn_release ) ppm_remote_free_pages( page_cxy , page_ptr );
 
 #if( DEBUG_VMM_REMOVE_VSEG & 1 )
@@ -1681,7 +1668,6 @@
 //////////////////////////////////////////////////////////////////////////////////////
 // This static function compute the target cluster to allocate a physical page
-// for a given <vpn> in a given <vseg>, allocates the page (with an RPC if required)
-// and returns an extended pointer on the allocated page descriptor.
-// It can be called by a thread running in any cluster.
+// for a given <vpn> in a given <vseg>, allocates the page and returns an extended 
+// pointer on the allocated page descriptor.
 // The vseg cannot have the FILE type.
 //////////////////////////////////////////////////////////////////////////////////////
@@ -1690,15 +1676,14 @@
 {
 
-#if DEBUG_VMM_ALLOCATE_PAGE
+#if DEBUG_VMM_PAGE_ALLOCATE
 uint32_t   cycle   = (uint32_t)hal_get_cycles();
 thread_t * this    = CURRENT_THREAD;
-if( DEBUG_VMM_ALLOCATE_PAGE < (uint32_t)hal_get_cycles() )
+if( DEBUG_VMM_PAGE_ALLOCATE < cycle )
 printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
 __FUNCTION__ , this->process->pid, this->trdid, vpn, cycle );
 #endif
 
-    page_t     * page_ptr;
+    xptr_t       page_xp;
     cxy_t        page_cxy;
-    kmem_req_t   req;
     uint32_t     index;
 
@@ -1727,27 +1712,15 @@
     }
 
-    // allocate a physical page from target cluster
-    if( page_cxy == local_cxy )  // target cluster is the local cluster
-    {
-        req.type  = KMEM_PAGE;
-        req.size  = 0;
-        req.flags = AF_NONE;
-        page_ptr  = (page_t *)kmem_alloc( &req );
-    }
-    else                           // target cluster is not the local cluster
-    {
-        rpc_pmem_get_pages_client( page_cxy , 0 , &page_ptr );
-    }
-
-#if DEBUG_VMM_ALLOCATE_PAGE
+    // allocate a 4 Kbytes physical page from target cluster
+    page_xp = ppm_remote_alloc_pages( page_cxy , 0 );
+
+#if DEBUG_VMM_PAGE_ALLOCATE
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_ALLOCATE_PAGE < (uint32_t)hal_get_cycles() )
-printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle %d\n",
-__FUNCTION__ , this->process->pid, this->trdid, vpn,
-ppm_page2ppn( XPTR( page_cxy , page_ptr ) , cycle );
-#endif
-
-    if( page_ptr == NULL ) return XPTR_NULL;
-    else                   return XPTR( page_cxy , page_ptr );
+if( DEBUG_VMM_PAGE_ALLOCATE < cycle )
+printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cluster %x / cycle %d\n",
+__FUNCTION__ , this->process->pid, this->trdid, vpn, ppm_page2ppn(page_xp), page_cxy, cycle );
+#endif
+
+    return page_xp;
 
 }  // end vmm_page_allocate()  
@@ -1769,5 +1742,6 @@
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
-if( DEBUG_VMM_GET_ONE_PPN < cycle )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] enter for vpn %x / type %s / page_id  %d / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, vseg_type_str(type), page_id, cycle );
@@ -1815,5 +1789,6 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] for vpn = %x / elf_offset = %x\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, elf_offset );
@@ -1829,5 +1804,6 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] for vpn  %x / fully in BSS\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn );
@@ -1846,5 +1822,6 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] for vpn  %x / fully in mapper\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn );
@@ -1863,5 +1840,6 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] for vpn  %x / both mapper & BSS\n"
 "      %d bytes from mapper / %d bytes from BSS\n",
@@ -1897,5 +1875,6 @@
 #if DEBUG_VMM_GET_ONE_PPN
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_ONE_PPN < cycle )
+// if( DEBUG_VMM_GET_ONE_PPN < cycle )
+if( vpn == 0x40B )
 printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle\n",
 __FUNCTION__ , this->process->pid, this->trdid , vpn , *ppn, cycle );
@@ -1928,5 +1907,5 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
+if( vpn == 0x40b )
 printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle );
@@ -1950,7 +1929,8 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle )
-printk("\n[%s] thread[%x,%x] found vseg %s\n",
-__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] found vseg %s / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type), cycle );
 #endif
 
@@ -1958,5 +1938,5 @@
     local_gpt_xp  = XPTR( local_cxy , &process->vmm.gpt );
 
-    // lock target PTE in local GPT and get current PPN and attributes
+    // lock PTE in local GPT and get current PPN and attributes
     error = hal_gpt_lock_pte( local_gpt_xp,
                               vpn,
@@ -1971,5 +1951,12 @@
     }
 
-    // handle page fault only if PTE still unmapped after lock
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+cycle = (uint32_t)hal_get_cycles();
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] locked vpn %x in cluster %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, cycle );
+#endif
+
+    // handle page fault only if local PTE still unmapped after lock
     if( (attr & GPT_MAPPED) == 0 )
     {
@@ -1984,5 +1971,11 @@
             (ref_cxy    == local_cxy ) )
         {
-            // allocate and initialise a physical page depending on the vseg type
+
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] : access local gpt : local_cxy %x / ref_cxy %x / type %s\n",
+__FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
+#endif
+            // allocate and initialise a physical page 
             error = vmm_get_one_ppn( vseg , vpn , &ppn );
 
@@ -1999,5 +1992,5 @@
 
             // define attr from vseg flags 
-            attr = GPT_MAPPED | GPT_SMALL;
+            attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE;
             if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
             if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
@@ -2006,4 +1999,5 @@
 
             // set PTE to local GPT 
+            // it unlocks this PTE
             hal_gpt_set_pte( local_gpt_xp,
                              vpn,
@@ -2016,7 +2010,7 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
-printk("\n[%s] local page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
-__FUNCTION__, vpn, ppn, attr, end_cycle );
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] handled local pgfault / ppn %x / attr %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
 #endif
 
@@ -2033,17 +2027,39 @@
         else                                
         {
+
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] access ref gpt : local_cxy %x / ref_cxy %x / type %s\n",
+__FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
+#endif
             // build extended pointer on reference GPT
             ref_gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt );
 
-            // get current PPN and attributes from reference GPT
-            // without locking the PTE (in case of false page fault)
-            hal_gpt_get_pte( ref_gpt_xp,
-                             vpn,
-                             &ref_attr,
-                             &ref_ppn );
-
-            if( ref_attr & GPT_MAPPED )        // false page fault => update local GPT
+            // lock PTE in reference GPT and get current PPN and attributes
+            error = hal_gpt_lock_pte( ref_gpt_xp,
+                                      vpn,
+                                      &ref_attr,
+                                      &ref_ppn );
+            if( error )
+            {
+                printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n",
+                __FUNCTION__ , vpn , process->pid );
+        
+                // unlock PTE in local GPT
+                hal_gpt_unlock_pte( local_gpt_xp , vpn );
+                    
+                return EXCP_KERNEL_PANIC;
+            }
+
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] get pte from ref gpt / attr %x / ppn %x\n",
+__FUNCTION__, this->process->pid, this->trdid, ref_attr, ref_ppn );
+#endif
+
+            if( ref_attr & GPT_MAPPED )        // false page fault 
             {
                 // update local GPT from reference GPT values
+                // this unlocks the PTE in local GPT
                 hal_gpt_set_pte( local_gpt_xp,
                                  vpn,
@@ -2051,4 +2067,19 @@
                                  ref_ppn );
 
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] updated local gpt for a false pgfault\n",
+__FUNCTION__, this->process->pid, this->trdid );
+#endif
+
+                // unlock the PTE in reference GPT
+                hal_gpt_unlock_pte( ref_gpt_xp, vpn );
+                             
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] unlock the ref gpt after a false pgfault\n",
+__FUNCTION__, this->process->pid, this->trdid );
+#endif
+
 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
 uint32_t end_cycle = (uint32_t)hal_get_cycles();
@@ -2056,7 +2087,7 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
-printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
-__FUNCTION__, vpn, ref_ppn, ref_attr, end_cycle );
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] handled false pgfault / ppn %x / attr %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, ref_ppn, ref_attr, end_cycle );
 #endif
 
@@ -2067,5 +2098,5 @@
                 return EXCP_NON_FATAL;
             }
-            else                            // true page fault => update both GPTs
+            else                            // true page fault 
             {
                 // allocate and initialise a physical page depending on the vseg type
@@ -2077,28 +2108,13 @@
                     __FUNCTION__ , process->pid , vpn );
 
-                    // unlock PTE in local GPT
+                    // unlock PTE in local GPT and in reference GPT
                     hal_gpt_unlock_pte( local_gpt_xp , vpn );
+                    hal_gpt_unlock_pte( ref_gpt_xp   , vpn );
                     
                     return EXCP_KERNEL_PANIC;
                 }
 
-                // lock PTE in reference GPT
-                error = hal_gpt_lock_pte( ref_gpt_xp,
-                                          vpn,
-                                          &ref_attr,
-                                          &ref_ppn );
-                if( error )
-                {
-                    printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n",
-                    __FUNCTION__ , vpn , process->pid );
-        
-                    // unlock PTE in local GPT
-                    hal_gpt_unlock_pte( local_gpt_xp , vpn );
-                    
-                    return EXCP_KERNEL_PANIC;
-                }
-
                 // define attr from vseg flags 
-                attr = GPT_MAPPED | GPT_SMALL;
+                attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE;
                 if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
                 if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE;
@@ -2106,5 +2122,11 @@
                 if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
 
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] build a new PTE for a true pgfault\n",
+__FUNCTION__, this->process->pid, this->trdid );
+#endif
                 // set PTE in reference GPT
+                // this unlock the PTE 
                 hal_gpt_set_pte( ref_gpt_xp,
                                  vpn,
@@ -2112,5 +2134,12 @@
                                  ppn );
 
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] set new PTE in ref gpt for a true page fault\n",
+__FUNCTION__, this->process->pid, this->trdid );
+#endif
+
                 // set PTE in local GPT 
+                // this unlock the PTE 
                 hal_gpt_set_pte( local_gpt_xp,
                                  vpn,
@@ -2123,7 +2152,7 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle )
-printk("\n[%s] global page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",
-__FUNCTION__, vpn, ppn, attr, end_cycle );
+if( vpn == 0x40b )
+printk("\n[%s] thread[%x,%x] handled global pgfault / ppn %x / attr %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
 #endif
 
@@ -2138,7 +2167,21 @@
     else   // page has been locally mapped by another concurrent thread
     {
-        // unlock PTE in local GPT
+        // unlock the PTE in local GPT
         hal_gpt_unlock_pte( local_gpt_xp , vpn );
 
+#if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
+uint32_t end_cycle = (uint32_t)hal_get_cycles();
+#endif
+
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
+if( vpn == 0x40b )
+printk("\n[%s] handled by another thread / vpn %x / ppn %x / attr %x / cycle %d\n",
+__FUNCTION__, vpn, ppn, attr, end_cycle );
+#endif
+
+#if CONFIG_INSTRUMENTATION_PGFAULTS 
+this->info.false_pgfault_nr++;
+this->info.false_pgfault_cost += (end_cycle - start_cycle);
+#endif
         return EXCP_NON_FATAL;
     }
@@ -2214,4 +2257,5 @@
 
     // lock target PTE in relevant GPT (local or reference) 
+    // and get current PTE value
     error = hal_gpt_lock_pte( gpt_xp,
                               vpn,
