1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 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: ipc_kobject.c,v $
29 * Revision 2.15 93/01/24 13:19:00 danner
30 * Introduce Mach4 interface. Initially for pc sampling.
31 * [93/01/11 rvb]
32 *
33 * Revision 2.14 92/08/03 17:37:23 jfriedl
34 * removed silly prototypes
35 * [92/08/02 jfriedl]
36 *
37 * Revision 2.13 92/05/21 17:13:47 jfriedl
38 * Made correct for when assert is off.
39 * [92/05/16 jfriedl]
40 *
41 * Revision 2.12 92/03/10 16:26:28 jsb
42 * Add IKOT_PAGER_TERMINATING case to ipc_kobject_destroy.
43 * [92/02/25 dlb]
44 * Added ipc_kobject_notify for kernel-requested notifications.
45 * Added code to correctly release send-once kobject destinations.
46 * [92/01/21 18:20:19 jsb]
47 *
48 * Revision 2.11 92/01/03 20:14:32 dbg
49 * Call <subsystem>_routine_name to find IPC stub to execute.
50 * Build reply message header by hand. (XXX)
51 * Simplify cleanup of request message when reply is success.
52 * [91/12/18 dbg]
53 *
54 * Revision 2.10 91/12/13 13:42:24 jsb
55 * Added support for norma/norma_internal.defs.
56 *
57 * Revision 2.9 91/08/01 14:36:18 dbg
58 * Call machine-dependent interface routine, under
59 * MACH_MACHINE_ROUTINES.
60 * [91/08/01 dbg]
61 *
62 * Revision 2.8 91/06/17 15:47:02 jsb
63 * Renamed NORMA conditionals. Added NORMA_VM support.
64 * [91/06/17 13:46:55 jsb]
65 *
66 * Revision 2.7 91/06/06 17:07:05 jsb
67 * Added NORMA_TASK support.
68 * [91/05/14 09:05:48 jsb]
69 *
70 * Revision 2.6 91/05/18 14:31:42 rpd
71 * Added check_simple_locks.
72 * [91/04/01 rpd]
73 *
74 * Revision 2.5 91/05/14 16:42:00 mrt
75 * Correcting copyright
76 *
77 * Revision 2.4 91/03/16 14:50:02 rpd
78 * Replaced ith_saved with ikm_cache.
79 * [91/02/16 rpd]
80 *
81 * Revision 2.3 91/02/05 17:26:37 mrt
82 * Changed to new Mach copyright
83 * [91/02/01 16:12:51 mrt]
84 *
85 * Revision 2.2 90/06/02 14:54:08 rpd
86 * Created for new IPC.
87 * [90/03/26 23:46:53 rpd]
88 *
89 */
90 /*
91 * File: kern/ipc_kobject.c
92 * Author: Rich Draves
93 * Date: 1989
94 *
95 * Functions for letting a port represent a kernel object.
96 */
97
98 #include <mach_debug.h>
99 #include <mach_ipc_test.h>
100 #include <mach_machine_routines.h>
101 #include <norma_task.h>
102 #include <norma_vm.h>
103
104 #include <mach/port.h>
105 #include <mach/kern_return.h>
106 #include <mach/message.h>
107 #include <mach/mig_errors.h>
108 #include <mach/notify.h>
109 #include <kern/ipc_kobject.h>
110 #include <ipc/ipc_object.h>
111 #include <ipc/ipc_kmsg.h>
112 #include <ipc/ipc_port.h>
113 #include <ipc/ipc_thread.h>
114
115 #if MACH_MACHINE_ROUTINES
116 #include <machine/machine_routines.h>
117 #endif
118
119
120 /*
121 * Routine: ipc_kobject_server
122 * Purpose:
123 * Handle a message sent to the kernel.
124 * Generates a reply message.
125 * Conditions:
126 * Nothing locked.
127 */
128
129 ipc_kmsg_t
130 ipc_kobject_server(request)
131 ipc_kmsg_t request;
132 {
133 mach_msg_size_t reply_size = ikm_less_overhead(8192);
134 ipc_kmsg_t reply;
135 kern_return_t kr;
136 mig_routine_t routine;
137 ipc_port_t *destp;
138
139 reply = ikm_alloc(reply_size);
140 if (reply == IKM_NULL) {
141 printf("ipc_kobject_server: dropping request\n");
142 ipc_kmsg_destroy(request);
143 return IKM_NULL;
144 }
145 ikm_init(reply, reply_size);
146
147 /*
148 * Initialize reply message.
149 */
150 {
151 #define InP ((mach_msg_header_t *) &request->ikm_header)
152 #define OutP ((mig_reply_header_t *) &reply->ikm_header)
153
154 static mach_msg_type_t RetCodeType = {
155 /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
156 /* msgt_size = */ 32,
157 /* msgt_number = */ 1,
158 /* msgt_inline = */ TRUE,
159 /* msgt_longform = */ FALSE,
160 /* msgt_unused = */ 0
161 };
162 OutP->Head.msgh_bits =
163 MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
164 OutP->Head.msgh_size = sizeof(mig_reply_header_t);
165 OutP->Head.msgh_remote_port = InP->msgh_local_port;
166 OutP->Head.msgh_local_port = MACH_PORT_NULL;
167 OutP->Head.msgh_seqno = 0;
168 OutP->Head.msgh_id = InP->msgh_id + 100;
169
170 OutP->RetCodeType = RetCodeType;
171
172 #undef InP
173 #undef OutP
174 }
175
176 /*
177 * Find the server routine to call, and call it
178 * to perform the kernel function
179 */
180 {
181 extern mig_routine_t mach_server_routine(),
182 mach_port_server_routine(),
183 mach_host_server_routine(),
184 device_server_routine(),
185 device_pager_server_routine(),
186 mach4_server_routine();
187 #if MACH_DEBUG
188 extern mig_routine_t mach_debug_server_routine();
189 #endif
190 #if NORMA_TASK
191 extern mig_routine_t mach_norma_server_routine();
192 extern mig_routine_t norma_internal_server_routine();
193 #endif
194 #if NORMA_VM
195 extern mig_routine_t proxy_server_routine();
196 #endif
197
198 #if MACH_MACHINE_ROUTINES
199 extern mig_routine_t MACHINE_SERVER_ROUTINE();
200 #endif
201
202 check_simple_locks();
203 if ((routine = mach_server_routine(&request->ikm_header)) != 0
204 || (routine = mach_port_server_routine(&request->ikm_header)) != 0
205 || (routine = mach_host_server_routine(&request->ikm_header)) != 0
206 || (routine = device_server_routine(&request->ikm_header)) != 0
207 || (routine = device_pager_server_routine(&request->ikm_header)) != 0
208 #if MACH_DEBUG
209 || (routine = mach_debug_server_routine(&request->ikm_header)) != 0
210 #endif MACH_DEBUG
211 #if NORMA_TASK
212 || (routine = mach_norma_server_routine(&request->ikm_header)) != 0
213 || (routine = norma_internal_server_routine(&request->ikm_header)) != 0
214 #endif NORMA_TASK
215 #if NORMA_VM
216 || (routine = proxy_server_routine(&request->ikm_header)) != 0
217 #endif NORMA_VM
218 || (routine = mach4_server_routine(&request->ikm_header)) != 0
219 #if MACH_MACHINE_ROUTINES
220 || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
221 #endif MACH_MACHINE_ROUTINES
222 ) {
223 (*routine)(&request->ikm_header, &reply->ikm_header);
224 }
225 else if (!ipc_kobject_notify(&request->ikm_header,&reply->ikm_header)){
226 ((mig_reply_header_t *) &reply->ikm_header)->RetCode
227 = MIG_BAD_ID;
228 #if MACH_IPC_TEST
229 printf("ipc_kobject_server: bogus kernel message, id=%d\n",
230 request->ikm_header.msgh_id);
231 #endif MACH_IPC_TEST
232 }
233 }
234 check_simple_locks();
235
236 /*
237 * Destroy destination. The following code differs from
238 * ipc_object_destroy in that we release the send-once
239 * right instead of generating a send-once notification
240 * (which would bring us here again, creating a loop).
241 * It also differs in that we only expect send or
242 * send-once rights, never receive rights.
243 *
244 * We set msgh_remote_port to IP_NULL so that the kmsg
245 * destroy routines don't try to destroy the port twice.
246 */
247 destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
248 switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
249 case MACH_MSG_TYPE_PORT_SEND:
250 ipc_port_release_send(*destp);
251 break;
252
253 case MACH_MSG_TYPE_PORT_SEND_ONCE:
254 ipc_port_release_sonce(*destp);
255 break;
256
257 default:
258 #if MACH_ASSERT
259 assert(!"ipc_object_destroy: strange destination rights");
260 #else
261 panic("ipc_object_destroy: strange destination rights");
262 #endif
263 }
264 *destp = IP_NULL;
265
266 kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
267 if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
268 /*
269 * The server function is responsible for the contents
270 * of the message. The reply port right is moved
271 * to the reply message, and we have deallocated
272 * the destination port right, so we just need
273 * to free the kmsg.
274 */
275
276 /* like ipc_kmsg_put, but without the copyout */
277
278 ikm_check_initialized(request, request->ikm_size);
279 if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
280 (ikm_cache() == IKM_NULL))
281 ikm_cache() = request;
282 else
283 ikm_free(request);
284 } else {
285 /*
286 * The message contents of the request are intact.
287 * Destroy everthing except the reply port right,
288 * which is needed in the reply message.
289 */
290
291 request->ikm_header.msgh_local_port = MACH_PORT_NULL;
292 ipc_kmsg_destroy(request);
293 }
294
295 if (kr == MIG_NO_REPLY) {
296 /*
297 * The server function will send a reply message
298 * using the reply port right, which it has saved.
299 */
300
301 ikm_free(reply);
302 return IKM_NULL;
303 } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
304 /*
305 * Can't queue the reply message if the destination
306 * (the reply port) isn't valid.
307 */
308
309 ipc_kmsg_destroy(reply);
310 return IKM_NULL;
311 }
312
313 return reply;
314 }
315
316 /*
317 * Routine: ipc_kobject_set
318 * Purpose:
319 * Make a port represent a kernel object of the given type.
320 * The caller is responsible for handling refs for the
321 * kernel object, if necessary.
322 * Conditions:
323 * Nothing locked. The port must be active.
324 */
325
326 void
327 ipc_kobject_set(port, kobject, type)
328 ipc_port_t port;
329 ipc_kobject_t kobject;
330 ipc_kobject_type_t type;
331 {
332 ip_lock(port);
333 assert(ip_active(port));
334 port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
335 port->ip_kobject = kobject;
336 ip_unlock(port);
337 }
338
339 /*
340 * Routine: ipc_kobject_destroy
341 * Purpose:
342 * Release any kernel object resources associated
343 * with the port, which is being destroyed.
344 *
345 * This should only be needed when resources are
346 * associated with a user's port. In the normal case,
347 * when the kernel is the receiver, the code calling
348 * ipc_port_dealloc_kernel should clean up the resources.
349 * Conditions:
350 * The port is not locked, but it is dead.
351 */
352
353 void
354 ipc_kobject_destroy(port)
355 ipc_port_t port;
356 {
357 switch (ip_kotype(port)) {
358 case IKOT_PAGER:
359 vm_object_destroy(port);
360 break;
361
362 case IKOT_PAGER_TERMINATING:
363 vm_object_pager_wakeup(port);
364 break;
365
366 default:
367 #if MACH_ASSERT
368 printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n",
369 port, port->ip_kobject, ip_kotype(port));
370 #endif MACH_ASSERT
371 break;
372 }
373 }
374
375 /*
376 * Routine: ipc_kobject_notify
377 * Purpose:
378 * Deliver notifications to kobjects that care about them.
379 */
380
381 boolean_t
382 ipc_kobject_notify(request_header, reply_header)
383 mach_msg_header_t *request_header;
384 mach_msg_header_t *reply_header;
385 {
386 ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
387
388 ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
389 switch (request_header->msgh_id) {
390 case MACH_NOTIFY_PORT_DELETED:
391 case MACH_NOTIFY_MSG_ACCEPTED:
392 case MACH_NOTIFY_PORT_DESTROYED:
393 case MACH_NOTIFY_NO_SENDERS:
394 case MACH_NOTIFY_SEND_ONCE:
395 case MACH_NOTIFY_DEAD_NAME:
396 break;
397
398 default:
399 return FALSE;
400 }
401 switch (ip_kotype(port)) {
402 #if NORMA_VM
403 case IKOT_XMM_OBJECT:
404 return xmm_object_notify(request_header);
405
406 case IKOT_XMM_PAGER:
407 return xmm_pager_notify(request_header);
408
409 case IKOT_XMM_KERNEL:
410 return xmm_kernel_notify(request_header);
411
412 case IKOT_XMM_REPLY:
413 return xmm_reply_notify(request_header);
414 #endif NORMA_VM
415
416 case IKOT_DEVICE:
417 return ds_notify(request_header);
418
419 default:
420 return FALSE;
421 }
422 }
Cache object: 7140ede940663e00244204f5621b64c3
|