Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 438)
+++ trunk/kernel/mm/vmm.c	(revision 440)
@@ -198,12 +198,9 @@
                   bool_t      mapping )
 {
-    assert( (process->ref_xp == XPTR( local_cxy , process )) , __FUNCTION__,
-    "this function must be executed in reference cluster" );
-
     vmm_t * vmm = &process->vmm;
     gpt_t * gpt = &vmm->gpt;
 
-    printk("\n***** VSL and GPT for process %x\n\n", 
-    process->pid );
+    printk("\n***** VSL and GPT for process %x in cluster %x\n\n", 
+    process->pid , local_cxy );
 
     // get lock protecting the vseg list
@@ -1036,62 +1033,4 @@
 }  // end vmm_remove_vseg()
 
-//////////////////////////////////////////////
-error_t vmm_map_kernel_vseg( vseg_t    * vseg,
-                             uint32_t    attr )
-{
-    vpn_t       vpn;        // VPN of PTE to be set
-    vpn_t       vpn_min;    // VPN of first PTE to be set
-    vpn_t       vpn_max;    // VPN of last PTE to be set (excluded)
-	ppn_t       ppn;        // PPN of allocated physical page
-	uint32_t    order;      // ln( number of small pages for one single PTE )
-	page_t    * page;
-    error_t     error;
-
-    // check vseg type : must be a kernel vseg
-    uint32_t type = vseg->type;
-    assert( ((type==VSEG_TYPE_KCODE) || (type==VSEG_TYPE_KDATA) || (type==VSEG_TYPE_KDEV)),
-            __FUNCTION__ , "not a kernel vseg\n" );
-
-    // get pointer on page table
-    gpt_t * gpt = &process_zero.vmm.gpt;
-
-    // define number of small pages per PTE
-	if( attr & GPT_SMALL ) order = 0;   // 1 small page
-	else                   order = 9;   // 512 small pages
-
-    // loop on pages in vseg
-    vpn_min = vseg->vpn_base;
-    vpn_max = vpn_min + vseg->vpn_size;
-	for( vpn = vpn_min ; vpn < vpn_max ; vpn++ )
-	{
-        // allocate a physical page from local PPM
-	    kmem_req_t req;
-	    req.type  = KMEM_PAGE;
-	    req.size  = order;
-	    req.flags = AF_KERNEL | AF_ZERO;
-	    page      = (page_t *)kmem_alloc( &req );
-		if( page == NULL )
-        {
-            printk("\n[ERROR] in %s : cannot allocate physical memory\n", __FUNCTION__ );
-            return ENOMEM;
-        }
-
-        // set page table entry
-        ppn = ppm_page2ppn( XPTR( local_cxy , page ) );
-        error = hal_gpt_set_pte( gpt,
-                                 vpn,
-                                 attr,
-                                 ppn );
-		if( error )
-        {
-            printk("\n[ERROR] in %s : cannot register PPE\n", __FUNCTION__ );
-            return ENOMEM;
-        }
-	}
-
-	return 0;
-
-}  // end vmm_map_kernel_vseg()
-
 /////////////////////////////////////////
 void vmm_unmap_vseg( process_t * process,
@@ -1193,7 +1132,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This low-level static function is called by the vmm_get_vseg() and vmm_resize_vseg()
-// functions.  It scan the list of registered vsegs to find the unique vseg containing
-// a given virtual address.
+// This low-level static function is called by the vmm_get_vseg(), vmm_get_pte(),
+// and vmm_resize_vseg() functions.  It scan the local VSL to find the unique vseg 
+// containing a given virtual address.
 //////////////////////////////////////////////////////////////////////////////////////////
 // @ vmm     : pointer on the process VMM.
@@ -1331,8 +1270,14 @@
                        vseg_t   ** found_vseg )
 {
-    vmm_t  * vmm = &process->vmm;
-
-    // get vseg from vaddr
-    vseg_t * vseg = vseg_from_vaddr( vmm , vaddr );
+    xptr_t   vseg_xp;
+    error_t  error;
+    vseg_t * vseg;
+    vmm_t  * vmm;
+
+    // get pointer on local VMM
+    vmm = &process->vmm;
+
+    // try to get vseg from local VMM
+    vseg = vseg_from_vaddr( vmm , vaddr );
 
     if( vseg == NULL )   // vseg not found in local cluster => try to get it from ref
@@ -1348,15 +1293,12 @@
 
         // get extended pointer on reference vseg
-        xptr_t   vseg_xp;
-        error_t  error;
-
         rpc_vmm_get_vseg_client( ref_cxy , ref_ptr , vaddr , &vseg_xp , &error );
             
-        if( error )   return -1;       // vseg not found => illegal user vaddr 
+        if( error )   return -1;                // vseg not found => illegal user vaddr 
         
         // allocate a vseg in local cluster
         vseg = vseg_alloc();
 
-        if( vseg == NULL ) return -1;
+        if( vseg == NULL ) return -1;           // cannot allocate a local vseg
 
         // initialise local vseg from reference
@@ -1496,5 +1438,5 @@
 
         // initialise missing page from .elf file mapper for DATA and CODE types
-        // (the vseg->mapper_xp field is an extended pointer on the .elf file mapper)
+        // the vseg->mapper_xp field is an extended pointer on the .elf file mapper
         if( (type == VSEG_TYPE_CODE) || (type == VSEG_TYPE_DATA) )
         {
@@ -1521,4 +1463,5 @@
 #endif
 
+
             // compute extended pointer on page base 
             xptr_t base_xp  = ppm_page2base( page_xp );
@@ -1535,4 +1478,5 @@
 __FUNCTION__, CURRENT_THREAD, vpn );
 #endif
+
 
                 if( GET_CXY( page_xp ) == local_cxy )
@@ -1553,5 +1497,4 @@
 __FUNCTION__, CURRENT_THREAD, vpn );
 #endif
-
                 if( mapper_cxy == local_cxy ) 
                 {
@@ -1644,14 +1587,11 @@
                      ppn_t     * ppn )
 {
-    vseg_t  * vseg;       // vseg containing VPN
-    ppn_t     old_ppn;    // current PTE_PPN
-    uint32_t  old_attr;   // current PTE_ATTR
-    ppn_t     new_ppn;    // new PTE_PPN
-    uint32_t  new_attr;   // new PTE_ATTR
-    error_t   error;
-
-    // this function must be called by a thread running in the reference cluster
-    assert( (GET_CXY( process->ref_xp ) == local_cxy ) , __FUNCTION__ ,
-    "not called in the reference cluster\n" );
+    ppn_t      old_ppn;    // current PTE_PPN
+    uint32_t   old_attr;   // current PTE_ATTR
+    ppn_t      new_ppn;    // new PTE_PPN
+    uint32_t   new_attr;   // new PTE_ATTR
+    vmm_t    * vmm;
+    vseg_t   * vseg;      
+    error_t    error;
 
 #if DEBUG_VMM_GET_PTE
@@ -1663,37 +1603,31 @@
 
     // get VMM pointer
-    vmm_t * vmm = &process->vmm;
-
-    // get vseg pointer from reference VSL
-    error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg );
-
-    if( error )
-    {
-        printk("\n[ERROR] in %s : out of segment / process = %x / vpn = %x\n",
-        __FUNCTION__ , process->pid , vpn );
-        return error;
-    }
-
-#if( DEBUG_VMM_GET_PTE & 1 )
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_PTE < cycle )
-printk("\n[DBG] %s : thread %x found vseg %s / vpn_base = %x / vpn_size = %x\n",
-__FUNCTION__, CURRENT_THREAD, vseg_type_str(vseg->type), vseg->vpn_base, vseg->vpn_size );
-#endif
+    vmm = &process->vmm;
+
+    // get local vseg descriptor
+    error =  vmm_get_vseg( process, 
+                           ((intptr_t)vpn << CONFIG_PPM_PAGE_SHIFT), 
+                           &vseg );
+
+    // vseg has been checked by the vmm_handle_page_fault() function
+    assert( (vseg != NULL) , __FUNCTION__,
+    "vseg undefined / vpn %x / thread %x / process %x / core[%x,%d] / cycle %d\n", 
+    vpn, CURRENT_THREAD, process->pid, local_cxy, CURRENT_THREAD->core->lid,
+    (uint32_t)hal_get_cycles() );
 
     if( cow )  //////////////// copy_on_write request //////////////////////
-               // get PTE from reference GPT
+               // get PTE from local GPT
                // allocate a new physical page if there is pending forks,
                // initialize it from old physical page content,
                // update PTE in all GPT copies, 
     {
-        // access GPT to get current PTE attributes and PPN
+        // access local GPT to get current PTE attributes and PPN
         hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn );
 
-        assert( (old_attr & GPT_MAPPED) , __FUNCTION__ , 
-        "PTE must be mapped for a copy-on-write exception\n" );
+        assert( (old_attr & GPT_MAPPED), __FUNCTION__,
+        "PTE unmapped for a COW exception / vpn %x / thread %x / process %x / cycle %d\n",
+        vpn, CURRENT_THREAD, process->pid, (uint32_t)hal_get_cycles() );
 
 #if( DEBUG_VMM_GET_PTE & 1 )
-cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VMM_GET_PTE < cycle )
 printk("\n[DBG] %s : thread %x handling COW for vpn %x in process %x\n",
@@ -1745,9 +1679,10 @@
     }
     else        //////////// page_fault request ///////////////////////////
-                // get PTE from reference GPT
+                // get PTE from local GPT
                 // allocate a physical page if it is a true page fault,
+                // initialize it if type is FILE, CODE, or DATA,
                 // register in reference GPT, but don't update GPT copies
     {  
-        // access GPT to get current PTE 
+        // access local GPT to get current PTE 
         hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn );
 
@@ -1756,11 +1691,9 @@
 
 #if( DEBUG_VMM_GET_PTE & 1 )
-cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VMM_GET_PTE < cycle )
 printk("\n[DBG] %s : thread %x handling page fault for vpn %x in process %x\n",
 __FUNCTION__, CURRENT_THREAD, vpn, process->pid );
 #endif
-
-            // allocate new_ppn, depending on vseg type
+            // allocate new_ppn, and initialize the new page
             error = vmm_get_one_ppn( vseg , vpn , &new_ppn );
             if( error )
@@ -1801,5 +1734,5 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_VMM_GET_PTE < cycle )
-printk("\n[DBG] %s : thread,%x exit / vpn %x in process %x / ppn %x / attr %x / cycle %d\n",
+printk("\n[DBG] %s : thread %x exit / vpn %x in process %x / ppn %x / attr %x / cycle %d\n",
 __FUNCTION__, CURRENT_THREAD, vpn, process->pid, new_ppn, new_attr, cycle );
 #endif
@@ -1814,22 +1747,53 @@
 ///////////////////////////////////////////////////
 error_t vmm_handle_page_fault( process_t * process,
-                               vpn_t       vpn )
+                               vpn_t       vpn,
+                               bool_t      is_cow )
 {
     uint32_t         attr;          // missing page attributes
     ppn_t            ppn;           // missing page PPN
+    vseg_t         * vseg;          // vseg containing vpn
+    uint32_t         type;          // vseg type
+    cxy_t            ref_cxy;       // reference cluster for missing vpn
+    process_t      * ref_ptr;       // reference process for missing vpn
     error_t          error;
 
-#if DEBUG_VMM_GET_PTE
+    thread_t       * this = CURRENT_THREAD;
+
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
 uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_PTE < cycle )
-printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle );
-#endif
+if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
+printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / core[%x,%d] / cycle %d\n",
+__FUNCTION__, this, vpn, process->pid, local_cxy, this->core->lid, cycle );
+#endif
+
+    // get local vseg (access reference VSL if required)
+    error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : vpn %x / process %x / thread %x / core[%x,%d] / cycle %d\n",
+        __FUNCTION__, vpn, process->pid, this->trdid, local_cxy, this->core->lid,
+        (uint32_t)hal_get_cycles() );
+        return error;
+    }
+
+    // get segment type
+    type = vseg->type;
 
     // get reference process cluster and local pointer
-    cxy_t       ref_cxy = GET_CXY( process->ref_xp );
-    process_t * ref_ptr = GET_PTR( process->ref_xp );
-
-    // get missing PTE attributes and PPN from reference cluster
+    // for private vsegs (CODE and DATA type), 
+    // the reference is the local process descriptor.
+    if( (type == VSEG_TYPE_STACK) || (type == VSEG_TYPE_CODE) )
+    {
+        ref_cxy = local_cxy;
+        ref_ptr = process;
+    }
+    else
+    {
+        ref_cxy = GET_CXY( process->ref_xp );
+        ref_ptr = GET_PTR( process->ref_xp );
+    }
+
+    // get missing PTE attributes and PPN 
     if( local_cxy != ref_cxy )  
     {
@@ -1837,5 +1801,5 @@
                                 ref_ptr,
                                 vpn,
-                                false,    // page_fault
+                                is_cow,
                                 &attr,
                                 &ppn,
@@ -1855,14 +1819,14 @@
         error = vmm_get_pte( process,
                              vpn,
-                             false,      // page-fault
+                             is_cow,
                              &attr,
                              &ppn );
     }
 
-#if DEBUG_VMM_GET_PTE
+#if DEBUG_VMM_HANDLE_PAGE_FAULT
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_PTE < cycle )
+if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
 printk("\n[DBG] %s : thread %x exit for vpn %x / process %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle );
+__FUNCTION__, this->trdid, vpn, process->pid, cycle );
 #endif
 
@@ -1871,76 +1835,10 @@
 }  // end vmm_handle_page_fault()
 
-////////////////////////////////////////////
-error_t vmm_handle_cow( process_t * process,
-                        vpn_t       vpn )
-{
-    uint32_t         attr;          // page attributes
-    ppn_t            ppn;           // page PPN
-    error_t          error;
-
-#if DEBUG_VMM_GET_PTE
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_PTE < cycle )
-printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle );
-#endif
-    
-    // get reference process cluster and local pointer
-    cxy_t       ref_cxy = GET_CXY( process->ref_xp );
-    process_t * ref_ptr = GET_PTR( process->ref_xp );
-
-    // get new PTE attributes and PPN from reference cluster
-    if( local_cxy != ref_cxy )
-    {
-        rpc_vmm_get_pte_client( ref_cxy,
-                                ref_ptr,
-                                vpn,
-                                true,     // copy-on-write
-                                &attr,
-                                &ppn,
-                                &error );
-
-        // get local VMM pointer
-        vmm_t * vmm = &process->vmm;
-
-        // update local GPT
-        error |= hal_gpt_set_pte( &vmm->gpt,
-                                  vpn,
-                                  attr,
-                                  ppn );
-    }
-    else   // local cluster is the reference cluster
-    {
-        error = vmm_get_pte( process,
-                             vpn,
-                             true,      // copy-on-write
-                             &attr,
-                             &ppn );
-    }
-
-#if DEBUG_VMM_GET_PTE
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_GET_PTE < cycle )
-printk("\n[DBG] %s : thread %x exit for vpn %x / process %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle );
-#endif
-
-    return error;
-
-}  // end vmm_handle_cow()
-
-///////////////////////////////////////////
-error_t vmm_v2p_translate( bool_t    ident,
-                           void    * ptr,
-                           paddr_t * paddr )
-{
-    process_t * process = CURRENT_THREAD->process;
-
-    if( ident )  // identity mapping
-    {
-        *paddr = (paddr_t)PADDR( local_cxy , (lpa_t)ptr );
-        return 0;
-    }
-
+/* deprecated April 2018  [AG]
+
+error_t vmm_v2p_translate( process_t * process,
+                           void      * ptr,
+                           paddr_t   * paddr )
+{
     // access page table
     error_t  error;
@@ -1953,5 +1851,5 @@
     offset = (uint32_t)( ((intptr_t)ptr) & CONFIG_PPM_PAGE_MASK );
 
-    if( local_cxy == GET_CXY( process->ref_xp) ) // calling process is reference process
+    if( local_cxy == GET_CXY( process->ref_xp) ) // local process is reference process
     {
         error = vmm_get_pte( process, vpn , false , &attr , &ppn );
@@ -1971,3 +1869,3 @@
 }  // end vmm_v2p_translate()
 
-
+*/
