Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 286)
+++ trunk/kernel/mm/vmm.c	(revision 313)
@@ -741,4 +741,170 @@
 }
 
+////////////////////////////////////////
+error_t vmm_get_one_ppn( vseg_t * vseg,
+                         vpn_t    vpn,
+                         ppn_t  * ppn )
+{
+    error_t    error;
+    cxy_t      page_cxy;          // physical page cluster
+    page_t   * page_ptr;          // local pointer on physical page descriptor
+
+    uint32_t   type      = vseg->type;
+    xptr_t     mapper_xp = vseg->mapper_xp;
+
+    // get mapper cluster and local pointer
+    cxy_t      mapper_cxy = GET_CXY( mapper_xp );
+    mapper_t * mapper_ptr = (mapper_t *)GET_PTR( mapper_xp );
+
+    // FILE type : simply get the physical page from the file mapper
+    if( type == VSEG_TYPE_FILE )
+    {
+        // compute index in file mapper
+        uint32_t index = vpn - vseg->vpn_base;
+
+        // get page descriptor from mapper
+        if( mapper_cxy == local_cxy )             // mapper is local
+        {
+            page_ptr = mapper_get_page( mapper_ptr , index );
+        }
+        else                                      // mapper is remote
+        {
+            rpc_mapper_get_page_client( mapper_cxy , mapper_ptr , index , &page_ptr );
+        }
+
+        if ( page_ptr == NULL ) return EINVAL;
+
+        page_cxy = mapper_cxy;
+    }
+
+    // all other types : allocate a physical page from target cluster,
+    else
+    {
+        // get target cluster for physical page
+        if( flags & VSEG_DISTRIB ) // depends on VPN LSB
+        {
+            uint32_t x_width = LOCAL_CLUSTER->x_width;
+            uint32_t y_width = LOCAL_CLUSTER->y_width;
+            page_cxy = vpn & ((1<<(x_width + y_width)) - 1);
+        }
+        else                       // defined in vseg descriptor
+        {
+            page_cxy = vseg->cxy;
+        }
+
+        // allocate a physical page in target cluster
+        kmem_req_t   req;
+        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( page_ptr == NULL ) return ENOMEM;
+
+        // initialise page from .elf file mapper for DATA and CODE types
+        if( (type == VSEG_TYPE_CODE) || (type == VSEG_TYPE_DATA) )
+        {
+            // compute missing page index in vseg
+            vpn_t page_index = vpn - vseg->vpn_base;
+
+            // compute missing page offset in .elf file
+            intptr_t page_offset = vseg->file_offset + (page_index << PPM_PAGE_SHIFT);
+
+            // compute both local and extended pointer on page first byte 
+            // WARNING : the pages_offset must have the same value in all clusters !!!
+            //           to use this ppm_page2vaddr() function for a remote cluster
+            uint8_t * base_ptr = (uint8_t *)ppm_page2vaddr( page_ptr );
+            xptr_t    base_xp  = XPTR( page_cxy , base_ptr );
+
+            // file_size can be smaller than vseg_size for BSS
+            file_size = vseg->file_size;
+
+            if( file_size < page_offset )                          // page fully in  BSS 
+            {
+                if( page_cxy == local_cxy )
+                {
+                    memset( base_ptr , 0 , PPM_PAGE_SIZE );
+                }
+                else
+                {
+                   hal_remote_memset( base_xp , 0 , PPM_PAGE_SIZE );       
+                }
+            }
+            else if( file size >= (page_offset + PPM_PAGE_SIZE) )  // page fully in  mapper
+    
+                if( mapper_cxy == local_cxy ) 
+                {
+                    error = mapper_move_kernel( mapper_ptr,
+                                                true,             // to_buffer
+                                                page_offset,
+                                                base_xp,
+                                                PPM_PAGE_SIZE ); 
+                }
+                else 
+                {
+                    rpc_mapper_move_buffer_client( mapper_cxy,
+                                                   mapper_ptr,
+                                                   true,         // to buffer
+                                                   false,        // kernel buffer
+                                                   page_offset,
+                                                   (uint64_t)base_xp,
+                                                   PPM_PAGE_SIZE,
+                                                   &error );
+                }
+                if( error ) return EINVAL;
+            }
+            else  // in mapper : from page_offset -> (file_size - page_offset)
+                  // in BSS    : from file_size   -> (page_offset + page_size)
+            {
+                // initialize mapper part
+                if( mapper_cxy == local_cxy )                    // mapper is local
+                {
+                    error = mapper_move_kernel( mapper_ptr,
+                                                true,         // to_buffer
+                                                page_offset,
+                                                base_xp,
+                                                file_size - page_offset ); 
+                }
+                else                                             // mapper is remote
+                {
+                    rpc_mapper_move_buffer_client( mapper_cxy,
+                                                   mapper_ptr,
+                                                   true,
+                                                   false,        // kernel buffer
+                                                   page_offset,
+                                                   (uint64_t)base_xp,
+                                                   file_size - page_offset, 
+                                                   &error );
+                }
+                if( error ) return EINVAL;
+
+                // initialize BSS part
+                if( page_cxy == local_cxy )
+                {
+                    memset( base_ptr + file_size - page_offset , 0 , 
+                            page_offset + PPM_PAGE_SIZE - file_size );
+                }
+                else
+                {
+                   hal_remote_memset( base_xp + file_size - page_offset , 0 , 
+                                      page_offset + PPM_PAGE_SIZE - file_size );
+                }
+            }    
+        }  // end initialisation for CODE or DATA types   
+    } 
+
+    // return ppn
+    *ppn = hal_page2ppn( XPTR( page_cxy , page_ptr ) );
+    return 0;
+
+}  // end vmm_get_one_ppn()
+
 /////////////////////////////////////////
 error_t vmm_get_pte( process_t * process,
@@ -748,5 +914,5 @@
 {
     vseg_t  * vseg;   // pointer on vseg containing VPN
-    ppn_t     ppn;    // PPN from GPT entry
+    ppn_t     ppn;    // physical page number
     uint32_t  attr;   // attributes from GPT entry
     error_t   error;
@@ -762,8 +928,11 @@
     hal_gpt_get_pte( &vmm->gpt , vpn , &attr , &ppn );
 
-    // if PTE unmapped => allocate one small physical page to map it
+    // if PTE is unmapped
+    // 1) get VSEG containing the missing VPN
+    // 2) get & initialize physical page (depending on vseg type),
+    // 3) register the PTE in reference GPT 
     if( (attr & GPT_MAPPED) == 0 )
     {
-        // get vseg pointer
+        // 1. get vseg pointer
         vseg = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT );
 
@@ -775,34 +944,6 @@
         }
 
-        // select the target cluster for physical mapping
-        uint32_t target_cxy;
-        if( vseg->flags & VSEG_DISTRIB ) // depends on VPN LSB
-        {
-            uint32_t x_width = LOCAL_CLUSTER->x_width;
-            uint32_t y_width = LOCAL_CLUSTER->y_width;
-            target_cxy = vpn & ((1<<(x_width + y_width)) - 1);
-        }
-        else                             // defined in vseg descriptor
-        {
-            target_cxy = vseg->cxy;
-        }
-
-        // allocate memory for page fault
-        kmem_req_t   req;
-        page_t     * page;
-        if( target_cxy == local_cxy )        // target cluster is the local cluster
-        {
-            req.type  = KMEM_PAGE;
-            req.size  = 0;
-            req.flags = AF_NONE;
-            page      = (page_t *)kmem_alloc( &req );
-
-            error = ( page == NULL ) ? 1 : 0;
-            ppn   = ppm_page2ppn( page );
-        }
-        else                                 // target cluster is not the local cluster
-        {
-            rpc_pmem_get_pages_client( target_cxy , 0 , &error , &ppn );
-        }
+        // 2. get physical page number, depending on vseg type
+        error = vmm_get_one_ppn( vseg , vpn , &ppn );
 
         if( error )
@@ -810,8 +951,8 @@
             printk("\n[ERROR] in %s : cannot allocate memory / process = %x / vpn = %x\n",
                    __FUNCTION__ , process->pid , vpn );
-            return ENOMEM;
+            return error;
         }
 
-        // define GPT attributes from vseg flags
+        // 3. define attributes from vseg flags and register in GPT
         attr = GPT_MAPPED | GPT_SMALL;
         if( vseg->flags & VSEG_USER  ) attr |= GPT_USER;
@@ -820,6 +961,6 @@
         if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
 
-        // set the missing PTE in local VMM
         error = hal_gpt_set_pte( &vmm->gpt , vpn , ppn , attr );
+
         if( error )
         {
@@ -828,10 +969,11 @@
             return ENOMEM;
         }
-    }
+    }  // end new PTE
 
     *ret_ppn  = ppn;
     *ret_attr = attr;
     return 0;
-}
+
+}  // end vmm_get_pte()
 
 ///////////////////////////////////////////////////
@@ -851,5 +993,5 @@
     process_t * ref_ptr = (process_t *)GET_PTR( process->ref_xp );
 
-    // get missing PTE attributes and PPN
+    // get missing PTE attributes and PPN from reference cluster
     if( local_cxy != ref_cxy )   // local cluster is not the reference cluster
     {
@@ -879,5 +1021,7 @@
 
     return 0;
-}
+
+}  // end vmm_handle_page_fault()
+
 
 ///////////////////////////////////////////
@@ -919,6 +1063,6 @@
 
     return error;
+
 }
-
 /*
 
