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