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