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