FreeBSD/Linux Kernel Cross Reference
sys/norma/kern_task.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: kern_task.c,v $
29 * Revision 2.9 92/03/10 16:28:44 jsb
30 * Check for null parent task in task_create.
31 * [92/03/10 13:46:21 jsb]
32 *
33 * Merged in norma branch changes as of NORMA_MK7.
34 * [92/03/09 12:50:50 jsb]
35 *
36 * Revision 2.7.2.4 92/03/04 16:07:16 jeffreyh
37 * Converted to use out-of-line forms of task_{get,set}_emulation_vector.
38 * [92/03/04 14:55:51 jsb]
39 *
40 * Revision 2.7.2.3 92/02/21 11:25:15 jsb
41 * Release send right to memory_object after mapping it in remote task
42 * in task_copy_vm.
43 * [92/02/20 10:29:45 jsb]
44 *
45 * Set copy flag TRUE in r_vm_map call in task_copy_vm.
46 * This is now practical due to smarter copy strategy management
47 * in xmm_svm (compared to when it always used MEMORY_OBJECT_COPY_NONE).
48 * It also keeps xmm_copy from having to deal with data writes without
49 * having to use an xmm_shadow layer.
50 * [92/02/11 11:39:23 jsb]
51 *
52 * Release map reference in task_copy_vm.
53 * [92/01/22 10:29:57 jsb]
54 *
55 * Revision 2.7.2.2 92/01/09 18:46:08 jsb
56 * Added logic in task_create to alternate task creation between local
57 * node and a patchable remote node. For testing purposes only.
58 * [92/01/08 16:41:27 jsb]
59 *
60 * Use varargs for debugging printfs.
61 * [92/01/08 10:22:12 jsb]
62 *
63 * Use remote_host() instead of norma_get_special_port().
64 * [92/01/04 18:17:46 jsb]
65 *
66 * Revision 2.7.2.1 92/01/03 16:38:29 jsb
67 * Removed unused routine ipc_task_reinit.
68 * [91/12/28 17:59:18 jsb]
69 *
70 * Revision 2.7 91/12/13 13:53:22 jsb
71 * Changed name of task_create_remote to norma_task_create.
72 * Added check for local case in norma_task_create.
73 *
74 * Revision 2.6 91/12/10 13:26:19 jsb
75 * Changed printfs to frets.
76 * [91/12/10 11:34:35 jsb]
77 *
78 * Revision 2.5 91/11/14 16:51:51 rpd
79 * Use new child_node task field in place of task_server_node to decide
80 * upon what node to create child task. Also add task_set_child_node().
81 * [91/09/23 09:22:18 jsb]
82 *
83 * Revision 2.4 91/08/28 11:16:18 jsb
84 * Turned off remaining printf.
85 * [91/08/26 11:16:11 jsb]
86 *
87 * Added support for remote task creation with inherited memory.
88 * Remove task creation is accessible either via task_create_remote,
89 * or task_create with task_server_node patched to some reasonable value.
90 * [91/08/15 13:55:54 jsb]
91 *
92 * Revision 2.3 91/06/17 15:48:07 jsb
93 * Moved routines here from kern/ipc_tt.c and kern/task.c.
94 * [91/06/17 11:01:51 jsb]
95 *
96 * Revision 2.2 91/06/06 17:08:15 jsb
97 * First checkin.
98 * [91/05/25 11:47:39 jsb]
99 *
100 */
101 /*
102 * File: norma/kern_task.c
103 * Author: Joseph S. Barrera III
104 *
105 * NORMA task support.
106 */
107
108 #include <norma_task.h>
109
110 #include <mach/machine/vm_types.h>
111 #include <mach/vm_param.h>
112 #include <mach/task_info.h>
113 #include <mach/task_special_ports.h>
114 #include <ipc/ipc_space.h>
115 #include <kern/mach_param.h>
116 #include <kern/task.h>
117 #include <kern/host.h>
118 #include <kern/thread.h>
119 #include <kern/zalloc.h>
120 #include <kern/kalloc.h>
121 #include <kern/processor.h>
122 #include <kern/ipc_tt.h>
123 #include <sys/varargs.h>
124
125 ipc_port_t norma_task_server;
126 decl_simple_lock_data(,norma_task_server_lock)
127
128 extern zone_t task_zone;
129
130 /*
131 * XXX This definition should be elsewhere
132 */
133 norma_node_self(host, node)
134 host_t host;
135 int *node;
136 {
137 *node = node_self();
138 return KERN_SUCCESS;
139 }
140
141 #if NORMA_TASK
142
143 int fff = 1;
144 int mmm = 0;
145 int bbb = 0;
146 extern cnputc();
147
148 fret(fmt, va_alist)
149 char* fmt;
150 va_dcl
151 {
152 va_list listp;
153
154 if (fff) {
155 va_start(listp);
156 _doprnt(fmt, &listp, cnputc, 0);
157 va_end(listp);
158 }
159 }
160
161 mumble(fmt, va_alist)
162 char* fmt;
163 va_dcl
164 {
165 va_list listp;
166
167 if (mmm) {
168 va_start(listp);
169 _doprnt(fmt, &listp, cnputc, 0);
170 va_end(listp);
171 }
172 }
173
174 babble(fmt, va_alist)
175 char* fmt;
176 va_dcl
177 {
178 va_list listp;
179
180 if (bbb) {
181 va_start(listp);
182 _doprnt(fmt, &listp, cnputc, 0);
183 va_end(listp);
184 }
185 }
186
187 int task_create_remote_node = -1;
188 boolean_t task_create_use_remote = FALSE;
189
190 kern_return_t task_create(parent_task, inherit_memory, child_task)
191 task_t parent_task;
192 boolean_t inherit_memory;
193 task_t *child_task; /* OUT */
194 {
195 if (task_create_remote_node != -1) {
196 task_create_use_remote = ! task_create_use_remote;
197 if (task_create_use_remote) {
198 return norma_task_create(parent_task, inherit_memory,
199 task_create_remote_node,
200 child_task);
201 } else {
202 return task_create_local(parent_task, inherit_memory,
203 child_task);
204 }
205 }
206 if (! parent_task || parent_task->child_node == -1) {
207 return task_create_local(parent_task, inherit_memory,
208 child_task);
209 } else {
210 return norma_task_create(parent_task, inherit_memory,
211 parent_task->child_node,
212 child_task);
213 }
214 }
215
216 kern_return_t task_set_child_node(task, child_node)
217 task_t task;
218 int child_node;
219 {
220 if (task == TASK_NULL) {
221 return KERN_INVALID_ARGUMENT;
222 } else {
223 task->child_node = child_node;
224 return KERN_SUCCESS;
225 }
226 }
227
228 /*
229 * This allows us to create a task without providing a parent.
230 */
231 kern_return_t norma_task_allocate(host, task)
232 host_t host;
233 task_t *task; /* OUT */
234 {
235 babble("norma_task_allocate: called...\n");
236 return task_create_local(TASK_NULL, FALSE, task);
237 }
238
239 kern_return_t
240 task_get_inherited_ports(task, r0, r1, r2, r3, exception, bootstrap)
241 task_t task;
242 ipc_port_t *r0;
243 ipc_port_t *r1;
244 ipc_port_t *r2;
245 ipc_port_t *r3;
246 ipc_port_t *exception;
247 ipc_port_t *bootstrap;
248 {
249 if (task == TASK_NULL) {
250 return KERN_INVALID_ARGUMENT;
251 }
252 itk_lock(task);
253 *r0 = ipc_port_copy_send(task->itk_registered[0]);
254 *r1 = ipc_port_copy_send(task->itk_registered[1]);
255 *r2 = ipc_port_copy_send(task->itk_registered[2]);
256 *r3 = ipc_port_copy_send(task->itk_registered[3]);
257 *exception = ipc_port_copy_send(task->itk_exception);
258 *bootstrap = ipc_port_copy_send(task->itk_bootstrap);
259 itk_unlock(task);
260 return KERN_SUCCESS;
261 }
262
263 kern_return_t
264 task_set_inherited_ports(task, r0, r1, r2, r3, exception, bootstrap)
265 task_t task;
266 ipc_port_t r0;
267 ipc_port_t r1;
268 ipc_port_t r2;
269 ipc_port_t r3;
270 ipc_port_t exception;
271 ipc_port_t bootstrap;
272 {
273 int i;
274
275 if (task == TASK_NULL) {
276 return KERN_INVALID_ARGUMENT;
277 }
278 itk_lock(task);
279 for (i = 0; i < 4; i++) {
280 if (IP_VALID(task->itk_registered[i])) {
281 ipc_port_release_send(task->itk_registered[i]);
282 }
283 }
284 if (IP_VALID(task->itk_exception)) {
285 ipc_port_release_send(task->itk_exception);
286 }
287 if (IP_VALID(task->itk_bootstrap)) {
288 ipc_port_release_send(task->itk_bootstrap);
289 }
290 task->itk_registered[0] = r0;
291 task->itk_registered[1] = r1;
292 task->itk_registered[2] = r2;
293 task->itk_registered[3] = r3;
294 task->itk_exception = exception;
295 task->itk_bootstrap = bootstrap;
296 itk_unlock(task);
297 return KERN_SUCCESS;
298 }
299
300 kern_return_t norma_task_create(parent_task, inherit_memory, child_node,
301 child_task)
302 task_t parent_task;
303 boolean_t inherit_memory;
304 int child_node;
305 task_t *child_task; /* OUT */
306 {
307 ipc_port_t remote_task;
308 task_t new_task;
309 kern_return_t kr;
310 int vector_start;
311 unsigned int entry_vector_count;
312 mach_port_t r0, r1, r2, r3, exception, bootstrap;
313 emulation_vector_t *entry_vector;
314
315 if (child_node == node_self()) {
316 return task_create_local(parent_task, inherit_memory,
317 child_task);
318 }
319
320 babble("task_create: doing %d -> %d\n", node_self(), child_node);
321
322 kr = r_norma_task_allocate(remote_host(child_node), &remote_task);
323 if (kr != KERN_SUCCESS) {
324 return kr;
325 }
326
327 kr = task_get_emulation_vector(parent_task, &vector_start,
328 &entry_vector, &entry_vector_count);
329 if (kr != KERN_SUCCESS) {
330 fret("task_get_emulation_vector failed: kr %d %x\n", kr, kr);
331 return kr;
332 }
333
334 kr = r_task_set_emulation_vector(remote_task, vector_start,
335 entry_vector, entry_vector_count);
336 if (kr != KERN_SUCCESS) {
337 fret("task_set_emulation_vector failed: kr %d %x\n", kr, kr);
338 return kr;
339 }
340
341 kr = task_get_inherited_ports(parent_task, &r0, &r1, &r2, &r3,
342 &exception, &bootstrap);
343 if (kr != KERN_SUCCESS) {
344 fret("task_get_inherited_ports failed: kr %d %x\n", kr, kr);
345 return kr;
346 }
347
348 mumble("%x %x %x %x %x %x\n", r0, r1, r2, r3, exception, bootstrap);
349 kr = r_task_set_inherited_ports(remote_task, r0, r1, r2, r3,
350 exception, bootstrap);
351 if (kr != KERN_SUCCESS) {
352 fret("task_set_inherited_ports failed: kr %d %x\n", kr, kr);
353 return kr;
354 }
355
356 if (inherit_memory) {
357 kr = task_copy_vm(parent_task->map, remote_task);
358 mumble("task_create: task_copy_vm: (%x)\n", kr);
359 if (kr != KERN_SUCCESS) {
360 return kr;
361 }
362 }
363
364 /*
365 * Create a placeholder task for the benefit of convert_task_to_port.
366 * Set new_task->map to VM_MAP_NULL so that task_deallocate will
367 * know that this is only a placeholder task.
368 * XXX decr send-right count?
369 */
370 new_task = (task_t) zalloc(task_zone);
371 if (new_task == TASK_NULL) {
372 panic("task_create: no memory for task structure");
373 }
374
375 /* only one ref, for our caller */
376 new_task->ref_count = 1;
377
378 new_task->map = VM_MAP_NULL;
379 new_task->itk_self = remote_task;
380 simple_lock_init(&new_task->lock);
381
382 babble("task_create: did %d -> %d\n", node_self(), child_node);
383
384 *child_task = new_task;
385 return(KERN_SUCCESS);
386 }
387
388 task_copy_vm(from0, to)
389 vm_map_t from0;
390 ipc_port_t to;
391 {
392 vm_offset_t address;
393 vm_size_t size;
394 vm_prot_t protection, max_protection;
395 vm_inherit_t inheritance;
396 boolean_t shared;
397 port_t object_name;
398 vm_offset_t offset;
399 kern_return_t kr;
400 vm_map_t from;
401 ipc_port_t memory_object;
402
403 from = vm_map_fork(from0);
404 if (from == VM_MAP_NULL) {
405 panic("task_copy_vm: vm_map_fork\n");
406 }
407 for (address = 0;; address += size) {
408 kr = vm_region(from, &address, &size, &protection,
409 &max_protection, &inheritance, &shared,
410 &object_name, &offset);
411 if (kr == KERN_NO_SPACE) {
412 break;
413 }
414 switch (inheritance) {
415 case VM_INHERIT_NONE:
416 break;
417
418 case VM_INHERIT_SHARE:
419 fret("task_copy_vm: VM_INHERIT_SHARE!\n");
420 return KERN_FAILURE;
421
422 case VM_INHERIT_COPY:
423 kr = norma_copy_create(from, address, size,
424 &memory_object);
425 if (kr != KERN_SUCCESS) {
426 fret("task_cv: copy_create: %d 0x%x\n",
427 kr, kr);
428 return kr;
429 }
430 kr = r_vm_map(to, &address, size, 0, FALSE,
431 memory_object, 0, TRUE,
432 protection, max_protection,
433 inheritance);
434 if (kr != KERN_SUCCESS) {
435 fret("task_cv: vm_map: %d 0x%x\n",
436 kr, kr);
437 return kr;
438 }
439 ipc_port_release_send(memory_object);
440 break;
441
442 default:
443 panic("task_copy_vm: inheritance=%d!\n",
444 inheritance);
445 }
446 }
447 vm_map_deallocate(from);
448 return KERN_SUCCESS;
449 }
450 #else NORMA_TASK
451 task_create_local()
452 {
453 }
454
455 norma_task_allocate()
456 {
457 }
458
459 task_get_inherited_ports()
460 {
461 }
462
463 task_set_inherited_ports()
464 {
465 }
466
467 norma_task_create()
468 {
469 }
470
471 norma_copy_create()
472 {
473 }
474
475 #endif NORMA_TASK
Cache object: 14e50f9e9469c0dc5bc438f288466860
|