xref: /minix/minix/kernel/system/do_update.c (revision 35b65c5a)
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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