xref: /minix3/minix/kernel/system/do_update.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* The kernel call implemented in this file:
2*433d6423SLionel Sambuc  *   m_type:	SYS_UPDATE
3*433d6423SLionel Sambuc  *
4*433d6423SLionel Sambuc  * The parameters for this kernel call are:
5*433d6423SLionel Sambuc  *    m2_i1:	SYS_UPD_SRC_ENDPT 	(source process endpoint)
6*433d6423SLionel Sambuc  *    m2_i2:	SYS_UPD_DST_ENDPT	(destination process endpoint)
7*433d6423SLionel Sambuc  */
8*433d6423SLionel Sambuc 
9*433d6423SLionel Sambuc #include "kernel/system.h"
10*433d6423SLionel Sambuc #include "kernel/ipc.h"
11*433d6423SLionel Sambuc #include <string.h>
12*433d6423SLionel Sambuc #include <assert.h>
13*433d6423SLionel Sambuc 
14*433d6423SLionel Sambuc #if USE_UPDATE
15*433d6423SLionel Sambuc 
16*433d6423SLionel Sambuc #define DEBUG 0
17*433d6423SLionel Sambuc 
18*433d6423SLionel Sambuc #define proc_is_updatable(p) \
19*433d6423SLionel Sambuc     (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
20*433d6423SLionel Sambuc     || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING)))
21*433d6423SLionel Sambuc 
22*433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
23*433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv
24*433d6423SLionel Sambuc 	*from_privp);
25*433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc
26*433d6423SLionel Sambuc 	*src_rp, struct proc *dst_rp);
27*433d6423SLionel Sambuc 
28*433d6423SLionel Sambuc /*===========================================================================*
29*433d6423SLionel Sambuc  *				do_update				     *
30*433d6423SLionel Sambuc  *===========================================================================*/
31*433d6423SLionel Sambuc int do_update(struct proc * caller, message * m_ptr)
32*433d6423SLionel Sambuc {
33*433d6423SLionel Sambuc /* Handle sys_update(). Update a process into another by swapping their process
34*433d6423SLionel Sambuc  * slots.
35*433d6423SLionel Sambuc  */
36*433d6423SLionel Sambuc   endpoint_t src_e, dst_e;
37*433d6423SLionel Sambuc   int src_p, dst_p;
38*433d6423SLionel Sambuc   struct proc *src_rp, *dst_rp;
39*433d6423SLionel Sambuc   struct priv *src_privp, *dst_privp;
40*433d6423SLionel Sambuc   struct proc orig_src_proc;
41*433d6423SLionel Sambuc   struct proc orig_dst_proc;
42*433d6423SLionel Sambuc   struct priv orig_src_priv;
43*433d6423SLionel Sambuc   struct priv orig_dst_priv;
44*433d6423SLionel Sambuc   int i;
45*433d6423SLionel Sambuc 
46*433d6423SLionel Sambuc   /* Lookup slots for source and destination process. */
47*433d6423SLionel Sambuc   src_e = m_ptr->SYS_UPD_SRC_ENDPT;
48*433d6423SLionel Sambuc   if(!isokendpt(src_e, &src_p)) {
49*433d6423SLionel Sambuc       return EINVAL;
50*433d6423SLionel Sambuc   }
51*433d6423SLionel Sambuc   src_rp = proc_addr(src_p);
52*433d6423SLionel Sambuc   src_privp = priv(src_rp);
53*433d6423SLionel Sambuc   if(!(src_privp->s_flags & SYS_PROC)) {
54*433d6423SLionel Sambuc       return EPERM;
55*433d6423SLionel Sambuc   }
56*433d6423SLionel Sambuc 
57*433d6423SLionel Sambuc   dst_e = m_ptr->SYS_UPD_DST_ENDPT;
58*433d6423SLionel Sambuc   if(!isokendpt(dst_e, &dst_p)) {
59*433d6423SLionel Sambuc       return EINVAL;
60*433d6423SLionel Sambuc   }
61*433d6423SLionel Sambuc   dst_rp = proc_addr(dst_p);
62*433d6423SLionel Sambuc   dst_privp = priv(dst_rp);
63*433d6423SLionel Sambuc   if(!(dst_privp->s_flags & SYS_PROC)) {
64*433d6423SLionel Sambuc       return EPERM;
65*433d6423SLionel Sambuc   }
66*433d6423SLionel Sambuc 
67*433d6423SLionel Sambuc   assert(!proc_is_runnable(src_rp) && !proc_is_runnable(dst_rp));
68*433d6423SLionel Sambuc 
69*433d6423SLionel Sambuc   /* Check if processes are updatable. */
70*433d6423SLionel Sambuc   if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) {
71*433d6423SLionel Sambuc       return EBUSY;
72*433d6423SLionel Sambuc   }
73*433d6423SLionel Sambuc 
74*433d6423SLionel Sambuc #if DEBUG
75*433d6423SLionel Sambuc   printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n",
76*433d6423SLionel Sambuc       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
77*433d6423SLionel Sambuc       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
78*433d6423SLionel Sambuc 
79*433d6423SLionel Sambuc   proc_stacktrace(src_rp);
80*433d6423SLionel Sambuc   proc_stacktrace(dst_rp);
81*433d6423SLionel Sambuc   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
82*433d6423SLionel Sambuc #endif
83*433d6423SLionel Sambuc 
84*433d6423SLionel Sambuc   /* Let destination inherit the target mask from source. */
85*433d6423SLionel Sambuc   for (i=0; i < NR_SYS_PROCS; i++) {
86*433d6423SLionel Sambuc       if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) {
87*433d6423SLionel Sambuc           set_sendto_bit(dst_rp, i);
88*433d6423SLionel Sambuc       }
89*433d6423SLionel Sambuc   }
90*433d6423SLionel Sambuc 
91*433d6423SLionel Sambuc   /* Save existing data. */
92*433d6423SLionel Sambuc   orig_src_proc = *src_rp;
93*433d6423SLionel Sambuc   orig_src_priv = *(priv(src_rp));
94*433d6423SLionel Sambuc   orig_dst_proc = *dst_rp;
95*433d6423SLionel Sambuc   orig_dst_priv = *(priv(dst_rp));
96*433d6423SLionel Sambuc 
97*433d6423SLionel Sambuc   /* Swap slots. */
98*433d6423SLionel Sambuc   *src_rp = orig_dst_proc;
99*433d6423SLionel Sambuc   *src_privp = orig_dst_priv;
100*433d6423SLionel Sambuc   *dst_rp = orig_src_proc;
101*433d6423SLionel Sambuc   *dst_privp = orig_src_priv;
102*433d6423SLionel Sambuc 
103*433d6423SLionel Sambuc   /* Adjust process slots. */
104*433d6423SLionel Sambuc   adjust_proc_slot(src_rp, &orig_src_proc);
105*433d6423SLionel Sambuc   adjust_proc_slot(dst_rp, &orig_dst_proc);
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc   /* Adjust privilege slots. */
108*433d6423SLionel Sambuc   adjust_priv_slot(priv(src_rp), &orig_src_priv);
109*433d6423SLionel Sambuc   adjust_priv_slot(priv(dst_rp), &orig_dst_priv);
110*433d6423SLionel Sambuc 
111*433d6423SLionel Sambuc   /* Swap global process slot addresses. */
112*433d6423SLionel Sambuc   swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp);
113*433d6423SLionel Sambuc 
114*433d6423SLionel Sambuc #if DEBUG
115*433d6423SLionel Sambuc   printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n",
116*433d6423SLionel Sambuc       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
117*433d6423SLionel Sambuc       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
118*433d6423SLionel Sambuc 
119*433d6423SLionel Sambuc   proc_stacktrace(src_rp);
120*433d6423SLionel Sambuc   proc_stacktrace(dst_rp);
121*433d6423SLionel Sambuc   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
122*433d6423SLionel Sambuc #endif
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc #ifdef CONFIG_SMP
125*433d6423SLionel Sambuc   bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS);
126*433d6423SLionel Sambuc   bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS);
127*433d6423SLionel Sambuc #endif
128*433d6423SLionel Sambuc 
129*433d6423SLionel Sambuc   return OK;
130*433d6423SLionel Sambuc }
131*433d6423SLionel Sambuc 
132*433d6423SLionel Sambuc /*===========================================================================*
133*433d6423SLionel Sambuc  *			     adjust_proc_slot				     *
134*433d6423SLionel Sambuc  *===========================================================================*/
135*433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
136*433d6423SLionel Sambuc {
137*433d6423SLionel Sambuc   /* Preserve endpoints, slot numbers, priv structure, and IPC. */
138*433d6423SLionel Sambuc   rp->p_endpoint = from_rp->p_endpoint;
139*433d6423SLionel Sambuc   rp->p_nr = from_rp->p_nr;
140*433d6423SLionel Sambuc   rp->p_priv = from_rp->p_priv;
141*433d6423SLionel Sambuc   priv(rp)->s_proc_nr = from_rp->p_nr;
142*433d6423SLionel Sambuc   rp->p_caller_q = from_rp->p_caller_q;
143*433d6423SLionel Sambuc 
144*433d6423SLionel Sambuc   /* preserve scheduling */
145*433d6423SLionel Sambuc   rp->p_scheduler = from_rp->p_scheduler;
146*433d6423SLionel Sambuc #ifdef CONFIG_SMP
147*433d6423SLionel Sambuc   rp->p_cpu = from_rp->p_cpu;
148*433d6423SLionel Sambuc   memcpy(rp->p_cpu_mask, from_rp->p_cpu_mask,
149*433d6423SLionel Sambuc 		  sizeof(bitchunk_t) * BITMAP_CHUNKS(CONFIG_MAX_CPUS));
150*433d6423SLionel Sambuc #endif
151*433d6423SLionel Sambuc }
152*433d6423SLionel Sambuc 
153*433d6423SLionel Sambuc /*===========================================================================*
154*433d6423SLionel Sambuc  *			     adjust_priv_slot				     *
155*433d6423SLionel Sambuc  *===========================================================================*/
156*433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv *from_privp)
157*433d6423SLionel Sambuc {
158*433d6423SLionel Sambuc   /* Preserve privilege ids and non-privilege stuff in the priv structure. */
159*433d6423SLionel Sambuc   privp->s_id = from_privp->s_id;
160*433d6423SLionel Sambuc   privp->s_notify_pending = from_privp->s_notify_pending;
161*433d6423SLionel Sambuc   privp->s_int_pending = from_privp->s_int_pending;
162*433d6423SLionel Sambuc   privp->s_sig_pending = from_privp->s_sig_pending;
163*433d6423SLionel Sambuc   privp->s_alarm_timer = from_privp->s_alarm_timer;
164*433d6423SLionel Sambuc   privp->s_diag_sig = from_privp->s_diag_sig;
165*433d6423SLionel Sambuc }
166*433d6423SLionel Sambuc 
167*433d6423SLionel Sambuc /*===========================================================================*
168*433d6423SLionel Sambuc  *			   swap_proc_slot_pointer			     *
169*433d6423SLionel Sambuc  *===========================================================================*/
170*433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp,
171*433d6423SLionel Sambuc     struct proc *dst_rp)
172*433d6423SLionel Sambuc {
173*433d6423SLionel Sambuc   if(*rpp == src_rp) {
174*433d6423SLionel Sambuc       *rpp = dst_rp;
175*433d6423SLionel Sambuc   }
176*433d6423SLionel Sambuc   else if(*rpp == dst_rp) {
177*433d6423SLionel Sambuc       *rpp = src_rp;
178*433d6423SLionel Sambuc   }
179*433d6423SLionel Sambuc }
180*433d6423SLionel Sambuc 
181*433d6423SLionel Sambuc #endif /* USE_UPDATE */
182*433d6423SLionel Sambuc 
183