1*433d6423SLionel Sambuc 2*433d6423SLionel Sambuc #define _SYSTEM 1 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc #include <minix/callnr.h> 5*433d6423SLionel Sambuc #include <minix/com.h> 6*433d6423SLionel Sambuc #include <minix/config.h> 7*433d6423SLionel Sambuc #include <minix/const.h> 8*433d6423SLionel Sambuc #include <minix/ds.h> 9*433d6423SLionel Sambuc #include <minix/endpoint.h> 10*433d6423SLionel Sambuc #include <minix/minlib.h> 11*433d6423SLionel Sambuc #include <minix/type.h> 12*433d6423SLionel Sambuc #include <minix/ipc.h> 13*433d6423SLionel Sambuc #include <minix/sysutil.h> 14*433d6423SLionel Sambuc #include <minix/syslib.h> 15*433d6423SLionel Sambuc #include <minix/debug.h> 16*433d6423SLionel Sambuc #include <minix/bitmap.h> 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc #include <string.h> 19*433d6423SLionel Sambuc #include <errno.h> 20*433d6423SLionel Sambuc #include <env.h> 21*433d6423SLionel Sambuc #include <assert.h> 22*433d6423SLionel Sambuc 23*433d6423SLionel Sambuc #include "glo.h" 24*433d6423SLionel Sambuc #include "vm.h" 25*433d6423SLionel Sambuc #include "proto.h" 26*433d6423SLionel Sambuc #include "util.h" 27*433d6423SLionel Sambuc #include "sanitycheck.h" 28*433d6423SLionel Sambuc #include "region.h" 29*433d6423SLionel Sambuc 30*433d6423SLionel Sambuc /*===========================================================================* 31*433d6423SLionel Sambuc * do_fork * 32*433d6423SLionel Sambuc *===========================================================================*/ 33*433d6423SLionel Sambuc int do_fork(message *msg) 34*433d6423SLionel Sambuc { 35*433d6423SLionel Sambuc int r, proc, childproc; 36*433d6423SLionel Sambuc struct vmproc *vmp, *vmc; 37*433d6423SLionel Sambuc pt_t origpt; 38*433d6423SLionel Sambuc vir_bytes msgaddr; 39*433d6423SLionel Sambuc 40*433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 41*433d6423SLionel Sambuc 42*433d6423SLionel Sambuc if(vm_isokendpt(msg->VMF_ENDPOINT, &proc) != OK) { 43*433d6423SLionel Sambuc printf("VM: bogus endpoint VM_FORK %d\n", msg->VMF_ENDPOINT); 44*433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 45*433d6423SLionel Sambuc return EINVAL; 46*433d6423SLionel Sambuc } 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc childproc = msg->VMF_SLOTNO; 49*433d6423SLionel Sambuc if(childproc < 0 || childproc >= NR_PROCS) { 50*433d6423SLionel Sambuc printf("VM: bogus slotno VM_FORK %d\n", msg->VMF_SLOTNO); 51*433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 52*433d6423SLionel Sambuc return EINVAL; 53*433d6423SLionel Sambuc } 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc vmp = &vmproc[proc]; /* parent */ 56*433d6423SLionel Sambuc vmc = &vmproc[childproc]; /* child */ 57*433d6423SLionel Sambuc assert(vmc->vm_slot == childproc); 58*433d6423SLionel Sambuc 59*433d6423SLionel Sambuc /* The child is basically a copy of the parent. */ 60*433d6423SLionel Sambuc origpt = vmc->vm_pt; 61*433d6423SLionel Sambuc *vmc = *vmp; 62*433d6423SLionel Sambuc vmc->vm_slot = childproc; 63*433d6423SLionel Sambuc region_init(&vmc->vm_regions_avl); 64*433d6423SLionel Sambuc vmc->vm_endpoint = NONE; /* In case someone tries to use it. */ 65*433d6423SLionel Sambuc vmc->vm_pt = origpt; 66*433d6423SLionel Sambuc 67*433d6423SLionel Sambuc #if VMSTATS 68*433d6423SLionel Sambuc vmc->vm_bytecopies = 0; 69*433d6423SLionel Sambuc #endif 70*433d6423SLionel Sambuc 71*433d6423SLionel Sambuc if(pt_new(&vmc->vm_pt) != OK) { 72*433d6423SLionel Sambuc return ENOMEM; 73*433d6423SLionel Sambuc } 74*433d6423SLionel Sambuc 75*433d6423SLionel Sambuc SANITYCHECK(SCL_DETAIL); 76*433d6423SLionel Sambuc 77*433d6423SLionel Sambuc if(map_proc_copy(vmc, vmp) != OK) { 78*433d6423SLionel Sambuc printf("VM: fork: map_proc_copy failed\n"); 79*433d6423SLionel Sambuc pt_free(&vmc->vm_pt); 80*433d6423SLionel Sambuc return(ENOMEM); 81*433d6423SLionel Sambuc } 82*433d6423SLionel Sambuc 83*433d6423SLionel Sambuc /* Only inherit these flags. */ 84*433d6423SLionel Sambuc vmc->vm_flags &= VMF_INUSE; 85*433d6423SLionel Sambuc 86*433d6423SLionel Sambuc /* Deal with ACLs. */ 87*433d6423SLionel Sambuc acl_fork(vmc); 88*433d6423SLionel Sambuc 89*433d6423SLionel Sambuc /* Tell kernel about the (now successful) FORK. */ 90*433d6423SLionel Sambuc if((r=sys_fork(vmp->vm_endpoint, childproc, 91*433d6423SLionel Sambuc &vmc->vm_endpoint, PFF_VMINHIBIT, &msgaddr)) != OK) { 92*433d6423SLionel Sambuc panic("do_fork can't sys_fork: %d", r); 93*433d6423SLionel Sambuc } 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc if((r=pt_bind(&vmc->vm_pt, vmc)) != OK) 96*433d6423SLionel Sambuc panic("fork can't pt_bind: %d", r); 97*433d6423SLionel Sambuc 98*433d6423SLionel Sambuc { 99*433d6423SLionel Sambuc vir_bytes vir; 100*433d6423SLionel Sambuc /* making these messages writable is an optimisation 101*433d6423SLionel Sambuc * and its return value needn't be checked. 102*433d6423SLionel Sambuc */ 103*433d6423SLionel Sambuc vir = msgaddr; 104*433d6423SLionel Sambuc if (handle_memory_once(vmc, vir, sizeof(message), 1) != OK) 105*433d6423SLionel Sambuc panic("do_fork: handle_memory for child failed\n"); 106*433d6423SLionel Sambuc vir = msgaddr; 107*433d6423SLionel Sambuc if (handle_memory_once(vmp, vir, sizeof(message), 1) != OK) 108*433d6423SLionel Sambuc panic("do_fork: handle_memory for parent failed\n"); 109*433d6423SLionel Sambuc } 110*433d6423SLionel Sambuc 111*433d6423SLionel Sambuc /* Inform caller of new child endpoint. */ 112*433d6423SLionel Sambuc msg->VMF_CHILD_ENDPOINT = vmc->vm_endpoint; 113*433d6423SLionel Sambuc 114*433d6423SLionel Sambuc SANITYCHECK(SCL_FUNCTIONS); 115*433d6423SLionel Sambuc return OK; 116*433d6423SLionel Sambuc } 117*433d6423SLionel Sambuc 118