1*433d6423SLionel Sambuc /* The kernel call implemented in this file: 2*433d6423SLionel Sambuc * m_type: SYS_VMCTL 3*433d6423SLionel Sambuc * 4*433d6423SLionel Sambuc * The parameters for this kernel call are: 5*433d6423SLionel Sambuc * SVMCTL_WHO which process 6*433d6423SLionel Sambuc * SVMCTL_PARAM set this setting (VMCTL_*) 7*433d6423SLionel Sambuc * SVMCTL_VALUE to this value 8*433d6423SLionel Sambuc */ 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc #include "kernel/system.h" 11*433d6423SLionel Sambuc #include "kernel/vm.h" 12*433d6423SLionel Sambuc #include "kernel/debug.h" 13*433d6423SLionel Sambuc #include <assert.h> 14*433d6423SLionel Sambuc #include <minix/type.h> 15*433d6423SLionel Sambuc 16*433d6423SLionel Sambuc /*===========================================================================* 17*433d6423SLionel Sambuc * do_vmctl * 18*433d6423SLionel Sambuc *===========================================================================*/ 19*433d6423SLionel Sambuc int do_vmctl(struct proc * caller, message * m_ptr) 20*433d6423SLionel Sambuc { 21*433d6423SLionel Sambuc int proc_nr; 22*433d6423SLionel Sambuc endpoint_t ep = m_ptr->SVMCTL_WHO; 23*433d6423SLionel Sambuc struct proc *p, *rp, *target; 24*433d6423SLionel Sambuc 25*433d6423SLionel Sambuc if(ep == SELF) { ep = caller->p_endpoint; } 26*433d6423SLionel Sambuc 27*433d6423SLionel Sambuc if(!isokendpt(ep, &proc_nr)) { 28*433d6423SLionel Sambuc printf("do_vmctl: unexpected endpoint %d from VM\n", ep); 29*433d6423SLionel Sambuc return EINVAL; 30*433d6423SLionel Sambuc } 31*433d6423SLionel Sambuc 32*433d6423SLionel Sambuc p = proc_addr(proc_nr); 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc switch(m_ptr->SVMCTL_PARAM) { 35*433d6423SLionel Sambuc case VMCTL_CLEAR_PAGEFAULT: 36*433d6423SLionel Sambuc assert(RTS_ISSET(p,RTS_PAGEFAULT)); 37*433d6423SLionel Sambuc RTS_UNSET(p, RTS_PAGEFAULT); 38*433d6423SLionel Sambuc return OK; 39*433d6423SLionel Sambuc case VMCTL_MEMREQ_GET: 40*433d6423SLionel Sambuc /* Send VM the information about the memory request. */ 41*433d6423SLionel Sambuc if(!(rp = vmrequest)) 42*433d6423SLionel Sambuc return ESRCH; 43*433d6423SLionel Sambuc assert(RTS_ISSET(rp, RTS_VMREQUEST)); 44*433d6423SLionel Sambuc 45*433d6423SLionel Sambuc okendpt(rp->p_vmrequest.target, &proc_nr); 46*433d6423SLionel Sambuc target = proc_addr(proc_nr); 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc /* Reply with request fields. */ 49*433d6423SLionel Sambuc switch(rp->p_vmrequest.req_type) { 50*433d6423SLionel Sambuc case VMPTYPE_CHECK: 51*433d6423SLionel Sambuc m_ptr->SVMCTL_MRG_TARGET = 52*433d6423SLionel Sambuc rp->p_vmrequest.target; 53*433d6423SLionel Sambuc m_ptr->SVMCTL_MRG_ADDR = 54*433d6423SLionel Sambuc rp->p_vmrequest.params.check.start; 55*433d6423SLionel Sambuc m_ptr->SVMCTL_MRG_LENGTH = 56*433d6423SLionel Sambuc rp->p_vmrequest.params.check.length; 57*433d6423SLionel Sambuc m_ptr->SVMCTL_MRG_FLAG = 58*433d6423SLionel Sambuc rp->p_vmrequest.params.check.writeflag; 59*433d6423SLionel Sambuc m_ptr->SVMCTL_MRG_REQUESTOR = 60*433d6423SLionel Sambuc (void *) rp->p_endpoint; 61*433d6423SLionel Sambuc break; 62*433d6423SLionel Sambuc default: 63*433d6423SLionel Sambuc panic("VMREQUEST wrong type"); 64*433d6423SLionel Sambuc } 65*433d6423SLionel Sambuc 66*433d6423SLionel Sambuc rp->p_vmrequest.vmresult = VMSUSPEND; 67*433d6423SLionel Sambuc 68*433d6423SLionel Sambuc /* Remove from request chain. */ 69*433d6423SLionel Sambuc vmrequest = vmrequest->p_vmrequest.nextrequestor; 70*433d6423SLionel Sambuc 71*433d6423SLionel Sambuc return rp->p_vmrequest.req_type; 72*433d6423SLionel Sambuc case VMCTL_MEMREQ_REPLY: 73*433d6423SLionel Sambuc assert(RTS_ISSET(p, RTS_VMREQUEST)); 74*433d6423SLionel Sambuc assert(p->p_vmrequest.vmresult == VMSUSPEND); 75*433d6423SLionel Sambuc okendpt(p->p_vmrequest.target, &proc_nr); 76*433d6423SLionel Sambuc target = proc_addr(proc_nr); 77*433d6423SLionel Sambuc p->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE; 78*433d6423SLionel Sambuc assert(p->p_vmrequest.vmresult != VMSUSPEND); 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc switch(p->p_vmrequest.type) { 81*433d6423SLionel Sambuc case VMSTYPE_KERNELCALL: 82*433d6423SLionel Sambuc /* 83*433d6423SLionel Sambuc * we will have to resume execution of the kernel call 84*433d6423SLionel Sambuc * as soon the scheduler picks up this process again 85*433d6423SLionel Sambuc */ 86*433d6423SLionel Sambuc p->p_misc_flags |= MF_KCALL_RESUME; 87*433d6423SLionel Sambuc break; 88*433d6423SLionel Sambuc case VMSTYPE_DELIVERMSG: 89*433d6423SLionel Sambuc assert(p->p_misc_flags & MF_DELIVERMSG); 90*433d6423SLionel Sambuc assert(p == target); 91*433d6423SLionel Sambuc assert(RTS_ISSET(p, RTS_VMREQUEST)); 92*433d6423SLionel Sambuc break; 93*433d6423SLionel Sambuc case VMSTYPE_MAP: 94*433d6423SLionel Sambuc assert(RTS_ISSET(p, RTS_VMREQUEST)); 95*433d6423SLionel Sambuc break; 96*433d6423SLionel Sambuc default: 97*433d6423SLionel Sambuc panic("strange request type: %d",p->p_vmrequest.type); 98*433d6423SLionel Sambuc } 99*433d6423SLionel Sambuc 100*433d6423SLionel Sambuc RTS_UNSET(p, RTS_VMREQUEST); 101*433d6423SLionel Sambuc return OK; 102*433d6423SLionel Sambuc 103*433d6423SLionel Sambuc case VMCTL_KERN_PHYSMAP: 104*433d6423SLionel Sambuc { 105*433d6423SLionel Sambuc int i = m_ptr->SVMCTL_VALUE; 106*433d6423SLionel Sambuc return arch_phys_map(i, 107*433d6423SLionel Sambuc (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_ADDR, 108*433d6423SLionel Sambuc (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_LEN, 109*433d6423SLionel Sambuc &m_ptr->SVMCTL_MAP_FLAGS); 110*433d6423SLionel Sambuc } 111*433d6423SLionel Sambuc case VMCTL_KERN_MAP_REPLY: 112*433d6423SLionel Sambuc { 113*433d6423SLionel Sambuc return arch_phys_map_reply(m_ptr->SVMCTL_VALUE, 114*433d6423SLionel Sambuc (vir_bytes) m_ptr->SVMCTL_MAP_VIR_ADDR); 115*433d6423SLionel Sambuc } 116*433d6423SLionel Sambuc case VMCTL_VMINHIBIT_SET: 117*433d6423SLionel Sambuc /* check if we must stop a process on a different CPU */ 118*433d6423SLionel Sambuc #if CONFIG_SMP 119*433d6423SLionel Sambuc if (p->p_cpu != cpuid) { 120*433d6423SLionel Sambuc smp_schedule_vminhibit(p); 121*433d6423SLionel Sambuc } else 122*433d6423SLionel Sambuc #endif 123*433d6423SLionel Sambuc RTS_SET(p, RTS_VMINHIBIT); 124*433d6423SLionel Sambuc #if CONFIG_SMP 125*433d6423SLionel Sambuc p->p_misc_flags |= MF_FLUSH_TLB; 126*433d6423SLionel Sambuc #endif 127*433d6423SLionel Sambuc return OK; 128*433d6423SLionel Sambuc case VMCTL_VMINHIBIT_CLEAR: 129*433d6423SLionel Sambuc assert(RTS_ISSET(p, RTS_VMINHIBIT)); 130*433d6423SLionel Sambuc /* 131*433d6423SLionel Sambuc * the processes is certainly not runnable, no need to tell its 132*433d6423SLionel Sambuc * cpu 133*433d6423SLionel Sambuc */ 134*433d6423SLionel Sambuc RTS_UNSET(p, RTS_VMINHIBIT); 135*433d6423SLionel Sambuc #ifdef CONFIG_SMP 136*433d6423SLionel Sambuc if (p->p_misc_flags & MF_SENDA_VM_MISS) { 137*433d6423SLionel Sambuc struct priv *privp; 138*433d6423SLionel Sambuc p->p_misc_flags &= ~MF_SENDA_VM_MISS; 139*433d6423SLionel Sambuc privp = priv(p); 140*433d6423SLionel Sambuc try_deliver_senda(p, (asynmsg_t *) privp->s_asyntab, 141*433d6423SLionel Sambuc privp->s_asynsize); 142*433d6423SLionel Sambuc } 143*433d6423SLionel Sambuc /* 144*433d6423SLionel Sambuc * We don't know whether kernel has the changed mapping 145*433d6423SLionel Sambuc * installed to access userspace memory. And if so, on what CPU. 146*433d6423SLionel Sambuc * More over we don't know what mapping has changed and how and 147*433d6423SLionel Sambuc * therefore we must invalidate all mappings we have anywhere. 148*433d6423SLionel Sambuc * Next time we map memory, we map it fresh. 149*433d6423SLionel Sambuc */ 150*433d6423SLionel Sambuc bits_fill(p->p_stale_tlb, CONFIG_MAX_CPUS); 151*433d6423SLionel Sambuc #endif 152*433d6423SLionel Sambuc return OK; 153*433d6423SLionel Sambuc case VMCTL_CLEARMAPCACHE: 154*433d6423SLionel Sambuc /* VM says: forget about old mappings we have cached. */ 155*433d6423SLionel Sambuc mem_clear_mapcache(); 156*433d6423SLionel Sambuc return OK; 157*433d6423SLionel Sambuc case VMCTL_BOOTINHIBIT_CLEAR: 158*433d6423SLionel Sambuc RTS_UNSET(p, RTS_BOOTINHIBIT); 159*433d6423SLionel Sambuc return OK; 160*433d6423SLionel Sambuc } 161*433d6423SLionel Sambuc 162*433d6423SLionel Sambuc /* Try architecture-specific vmctls. */ 163*433d6423SLionel Sambuc return arch_do_vmctl(m_ptr, p); 164*433d6423SLionel Sambuc } 165