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