Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 21)
+++ trunk/kernel/mm/vmm.c	(revision 23)
@@ -29,4 +29,5 @@
 #include <hal_gpt.h>
 #include <printk.h>
+#include <memcpy.h>
 #include <rwlock.h>
 #include <list.h>
@@ -94,6 +95,6 @@
 
     // initialize local list of vsegs and radix-tree
+    vmm->vsegs_nr = 0;
 	list_root_init( &vmm->vsegs_root );
-    vmm->vsegs_nr = 0;
     error = grdxt_init( &vmm->grdxt,
                         CONFIG_VMM_GRDXT_W1,
@@ -182,4 +183,125 @@
 
 }  // end vmm_init()
+
+//////////////////////////////////////////
+error_t vmm_copy( process_t * dst_process,
+                  process_t * src_process )
+{
+    error_t error;
+
+    vmm_t * src_vmm = &src_process->vmm;
+    vmm_t * dst_vmm = &dst_process->vmm;
+
+    // take the src_vmm vsegs_lock
+    rwlock_wr_lock( &src_vmm->vsegs_lock );
+
+    // initialise dst_vmm vsegs_lock
+    rwlock_init( &dst_vmm->vsegs_lock );
+
+    // initialise the dst_vmm vsegs list and the radix tree
+    dst_vmm->vsegs_nr = 0;
+    list_root_init( &dst_vmm->vsegs_root );
+    error = grdxt_init( &dst_vmm->grdxt,
+                        CONFIG_VMM_GRDXT_W1,
+                        CONFIG_VMM_GRDXT_W2,
+                        CONFIG_VMM_GRDXT_W3 );
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot initialise radix tree for process %x\n",
+               __FUNCTION__ , dst_process->pid );
+        return ENOMEM;
+    }
+
+    // loop on src_vmm list of vsegs to create
+    // and register vsegs copies in dst_vmm
+    list_entry_t * iter;
+    vseg_t       * src_vseg;
+    vseg_t       * dst_vseg;
+    LIST_FOREACH( &src_vmm->vsegs_root , iter )
+    {
+        // get pointer on current src_vseg
+        src_vseg = LIST_ELEMENT( iter , vseg_t , list );
+
+        // allocate memory for a new dst_vseg
+        dst_vseg = vseg_alloc();
+
+        if( dst_vseg == NULL ) 
+        {
+            // release all allocated vsegs
+            LIST_FOREACH( &dst_vmm->vsegs_root , iter )
+            {
+                dst_vseg = LIST_ELEMENT( iter , vseg_t , list );
+                vseg_free( dst_vseg );
+            }
+            return ENOMEM;
+        }
+
+        // copy src_vseg to dst_vseg
+        vseg_init_from_ref( dst_vseg , XPTR( local_cxy , src_vseg ) );
+
+        // register dst_vseg in dst_vmm
+        vseg_attach( dst_vmm , dst_vseg );
+    }
+
+    // release the src_vmm vsegs_lock
+    rwlock_wr_unlock( &src_vmm->vsegs_lock );
+
+    // initialize generic page table
+    error = hal_gpt_create( &dst_vmm->gpt );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ );
+        return ENOMEM;
+    }
+
+    // initialize STACK allocator
+    dst_vmm->stack_mgr.bitmap   = 0;
+    dst_vmm->stack_mgr.vpn_base = CONFIG_VMM_STACK_BASE;
+
+    // initialize MMAP allocator
+    dst_vmm->mmap_mgr.vpn_base        = CONFIG_VMM_MMAP_BASE;
+    dst_vmm->mmap_mgr.vpn_size        = CONFIG_VMM_STACK_BASE - CONFIG_VMM_MMAP_BASE;
+    dst_vmm->mmap_mgr.first_free_vpn  = CONFIG_VMM_MMAP_BASE;
+    uint32_t i;
+    for( i = 0 ; i < 32 ; i++ ) list_root_init( &dst_vmm->mmap_mgr.zombi_list[i] );
+
+    // initialise instrumentation counters
+	dst_vmm->pgfault_nr    = 0;
+	dst_vmm->u_err_nr      = 0;
+	dst_vmm->m_err_nr      = 0;
+
+    // copy base addresses
+    dst_vmm->kent_vpn_base = src_vmm->kent_vpn_base; 
+    dst_vmm->args_vpn_base = src_vmm->args_vpn_base; 
+    dst_vmm->envs_vpn_base = src_vmm->envs_vpn_base; 
+    dst_vmm->heap_vpn_base = src_vmm->heap_vpn_base; 
+    dst_vmm->code_vpn_base = src_vmm->code_vpn_base; 
+    dst_vmm->data_vpn_base = src_vmm->data_vpn_base; 
+
+    dst_vmm->entry_point   = src_vmm->entry_point;
+
+    // HEAP TODO : new heap for child ???
+    dst_vmm->heap_vseg     = src_vmm->heap_vseg;
+
+    // initialize generic page table
+    error = hal_gpt_create( &dst_vmm->gpt );
+
+    if( error )
+    {
+        printk("\n[ERROR] in %s : cannot initialize page table\n", __FUNCTION__ );
+        return ENOMEM;
+    }
+
+    // copy GPT content from src_vmm to dst_vmm, activating "Copy-On-Write"
+    // TODO register Copy-On_Write in page descriptors
+    bool_t cow = true;
+    hal_gpt_copy( &dst_vmm->gpt , &src_vmm->gpt , cow );
+
+    hal_wbflush();
+
+    return 0;
+
+}  // end vmm_copy()
 
 ///////////////////////////////////////
@@ -659,6 +781,6 @@
     error_t   error;
 
-    // this function must be called by in the reference cluster
-    if( process->is_ref == false );
+    // this function must be called by a thread running in the reference cluster 
+    if( GET_CXY( process->ref_xp ) != local_cxy );
     {
         printk("\n[PANIC] in %s : not called in the reference cluster\n", __FUNCTION__ );
@@ -796,12 +918,9 @@
                            paddr_t * paddr )
 {
-    uint32_t vaddr = (uint32_t)ptr;
-
-    thread_t  * this    = CURRENT_THREAD;
-    process_t * process = this->process;
+    process_t * process = CURRENT_THREAD->process;
 
     if( ident )  // identity mapping
     {
-        *paddr = (paddr_t)PADDR( local_cxy , vaddr );
+        *paddr = (paddr_t)PADDR( local_cxy , (lpa_t)ptr );
         return 0;
     }
@@ -814,12 +933,12 @@
     uint32_t offset;
 
-    vpn    = (vpn_t)( vaddr >> CONFIG_PPM_PAGE_SHIFT );
-    offset = (uint32_t)( vaddr & CONFIG_PPM_PAGE_MASK );
-
-    if( process->is_ref )   // calling process is reference process
+    vpn    = (vpn_t)( (intptr_t)ptr >> CONFIG_PPM_PAGE_SHIFT );
+    offset = (uint32_t)( ((intptr_t)ptr) & CONFIG_PPM_PAGE_MASK );
+
+    if( local_cxy == GET_CXY( process->ref_xp) )   // calling process is reference process
     {
         error = vmm_get_pte( process, vpn , &attr , &ppn );
     }
-    else                    // use a RPC
+    else                                           // use a RPC
     {
         cxy_t       ref_cxy = GET_CXY( process->ref_xp );
@@ -828,16 +947,12 @@
     }
 
-    if( error )
-    {
-        printk("\n[ERROR] in %s : cannot get physical address for vaddr = %x\n",
-               __FUNCTION__ , vaddr );
-        return error;
-    }
-
-    // return paddr
+    // set paddr
     *paddr = (((paddr_t)ppn) << CONFIG_PPM_PAGE_SHIFT) | offset;
-    return 0;
+
+    return error;
 
 }  // end vmm_v2p_translate()
+
+//////////////////////////////////////////////
 
 
