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