1 /* The kernel call implemented in this file:
2 * m_type: SYS_UPDATE
3 *
4 * The parameters for this kernel call are:
5 * m2_i1: SYS_UPD_SRC_ENDPT (source process endpoint)
6 * m2_i2: SYS_UPD_DST_ENDPT (destination process endpoint)
7 * m2_i3: SYS_UPD_FLAGS (update flags)
8 */
9
10 #include "kernel/system.h"
11 #include <string.h>
12 #include <assert.h>
13
14 #if USE_UPDATE
15
16 #define DEBUG 0
17
18 #define proc_is_updatable(p) \
19 (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
20 || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING)))
21
22 static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp);
23 static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp);
24 static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp);
25 static void abort_proc_ipc_send(struct proc *rp);
26 static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
27 static void adjust_priv_slot(struct priv *privp, struct priv
28 *from_privp);
29 static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp);
30 static void swap_proc_slot_pointer(struct proc **rpp, struct proc
31 *src_rp, struct proc *dst_rp);
32 static void swap_memreq(struct proc *src_rp, struct proc *dst_rp);
33
34 /*===========================================================================*
35 * do_update *
36 *===========================================================================*/
do_update(struct proc * caller,message * m_ptr)37 int do_update(struct proc * caller, message * m_ptr)
38 {
39 /* Handle sys_update(). Update a process into another by swapping their process
40 * slots.
41 */
42 endpoint_t src_e, dst_e;
43 int src_p, dst_p, flags;
44 struct proc *src_rp, *dst_rp;
45 struct priv *src_privp, *dst_privp;
46 struct proc orig_src_proc;
47 struct proc orig_dst_proc;
48 struct priv orig_src_priv;
49 struct priv orig_dst_priv;
50 int i, r;
51
52 /* Lookup slots for source and destination process. */
53 flags = m_ptr->SYS_UPD_FLAGS;
54 src_e = m_ptr->SYS_UPD_SRC_ENDPT;
55 if(!isokendpt(src_e, &src_p)) {
56 return EINVAL;
57 }
58 src_rp = proc_addr(src_p);
59 src_privp = priv(src_rp);
60 if(!(src_privp->s_flags & SYS_PROC)) {
61 return EPERM;
62 }
63
64 dst_e = m_ptr->SYS_UPD_DST_ENDPT;
65 if(!isokendpt(dst_e, &dst_p)) {
66 return EINVAL;
67 }
68 dst_rp = proc_addr(dst_p);
69 dst_privp = priv(dst_rp);
70 if(!(dst_privp->s_flags & SYS_PROC)) {
71 return EPERM;
72 }
73
74 assert(!proc_is_runnable(src_rp) && !proc_is_runnable(dst_rp));
75
76 /* Check if processes are updatable. */
77 if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) {
78 return EBUSY;
79 }
80
81 #if DEBUG
82 printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n",
83 src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
84 dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
85
86 proc_stacktrace(src_rp);
87 proc_stacktrace(dst_rp);
88 printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
89 printf("do_update: endpoint %d rts flags %x asyn tab %08x asyn endpoint %d grant tab %08x grant endpoint %d\n", src_rp->p_endpoint, src_rp->p_rts_flags, priv(src_rp)->s_asyntab, priv(src_rp)->s_asynendpoint, priv(src_rp)->s_grant_table, priv(src_rp)->s_grant_endpoint);
90 printf("do_update: endpoint %d rts flags %x asyn tab %08x asyn endpoint %d grant tab %08x grant endpoint %d\n", dst_rp->p_endpoint, dst_rp->p_rts_flags, priv(dst_rp)->s_asyntab, priv(dst_rp)->s_asynendpoint, priv(dst_rp)->s_grant_table, priv(dst_rp)->s_grant_endpoint);
91 #endif
92
93 /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */
94 r = inherit_priv_irq(src_rp, dst_rp);
95 if(r != OK) {
96 return r;
97 }
98 r = inherit_priv_io(src_rp, dst_rp);
99 if(r != OK) {
100 return r;
101 }
102 r = inherit_priv_mem(src_rp, dst_rp);
103 if(r != OK) {
104 return r;
105 }
106
107 /* Let destination inherit the target mask from source. */
108 for (i=0; i < NR_SYS_PROCS; i++) {
109 if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) {
110 set_sendto_bit(dst_rp, i);
111 }
112 }
113
114 /* Save existing data. */
115 orig_src_proc = *src_rp;
116 orig_src_priv = *(priv(src_rp));
117 orig_dst_proc = *dst_rp;
118 orig_dst_priv = *(priv(dst_rp));
119
120 /* Adjust asyn tables. */
121 adjust_asyn_table(priv(src_rp), priv(dst_rp));
122 adjust_asyn_table(priv(dst_rp), priv(src_rp));
123
124 /* Abort any pending send() on rollback. */
125 if(flags & SYS_UPD_ROLLBACK) {
126 abort_proc_ipc_send(src_rp);
127 }
128
129 /* Swap slots. */
130 *src_rp = orig_dst_proc;
131 *src_privp = orig_dst_priv;
132 *dst_rp = orig_src_proc;
133 *dst_privp = orig_src_priv;
134
135 /* Adjust process slots. */
136 adjust_proc_slot(src_rp, &orig_src_proc);
137 adjust_proc_slot(dst_rp, &orig_dst_proc);
138
139 /* Adjust privilege slots. */
140 adjust_priv_slot(priv(src_rp), &orig_src_priv);
141 adjust_priv_slot(priv(dst_rp), &orig_dst_priv);
142
143 /* Swap global process slot addresses. */
144 swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp);
145
146 /* Swap VM request entries. */
147 swap_memreq(src_rp, dst_rp);
148
149 #if DEBUG
150 printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n",
151 src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
152 dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
153
154 proc_stacktrace(src_rp);
155 proc_stacktrace(dst_rp);
156 printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
157 printf("do_update: endpoint %d rts flags %x asyn tab %08x asyn endpoint %d grant tab %08x grant endpoint %d\n", src_rp->p_endpoint, src_rp->p_rts_flags, priv(src_rp)->s_asyntab, priv(src_rp)->s_asynendpoint, priv(src_rp)->s_grant_table, priv(src_rp)->s_grant_endpoint);
158 printf("do_update: endpoint %d rts flags %x asyn tab %08x asyn endpoint %d grant tab %08x grant endpoint %d\n", dst_rp->p_endpoint, dst_rp->p_rts_flags, priv(dst_rp)->s_asyntab, priv(dst_rp)->s_asynendpoint, priv(dst_rp)->s_grant_table, priv(dst_rp)->s_grant_endpoint);
159 #endif
160
161 #ifdef CONFIG_SMP
162 bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS);
163 bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS);
164 #endif
165
166 return OK;
167 }
168
169 /*===========================================================================*
170 * inherit_priv_irq *
171 *===========================================================================*/
inherit_priv_irq(struct proc * src_rp,struct proc * dst_rp)172 int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp)
173 {
174 int i, r;
175 for (i= 0; i<priv(src_rp)->s_nr_irq; i++) {
176 r = priv_add_irq(dst_rp, priv(src_rp)->s_irq_tab[i]);
177 if(r != OK) {
178 return r;
179 }
180 }
181
182 return OK;
183 }
184
185 /*===========================================================================*
186 * inherit_priv_io *
187 *===========================================================================*/
inherit_priv_io(struct proc * src_rp,struct proc * dst_rp)188 int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp)
189 {
190 int i, r;
191 for (i= 0; i<priv(src_rp)->s_nr_io_range; i++) {
192 r = priv_add_io(dst_rp, &(priv(src_rp)->s_io_tab[i]));
193 if(r != OK) {
194 return r;
195 }
196 }
197
198 return OK;
199 }
200
201 /*===========================================================================*
202 * inherit_priv_mem *
203 *===========================================================================*/
inherit_priv_mem(struct proc * src_rp,struct proc * dst_rp)204 int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp)
205 {
206 int i, r;
207 for (i= 0; i<priv(src_rp)->s_nr_mem_range; i++) {
208 r = priv_add_mem(dst_rp, &(priv(src_rp)->s_mem_tab[i]));
209 if(r != OK) {
210 return r;
211 }
212 }
213
214 return OK;
215 }
216
217 /*===========================================================================*
218 * abort_proc_ipc_send *
219 *===========================================================================*/
abort_proc_ipc_send(struct proc * rp)220 void abort_proc_ipc_send(struct proc *rp)
221 {
222 if(RTS_ISSET(rp, RTS_SENDING)) {
223 struct proc **xpp;
224 RTS_UNSET(rp, RTS_SENDING);
225 rp->p_misc_flags &= ~MF_SENDING_FROM_KERNEL;
226 xpp = &(proc_addr(_ENDPOINT_P(rp->p_sendto_e))->p_caller_q);
227 while (*xpp) {
228 if(*xpp == rp) {
229 *xpp = rp->p_q_link;
230 rp->p_q_link = NULL;
231 break;
232 }
233 xpp = &(*xpp)->p_q_link;
234 }
235 }
236 }
237
238 /*===========================================================================*
239 * adjust_proc_slot *
240 *===========================================================================*/
adjust_proc_slot(struct proc * rp,struct proc * from_rp)241 static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
242 {
243 /* Preserve endpoints, slot numbers, priv structure, and IPC. */
244 rp->p_endpoint = from_rp->p_endpoint;
245 rp->p_nr = from_rp->p_nr;
246 rp->p_priv = from_rp->p_priv;
247 priv(rp)->s_proc_nr = from_rp->p_nr;
248
249 rp->p_caller_q = from_rp->p_caller_q;
250
251 /* preserve scheduling */
252 rp->p_scheduler = from_rp->p_scheduler;
253 #ifdef CONFIG_SMP
254 rp->p_cpu = from_rp->p_cpu;
255 memcpy(rp->p_cpu_mask, from_rp->p_cpu_mask,
256 sizeof(bitchunk_t) * BITMAP_CHUNKS(CONFIG_MAX_CPUS));
257 #endif
258 }
259
260 /*===========================================================================*
261 * adjust_asyn_table *
262 *===========================================================================*/
adjust_asyn_table(struct priv * src_privp,struct priv * dst_privp)263 static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp)
264 {
265 /* Transfer the asyn table if source's table belongs to the destination. */
266 endpoint_t src_e = proc_addr(src_privp->s_proc_nr)->p_endpoint;
267 endpoint_t dst_e = proc_addr(dst_privp->s_proc_nr)->p_endpoint;
268
269 if(src_privp->s_asynsize > 0 && dst_privp->s_asynsize > 0 && src_privp->s_asynendpoint == dst_e) {
270 if(data_copy(src_e, src_privp->s_asyntab, dst_e, dst_privp->s_asyntab,
271 src_privp->s_asynsize*sizeof(asynmsg_t)) != OK) {
272 printf("Warning: unable to transfer asyn table from ep %d to ep %d\n",
273 src_e, dst_e);
274 }
275 else {
276 dst_privp->s_asynsize = src_privp->s_asynsize;
277 }
278 }
279 }
280
281 /*===========================================================================*
282 * adjust_priv_slot *
283 *===========================================================================*/
adjust_priv_slot(struct priv * privp,struct priv * from_privp)284 static void adjust_priv_slot(struct priv *privp, struct priv *from_privp)
285 {
286 /* Preserve privilege ids and non-privilege stuff in the priv structure. */
287 privp->s_id = from_privp->s_id;
288 privp->s_asyn_pending = from_privp->s_asyn_pending;
289 privp->s_notify_pending = from_privp->s_notify_pending;
290 privp->s_int_pending = from_privp->s_int_pending;
291 privp->s_sig_pending = from_privp->s_sig_pending;
292 privp->s_alarm_timer = from_privp->s_alarm_timer;
293 privp->s_diag_sig = from_privp->s_diag_sig;
294 }
295
296 /*===========================================================================*
297 * swap_proc_slot_pointer *
298 *===========================================================================*/
swap_proc_slot_pointer(struct proc ** rpp,struct proc * src_rp,struct proc * dst_rp)299 static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp,
300 struct proc *dst_rp)
301 {
302 if(*rpp == src_rp) {
303 *rpp = dst_rp;
304 }
305 else if(*rpp == dst_rp) {
306 *rpp = src_rp;
307 }
308 }
309
310 /*===========================================================================*
311 * swap_memreq *
312 *===========================================================================*/
swap_memreq(struct proc * src_rp,struct proc * dst_rp)313 static void swap_memreq(struct proc *src_rp, struct proc *dst_rp)
314 {
315 /* If either the source or the destination process is part of the VM request
316 * chain, but not both, then swap the process pointers in the chain.
317 */
318 struct proc **rpp;
319
320 if (RTS_ISSET(src_rp, RTS_VMREQUEST) == RTS_ISSET(dst_rp, RTS_VMREQUEST))
321 return; /* nothing to do */
322
323 for (rpp = &vmrequest; *rpp != NULL;
324 rpp = &(*rpp)->p_vmrequest.nextrequestor) {
325 if (*rpp == src_rp) {
326 dst_rp->p_vmrequest.nextrequestor =
327 src_rp->p_vmrequest.nextrequestor;
328 *rpp = dst_rp;
329 break;
330 } else if (*rpp == dst_rp) {
331 src_rp->p_vmrequest.nextrequestor =
332 dst_rp->p_vmrequest.nextrequestor;
333 *rpp = src_rp;
334 break;
335 }
336 }
337 }
338
339 #endif /* USE_UPDATE */
340
341