xref: /minix3/minix/kernel/system/do_update.c (revision 56e56d2af29bb588b94d97ee83c57c2b7879291e)
1433d6423SLionel Sambuc /* The kernel call implemented in this file:
2433d6423SLionel Sambuc  *   m_type:	SYS_UPDATE
3433d6423SLionel Sambuc  *
4433d6423SLionel Sambuc  * The parameters for this kernel call are:
5433d6423SLionel Sambuc  *    m2_i1:	SYS_UPD_SRC_ENDPT 	(source process endpoint)
6433d6423SLionel Sambuc  *    m2_i2:	SYS_UPD_DST_ENDPT	(destination process endpoint)
7a1760b57SCristiano Giuffrida  *    m2_i3:	SYS_UPD_FLAGS		(update flags)
8433d6423SLionel Sambuc  */
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc #include "kernel/system.h"
11433d6423SLionel Sambuc #include "kernel/ipc.h"
12433d6423SLionel Sambuc #include <string.h>
13433d6423SLionel Sambuc #include <assert.h>
14433d6423SLionel Sambuc 
15433d6423SLionel Sambuc #if USE_UPDATE
16433d6423SLionel Sambuc 
17433d6423SLionel Sambuc #define DEBUG 0
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc #define proc_is_updatable(p) \
20433d6423SLionel Sambuc     (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
21433d6423SLionel Sambuc     || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING)))
22433d6423SLionel Sambuc 
23*56e56d2aSCristiano Giuffrida static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp);
24*56e56d2aSCristiano Giuffrida static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp);
25*56e56d2aSCristiano Giuffrida static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp);
26433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
27433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv
28433d6423SLionel Sambuc 	*from_privp);
29433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc
30433d6423SLionel Sambuc 	*src_rp, struct proc *dst_rp);
31433d6423SLionel Sambuc 
32433d6423SLionel Sambuc /*===========================================================================*
33433d6423SLionel Sambuc  *				do_update				     *
34433d6423SLionel Sambuc  *===========================================================================*/
35433d6423SLionel Sambuc int do_update(struct proc * caller, message * m_ptr)
36433d6423SLionel Sambuc {
37433d6423SLionel Sambuc /* Handle sys_update(). Update a process into another by swapping their process
38433d6423SLionel Sambuc  * slots.
39433d6423SLionel Sambuc  */
40433d6423SLionel Sambuc   endpoint_t src_e, dst_e;
41433d6423SLionel Sambuc   int src_p, dst_p;
42433d6423SLionel Sambuc   struct proc *src_rp, *dst_rp;
43433d6423SLionel Sambuc   struct priv *src_privp, *dst_privp;
44433d6423SLionel Sambuc   struct proc orig_src_proc;
45433d6423SLionel Sambuc   struct proc orig_dst_proc;
46433d6423SLionel Sambuc   struct priv orig_src_priv;
47433d6423SLionel Sambuc   struct priv orig_dst_priv;
48*56e56d2aSCristiano Giuffrida   int i, r;
49433d6423SLionel Sambuc 
50433d6423SLionel Sambuc   /* Lookup slots for source and destination process. */
51433d6423SLionel Sambuc   src_e = m_ptr->SYS_UPD_SRC_ENDPT;
52433d6423SLionel Sambuc   if(!isokendpt(src_e, &src_p)) {
53433d6423SLionel Sambuc       return EINVAL;
54433d6423SLionel Sambuc   }
55433d6423SLionel Sambuc   src_rp = proc_addr(src_p);
56433d6423SLionel Sambuc   src_privp = priv(src_rp);
57433d6423SLionel Sambuc   if(!(src_privp->s_flags & SYS_PROC)) {
58433d6423SLionel Sambuc       return EPERM;
59433d6423SLionel Sambuc   }
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc   dst_e = m_ptr->SYS_UPD_DST_ENDPT;
62433d6423SLionel Sambuc   if(!isokendpt(dst_e, &dst_p)) {
63433d6423SLionel Sambuc       return EINVAL;
64433d6423SLionel Sambuc   }
65433d6423SLionel Sambuc   dst_rp = proc_addr(dst_p);
66433d6423SLionel Sambuc   dst_privp = priv(dst_rp);
67433d6423SLionel Sambuc   if(!(dst_privp->s_flags & SYS_PROC)) {
68433d6423SLionel Sambuc       return EPERM;
69433d6423SLionel Sambuc   }
70433d6423SLionel Sambuc 
71433d6423SLionel Sambuc   assert(!proc_is_runnable(src_rp) && !proc_is_runnable(dst_rp));
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc   /* Check if processes are updatable. */
74433d6423SLionel Sambuc   if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) {
75433d6423SLionel Sambuc       return EBUSY;
76433d6423SLionel Sambuc   }
77433d6423SLionel Sambuc 
78433d6423SLionel Sambuc #if DEBUG
79433d6423SLionel Sambuc   printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n",
80433d6423SLionel Sambuc       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
81433d6423SLionel Sambuc       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc   proc_stacktrace(src_rp);
84433d6423SLionel Sambuc   proc_stacktrace(dst_rp);
85433d6423SLionel Sambuc   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
86433d6423SLionel Sambuc #endif
87433d6423SLionel Sambuc 
88*56e56d2aSCristiano Giuffrida   /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */
89*56e56d2aSCristiano Giuffrida   r = inherit_priv_irq(src_rp, dst_rp);
90*56e56d2aSCristiano Giuffrida   if(r != OK) {
91*56e56d2aSCristiano Giuffrida       return r;
92*56e56d2aSCristiano Giuffrida   }
93*56e56d2aSCristiano Giuffrida   r = inherit_priv_io(src_rp, dst_rp);
94*56e56d2aSCristiano Giuffrida   if(r != OK) {
95*56e56d2aSCristiano Giuffrida       return r;
96*56e56d2aSCristiano Giuffrida   }
97*56e56d2aSCristiano Giuffrida   r = inherit_priv_mem(src_rp, dst_rp);
98*56e56d2aSCristiano Giuffrida   if(r != OK) {
99*56e56d2aSCristiano Giuffrida       return r;
100*56e56d2aSCristiano Giuffrida   }
101*56e56d2aSCristiano Giuffrida 
102433d6423SLionel Sambuc   /* Let destination inherit the target mask from source. */
103433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i++) {
104433d6423SLionel Sambuc       if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) {
105433d6423SLionel Sambuc           set_sendto_bit(dst_rp, i);
106433d6423SLionel Sambuc       }
107433d6423SLionel Sambuc   }
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc   /* Save existing data. */
110433d6423SLionel Sambuc   orig_src_proc = *src_rp;
111433d6423SLionel Sambuc   orig_src_priv = *(priv(src_rp));
112433d6423SLionel Sambuc   orig_dst_proc = *dst_rp;
113433d6423SLionel Sambuc   orig_dst_priv = *(priv(dst_rp));
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc   /* Swap slots. */
116433d6423SLionel Sambuc   *src_rp = orig_dst_proc;
117433d6423SLionel Sambuc   *src_privp = orig_dst_priv;
118433d6423SLionel Sambuc   *dst_rp = orig_src_proc;
119433d6423SLionel Sambuc   *dst_privp = orig_src_priv;
120433d6423SLionel Sambuc 
121433d6423SLionel Sambuc   /* Adjust process slots. */
122433d6423SLionel Sambuc   adjust_proc_slot(src_rp, &orig_src_proc);
123433d6423SLionel Sambuc   adjust_proc_slot(dst_rp, &orig_dst_proc);
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc   /* Adjust privilege slots. */
126433d6423SLionel Sambuc   adjust_priv_slot(priv(src_rp), &orig_src_priv);
127433d6423SLionel Sambuc   adjust_priv_slot(priv(dst_rp), &orig_dst_priv);
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   /* Swap global process slot addresses. */
130433d6423SLionel Sambuc   swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp);
131433d6423SLionel Sambuc 
132433d6423SLionel Sambuc #if DEBUG
133433d6423SLionel Sambuc   printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n",
134433d6423SLionel Sambuc       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
135433d6423SLionel Sambuc       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc   proc_stacktrace(src_rp);
138433d6423SLionel Sambuc   proc_stacktrace(dst_rp);
139433d6423SLionel Sambuc   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
140433d6423SLionel Sambuc #endif
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc #ifdef CONFIG_SMP
143433d6423SLionel Sambuc   bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS);
144433d6423SLionel Sambuc   bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS);
145433d6423SLionel Sambuc #endif
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc   return OK;
148433d6423SLionel Sambuc }
149433d6423SLionel Sambuc 
150433d6423SLionel Sambuc /*===========================================================================*
151*56e56d2aSCristiano Giuffrida  *			     inherit_priv_irq 				     *
152*56e56d2aSCristiano Giuffrida  *===========================================================================*/
153*56e56d2aSCristiano Giuffrida int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp)
154*56e56d2aSCristiano Giuffrida {
155*56e56d2aSCristiano Giuffrida   int i, r;
156*56e56d2aSCristiano Giuffrida   for (i= 0; i<priv(src_rp)->s_nr_irq; i++) {
157*56e56d2aSCristiano Giuffrida       r = priv_add_irq(dst_rp, priv(src_rp)->s_irq_tab[i]);
158*56e56d2aSCristiano Giuffrida       if(r != OK) {
159*56e56d2aSCristiano Giuffrida           return r;
160*56e56d2aSCristiano Giuffrida       }
161*56e56d2aSCristiano Giuffrida   }
162*56e56d2aSCristiano Giuffrida 
163*56e56d2aSCristiano Giuffrida   return OK;
164*56e56d2aSCristiano Giuffrida }
165*56e56d2aSCristiano Giuffrida 
166*56e56d2aSCristiano Giuffrida /*===========================================================================*
167*56e56d2aSCristiano Giuffrida  *			     inherit_priv_io 				     *
168*56e56d2aSCristiano Giuffrida  *===========================================================================*/
169*56e56d2aSCristiano Giuffrida  int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp)
170*56e56d2aSCristiano Giuffrida {
171*56e56d2aSCristiano Giuffrida   int i, r;
172*56e56d2aSCristiano Giuffrida   for (i= 0; i<priv(src_rp)->s_nr_io_range; i++) {
173*56e56d2aSCristiano Giuffrida       r = priv_add_io(dst_rp, &(priv(src_rp)->s_io_tab[i]));
174*56e56d2aSCristiano Giuffrida       if(r != OK) {
175*56e56d2aSCristiano Giuffrida           return r;
176*56e56d2aSCristiano Giuffrida       }
177*56e56d2aSCristiano Giuffrida   }
178*56e56d2aSCristiano Giuffrida 
179*56e56d2aSCristiano Giuffrida   return OK;
180*56e56d2aSCristiano Giuffrida }
181*56e56d2aSCristiano Giuffrida 
182*56e56d2aSCristiano Giuffrida /*===========================================================================*
183*56e56d2aSCristiano Giuffrida  *			     inherit_priv_mem 				     *
184*56e56d2aSCristiano Giuffrida  *===========================================================================*/
185*56e56d2aSCristiano Giuffrida int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp)
186*56e56d2aSCristiano Giuffrida {
187*56e56d2aSCristiano Giuffrida   int i, r;
188*56e56d2aSCristiano Giuffrida   for (i= 0; i<priv(src_rp)->s_nr_mem_range; i++) {
189*56e56d2aSCristiano Giuffrida       r = priv_add_mem(dst_rp, &(priv(src_rp)->s_mem_tab[i]));
190*56e56d2aSCristiano Giuffrida       if(r != OK) {
191*56e56d2aSCristiano Giuffrida           return r;
192*56e56d2aSCristiano Giuffrida       }
193*56e56d2aSCristiano Giuffrida   }
194*56e56d2aSCristiano Giuffrida 
195*56e56d2aSCristiano Giuffrida   return OK;
196*56e56d2aSCristiano Giuffrida }
197*56e56d2aSCristiano Giuffrida 
198*56e56d2aSCristiano Giuffrida /*===========================================================================*
199433d6423SLionel Sambuc  *			     adjust_proc_slot				     *
200433d6423SLionel Sambuc  *===========================================================================*/
201433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
202433d6423SLionel Sambuc {
203433d6423SLionel Sambuc   /* Preserve endpoints, slot numbers, priv structure, and IPC. */
204433d6423SLionel Sambuc   rp->p_endpoint = from_rp->p_endpoint;
205433d6423SLionel Sambuc   rp->p_nr = from_rp->p_nr;
206433d6423SLionel Sambuc   rp->p_priv = from_rp->p_priv;
207433d6423SLionel Sambuc   priv(rp)->s_proc_nr = from_rp->p_nr;
208433d6423SLionel Sambuc   rp->p_caller_q = from_rp->p_caller_q;
209433d6423SLionel Sambuc 
210433d6423SLionel Sambuc   /* preserve scheduling */
211433d6423SLionel Sambuc   rp->p_scheduler = from_rp->p_scheduler;
212433d6423SLionel Sambuc #ifdef CONFIG_SMP
213433d6423SLionel Sambuc   rp->p_cpu = from_rp->p_cpu;
214433d6423SLionel Sambuc   memcpy(rp->p_cpu_mask, from_rp->p_cpu_mask,
215433d6423SLionel Sambuc 		  sizeof(bitchunk_t) * BITMAP_CHUNKS(CONFIG_MAX_CPUS));
216433d6423SLionel Sambuc #endif
217433d6423SLionel Sambuc }
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc /*===========================================================================*
220433d6423SLionel Sambuc  *			     adjust_priv_slot				     *
221433d6423SLionel Sambuc  *===========================================================================*/
222433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv *from_privp)
223433d6423SLionel Sambuc {
224433d6423SLionel Sambuc   /* Preserve privilege ids and non-privilege stuff in the priv structure. */
225433d6423SLionel Sambuc   privp->s_id = from_privp->s_id;
226433d6423SLionel Sambuc   privp->s_notify_pending = from_privp->s_notify_pending;
227433d6423SLionel Sambuc   privp->s_int_pending = from_privp->s_int_pending;
228433d6423SLionel Sambuc   privp->s_sig_pending = from_privp->s_sig_pending;
229433d6423SLionel Sambuc   privp->s_alarm_timer = from_privp->s_alarm_timer;
230433d6423SLionel Sambuc   privp->s_diag_sig = from_privp->s_diag_sig;
231433d6423SLionel Sambuc }
232433d6423SLionel Sambuc 
233433d6423SLionel Sambuc /*===========================================================================*
234433d6423SLionel Sambuc  *			   swap_proc_slot_pointer			     *
235433d6423SLionel Sambuc  *===========================================================================*/
236433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp,
237433d6423SLionel Sambuc     struct proc *dst_rp)
238433d6423SLionel Sambuc {
239433d6423SLionel Sambuc   if(*rpp == src_rp) {
240433d6423SLionel Sambuc       *rpp = dst_rp;
241433d6423SLionel Sambuc   }
242433d6423SLionel Sambuc   else if(*rpp == dst_rp) {
243433d6423SLionel Sambuc       *rpp = src_rp;
244433d6423SLionel Sambuc   }
245433d6423SLionel Sambuc }
246433d6423SLionel Sambuc 
247433d6423SLionel Sambuc #endif /* USE_UPDATE */
248433d6423SLionel Sambuc 
249