Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 385)
+++ trunk/kernel/mm/vmm.c	(revision 388)
@@ -722,22 +722,60 @@
 
 ///////////////////////////////////////////
-vseg_t * vmm_get_vseg( process_t * process,
-                       intptr_t    vaddr )
-{
+error_t  vmm_get_vseg( process_t * process,
+                       intptr_t    vaddr
+                       vseg_t   ** found_vseg )
+{
+    vmm_t    * vmm;
+    vseg_t   * vseg;
 
     // get pointer on process VMM
-    vmm_t * vmm = &process->vmm;
+    vmm = &process->vmm;
 
     // get lock protecting the vseg list
     rwlock_rd_lock( &vmm->vsegs_lock );
 
-    // get pointer on vseg from radix tree
-	vseg_t * vseg = grdxt_lookup( &vmm->grdxt, (uint32_t)(vaddr >> CONFIG_PPM_PAGE_SHIFT) );
+    // get pointer on vseg from local radix tree
+	vseg = grdxt_lookup( &vmm->grdxt, (uint32_t)(vaddr >> CONFIG_PPM_PAGE_SHIFT) );
 
     // release the lock
     rwlock_rd_unlock( &vmm->vsegs_lock );
 
-    return vseg;
-}
+    if( vseg == NULL )   // vseg not found in local cluster => try to get it from ref
+	{
+        // get extended pointer on reference process
+        xptr_t ref_xp = process->ref_xp;
+
+        // get cluster and local pointer on reference process 
+        cxy_t       ref_cxy = GET_CXY( ref_xp );
+        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
+
+        if( local_cxy == ref_cxy )  return -1;   // local cluster is the reference
+
+        // get extended pointer on reference vseg
+        xptr_t   vseg_xp;
+        error_t  error;
+        rpc_vmm_get_ref_vseg_client( ref_cxy , ref_ptr , bad_vaddr , &vseg_xp , &error );
+            
+        if( error )   return -1;       // vseg not found => illegal user vaddr 
+        
+        // allocate a vseg in local cluster
+        vseg = vseg_alloc();
+
+        if( vseg == NULL ) panic("no memory for vseg copy in cluster %x", local_cxy );
+
+        // initialise local vseg from reference
+        vseg_init_from_ref( vseg , vseg_xp );
+
+        // register local vseg in local VMM
+        error = vseg_attach( &process->vmm , vseg );
+
+        if( error ) panic("no memory for vseg registration in cluster %x", local_cxy );
+    }   
+    
+    // success
+    *found_vseg = vseg;
+    return O;
+
+}  // end vmm_get_vseg()
 
 ////////////////////////////////////////
@@ -1002,13 +1040,5 @@
     }
 
-    // check page allocation error
-    if( error )
-    {
-        printk("\n[ERROR] in %s : cannot allocate memory / process = %x / vpn = %x\n",
-               __FUNCTION__ , process->pid , vpn );
-	    return ENOMEM;
-    }
-
-    return 0;
+    return error;
 
 }  // end vmm_handle_page_fault()
@@ -1056,575 +1086,3 @@
 }  // end vmm_v2p_translate()
 
-/* deprecated
-
-///////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////
-error_t vmm_inval_shared_page( vseg_t *vseg, vma_t vaddr, ppn_t ppn)
-{
-	pmm_page_info_t current;
-	error_t err;
-
-	error= pmm_get_page(&vseg->vmm->pmm, vaddr, &current);
-
-	if((err) || (current.ppn != ppn))
-		goto ended;
-
-	current.ppn     = 0;
-	current.attr    = 0;
-	current.cluster = NULL;	
-
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr, &current);
-
-ended:
-	return err;
-}
-
-error_t vmm_update_shared_page( vseg_t *vseg, vma_t vaddr, ppn_t ppn)
-{
-	pmm_page_info_t current;
-	error_t err;
-
-	error= pmm_get_page(&vseg->vmm->pmm, vaddr, &current);
-
-	if((err) || (current.attr != 0))
-		goto ended;
-
-	current.ppn     = ppn;
-	current.attr    = vseg->vm_pgprot;
-	current.cluster = NULL;	// this function is called after invalidate one
-
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr , &current);
-
-ended:
-	return err;
-}
-
-// Hypothesis: the vseg is shared-anon, mapper list is rdlocked, page is locked
-error_t vmm_migrate_shared_page_seq( vseg_t *vseg, struct page_s *page, struct page_s **new)
-{
-	register  vseg_t *reg;
-	register struct process_s *process;
-	register struct process_s *this_process;
-	struct page_s *new_pg;
-	struct list_entry *iter;
-	kmem_req_t req;
-	vma_t vaddr;
-	ppn_t ppn;
-	error_t err;
-
-	vaddr     = (page->index << PMM_PAGE_SHIFT) + vseg->vm_start + vseg->vm_offset;
-	ppn       = ppm_page2ppn(page);
-	this_process = (new == NULL) ? NULL : current_process;
-	iter      = &vseg->vm_shared_list;
-	error      = ECANCELED;
-
-	// Invalidate All
-	do
-	{
-		reg  = list_element(iter,  vseg_t, vm_shared_list);
-
-		process = vmm_get_process(reg->vmm);
-
-		if(process != this_process)
-		{
-			error= vmm_inval_shared_page(reg, vaddr, ppn);
-
-			if(err) goto fail_inval;
-		}
-
-		assert(vseg->vm_mapper.m_home_cid == current_cid);
-		iter = list_next(&vseg->vm_mapper.m_reg_root, iter);
-
-	}while(iter != NULL);
-
-	req.type  = KMEM_PAGE;
-	req.size  = 0;
-	req.excep_code = AF_USER;
-
-	new_pg    = kmem_alloc(&req);
-	*new      = new_pg;
-
-	if(new_pg == NULL)
-	{
-		error= ENOMEM;
-		goto fail_alloc;
-	}
-
-	page_copy(new_pg, page);
-
-	page_lock(new_pg);
-
-	new_pg->mapper = page->mapper;
-	new_pg->index  = page->index;
-
-	// TODO: do the complet job regading dirty page
-	if(PAGE_IS(page, PG_DIRTY))
-		PAGE_SET(new_pg, PG_DIRTY);
-
-	ppn  = ppm_page2ppn(new_pg);
-	iter = &vseg->vm_shared_list;
-
-	// Update All
-	do
-	{
-		reg  = list_element(iter,  vseg_t, vm_shared_list);
-
-		process = vmm_get_process(reg->vmm);
-
-		if(process != this_process)
-			(void) vmm_update_shared_page(reg, vaddr, ppn);
-
-		assert(vseg->vm_mapper.m_home_cid == current_cid);
-		iter = list_next(&vseg->vm_mapper.m_reg_root, iter);
-
-
-	}while(iter != NULL);
-
-	page_unlock(new_pg);
-
-fail_alloc:
-fail_inval:
-	return err;
-}
-
-//TODO: revisit all manipulation of the page->refcount
-///////////////////////////////////////////////////////////////
-static inline error_t vmm_do_migrate( vseg_t     * vseg,
-                                      pmm_page_info_t * pinfo,
-                                      uint32_t          vaddr )
-{
-	kmem_req_t        req;
-	pmm_page_info_t   current;
-	page_t          * newpage;
-	cluster_t       * cluster;
-	thread_t        * this;
-	error_t           err;
-	ppn_t             ppn;
-
-	assert( pinfo->ppn != 0 );
-
-	ppn = pinfo->ppn;
-	this = current_thread;
-	newpage = NULL;
-	cluster = current_cluster;
-
-	current.attr = 0;
-	current.ppn  = 0;
-
-	error= pmm_lock_page(&vseg->vmm->pmm, vaddr, &current);
-
-	if(error|| (current.isAtomic == false) ||
-              (current.ppn != ppn) || !(current.attr & PMM_MIGRATE))
-	{
-#if CONFIG_SHOW_SPURIOUS_PGFAULT
-		printk(INFO, "%s: pid %d, tid %d, cpu %d, nothing to do for vaddr %x\n",
-		       __FUNCTION__,
-		       this->process->pid,
-		       this->info.order,
-		       cpu_get_id(),
-		       vaddr);
-#endif
-		this->info.spurious_pgfault_cntr ++;
-		pmm_unlock_page(&vseg->vmm->pmm, vaddr, &current);
-		pmm_tlb_flush_vaddr(vaddr, PMM_DATA);
-		return 0;
-	}
-
-	if(!ppn_is_local(ppn))
-	{
-		req.type  = KMEM_PAGE;
-		req.size  = 0;
-		req.excep_code = AF_PGFAULT;
-
-		newpage = kmem_alloc(&req);
-
-		if(newpage)
-		{
-			newpage->mapper = NULL;//?
-			ppn_copy(ppm_page2ppn(newpage), ppn);
-
-			if(current.attr & PMM_COW)
-			{
-				current.attr |= PMM_WRITE;
-				current.attr &= ~(PMM_COW);
-			}
-
-			current.ppn = ppm_page2ppn(newpage);
-		}
-	}
-
-	current.attr   |= PMM_PRESENT;
-	current.attr   &= ~(PMM_MIGRATE);
-	current.attr   &= ~(PMM_LOCKED);
-	current.cluster = NULL;
-
-	//also unlock the table entry
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr, &current);
-	
-	if(err)
-	{
-		// TODO: we should differ the kmem_free call
-		//page_unlock(page);
-		(void)pmm_unlock_page(&vseg->vmm->pmm, vaddr, &current);
-		req.ptr = newpage;
-		kmem_free(&req);
-		return err;
-	}
-
-
-	if(newpage)
-	{
-		ppn_refcount_down(ppn);
-		current_thread->info.remote_pages_cntr ++;
-#if CONFIG_SHOW_REMOTE_PGALLOC
-		printk(INFO, "%s: pid %d, tid %x, cpu %d, cid %d: got new remote page from cluster %d (vaddr %x)\n",
-		       __FUNCTION__,
-		       current_process->pid,
-		       current_thread,
-		       cpu_get_id(),
-		       cluster->id,
-		       newpage->cid,
-		       vaddr);
-#endif
-	}
-
-#if CONFIG_SHOW_VMMMGRT_MSG
-	printk(INFO, "%s: pid %d, tid %d, cpu %d: Asked to migrate page (vaddr %x) from cluster %d to cluster %d, error%d\n",
-	       __FUNCTION__,
-	       current_process->pid,
-	       current_thread->info.order,
-	       cpu_get_id(),
-	       vaddr,
-	       ppn_ppn2cid(ppn),
-	       cluster->id,
-	       err);
-#endif
-
-	return err;
-}
-
-error_t vmm_do_cow( vseg_t *vseg, pmm_page_info_t *pinfo, uint32_t vaddr)
-{
-	register struct page_s *newpage;
-	register struct page_s *page;
-	register struct thread_s *this;
-	register error_t err;
-	register uint32_t count;
-	register bool_t isCountDown;
-	pmm_page_info_t old;
-	pmm_page_info_t new;
-	kmem_req_t req;
-
-	this       = current_thread;
-	old.attr  = 0;
-	newpage    = NULL;
-	isCountDown = true;
-
-	vmm_dmsg(2,"%s: pid %d, tid %d, cpu %d, vaddr %x\n",
-		 __FUNCTION__,
-		 this->process->pid,
-		 this->info.order,
-		 cpu_get_id(),
-		 vaddr);
-
-
-	error= pmm_lock_page(&vseg->vmm->pmm, vaddr, &old);
-
-	//TODO: check this condition
-	if(error|| (old.isAtomic == false) || !(old.attr & PMM_COW))
-	{
-#if CONFIG_SHOW_SPURIOUS_PGFAULT
-		printk(INFO, "%s: pid %d, tid %d, cpu %d, nothing to do for vaddr %x\n",
-		       __FUNCTION__,
-		       this->process->pid,
-		       this->info.order,
-		       cpu_get_id(),
-		       vaddr);
-#endif
-		this->info.spurious_pgfault_cntr ++;
-		pmm_tlb_flush_vaddr(vaddr, PMM_DATA);
-		pmm_unlock_page(&vseg->vmm->pmm, vaddr, &old);
-		return err;
-		//goto VMM_COW_END;
-	}
-
-	//if the ppn is local and the others (processus with wich we share the page)
-	//has done cow, then use the old.ppn directly
-	if(ppn_is_local(old.ppn))
-	{
-		page = ppm_ppn2page(&current_cluster->ppm, old.ppn);
-
-		if(page->mapper == NULL)
-		{
-			count = page_refcount_get(page);
-			if(count == 1)
-			{
-				newpage = page;//don't copy the page. use it directly.
-				isCountDown = false;
-				vmm_dmsg(2, "%s: pid %d, tid %d, cpu %d, reuse same page for vaddr %x, pg_addr %x\n",
-					 __FUNCTION__,
-					 this->process->pid,
-					 this->info.order,
-					 cpu_get_id(),
-					 vaddr,
-					 ppm_page2addr(page));
-			}
-		}
-		//else: we need to do the cow even if it's local!
-
-	}
-
-	//else: alocate newpage and copy the data from the remote node
-	//also defcount down the ppn
-	if(newpage == NULL)
-	{
-		req.type  = KMEM_PAGE;
-		req.size  = 0;
-		req.excep_code = AF_PGFAULT;
-
-		if((newpage = kmem_alloc(&req)) == NULL)
-		{
-			(void)pmm_unlock_page(&vseg->vmm->pmm, vaddr, &old);
-			return ENOMEM;
-		}	
-
-		newpage->mapper = NULL;
-
-		ppn_copy(ppm_page2ppn(newpage), old.ppn);
-		assert(isCountDown);
-		
-		vmm_dmsg(2,
-			 "%s: pid %d, tid %d, cpu %d, newpage for vaddr %x, pg_addr %x\n",
-			 __FUNCTION__,
-			 this->process->pid,
-			 this->info.order,
-			 cpu_get_id(),
-			 vaddr,
-			 ppm_page2addr(newpage));
-
-		if(newpage->cid != current_cid)
-			this->info.remote_pages_cntr ++;
-	}
-
-	new.attr    = vseg->vm_pgprot | PMM_WRITE;
-	new.attr   &= ~(PMM_COW | PMM_MIGRATE);
-	new.ppn     = ppm_page2ppn(newpage);
-	new.cluster = NULL;
-
-	//this also unlock the table entry (if no error)
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr, &new);
-
-	if(err)
-	{
-		(void)pmm_unlock_page(&vseg->vmm->pmm, vaddr, &old);
-		req.ptr = newpage;
-		kmem_free(&req);
-		vmm_dmsg(3, "%s: ended [ error%d ]\n", __FUNCTION__, err);
-		return err;
-	}
-	
-	if(isCountDown) ppn_refcount_down(old.ppn);
-	
-	vmm_dmsg(2, "%s, pid %d, tid %d, cpu %d, COW ended [vaddr %x]\n",
-		 __FUNCTION__,
-		 this->process->pid,
-		 this->info.order,
-		 cpu_get_id(),
-		 vaddr);
-
-	return 0;
-}
-
-
-//refcount is taken on the file at mmap
-static inline error_t vmm_do_mapped( vseg_t *vseg, uint32_t vaddr, uint32_t excep_code)
-{
-	ppn_t ppn;
-	error_t err;
-	uint32_t index;
-	bool_t isDone;
-	pmm_page_info_t info;
-	pmm_page_info_t current;
-	struct thread_s *this;
-
-	this = current_thread;
-
-	current.attr = 1;
-	current.ppn  = 1;
-	isDone       = false;
-
-	error= pmm_lock_page(&vseg->vmm->pmm, vaddr, &current);
-	
-	if(err) return err;
-
-	if((current.isAtomic == false) || (current.attr != 0))
-	{
-#if CONFIG_SHOW_SPURIOUS_PGFAULT
-		printk(INFO, "%s: pid %d, tid %d, cpu %d, nothing to do for vaddr %x\n",
-		       __FUNCTION__,
-		       this->process->pid,
-		       this->info.order,
-		       cpu_get_id(),
-		       vaddr);
-#endif
-		this->info.spurious_pgfault_cntr ++;
-		pmm_tlb_flush_vaddr(vaddr, PMM_DATA);
-		return 0;
-	}
-
-	index = ((vaddr - vseg->vm_start) + vseg->vm_offset) >> PMM_PAGE_SHIFT;
-
-	//also hold a refcount!
-	ppn = mapper_get_ppn(&vseg->vm_mapper,
-			       index,
-			       MAPPER_SYNC_OP);
-
-	if(!ppn)
-	{
-		error= pmm_unlock_page(&vseg->vmm->pmm, vaddr, &current);
-		assert(!err); //FIXME: liberate the ppn ...
-		return (VFS_FILE_IS_NULL(vseg->vm_file)) ? EIO : ENOMEM;
-	}
-
-	info.attr    = vseg->vm_pgprot;
-	info.ppn     = ppn;
-	info.cluster = NULL;
-
-	//also unlock the page
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr, &info);
-
-	assert(!err);//FIXME: liberate the ppn and unlock the table entry ...
-	//error= pmm_unlock_page(&vseg->vmm->pmm, vaddr, &current);
-
-	return err;
-}
-
-/////////////////////////////////////////////////////
-static inline error_t vmm_do_aod( vseg_t *vseg, uint32_t vaddr)
-{
-	register error_t err;
-	register struct page_s *page;
-	register struct cluster_s *cluster;
-	struct thread_s *this;
-	pmm_page_info_t old;
-	pmm_page_info_t new;
-	kmem_req_t req;
-
-	page      = NULL;
-	old.attr  = 0;
-	this      = current_thread;
-
-	error= pmm_lock_page(&vseg->vmm->pmm, vaddr, &old);
-
-	if(err) return err;
-
-	if(old.isAtomic == false)
-	{
-		this->info.spurious_pgfault_cntr ++;
-		pmm_tlb_flush_vaddr(vaddr, PMM_DATA);
-		return 0;
-	}
-
-	req.type  = KMEM_PAGE;
-	req.size  = 0;
-	req.excep_code = AF_PGFAULT | AF_ZERO;
-
-	if((page = kmem_alloc(&req)) == NULL)
-	{
-		(void)pmm_unlock_page(&vseg->vmm->pmm, vaddr, &old);
-		return ENOMEM;
-	}
-
-	page->mapper = NULL;
-
-	new.attr    = vseg->vm_pgprot;
-	new.ppn     = ppm_page2ppn(page);
-	new.cluster = NULL;
-
-	error= pmm_set_page(&vseg->vmm->pmm, vaddr, &new);
-	
-	if(err) goto fail_set_pg;
-
-	cluster = current_cluster;
-
-	if(page->cid != cluster->id)
-		this->info.remote_pages_cntr ++;
-
-	return 0;
-
-fail_set_pg:
-	(void)pmm_unlock_page(&vseg->vmm->pmm, vaddr, &old);
-	req.ptr = page;
-	kmem_free(&req);
-
-	vmm_dmsg(3, "%s: ended [ error%d ]\n", __FUNCTION__, err);
-	return err;
-}
-
-VSEGION_PAGE_FAULT(vmm_default_pagefault)
-{
-	register struct thread_s *this;
-	register error_t err;
-	pmm_page_info_t info;
-
-	if((error= pmm_get_page(&vseg->vmm->pmm, vaddr, &info)))
-		return err;
-
-	if((info.attr != 0) && (info.ppn != 0))
-	{
-		if((info.attr & PMM_COW) && pmm_except_isWrite(excep_code))
-		{
-			error= vmm_do_cow(vseg, &info, vaddr);
-			return err;
-		}
-
-		if(info.attr & PMM_MIGRATE)
-			return vmm_do_migrate(vseg, &info, vaddr);
-
-		if(info.attr & PMM_PRESENT)
-		{
-			this = current_thread;
-
-#if CONFIG_SHOW_SPURIOUS_PGFAULT
-			printk(WARNING, "WARNING: %s: pid %d, tid %d, cpu %d, excep_code %x but vaddr is valid %x, attr %x, ppn %x\n",
-			       __FUNCTION__,
-			       this->process->pid,
-			       this->info.order,
-			       cpu_get_id(),
-			       excep_code,
-			       vaddr,
-			       info.attr,
-			       info.ppn);
-#endif
-
-			current_thread->info.spurious_pgfault_cntr ++;
-			pmm_tlb_flush_vaddr(vaddr, PMM_UNKNOWN);
-			return 0;
-		}
-
-		current_thread->info.spurious_pgfault_cntr ++;
-		pmm_tlb_flush_vaddr(vaddr, PMM_UNKNOWN);
-		return 0;
-#if 0
-#if CONFIG_SHOW_VMM_ERROR_MSG
-		printk(ERROR,
-		       "ERROR: %s: pid %d, cpu %d, Unexpected page attributes configuration for vaddr %x, found: ppn %x, attr %x\n",
-		       __FUNCTION__,
-		       current_process->pid,
-		       cpu_get_id(),
-		       vaddr,
-		       info.ppn,
-		       info.attr);
-#endif
-
-		return EPERM;
-#endif
-	}
-
-	if(!MAPPER_IS_NULL(vseg->vm_mapper))
-		return vmm_do_mapped(vseg, vaddr, excep_code);
-
-	return vmm_do_aod(vseg, vaddr);
-}
-*/
-
+
