xref: /minix/minix/servers/vm/rs.c (revision 7f5f010b)
1 
2 #define _SYSTEM 1
3 
4 #include <minix/callnr.h>
5 #include <minix/com.h>
6 #include <minix/config.h>
7 #include <minix/const.h>
8 #include <minix/ds.h>
9 #include <minix/endpoint.h>
10 #include <minix/minlib.h>
11 #include <minix/type.h>
12 #include <minix/ipc.h>
13 #include <minix/sysutil.h>
14 #include <minix/syslib.h>
15 #include <minix/safecopies.h>
16 #include <minix/bitmap.h>
17 
18 #include <errno.h>
19 #include <string.h>
20 #include <env.h>
21 #include <stdio.h>
22 #include <assert.h>
23 
24 #include "glo.h"
25 #include "proto.h"
26 #include "util.h"
27 #include "region.h"
28 
29 /*===========================================================================*
30  *				do_rs_set_priv				     *
31  *===========================================================================*/
32 int do_rs_set_priv(message *m)
33 {
34 	int r, n, nr;
35 	struct vmproc *vmp;
36 	bitchunk_t call_mask[VM_CALL_MASK_SIZE], *call_mask_p;
37 
38 	nr = m->VM_RS_NR;
39 
40 	if ((r = vm_isokendpt(nr, &n)) != OK) {
41 		printf("do_rs_set_priv: bad endpoint %d\n", nr);
42 		return EINVAL;
43 	}
44 
45 	vmp = &vmproc[n];
46 
47 	if (m->VM_RS_BUF) {
48 		r = sys_datacopy(m->m_source, (vir_bytes) m->VM_RS_BUF, SELF,
49 			(vir_bytes) call_mask, sizeof(call_mask));
50 		if (r != OK)
51 			return r;
52 		call_mask_p = call_mask;
53 	} else {
54 		if (m->VM_RS_SYS) {
55 			printf("VM: do_rs_set_priv: sys procs don't share!\n");
56 			return EINVAL;
57 		}
58 		call_mask_p = NULL;
59 	}
60 
61 	acl_set(vmp, call_mask_p, m->VM_RS_SYS);
62 
63 	return OK;
64 }
65 
66 /*===========================================================================*
67  *				do_rs_update	     			     *
68  *===========================================================================*/
69 int do_rs_update(message *m_ptr)
70 {
71 	endpoint_t src_e, dst_e, reply_e;
72 	int src_p, dst_p;
73 	struct vmproc *src_vmp, *dst_vmp;
74 	int r;
75 
76 	src_e = m_ptr->m_lsys_vm_update.src;
77 	dst_e = m_ptr->m_lsys_vm_update.dst;
78 
79 	/* Lookup slots for source and destination process. */
80 	if(vm_isokendpt(src_e, &src_p) != OK) {
81 		printf("do_rs_update: bad src endpoint %d\n", src_e);
82 		return EINVAL;
83 	}
84 	src_vmp = &vmproc[src_p];
85 	if(vm_isokendpt(dst_e, &dst_p) != OK) {
86 		printf("do_rs_update: bad dst endpoint %d\n", dst_e);
87 		return EINVAL;
88 	}
89 	dst_vmp = &vmproc[dst_p];
90 
91 	/* Let the kernel do the update first. */
92 	r = sys_update(src_e, dst_e);
93 	if(r != OK) {
94 		return r;
95 	}
96 
97 	/* Do the update in VM now. */
98 	r = swap_proc_slot(src_vmp, dst_vmp);
99 	if(r != OK) {
100 		return r;
101 	}
102 	r = swap_proc_dyn_data(src_vmp, dst_vmp);
103 	if(r != OK) {
104 		return r;
105 	}
106 	pt_bind(&src_vmp->vm_pt, src_vmp);
107 	pt_bind(&dst_vmp->vm_pt, dst_vmp);
108 
109 	/* Reply, update-aware. */
110 	reply_e = m_ptr->m_source;
111 	if(reply_e == src_e) reply_e = dst_e;
112 	else if(reply_e == dst_e) reply_e = src_e;
113 	m_ptr->m_type = OK;
114 	r = ipc_send(reply_e, m_ptr);
115 	if(r != OK) {
116 		panic("ipc_send() error");
117 	}
118 
119 	return SUSPEND;
120 }
121 
122 /*===========================================================================*
123  *		           rs_memctl_make_vm_instance			     *
124  *===========================================================================*/
125 static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp)
126 {
127 	int r;
128 	u32_t flags;
129 	int verify;
130 	struct vmproc *this_vm_vmp;
131 
132 	this_vm_vmp = &vmproc[VM_PROC_NR];
133 
134 	/* Pin memory for the new VM instance. */
135 	r = map_pin_memory(new_vm_vmp);
136 	if(r != OK) {
137 		return r;
138 	}
139 
140 	/* Preallocate page tables for the entire address space for both
141 	 * VM and the new VM instance.
142 	 */
143 	flags = 0;
144 	verify = FALSE;
145 	r = pt_ptalloc_in_range(&this_vm_vmp->vm_pt, 0, 0, flags, verify);
146 	if(r != OK) {
147 		return r;
148 	}
149 	r = pt_ptalloc_in_range(&new_vm_vmp->vm_pt, 0, 0, flags, verify);
150 	if(r != OK) {
151 		return r;
152 	}
153 
154 	/* Let the new VM instance map VM's page tables and its own. */
155 	r = pt_ptmap(this_vm_vmp, new_vm_vmp);
156 	if(r != OK) {
157 		return r;
158 	}
159 	r = pt_ptmap(new_vm_vmp, new_vm_vmp);
160 	if(r != OK) {
161 		return r;
162 	}
163 
164 	return OK;
165 }
166 
167 /*===========================================================================*
168  *				do_rs_memctl	     			     *
169  *===========================================================================*/
170 int do_rs_memctl(message *m_ptr)
171 {
172 	endpoint_t ep;
173 	int req, r, proc_nr;
174 	struct vmproc *vmp;
175 
176 	ep = m_ptr->VM_RS_CTL_ENDPT;
177 	req = m_ptr->VM_RS_CTL_REQ;
178 
179 	/* Lookup endpoint. */
180 	if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
181 		printf("do_rs_memctl: bad endpoint %d\n", ep);
182 		return EINVAL;
183 	}
184 	vmp = &vmproc[proc_nr];
185 
186 	/* Process request. */
187 	switch(req)
188 	{
189 	case VM_RS_MEM_PIN:
190 
191 		/* Do not perform VM_RS_MEM_PIN yet - it costs the full
192 		 * size of the RS stack (64MB by default) in memory,
193 		 * and it's needed for functionality that isn't complete /
194 		 * merged in current Minix (surviving VM crashes).
195 		 */
196 
197 #if 0
198 		r = map_pin_memory(vmp);
199 		return r;
200 #else
201 		return OK;
202 #endif
203 
204 	case VM_RS_MEM_MAKE_VM:
205 		r = rs_memctl_make_vm_instance(vmp);
206 		return r;
207 	default:
208 		printf("do_rs_memctl: bad request %d\n", req);
209 		return EINVAL;
210 	}
211 }
212 
213