1 /* The kernel call implemented in this file:
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)
10 #include "kernel/system.h"
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)))
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
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
);
34 /*===========================================================================*
36 *===========================================================================*/
37 int do_update(struct proc
* caller
, message
* m_ptr
)
39 /* Handle sys_update(). Update a process into another by swapping their process
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
;
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
)) {
58 src_rp
= proc_addr(src_p
);
59 src_privp
= priv(src_rp
);
60 if(!(src_privp
->s_flags
& SYS_PROC
)) {
64 dst_e
= m_ptr
->SYS_UPD_DST_ENDPT
;
65 if(!isokendpt(dst_e
, &dst_p
)) {
68 dst_rp
= proc_addr(dst_p
);
69 dst_privp
= priv(dst_rp
);
70 if(!(dst_privp
->s_flags
& SYS_PROC
)) {
74 assert(!proc_is_runnable(src_rp
) && !proc_is_runnable(dst_rp
));
76 /* Check if processes are updatable. */
77 if(!proc_is_updatable(src_rp
) || !proc_is_updatable(dst_rp
)) {
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
);
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
);
93 /* Let destination inherit allowed IRQ, I/O ranges, and memory ranges. */
94 r
= inherit_priv_irq(src_rp
, dst_rp
);
98 r
= inherit_priv_io(src_rp
, dst_rp
);
102 r
= inherit_priv_mem(src_rp
, dst_rp
);
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
);
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
));
120 /* Adjust asyn tables. */
121 adjust_asyn_table(priv(src_rp
), priv(dst_rp
));
122 adjust_asyn_table(priv(dst_rp
), priv(src_rp
));
124 /* Abort any pending send() on rollback. */
125 if(flags
& SYS_UPD_ROLLBACK
) {
126 abort_proc_ipc_send(src_rp
);
130 *src_rp
= orig_dst_proc
;
131 *src_privp
= orig_dst_priv
;
132 *dst_rp
= orig_src_proc
;
133 *dst_privp
= orig_src_priv
;
135 /* Adjust process slots. */
136 adjust_proc_slot(src_rp
, &orig_src_proc
);
137 adjust_proc_slot(dst_rp
, &orig_dst_proc
);
139 /* Adjust privilege slots. */
140 adjust_priv_slot(priv(src_rp
), &orig_src_priv
);
141 adjust_priv_slot(priv(dst_rp
), &orig_dst_priv
);
143 /* Swap global process slot addresses. */
144 swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc
), src_rp
, dst_rp
);
146 /* Swap VM request entries. */
147 swap_memreq(src_rp
, dst_rp
);
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
);
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
);
162 bits_fill(src_rp
->p_stale_tlb
, CONFIG_MAX_CPUS
);
163 bits_fill(dst_rp
->p_stale_tlb
, CONFIG_MAX_CPUS
);
169 /*===========================================================================*
171 *===========================================================================*/
172 int inherit_priv_irq(struct proc
*src_rp
, struct proc
*dst_rp
)
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
]);
185 /*===========================================================================*
187 *===========================================================================*/
188 int inherit_priv_io(struct proc
*src_rp
, struct proc
*dst_rp
)
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
]));
201 /*===========================================================================*
203 *===========================================================================*/
204 int inherit_priv_mem(struct proc
*src_rp
, struct proc
*dst_rp
)
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
]));
217 /*===========================================================================*
218 * abort_proc_ipc_send *
219 *===========================================================================*/
220 void abort_proc_ipc_send(struct proc
*rp
)
222 if(RTS_ISSET(rp
, RTS_SENDING
)) {
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
);
233 xpp
= &(*xpp
)->p_q_link
;
238 /*===========================================================================*
240 *===========================================================================*/
241 static void adjust_proc_slot(struct proc
*rp
, struct proc
*from_rp
)
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
;
249 rp
->p_caller_q
= from_rp
->p_caller_q
;
251 /* preserve scheduling */
252 rp
->p_scheduler
= from_rp
->p_scheduler
;
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
));
260 /*===========================================================================*
261 * adjust_asyn_table *
262 *===========================================================================*/
263 static void adjust_asyn_table(struct priv
*src_privp
, struct priv
*dst_privp
)
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
;
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",
276 dst_privp
->s_asynsize
= src_privp
->s_asynsize
;
281 /*===========================================================================*
283 *===========================================================================*/
284 static void adjust_priv_slot(struct priv
*privp
, struct priv
*from_privp
)
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
;
296 /*===========================================================================*
297 * swap_proc_slot_pointer *
298 *===========================================================================*/
299 static void swap_proc_slot_pointer(struct proc
**rpp
, struct proc
*src_rp
,
305 else if(*rpp
== dst_rp
) {
310 /*===========================================================================*
312 *===========================================================================*/
313 static void swap_memreq(struct proc
*src_rp
, struct proc
*dst_rp
)
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.
320 if (RTS_ISSET(src_rp
, RTS_VMREQUEST
) == RTS_ISSET(dst_rp
, RTS_VMREQUEST
))
321 return; /* nothing to do */
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
;
330 } else if (*rpp
== dst_rp
) {
331 src_rp
->p_vmrequest
.nextrequestor
=
332 dst_rp
->p_vmrequest
.nextrequestor
;
339 #endif /* USE_UPDATE */