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 23*56e56d2aSCristiano Giuffrida static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp); 24*56e56d2aSCristiano Giuffrida static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp); 25*56e56d2aSCristiano Giuffrida static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp); 26433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp); 27433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv 28433d6423SLionel Sambuc *from_privp); 29433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc 30433d6423SLionel Sambuc *src_rp, struct proc *dst_rp); 31433d6423SLionel Sambuc 32433d6423SLionel Sambuc /*===========================================================================* 33433d6423SLionel Sambuc * do_update * 34433d6423SLionel Sambuc *===========================================================================*/ 35433d6423SLionel Sambuc int do_update(struct proc * caller, message * m_ptr) 36433d6423SLionel Sambuc { 37433d6423SLionel Sambuc /* Handle sys_update(). Update a process into another by swapping their process 38433d6423SLionel Sambuc * slots. 39433d6423SLionel Sambuc */ 40433d6423SLionel Sambuc endpoint_t src_e, dst_e; 41433d6423SLionel Sambuc int src_p, dst_p; 42433d6423SLionel Sambuc struct proc *src_rp, *dst_rp; 43433d6423SLionel Sambuc struct priv *src_privp, *dst_privp; 44433d6423SLionel Sambuc struct proc orig_src_proc; 45433d6423SLionel Sambuc struct proc orig_dst_proc; 46433d6423SLionel Sambuc struct priv orig_src_priv; 47433d6423SLionel Sambuc struct priv orig_dst_priv; 48*56e56d2aSCristiano Giuffrida int i, r; 49433d6423SLionel Sambuc 50433d6423SLionel Sambuc /* Lookup slots for source and destination process. */ 51433d6423SLionel Sambuc src_e = m_ptr->SYS_UPD_SRC_ENDPT; 52433d6423SLionel Sambuc if(!isokendpt(src_e, &src_p)) { 53433d6423SLionel Sambuc return EINVAL; 54433d6423SLionel Sambuc } 55433d6423SLionel Sambuc src_rp = proc_addr(src_p); 56433d6423SLionel Sambuc src_privp = priv(src_rp); 57433d6423SLionel Sambuc if(!(src_privp->s_flags & SYS_PROC)) { 58433d6423SLionel Sambuc return EPERM; 59433d6423SLionel Sambuc } 60433d6423SLionel Sambuc 61433d6423SLionel Sambuc dst_e = m_ptr->SYS_UPD_DST_ENDPT; 62433d6423SLionel Sambuc if(!isokendpt(dst_e, &dst_p)) { 63433d6423SLionel Sambuc return EINVAL; 64433d6423SLionel Sambuc } 65433d6423SLionel Sambuc dst_rp = proc_addr(dst_p); 66433d6423SLionel Sambuc dst_privp = priv(dst_rp); 67433d6423SLionel Sambuc if(!(dst_privp->s_flags & SYS_PROC)) { 68433d6423SLionel Sambuc return EPERM; 69433d6423SLionel Sambuc } 70433d6423SLionel Sambuc 71433d6423SLionel Sambuc assert(!proc_is_runnable(src_rp) && !proc_is_runnable(dst_rp)); 72433d6423SLionel Sambuc 73433d6423SLionel Sambuc /* Check if processes are updatable. */ 74433d6423SLionel Sambuc if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) { 75433d6423SLionel Sambuc return EBUSY; 76433d6423SLionel Sambuc } 77433d6423SLionel Sambuc 78433d6423SLionel Sambuc #if DEBUG 79433d6423SLionel Sambuc printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n", 80433d6423SLionel Sambuc src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr, 81433d6423SLionel Sambuc dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr); 82433d6423SLionel Sambuc 83433d6423SLionel Sambuc proc_stacktrace(src_rp); 84433d6423SLionel Sambuc proc_stacktrace(dst_rp); 85433d6423SLionel Sambuc printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint); 86433d6423SLionel Sambuc #endif 87433d6423SLionel Sambuc 88*56e56d2aSCristiano Giuffrida /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */ 89*56e56d2aSCristiano Giuffrida r = inherit_priv_irq(src_rp, dst_rp); 90*56e56d2aSCristiano Giuffrida if(r != OK) { 91*56e56d2aSCristiano Giuffrida return r; 92*56e56d2aSCristiano Giuffrida } 93*56e56d2aSCristiano Giuffrida r = inherit_priv_io(src_rp, dst_rp); 94*56e56d2aSCristiano Giuffrida if(r != OK) { 95*56e56d2aSCristiano Giuffrida return r; 96*56e56d2aSCristiano Giuffrida } 97*56e56d2aSCristiano Giuffrida r = inherit_priv_mem(src_rp, dst_rp); 98*56e56d2aSCristiano Giuffrida if(r != OK) { 99*56e56d2aSCristiano Giuffrida return r; 100*56e56d2aSCristiano Giuffrida } 101*56e56d2aSCristiano Giuffrida 102433d6423SLionel Sambuc /* Let destination inherit the target mask from source. */ 103433d6423SLionel Sambuc for (i=0; i < NR_SYS_PROCS; i++) { 104433d6423SLionel Sambuc if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) { 105433d6423SLionel Sambuc set_sendto_bit(dst_rp, i); 106433d6423SLionel Sambuc } 107433d6423SLionel Sambuc } 108433d6423SLionel Sambuc 109433d6423SLionel Sambuc /* Save existing data. */ 110433d6423SLionel Sambuc orig_src_proc = *src_rp; 111433d6423SLionel Sambuc orig_src_priv = *(priv(src_rp)); 112433d6423SLionel Sambuc orig_dst_proc = *dst_rp; 113433d6423SLionel Sambuc orig_dst_priv = *(priv(dst_rp)); 114433d6423SLionel Sambuc 115433d6423SLionel Sambuc /* Swap slots. */ 116433d6423SLionel Sambuc *src_rp = orig_dst_proc; 117433d6423SLionel Sambuc *src_privp = orig_dst_priv; 118433d6423SLionel Sambuc *dst_rp = orig_src_proc; 119433d6423SLionel Sambuc *dst_privp = orig_src_priv; 120433d6423SLionel Sambuc 121433d6423SLionel Sambuc /* Adjust process slots. */ 122433d6423SLionel Sambuc adjust_proc_slot(src_rp, &orig_src_proc); 123433d6423SLionel Sambuc adjust_proc_slot(dst_rp, &orig_dst_proc); 124433d6423SLionel Sambuc 125433d6423SLionel Sambuc /* Adjust privilege slots. */ 126433d6423SLionel Sambuc adjust_priv_slot(priv(src_rp), &orig_src_priv); 127433d6423SLionel Sambuc adjust_priv_slot(priv(dst_rp), &orig_dst_priv); 128433d6423SLionel Sambuc 129433d6423SLionel Sambuc /* Swap global process slot addresses. */ 130433d6423SLionel Sambuc swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp); 131433d6423SLionel Sambuc 132433d6423SLionel Sambuc #if DEBUG 133433d6423SLionel Sambuc printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n", 134433d6423SLionel Sambuc src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr, 135433d6423SLionel Sambuc dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr); 136433d6423SLionel Sambuc 137433d6423SLionel Sambuc proc_stacktrace(src_rp); 138433d6423SLionel Sambuc proc_stacktrace(dst_rp); 139433d6423SLionel Sambuc printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint); 140433d6423SLionel Sambuc #endif 141433d6423SLionel Sambuc 142433d6423SLionel Sambuc #ifdef CONFIG_SMP 143433d6423SLionel Sambuc bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS); 144433d6423SLionel Sambuc bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS); 145433d6423SLionel Sambuc #endif 146433d6423SLionel Sambuc 147433d6423SLionel Sambuc return OK; 148433d6423SLionel Sambuc } 149433d6423SLionel Sambuc 150433d6423SLionel Sambuc /*===========================================================================* 151*56e56d2aSCristiano Giuffrida * inherit_priv_irq * 152*56e56d2aSCristiano Giuffrida *===========================================================================*/ 153*56e56d2aSCristiano Giuffrida int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp) 154*56e56d2aSCristiano Giuffrida { 155*56e56d2aSCristiano Giuffrida int i, r; 156*56e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_irq; i++) { 157*56e56d2aSCristiano Giuffrida r = priv_add_irq(dst_rp, priv(src_rp)->s_irq_tab[i]); 158*56e56d2aSCristiano Giuffrida if(r != OK) { 159*56e56d2aSCristiano Giuffrida return r; 160*56e56d2aSCristiano Giuffrida } 161*56e56d2aSCristiano Giuffrida } 162*56e56d2aSCristiano Giuffrida 163*56e56d2aSCristiano Giuffrida return OK; 164*56e56d2aSCristiano Giuffrida } 165*56e56d2aSCristiano Giuffrida 166*56e56d2aSCristiano Giuffrida /*===========================================================================* 167*56e56d2aSCristiano Giuffrida * inherit_priv_io * 168*56e56d2aSCristiano Giuffrida *===========================================================================*/ 169*56e56d2aSCristiano Giuffrida int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp) 170*56e56d2aSCristiano Giuffrida { 171*56e56d2aSCristiano Giuffrida int i, r; 172*56e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_io_range; i++) { 173*56e56d2aSCristiano Giuffrida r = priv_add_io(dst_rp, &(priv(src_rp)->s_io_tab[i])); 174*56e56d2aSCristiano Giuffrida if(r != OK) { 175*56e56d2aSCristiano Giuffrida return r; 176*56e56d2aSCristiano Giuffrida } 177*56e56d2aSCristiano Giuffrida } 178*56e56d2aSCristiano Giuffrida 179*56e56d2aSCristiano Giuffrida return OK; 180*56e56d2aSCristiano Giuffrida } 181*56e56d2aSCristiano Giuffrida 182*56e56d2aSCristiano Giuffrida /*===========================================================================* 183*56e56d2aSCristiano Giuffrida * inherit_priv_mem * 184*56e56d2aSCristiano Giuffrida *===========================================================================*/ 185*56e56d2aSCristiano Giuffrida int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp) 186*56e56d2aSCristiano Giuffrida { 187*56e56d2aSCristiano Giuffrida int i, r; 188*56e56d2aSCristiano Giuffrida for (i= 0; i<priv(src_rp)->s_nr_mem_range; i++) { 189*56e56d2aSCristiano Giuffrida r = priv_add_mem(dst_rp, &(priv(src_rp)->s_mem_tab[i])); 190*56e56d2aSCristiano Giuffrida if(r != OK) { 191*56e56d2aSCristiano Giuffrida return r; 192*56e56d2aSCristiano Giuffrida } 193*56e56d2aSCristiano Giuffrida } 194*56e56d2aSCristiano Giuffrida 195*56e56d2aSCristiano Giuffrida return OK; 196*56e56d2aSCristiano Giuffrida } 197*56e56d2aSCristiano Giuffrida 198*56e56d2aSCristiano Giuffrida /*===========================================================================* 199433d6423SLionel Sambuc * adjust_proc_slot * 200433d6423SLionel Sambuc *===========================================================================*/ 201433d6423SLionel Sambuc static void adjust_proc_slot(struct proc *rp, struct proc *from_rp) 202433d6423SLionel Sambuc { 203433d6423SLionel Sambuc /* Preserve endpoints, slot numbers, priv structure, and IPC. */ 204433d6423SLionel Sambuc rp->p_endpoint = from_rp->p_endpoint; 205433d6423SLionel Sambuc rp->p_nr = from_rp->p_nr; 206433d6423SLionel Sambuc rp->p_priv = from_rp->p_priv; 207433d6423SLionel Sambuc priv(rp)->s_proc_nr = from_rp->p_nr; 208433d6423SLionel Sambuc rp->p_caller_q = from_rp->p_caller_q; 209433d6423SLionel Sambuc 210433d6423SLionel Sambuc /* preserve scheduling */ 211433d6423SLionel Sambuc rp->p_scheduler = from_rp->p_scheduler; 212433d6423SLionel Sambuc #ifdef CONFIG_SMP 213433d6423SLionel Sambuc rp->p_cpu = from_rp->p_cpu; 214433d6423SLionel Sambuc memcpy(rp->p_cpu_mask, from_rp->p_cpu_mask, 215433d6423SLionel Sambuc sizeof(bitchunk_t) * BITMAP_CHUNKS(CONFIG_MAX_CPUS)); 216433d6423SLionel Sambuc #endif 217433d6423SLionel Sambuc } 218433d6423SLionel Sambuc 219433d6423SLionel Sambuc /*===========================================================================* 220433d6423SLionel Sambuc * adjust_priv_slot * 221433d6423SLionel Sambuc *===========================================================================*/ 222433d6423SLionel Sambuc static void adjust_priv_slot(struct priv *privp, struct priv *from_privp) 223433d6423SLionel Sambuc { 224433d6423SLionel Sambuc /* Preserve privilege ids and non-privilege stuff in the priv structure. */ 225433d6423SLionel Sambuc privp->s_id = from_privp->s_id; 226433d6423SLionel Sambuc privp->s_notify_pending = from_privp->s_notify_pending; 227433d6423SLionel Sambuc privp->s_int_pending = from_privp->s_int_pending; 228433d6423SLionel Sambuc privp->s_sig_pending = from_privp->s_sig_pending; 229433d6423SLionel Sambuc privp->s_alarm_timer = from_privp->s_alarm_timer; 230433d6423SLionel Sambuc privp->s_diag_sig = from_privp->s_diag_sig; 231433d6423SLionel Sambuc } 232433d6423SLionel Sambuc 233433d6423SLionel Sambuc /*===========================================================================* 234433d6423SLionel Sambuc * swap_proc_slot_pointer * 235433d6423SLionel Sambuc *===========================================================================*/ 236433d6423SLionel Sambuc static void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp, 237433d6423SLionel Sambuc struct proc *dst_rp) 238433d6423SLionel Sambuc { 239433d6423SLionel Sambuc if(*rpp == src_rp) { 240433d6423SLionel Sambuc *rpp = dst_rp; 241433d6423SLionel Sambuc } 242433d6423SLionel Sambuc else if(*rpp == dst_rp) { 243433d6423SLionel Sambuc *rpp = src_rp; 244433d6423SLionel Sambuc } 245433d6423SLionel Sambuc } 246433d6423SLionel Sambuc 247433d6423SLionel Sambuc #endif /* USE_UPDATE */ 248433d6423SLionel Sambuc 249