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