1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#include <mach_kdb.h>
54
55#include <mach/mach_types.h>
56#include <mach/boolean.h>
57#include <mach/kern_return.h>
58#include <mach/message.h>
59#include <mach/port.h>
60#include <mach/mig_errors.h>
61#include <mach/task.h>
62#include <mach/thread_status.h>
63#include <mach/exception_types.h>
64#include <ipc/port.h>
65#include <ipc/ipc_entry.h>
66#include <ipc/ipc_object.h>
67#include <ipc/ipc_notify.h>
68#include <ipc/ipc_space.h>
69#include <ipc/ipc_pset.h>
70#include <ipc/ipc_machdep.h>
71#include <kern/counters.h>
72#include <kern/ipc_tt.h>
73#include <kern/task.h>
74#include <kern/thread.h>
75#include <kern/processor.h>
76#include <kern/sched.h>
77#include <kern/sched_prim.h>
78#include <kern/host.h>
79#include <kern/misc_protos.h>
80#include <string.h>
81#include <mach/exc.h>
82
83#if MACH_KDB
84#include <ddb/db_trap.h>
85#endif
86
87#if MACH_KDB
88
89#include <ddb/db_output.h>
90
91#if iPSC386 || iPSC860
92boolean_t debug_user_with_kdb = TRUE;
93#else
94boolean_t debug_user_with_kdb = FALSE;
95#endif
96
97#endif
98
99unsigned long c_thr_exc_raise = 0;
100unsigned long c_thr_exc_raise_state = 0;
101unsigned long c_thr_exc_raise_state_id = 0;
102unsigned long c_tsk_exc_raise = 0;
103unsigned long c_tsk_exc_raise_state = 0;
104unsigned long c_tsk_exc_raise_state_id = 0;
105
106
107void exception_deliver(
108 exception_type_t exception,
109 exception_data_t code,
110 mach_msg_type_number_t codeCnt,
111 struct exception_action *excp,
112 mutex_t *mutex);
113
114#ifdef MACH_BSD
115kern_return_t bsd_exception(
116 exception_type_t exception,
117 exception_data_t code,
118 mach_msg_type_number_t codeCnt);
119#endif
120
121
122
123
124
125
126
127
128
129
130
131
132
133void
134exception_deliver(
135 exception_type_t exception,
136 exception_data_t code,
137 mach_msg_type_number_t codeCnt,
138 struct exception_action *excp,
139 mutex_t *mutex)
140{
141 thread_t self = current_thread();
142 ipc_port_t exc_port;
143 int behavior;
144 int flavor;
145 kern_return_t kr;
146
147
148
149
150
151 if (!self->active)
152 thread_exception_return();
153
154
155
156
157
158
159
160
161 mutex_lock(mutex);
162 exc_port = excp->port;
163 if (!IP_VALID(exc_port)) {
164 mutex_unlock(mutex);
165 return;
166 }
167 ip_lock(exc_port);
168 if (!ip_active(exc_port)) {
169 ip_unlock(exc_port);
170 mutex_unlock(mutex);
171 return;
172 }
173 ip_reference(exc_port);
174 exc_port->ip_srights++;
175 ip_unlock(exc_port);
176
177 flavor = excp->flavor;
178 behavior = excp->behavior;
179 mutex_unlock(mutex);
180
181 switch (behavior) {
182 case EXCEPTION_STATE: {
183 mach_msg_type_number_t state_cnt;
184 thread_state_data_t state;
185
186 c_thr_exc_raise_state++;
187 state_cnt = _MachineStateCount[flavor];
188 kr = thread_getstatus(self, flavor,
189 (thread_state_t)state,
190 &state_cnt);
191 if (kr == KERN_SUCCESS) {
192 kr = exception_raise_state(exc_port, exception,
193 code, codeCnt,
194 &flavor,
195 state, state_cnt,
196 state, &state_cnt);
197 if (kr == MACH_MSG_SUCCESS)
198 kr = thread_setstatus(self, flavor,
199 (thread_state_t)state,
200 state_cnt);
201 }
202
203 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
204 thread_exception_return();
205
206 return;
207 }
208
209 case EXCEPTION_DEFAULT:
210 c_thr_exc_raise++;
211 kr = exception_raise(exc_port,
212 retrieve_thread_self_fast(self),
213 retrieve_task_self_fast(self->task),
214 exception,
215 code, codeCnt);
216
217 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
218 thread_exception_return();
219
220 return;
221
222 case EXCEPTION_STATE_IDENTITY: {
223 mach_msg_type_number_t state_cnt;
224 thread_state_data_t state;
225
226 c_thr_exc_raise_state_id++;
227 state_cnt = _MachineStateCount[flavor];
228 kr = thread_getstatus(self, flavor,
229 (thread_state_t)state,
230 &state_cnt);
231 if (kr == KERN_SUCCESS) {
232 kr = exception_raise_state_identity(exc_port,
233 retrieve_thread_self_fast(self),
234 retrieve_task_self_fast(self->task),
235 exception,
236 code, codeCnt,
237 &flavor,
238 state, state_cnt,
239 state, &state_cnt);
240 if (kr == MACH_MSG_SUCCESS)
241 kr = thread_setstatus(self, flavor,
242 (thread_state_t)state,
243 state_cnt);
244 }
245
246 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
247 thread_exception_return();
248
249 return;
250 }
251
252 default:
253 panic ("bad exception behavior!");
254 }
255}
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270void
271exception_triage(
272 exception_type_t exception,
273 exception_data_t code,
274 mach_msg_type_number_t codeCnt)
275{
276 thread_t thread;
277 task_t task;
278 host_priv_t host_priv;
279 struct exception_action *excp;
280 mutex_t *mutex;
281
282 assert(exception != EXC_RPC_ALERT);
283
284 if (exception == KERN_SUCCESS)
285 panic("exception");
286
287
288
289
290 thread = current_thread();
291 mutex = mutex_addr(thread->mutex);
292 excp = &thread->exc_actions[exception];
293 exception_deliver(exception, code, codeCnt, excp, mutex);
294
295
296
297
298 task = current_task();
299 mutex = mutex_addr(task->lock);
300 excp = &task->exc_actions[exception];
301 exception_deliver(exception, code, codeCnt, excp, mutex);
302
303
304
305
306 host_priv = host_priv_self();
307 mutex = mutex_addr(host_priv->lock);
308 excp = &host_priv->exc_actions[exception];
309 exception_deliver(exception, code, codeCnt, excp, mutex);
310
311
312
313
314
315#if MACH_KDB
316 if (debug_user_with_kdb) {
317
318
319
320
321
322 db_printf("No exception server, calling kdb...\n");
323 thread_kdb_return();
324 }
325#endif
326
327 (void) task_terminate(task);
328 thread_exception_return();
329
330}
331
332kern_return_t
333bsd_exception(
334 exception_type_t exception,
335 exception_data_t code,
336 mach_msg_type_number_t codeCnt)
337{
338 task_t task;
339 struct exception_action *excp;
340 mutex_t *mutex;
341 thread_t self = current_thread();
342 ipc_port_t exc_port;
343 int behavior;
344 int flavor;
345 kern_return_t kr;
346
347
348
349
350 task = current_task();
351 mutex = mutex_addr(task->lock);
352 excp = &task->exc_actions[exception];
353
354
355
356
357
358 if (!self->active) {
359 return(KERN_FAILURE);
360 }
361
362
363
364
365
366
367
368
369 mutex_lock(mutex);
370 exc_port = excp->port;
371 if (!IP_VALID(exc_port)) {
372 mutex_unlock(mutex);
373 return(KERN_FAILURE);
374 }
375 ip_lock(exc_port);
376 if (!ip_active(exc_port)) {
377 ip_unlock(exc_port);
378 mutex_unlock(mutex);
379 return(KERN_FAILURE);
380 }
381 ip_reference(exc_port);
382 exc_port->ip_srights++;
383 ip_unlock(exc_port);
384
385 flavor = excp->flavor;
386 behavior = excp->behavior;
387 mutex_unlock(mutex);
388
389 switch (behavior) {
390 case EXCEPTION_STATE: {
391 mach_msg_type_number_t state_cnt;
392 thread_state_data_t state;
393
394 c_thr_exc_raise_state++;
395 state_cnt = _MachineStateCount[flavor];
396 kr = thread_getstatus(self, flavor,
397 (thread_state_t)state,
398 &state_cnt);
399 if (kr == KERN_SUCCESS) {
400 kr = exception_raise_state(exc_port, exception,
401 code, codeCnt,
402 &flavor,
403 state, state_cnt,
404 state, &state_cnt);
405 if (kr == MACH_MSG_SUCCESS)
406 kr = thread_setstatus(self, flavor,
407 (thread_state_t)state,
408 state_cnt);
409 }
410
411 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
412 return(KERN_SUCCESS);
413
414 return(KERN_FAILURE);
415 }
416
417 case EXCEPTION_DEFAULT:
418 c_thr_exc_raise++;
419 kr = exception_raise(exc_port,
420 retrieve_thread_self_fast(self),
421 retrieve_task_self_fast(self->task),
422 exception,
423 code, codeCnt);
424
425 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
426 return(KERN_SUCCESS);
427 return(KERN_FAILURE);
428
429 case EXCEPTION_STATE_IDENTITY: {
430 mach_msg_type_number_t state_cnt;
431 thread_state_data_t state;
432
433 c_thr_exc_raise_state_id++;
434 state_cnt = _MachineStateCount[flavor];
435 kr = thread_getstatus(self, flavor,
436 (thread_state_t)state,
437 &state_cnt);
438 if (kr == KERN_SUCCESS) {
439 kr = exception_raise_state_identity(exc_port,
440 retrieve_thread_self_fast(self),
441 retrieve_task_self_fast(self->task),
442 exception,
443 code, codeCnt,
444 &flavor,
445 state, state_cnt,
446 state, &state_cnt);
447 if (kr == MACH_MSG_SUCCESS)
448 kr = thread_setstatus(self, flavor,
449 (thread_state_t)state,
450 state_cnt);
451 }
452
453 if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED)
454 return(KERN_SUCCESS);
455 return(KERN_FAILURE);
456 }
457
458 default:
459
460 return(KERN_FAILURE);
461 }
462 return(KERN_FAILURE);
463}
464
465
466
467
468
469
470
471
472
473kern_return_t sys_perf_notify(struct task *task,
474 exception_data_t code,
475 mach_msg_type_number_t codeCnt)
476{
477 host_priv_t hostp;
478 struct exception_action *excp;
479 thread_t thread = current_thread();
480 ipc_port_t xport;
481 kern_return_t ret;
482 wait_interrupt_t wsave;
483
484 hostp = host_priv_self();
485 excp = &hostp->exc_actions[EXC_RPC_ALERT];
486
487 mutex_lock(&hostp->lock);
488 xport = excp->port;
489 if (!IP_VALID(xport)) {
490 mutex_unlock(&hostp->lock);
491 return(KERN_FAILURE);
492 }
493
494 ip_lock(xport);
495 if (!ip_active(xport)) {
496 ip_unlock(xport);
497 mutex_unlock(&hostp->lock);
498 return(KERN_FAILURE);
499 }
500
501 if (task->itk_space == xport->data.receiver) {
502 ip_unlock(xport);
503 mutex_unlock(&hostp->lock);
504 return(KERN_FAILURE);
505 }
506
507 ip_reference(xport);
508 xport->ip_srights++;
509 ip_unlock(xport);
510
511 mutex_unlock(&hostp->lock);
512
513 wsave = thread_interrupt_level(THREAD_UNINT);
514
515 ret = exception_raise(xport,
516 retrieve_thread_self_fast(thread),
517 retrieve_task_self_fast(thread->task),
518 EXC_RPC_ALERT,
519 code, codeCnt);
520
521 (void)thread_interrupt_level(wsave);
522
523 return(ret);
524}
525