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 2356e56d2aSCristiano Giuffrida static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp); 2456e56d2aSCristiano Giuffrida static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp); 2556e56d2aSCristiano Giuffrida static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp); 26062400c0SCristiano Giuffrida static void abort_proc_ipc_send(struct proc *rp); 27433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp); 28433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv 29433d6423SLionel Sambuc *from_privp); 30062400c0SCristiano Giuffrida static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp); 31433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc 32433d6423SLionel Sambuc *src_rp, struct proc *dst_rp); 33433d6423SLionel Sambuc 34433d6423SLionel Sambuc /*===========================================================================* 35433d6423SLionel Sambuc * do_update * 36433d6423SLionel Sambuc *===========================================================================*/ 37433d6423SLionel Sambuc int do_update(struct proc * caller, message * m_ptr) 38433d6423SLionel Sambuc { 39433d6423SLionel Sambuc /* Handle sys_update(). Update a process into another by swapping their process 40433d6423SLionel Sambuc * slots. 41433d6423SLionel Sambuc */ 42433d6423SLionel Sambuc endpoint_t src_e, dst_e; 43062400c0SCristiano Giuffrida int src_p, dst_p, flags; 44433d6423SLionel Sambuc struct proc *src_rp, *dst_rp; 45433d6423SLionel Sambuc struct priv *src_privp, *dst_privp; 46433d6423SLionel Sambuc struct proc orig_src_proc; 47433d6423SLionel Sambuc struct proc orig_dst_proc; 48433d6423SLionel Sambuc struct priv orig_src_priv; 49433d6423SLionel Sambuc struct priv orig_dst_priv; 5056e56d2aSCristiano Giuffrida int i, r; 51433d6423SLionel Sambuc 52433d6423SLionel Sambuc /* Lookup slots for source and destination process. */ 53062400c0SCristiano Giuffrida flags = m_ptr->SYS_UPD_FLAGS; 54433d6423SLionel Sambuc src_e = m_ptr->SYS_UPD_SRC_ENDPT; 55433d6423SLionel Sambuc if(!isokendpt(src_e, &src_p)) { 56433d6423SLionel Sambuc return EINVAL; 57433d6423SLionel Sambuc } 58433d6423SLionel Sambuc src_rp = proc_addr(src_p); 59433d6423SLionel Sambuc src_privp = priv(src_rp); 60433d6423SLionel Sambuc if(!(src_privp->s_flags & SYS_PROC)) { 61433d6423SLionel Sambuc return EPERM; 62433d6423SLionel Sambuc } 63433d6423SLionel Sambuc 64433d6423SLionel Sambuc dst_e = m_ptr->SYS_UPD_DST_ENDPT; 65433d6423SLionel Sambuc if(!isokendpt(dst_e, &dst_p)) { 66433d6423SLionel Sambuc return EINVAL; 67433d6423SLionel Sambuc } 68433d6423SLionel Sambuc dst_rp = proc_addr(dst_p); 69433d6423SLionel Sambuc dst_privp = priv(dst_rp); 70433d6423SLionel Sambuc if(!(dst_privp->s_flags & SYS_PROC)) { 71433d6423SLionel Sambuc return EPERM; 72433d6423SLionel Sambuc } 73433d6423SLionel Sambuc 74433d6423SLionel Sambuc assert(!proc_is_runnable(src_rp) && !proc_is_runnable(dst_rp)); 75433d6423SLionel Sambuc 76433d6423SLionel Sambuc /* Check if processes are updatable. */ 77433d6423SLionel Sambuc if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) { 78433d6423SLionel Sambuc return EBUSY; 79433d6423SLionel Sambuc } 80433d6423SLionel Sambuc 81433d6423SLionel Sambuc #if DEBUG 82433d6423SLionel Sambuc printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n", 83433d6423SLionel Sambuc src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr, 84433d6423SLionel Sambuc dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr); 85433d6423SLionel Sambuc 86433d6423SLionel Sambuc proc_stacktrace(src_rp); 87433d6423SLionel Sambuc proc_stacktrace(dst_rp); 88433d6423SLionel Sambuc printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint); 89*01c875ceSCristiano Giuffrida 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*01c875ceSCristiano Giuffrida 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); 91433d6423SLionel Sambuc #endif 92433d6423SLionel Sambuc 9356e56d2aSCristiano Giuffrida /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */ 9456e56d2aSCristiano Giuffrida r = inherit_priv_irq(src_rp, dst_rp); 9556e56d2aSCristiano Giuffrida if(r != OK) { 9656e56d2aSCristiano Giuffrida return r; 9756e56d2aSCristiano Giuffrida } 9856e56d2aSCristiano Giuffrida r = inherit_priv_io(src_rp, dst_rp); 9956e56d2aSCristiano Giuffrida if(r != OK) { 10056e56d2aSCristiano Giuffrida return r; 10156e56d2aSCristiano Giuffrida } 10256e56d2aSCristiano Giuffrida r = inherit_priv_mem(src_rp, dst_rp); 10356e56d2aSCristiano Giuffrida if(r != OK) { 10456e56d2aSCristiano Giuffrida return r; 10556e56d2aSCristiano Giuffrida } 10656e56d2aSCristiano Giuffrida 107433d6423SLionel Sambuc /* Let destination inherit the target mask from source. */ 108433d6423SLionel Sambuc for (i=0; i < NR_SYS_PROCS; i++) { 109433d6423SLionel Sambuc if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) { 110433d6423SLionel Sambuc set_sendto_bit(dst_rp, i); 111433d6423SLionel Sambuc } 112433d6423SLionel Sambuc } 113433d6423SLionel Sambuc 114433d6423SLionel Sambuc /* Save existing data. */ 115433d6423SLionel Sambuc orig_src_proc = *src_rp; 116433d6423SLionel Sambuc orig_src_priv = *(priv(src_rp)); 117433d6423SLionel Sambuc orig_dst_proc = *dst_rp; 118433d6423SLionel Sambuc orig_dst_priv = *(priv(dst_rp)); 119433d6423SLionel Sambuc 120062400c0SCristiano Giuffrida /* Adjust asyn tables. */ 121062400c0SCristiano Giuffrida adjust_asyn_table(priv(src_rp), priv(dst_rp)); 122062400c0SCristiano Giuffrida adjust_asyn_table(priv(dst_rp), priv(src_rp)); 123062400c0SCristiano Giuffrida 124062400c0SCristiano Giuffrida /* Abort any pending send() on rollback. */ 125062400c0SCristiano Giuffrida if(flags & SYS_UPD_ROLLBACK) { 126062400c0SCristiano Giuffrida abort_proc_ipc_send(src_rp); 127062400c0SCristiano Giuffrida } 128062400c0SCristiano Giuffrida 129433d6423SLionel Sambuc /* Swap slots. */ 130433d6423SLionel Sambuc *src_rp = orig_dst_proc; 131433d6423SLionel Sambuc *src_privp = orig_dst_priv; 132433d6423SLionel Sambuc *dst_rp = orig_src_proc; 133433d6423SLionel Sambuc *dst_privp = orig_src_priv; 134433d6423SLionel Sambuc 135433d6423SLionel Sambuc /* Adjust process slots. */ 136433d6423SLionel Sambuc adjust_proc_slot(src_rp, &orig_src_proc); 137433d6423SLionel Sambuc adjust_proc_slot(dst_rp, &orig_dst_proc); 138433d6423SLionel Sambuc 139433d6423SLionel Sambuc /* Adjust privilege slots. */ 140433d6423SLionel Sambuc adjust_priv_slot(priv(src_rp), &orig_src_priv); 141433d6423SLionel Sambuc adjust_priv_slot(priv(dst_rp), &orig_dst_priv); 142433d6423SLionel Sambuc 143433d6423SLionel Sambuc /* Swap global process slot addresses. */ 144433d6423SLionel Sambuc swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp); 145433d6423SLionel Sambuc 146433d6423SLionel Sambuc #if DEBUG 147433d6423SLionel Sambuc printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n", 148433d6423SLionel Sambuc src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr, 149433d6423SLionel Sambuc dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr); 150433d6423SLionel Sambuc 151433d6423SLionel Sambuc proc_stacktrace(src_rp); 152433d6423SLionel Sambuc proc_stacktrace(dst_rp); 153433d6423SLionel Sambuc printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint); 154*01c875ceSCristiano Giuffrida 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); 155*01c875ceSCristiano Giuffrida 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); 156433d6423SLionel Sambuc #endif 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc #ifdef CONFIG_SMP 159433d6423SLionel Sambuc bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS); 160433d6423SLionel Sambuc bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS); 161433d6423SLionel Sambuc #endif 162433d6423SLionel Sambuc 163433d6423SLionel Sambuc return OK; 164433d6423SLionel Sambuc } 165433d6423SLionel Sambuc 166433d6423SLionel Sambuc /*===========================================================================* 16756e56d2aSCristiano Giuffrida * inherit_priv_irq * 16856e56d2aSCristiano Giuffrida *===========================================================================*/ 16956e56d2aSCristiano Giuffrida int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp) 17056e56d2aSCristiano Giuffrida { 17156e56d2aSCristiano Giuffrida int i, r; 17256e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_irq; i++) { 17356e56d2aSCristiano Giuffrida r = priv_add_irq(dst_rp, priv(src_rp)->s_irq_tab[i]); 17456e56d2aSCristiano Giuffrida if(r != OK) { 17556e56d2aSCristiano Giuffrida return r; 17656e56d2aSCristiano Giuffrida } 17756e56d2aSCristiano Giuffrida } 17856e56d2aSCristiano Giuffrida 17956e56d2aSCristiano Giuffrida return OK; 18056e56d2aSCristiano Giuffrida } 18156e56d2aSCristiano Giuffrida 18256e56d2aSCristiano Giuffrida /*===========================================================================* 18356e56d2aSCristiano Giuffrida * inherit_priv_io * 18456e56d2aSCristiano Giuffrida *===========================================================================*/ 18556e56d2aSCristiano Giuffrida int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp) 18656e56d2aSCristiano Giuffrida { 18756e56d2aSCristiano Giuffrida int i, r; 18856e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_io_range; i++) { 18956e56d2aSCristiano Giuffrida r = priv_add_io(dst_rp, &(priv(src_rp)->s_io_tab[i])); 19056e56d2aSCristiano Giuffrida if(r != OK) { 19156e56d2aSCristiano Giuffrida return r; 19256e56d2aSCristiano Giuffrida } 19356e56d2aSCristiano Giuffrida } 19456e56d2aSCristiano Giuffrida 19556e56d2aSCristiano Giuffrida return OK; 19656e56d2aSCristiano Giuffrida } 19756e56d2aSCristiano Giuffrida 19856e56d2aSCristiano Giuffrida /*===========================================================================* 19956e56d2aSCristiano Giuffrida * inherit_priv_mem * 20056e56d2aSCristiano Giuffrida *===========================================================================*/ 20156e56d2aSCristiano Giuffrida int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp) 20256e56d2aSCristiano Giuffrida { 20356e56d2aSCristiano Giuffrida int i, r; 20456e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_mem_range; i++) { 20556e56d2aSCristiano Giuffrida r = priv_add_mem(dst_rp, &(priv(src_rp)->s_mem_tab[i])); 20656e56d2aSCristiano Giuffrida if(r != OK) { 20756e56d2aSCristiano Giuffrida return r; 20856e56d2aSCristiano Giuffrida } 20956e56d2aSCristiano Giuffrida } 21056e56d2aSCristiano Giuffrida 21156e56d2aSCristiano Giuffrida return OK; 21256e56d2aSCristiano Giuffrida } 21356e56d2aSCristiano Giuffrida 21456e56d2aSCristiano Giuffrida /*===========================================================================* 215062400c0SCristiano Giuffrida * abort_proc_ipc_send * 216062400c0SCristiano Giuffrida *===========================================================================*/ 217062400c0SCristiano Giuffrida void abort_proc_ipc_send(struct proc *rp) 218062400c0SCristiano Giuffrida { 219062400c0SCristiano Giuffrida if(RTS_ISSET(rp, RTS_SENDING)) { 220062400c0SCristiano Giuffrida struct proc **xpp; 221062400c0SCristiano Giuffrida RTS_UNSET(rp, RTS_SENDING); 222062400c0SCristiano Giuffrida rp->p_misc_flags &= ~MF_SENDING_FROM_KERNEL; 223062400c0SCristiano Giuffrida xpp = &(proc_addr(_ENDPOINT_P(rp->p_sendto_e))->p_caller_q); 224062400c0SCristiano Giuffrida while (*xpp) { 225062400c0SCristiano Giuffrida if(*xpp == rp) { 226062400c0SCristiano Giuffrida *xpp = rp->p_q_link; 227062400c0SCristiano Giuffrida rp->p_q_link = NULL; 228062400c0SCristiano Giuffrida break; 229062400c0SCristiano Giuffrida } 230062400c0SCristiano Giuffrida xpp = &(*xpp)->p_q_link; 231062400c0SCristiano Giuffrida } 232062400c0SCristiano Giuffrida } 233062400c0SCristiano Giuffrida } 234062400c0SCristiano Giuffrida 235062400c0SCristiano Giuffrida /*===========================================================================* 236433d6423SLionel Sambuc * adjust_proc_slot * 237433d6423SLionel Sambuc *===========================================================================*/ 238433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp) 239433d6423SLionel Sambuc { 240433d6423SLionel Sambuc /* Preserve endpoints, slot numbers, priv structure, and IPC. */ 241433d6423SLionel Sambuc rp->p_endpoint = from_rp->p_endpoint; 242433d6423SLionel Sambuc rp->p_nr = from_rp->p_nr; 243433d6423SLionel Sambuc rp->p_priv = from_rp->p_priv; 244433d6423SLionel Sambuc priv(rp)->s_proc_nr = from_rp->p_nr; 245062400c0SCristiano Giuffrida 246433d6423SLionel Sambuc rp->p_caller_q = from_rp->p_caller_q; 247433d6423SLionel Sambuc 248433d6423SLionel Sambuc /* preserve scheduling */ 249433d6423SLionel Sambuc rp->p_scheduler = from_rp->p_scheduler; 250433d6423SLionel Sambuc #ifdef CONFIG_SMP 251433d6423SLionel Sambuc rp->p_cpu = from_rp->p_cpu; 252433d6423SLionel Sambuc memcpy(rp->p_cpu_mask, from_rp->p_cpu_mask, 253433d6423SLionel Sambuc sizeof(bitchunk_t) * BITMAP_CHUNKS(CONFIG_MAX_CPUS)); 254433d6423SLionel Sambuc #endif 255433d6423SLionel Sambuc } 256433d6423SLionel Sambuc 257433d6423SLionel Sambuc /*===========================================================================* 258062400c0SCristiano Giuffrida * adjust_asyn_table * 259062400c0SCristiano Giuffrida *===========================================================================*/ 260062400c0SCristiano Giuffrida static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp) 261062400c0SCristiano Giuffrida { 262062400c0SCristiano Giuffrida /* Transfer the asyn table if source's table belongs to the destination. */ 263062400c0SCristiano Giuffrida endpoint_t src_e = proc_addr(src_privp->s_proc_nr)->p_endpoint; 264062400c0SCristiano Giuffrida endpoint_t dst_e = proc_addr(dst_privp->s_proc_nr)->p_endpoint; 265062400c0SCristiano Giuffrida 266062400c0SCristiano Giuffrida if(src_privp->s_asynsize > 0 && dst_privp->s_asynsize > 0 && src_privp->s_asynendpoint == dst_e) { 267062400c0SCristiano Giuffrida if(data_copy(src_e, src_privp->s_asyntab, dst_e, dst_privp->s_asyntab, 268062400c0SCristiano Giuffrida src_privp->s_asynsize*sizeof(asynmsg_t)) != OK) { 269062400c0SCristiano Giuffrida printf("Warning: unable to transfer asyn table from ep %d to ep %d\n", 270062400c0SCristiano Giuffrida src_e, dst_e); 271062400c0SCristiano Giuffrida } 272062400c0SCristiano Giuffrida else { 273062400c0SCristiano Giuffrida dst_privp->s_asynsize = src_privp->s_asynsize; 274062400c0SCristiano Giuffrida } 275062400c0SCristiano Giuffrida } 276062400c0SCristiano Giuffrida } 277062400c0SCristiano Giuffrida 278062400c0SCristiano Giuffrida /*===========================================================================* 279433d6423SLionel Sambuc * adjust_priv_slot * 280433d6423SLionel Sambuc *===========================================================================*/ 281433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv *from_privp) 282433d6423SLionel Sambuc { 283433d6423SLionel Sambuc /* Preserve privilege ids and non-privilege stuff in the priv structure. */ 284433d6423SLionel Sambuc privp->s_id = from_privp->s_id; 285433d6423SLionel Sambuc privp->s_notify_pending = from_privp->s_notify_pending; 286433d6423SLionel Sambuc privp->s_int_pending = from_privp->s_int_pending; 287433d6423SLionel Sambuc privp->s_sig_pending = from_privp->s_sig_pending; 288433d6423SLionel Sambuc privp->s_alarm_timer = from_privp->s_alarm_timer; 289433d6423SLionel Sambuc privp->s_diag_sig = from_privp->s_diag_sig; 290433d6423SLionel Sambuc } 291433d6423SLionel Sambuc 292433d6423SLionel Sambuc /*===========================================================================* 293433d6423SLionel Sambuc * swap_proc_slot_pointer * 294433d6423SLionel Sambuc *===========================================================================*/ 295433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp, 296433d6423SLionel Sambuc struct proc *dst_rp) 297433d6423SLionel Sambuc { 298433d6423SLionel Sambuc if(*rpp == src_rp) { 299433d6423SLionel Sambuc *rpp = dst_rp; 300433d6423SLionel Sambuc } 301433d6423SLionel Sambuc else if(*rpp == dst_rp) { 302433d6423SLionel Sambuc *rpp = src_rp; 303433d6423SLionel Sambuc } 304433d6423SLionel Sambuc } 305433d6423SLionel Sambuc 306433d6423SLionel Sambuc #endif /* USE_UPDATE */ 307433d6423SLionel Sambuc 308