105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* The kernel call implemented in this file:
 | |
|  *   m_type:	SYS_VMCTL
 | |
|  *
 | |
|  * The parameters for this kernel call are:
 | |
|  *   	SVMCTL_WHO	which process
 | |
|  *    	SVMCTL_PARAM	set this setting (VMCTL_*)
 | |
|  *    	SVMCTL_VALUE	to this value
 | |
|  */
 | |
| 
 | |
| #include "../system.h"
 | |
| #include "../vm.h"
 | |
| #include "../debug.h"
 | |
| #include <minix/type.h>
 | |
| #include <minix/config.h>
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_vmctl				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_vmctl(m_ptr)
 | |
| register message *m_ptr;	/* pointer to request message */
 | |
| {
 | |
|   int proc_nr, i;
 | |
|   endpoint_t ep = m_ptr->SVMCTL_WHO;
 | |
|   struct proc *p, *rp;
 | |
| 
 | |
|   if(ep == SELF) { ep = m_ptr->m_source; }
 | |
| 
 | |
|   vm_init();
 | |
| 
 | |
|   if(!isokendpt(ep, &proc_nr)) {
 | |
| 	kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep);
 | |
| 	return EINVAL;
 | |
|   }
 | |
| 
 | |
|   p = proc_addr(proc_nr);
 | |
| 
 | |
|   switch(m_ptr->SVMCTL_PARAM) {
 | |
| 	case VMCTL_CLEAR_PAGEFAULT:
 | |
| 		RTS_LOCK_UNSET(p, PAGEFAULT);
 | |
| 		return OK;
 | |
| 	case VMCTL_MEMREQ_GET:
 | |
| 		/* Send VM the information about the memory request.  */
 | |
| 		if(!(rp = vmrequest))
 | |
| 			return ESRCH;
 | |
| 		if(!RTS_ISSET(rp, VMREQUEST))
 | |
| 			minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
 | |
| 
 | |
| 		/* Reply with request fields. */
 | |
| 		m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
 | |
| 		m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
 | |
| 		m_ptr->SVMCTL_MRG_WRITE = rp->p_vmrequest.writeflag;
 | |
| 		m_ptr->SVMCTL_MRG_EP = rp->p_vmrequest.who;
 | |
| 		rp->p_vmrequest.vmresult = VMSUSPEND;
 | |
| 
 | |
| 		/* Remove from request chain. */
 | |
| 		vmrequest = vmrequest->p_vmrequest.nextrequestor;
 | |
| 
 | |
| 		return OK;
 | |
| 	case VMCTL_MEMREQ_REPLY:
 | |
| 		if(!(rp = p->p_vmrequest.requestor))
 | |
| 			minix_panic("do_vmctl: no requestor set", ep);
 | |
| 		p->p_vmrequest.requestor = NULL;
 | |
| 		if(!RTS_ISSET(rp, VMREQUEST))
 | |
| 			minix_panic("do_vmctl: no VMREQUEST set", ep);
 | |
| 		if(rp->p_vmrequest.vmresult != VMSUSPEND)
 | |
| 			minix_panic("do_vmctl: result not VMSUSPEND set",
 | |
| 				rp->p_vmrequest.vmresult);
 | |
| 		rp->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
 | |
| 		if(rp->p_vmrequest.vmresult == VMSUSPEND)
 | |
| 			minix_panic("VM returned VMSUSPEND?", NO_NUM);
 | |
| 		if(rp->p_vmrequest.vmresult != OK)
 | |
| 			kprintf("SYSTEM: VM replied %d to mem request\n",
 | |
| 				rp->p_vmrequest.vmresult);
 | |
| 
 | |
| 		/* Put on restart chain. */
 | |
| 		rp->p_vmrequest.nextrestart = vmrestart;
 | |
| 		vmrestart = rp;
 | |
| 
 | |
| #if DEBUG_VMASSERT
 | |
| 		/* Sanity check. */
 | |
| 		if(rp->p_vmrequest.vmresult == OK) {
 | |
| 			if(CHECKRANGE(p,
 | |
| 				rp->p_vmrequest.start,
 | |
| 				rp->p_vmrequest.length,
 | |
| 				rp->p_vmrequest.writeflag) != OK) {
 | |
| kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
 | |
| 	rp->p_endpoint,
 | |
| 	rp->p_vmrequest.start,  rp->p_vmrequest.start + rp->p_vmrequest.length,
 | |
| 	rp->p_vmrequest.writeflag); 
 | |
| 	
 | |
| 				minix_panic("SYSTEM: fail but VM said OK", NO_NUM);
 | |
| 			}
 | |
| 		}
 | |
| #endif
 | |
| 		return OK;
 | |
| #if VM_KERN_NOPAGEZERO
 | |
| 	case VMCTL_NOPAGEZERO:
 | |
| 		return OK;
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   /* Try architecture-specific vmctls. */
 | |
|   return arch_do_vmctl(m_ptr, p);
 | |
| }
 | 
