Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 651)
+++ trunk/kernel/mm/vmm.c	(revision 656)
@@ -1745,22 +1745,31 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////
-// 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>.
+// This static function is called by the vmm_remove_vseg() and vmm_resize_vseg() functions
+// to update the physical page descriptor identified by the <ppn> argument. 
+// It decrements the refcount, set the dirty bit when required, and releases the physical
+// page to kmem depending on the vseg type.
+// - KERNEL : refcount decremented / not released to kmem    / dirty bit not set
+// - FILE   : refcount decremented / not released to kmem    / dirty bit set when required.
+// - CODE   : refcount decremented / released to kmem        / dirty bit not set.
+// - STAK   : refcount decremented / released to kmem        / dirty bit not set.
+// - DATA   : refcount decremented / released to kmem if ref / dirty bit not set.
+// - MMAP   : refcount decremented / released to kmem if ref / dirty bit not set.
 ////////////////////////////////////////////////////////////////////////////////////////////
 // @ process  : local pointer on process.
 // @ vseg     : local pointer on vseg.
 // @ ppn      : released pysical page index. 
+// @ dirty    : set the dirty bit in page descriptor when non zero.
 ////////////////////////////////////////////////////////////////////////////////////////////
 static void vmm_ppn_release( process_t * process,
                              vseg_t    * vseg,
-                             ppn_t       ppn )
+                             ppn_t       ppn,
+                             uint32_t    dirty )
 {
-    bool_t do_release;
+    bool_t do_kmem_release;
 
     // get vseg type
     vseg_type_t type = vseg->type;
 
-    // compute is_ref
+    // compute is_ref <=> this vseg is the reference vseg
     bool_t is_ref = (GET_CXY( process->ref_xp ) == local_cxy);
 
@@ -1774,18 +1783,25 @@
     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) || 
+    // compute the do_kmem_release condition depending on vseg type
+    if( (type == VSEG_TYPE_KCODE) || 
         (type == VSEG_TYPE_KDATA) || 
         (type == VSEG_TYPE_KDEV) )            
     {
-        // no physical page release for FILE and KERNEL 
-        do_release = false;
-    }
+        // no physical page release for KERNEL 
+        do_kmem_release = false;
+    }
+    else if( type == VSEG_TYPE_FILE )
+    {
+        // no physical page release for KERNEL 
+        do_kmem_release = false;
+
+        // set dirty bit if required
+        if( dirty ) ppm_page_do_dirty( page_xp );
+    }   
     else if( (type == VSEG_TYPE_CODE)  ||
              (type == VSEG_TYPE_STACK) ) 
     {
         // always release physical page for private vsegs
-        do_release = true;
+        do_kmem_release = true;
     }
     else if( (type == VSEG_TYPE_ANON)  ||
@@ -1793,5 +1809,5 @@
     {
         // release physical page if reference cluster
-        do_release = is_ref;
+        do_kmem_release = is_ref;
     }
     else if( is_ref )  // vseg_type == DATA in reference cluster
@@ -1814,16 +1830,20 @@
 
         // release physical page if forks == 0
-        do_release = (forks == 0); 
+        do_kmem_release = (forks == 0); 
     }
     else              // vseg_type == DATA not in reference cluster
     {
         // no physical page release if not in reference cluster 
-        do_release = false;
+        do_kmem_release = false;
     }
 
     // release physical page to relevant kmem when required
-    if( do_release )
-    {
-        ppm_remote_free_pages( page_cxy , page_ptr );
+    if( do_kmem_release )
+    {
+        kmem_req_t req;
+        req.type = KMEM_PPM;
+        req.ptr  = GET_PTR( ppm_ppn2base( ppn ) );
+
+        kmem_remote_free( page_cxy , &req );
 
 #if DEBUG_VMM_PPN_RELEASE
@@ -1892,6 +1912,6 @@
             hal_gpt_reset_pte( gpt_xp , vpn );
 
-            // release physical page when required
-            vmm_ppn_release( process , vseg , ppn );
+            // release physical page depending on vseg type
+            vmm_ppn_release( process , vseg , ppn , attr & GPT_DIRTY );
         }
     }
@@ -1986,5 +2006,5 @@
 
             // release physical page when required
-            vmm_ppn_release( process , vseg , ppn );
+            vmm_ppn_release( process , vseg , ppn , attr & GPT_DIRTY );
         }
     }
@@ -2008,5 +2028,5 @@
 
             // release physical page when required
-            vmm_ppn_release( process , vseg , ppn );
+            vmm_ppn_release( process , vseg , ppn , attr & GPT_DIRTY );
         }
     }
@@ -2170,5 +2190,5 @@
 // @ vseg   : local pointer on vseg.
 // @ vpn    : unmapped vpn.
-// @ return an extended pointer on the allocated page
+// @ return an extended pointer on the allocated page descriptor.
 //////////////////////////////////////////////////////////////////////////////////////
 static xptr_t vmm_page_allocate( vseg_t * vseg,
@@ -2186,5 +2206,4 @@
     xptr_t       page_xp;
     cxy_t        page_cxy;
-    page_t     * page_ptr;
     uint32_t     index;
 
@@ -2197,4 +2216,5 @@
 assert( ( type != VSEG_TYPE_FILE ) , "illegal vseg type\n" );
 
+    // compute target cluster identifier
     if( flags & VSEG_DISTRIB )    // distributed => cxy depends on vpn LSB
     {
@@ -2214,7 +2234,14 @@
 
     // allocate one small physical page from target cluster
-    page_ptr = ppm_remote_alloc_pages( page_cxy , 0 );
-
-    page_xp = XPTR( page_cxy , page_ptr );
+    kmem_req_t req;
+    req.type  = KMEM_PPM;
+    req.order = 0;
+    req.flags = AF_ZERO;
+
+    // get local pointer on page base
+    void * ptr = kmem_remote_alloc( page_cxy , &req );
+
+    // get extended pointer on page descriptor
+    page_xp = ppm_base2page( XPTR( page_cxy , ptr ) );
 
 #if DEBUG_VMM_PAGE_ALLOCATE
@@ -2245,7 +2272,12 @@
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
-printk("\n[%s] thread[%x,%x] enter for vpn %x / type %s / page_id  %d / cycle %d\n",
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
+printk("\n[%s] thread[%x,%x] enter for vpn %x / vseg %s / page_id  %d / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, vseg_type_str(type), page_id, cycle );
+#endif
+
+#if (DEBUG_VMM_GET_ONE_PPN & 2)
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
 #endif
 
@@ -2291,5 +2323,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
 printk("\n[%s] thread[%x,%x] for vpn = %x / elf_offset = %x\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, elf_offset );
@@ -2305,5 +2337,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
 printk("\n[%s] thread[%x,%x] for vpn  %x / fully in BSS\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn );
@@ -2322,5 +2354,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
 printk("\n[%s] thread[%x,%x] for vpn  %x / fully in mapper\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn );
@@ -2339,5 +2371,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
 printk("\n[%s] thread[%x,%x] for vpn  %x / both mapper & BSS\n"
 "      %d bytes from mapper / %d bytes from BSS\n",
@@ -2365,5 +2397,6 @@
                 }
             }    
-        }  // end initialisation for CODE or DATA types   
+
+        }  // end if CODE or DATA types   
     } 
 
@@ -2372,8 +2405,12 @@
 
 #if DEBUG_VMM_GET_ONE_PPN
-cycle = (uint32_t)hal_get_cycles();
-if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
 printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle %d\n",
 __FUNCTION__ , this->process->pid, this->trdid , vpn , *ppn, cycle );
+#endif
+
+#if (DEBUG_VMM_GET_ONE_PPN & 2)
+if( DEBUG_VMM_GET_ONE_PPN < cycle )
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
 #endif
 
@@ -2404,12 +2441,12 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
+if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) & (vpn > 0) )
 printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
 __FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle );
 #endif
 
-#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
+#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 2)
 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
-hal_vmm_display( this->process , true );
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
 #endif
 
@@ -2504,5 +2541,4 @@
 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
 uint32_t end_cycle = (uint32_t)hal_get_cycles();
-uint32_t cost      = end_cycle - start_cycle;
 #endif
 
@@ -2513,5 +2549,11 @@
 #endif
 
+#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 2)
+if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
+#endif
+
 #if CONFIG_INSTRUMENTATION_PGFAULTS 
+uint32_t cost      = end_cycle - start_cycle;
 this->info.local_pgfault_nr++;
 this->info.local_pgfault_cost += cost;
@@ -2584,5 +2626,4 @@
 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
 uint32_t end_cycle = (uint32_t)hal_get_cycles();
-uint32_t cost      = end_cycle - start_cycle;
 #endif
 
@@ -2593,5 +2634,11 @@
 #endif
 
+#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 2)
+if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
+#endif
+
 #if CONFIG_INSTRUMENTATION_PGFAULTS 
+uint32_t cost      = end_cycle - start_cycle;
 this->info.false_pgfault_nr++;
 this->info.false_pgfault_cost += cost;
@@ -2651,5 +2698,4 @@
 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
 uint32_t end_cycle = (uint32_t)hal_get_cycles();
-uint32_t cost      = end_cycle - start_cycle;
 #endif
 
@@ -2660,5 +2706,11 @@
 #endif
 
+#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 2)
+if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
+hal_vmm_display( XPTR( local_cxy , this->process ) , true );
+#endif
+
 #if CONFIG_INSTRUMENTATION_PGFAULTS 
+uint32_t cost      = end_cycle - start_cycle;
 this->info.global_pgfault_nr++;
 this->info.global_pgfault_cost += cost;
@@ -2676,5 +2728,4 @@
 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT)
 uint32_t end_cycle = (uint32_t)hal_get_cycles();
-uint32_t cost      = end_cycle - start_cycle;
 #endif
 
@@ -2686,4 +2737,5 @@
 
 #if CONFIG_INSTRUMENTATION_PGFAULTS 
+uint32_t cost      = end_cycle - start_cycle;
 this->info.false_pgfault_nr++;
 this->info.false_pgfault_cost += cost;
@@ -2720,5 +2772,5 @@
 #endif
 
-#if ((DEBUG_VMM_HANDLE_COW & 3) == 3 )
+#if (DEBUG_VMM_HANDLE_COW & 2)
 hal_vmm_display( XPTR( local_cxy , process ) , true );
 #endif
@@ -2902,5 +2954,5 @@
 #endif
 
-#if ((DEBUG_VMM_HANDLE_COW & 3) == 3)
+#if (DEBUG_VMM_HANDLE_COW & 2)
 hal_vmm_display( XPTR( local_cxy , process ) , true );
 #endif
