]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurdfault.c
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
[thirdparty/glibc.git] / hurd / hurdfault.c
CommitLineData
28f540f4 1/* Handle faults in the signal thread.
8f480b4b
RM
2 Copyright (C) 1994,1995,1996,1997,2002,2005
3 Free Software Foundation, Inc.
10dc2a90 4 This file is part of the GNU C Library.
28f540f4 5
10dc2a90 6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
28f540f4 10
10dc2a90
UD
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
28f540f4 15
41bdb6e2
AJ
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
28f540f4
RM
20
21#include <hurd.h>
22#include <hurd/signal.h>
23#include "hurdfault.h"
24#include <errno.h>
25#include <string.h>
26#include <setjmp.h>
27#include <stdio.h>
8f480b4b 28#include <thread_state.h>
aa1075ea 29#include "faultexc_server.h" /* mig-generated header for our exc server. */
96aa2d94 30#include <assert.h>
28f540f4
RM
31
32jmp_buf _hurdsig_fault_env;
43b0e40f 33struct hurd_signal_preemptor _hurdsig_fault_preemptor = {0};
28f540f4 34
6bac11d9
MB
35/* XXX temporary to deal with spelling fix */
36weak_alias (_hurdsig_fault_preemptor, _hurdsig_fault_preempter)
37
28f540f4
RM
38static mach_port_t forward_sigexc;
39
28f540f4
RM
40kern_return_t
41_hurdsig_fault_catch_exception_raise (mach_port_t port,
42 thread_t thread,
43 task_t task,
f22a77e1
RM
44#ifdef EXC_MASK_ALL /* New interface flavor. */
45 exception_type_t exception,
46 exception_data_t code,
47 mach_msg_type_number_t codeCnt
48#else /* Vanilla Mach 3.0 interface. */
14906e37
RM
49 integer_t exception,
50 integer_t code, integer_t subcode
f22a77e1
RM
51#endif
52 )
28f540f4
RM
53{
54 int signo;
0e3426bb 55 struct hurd_signal_detail d;
28f540f4
RM
56
57 if (port != forward_sigexc ||
58 thread != _hurd_msgport_thread || task != __mach_task_self ())
59 return EPERM; /* Strange bogosity. */
60
0e3426bb 61 d.exc = exception;
f22a77e1
RM
62#ifdef EXC_MASK_ALL
63 assert (codeCnt >= 2);
64 d.exc_code = code[0];
65 d.exc_subcode = code[1];
66#else
0e3426bb
RM
67 d.exc_code = code;
68 d.exc_subcode = subcode;
f22a77e1 69#endif
0e3426bb 70
28f540f4
RM
71 /* Call the machine-dependent function to translate the Mach exception
72 codes into a signal number and subcode. */
0e3426bb 73 _hurd_exception2signal (&d, &signo);
28f540f4 74
10dc2a90 75 return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preemptor, signo, d.code)
7974fe21 76 ? 0 : EGREGIOUS;
28f540f4
RM
77}
78
f22a77e1
RM
79#ifdef EXC_MASK_ALL
80/* XXX New interface flavor has additional RPCs that we could be using
81 instead. These RPCs roll a thread_get_state/thread_set_state into
82 the message, so the signal thread ought to use these to save some calls.
83 */
84kern_return_t
85_hurdsig_fault_catch_exception_raise_state
86(mach_port_t port,
87 exception_type_t exception,
88 exception_data_t code,
89 mach_msg_type_number_t codeCnt,
90 int *flavor,
91 thread_state_t old_state,
92 mach_msg_type_number_t old_stateCnt,
93 thread_state_t new_state,
94 mach_msg_type_number_t *new_stateCnt)
95{
96 abort ();
97 return KERN_FAILURE;
98}
99
100kern_return_t
101_hurdsig_fault_catch_exception_raise_state_identity
102(mach_port_t exception_port,
103 thread_t thread,
104 task_t task,
105 exception_type_t exception,
106 exception_data_t code,
107 mach_msg_type_number_t codeCnt,
108 int *flavor,
109 thread_state_t old_state,
110 mach_msg_type_number_t old_stateCnt,
111 thread_state_t new_state,
112 mach_msg_type_number_t *new_stateCnt)
113{
114 abort ();
115 return KERN_FAILURE;
116}
117#endif
118
119
120#ifdef NDR_CHAR_ASCII /* OSF Mach flavors have different names. */
121# define mig_reply_header_t mig_reply_error_t
122#endif
123
28f540f4
RM
124static void
125faulted (void)
126{
127 struct
128 {
129 mach_msg_header_t head;
130 char buf[64];
131 } request;
f22a77e1 132 mig_reply_header_t reply;
28f540f4
RM
133 extern int _hurdsig_fault_exc_server (mach_msg_header_t *,
134 mach_msg_header_t *);
135
136 /* Wait for the exception_raise message forwarded by the proc server. */
137
138 if (__mach_msg (&request.head, MACH_RCV_MSG, 0,
139 sizeof request, forward_sigexc,
140 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
141 != MACH_MSG_SUCCESS)
142 __libc_fatal ("msg receive failed on signal thread exc\n");
143
144 /* Run the exc demuxer which should call the server function above.
145 That function returns 0 if the exception was expected. */
f22a77e1
RM
146 _hurdsig_fault_exc_server (&request.head, &reply.Head);
147 if (reply.Head.msgh_remote_port != MACH_PORT_NULL)
148 __mach_msg (&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size,
7974fe21 149 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
f22a77e1 150 if (reply.RetCode == MIG_BAD_ID)
7974fe21
RM
151 __mach_msg_destroy (&request.head);
152
f22a77e1 153 if (reply.RetCode)
7974fe21
RM
154 __libc_fatal ("BUG: unexpected fault in signal thread\n");
155
10dc2a90 156 _hurdsig_fault_preemptor.signals = 0;
28f540f4
RM
157 longjmp (_hurdsig_fault_env, 1);
158}
159
160static char faultstack[1024];
161
162/* Send exceptions for the signal thread to the proc server.
163 It will forward the message on to our message port,
164 and then restore the thread's state to code which
165 does `longjmp (_hurd_sigthread_fault_env, 1)'. */
166
167void
168_hurdsig_fault_init (void)
169{
170 error_t err;
171 struct machine_thread_state state;
172 mach_port_t sigexc;
173
63f89404
RM
174 /* Allocate a port to receive signal thread exceptions.
175 We will move this receive right to the proc server. */
a5a81fec
RM
176 err = __mach_port_allocate (__mach_task_self (),
177 MACH_PORT_RIGHT_RECEIVE, &sigexc);
178 assert_perror (err);
179 err = __mach_port_allocate (__mach_task_self (),
180 MACH_PORT_RIGHT_RECEIVE, &forward_sigexc);
181 assert_perror (err);
182
63f89404
RM
183 /* Allocate a port to receive the exception msgs forwarded
184 from the proc server. */
96aa2d94 185 err = __mach_port_insert_right (__mach_task_self (), sigexc,
a5a81fec
RM
186 sigexc, MACH_MSG_TYPE_MAKE_SEND);
187 assert_perror (err);
63f89404
RM
188
189 /* Set the queue limit for this port to just one. The proc server will
190 notice if we ever get a second exception while one remains queued and
191 unreceived, and decide we are hopelessly buggy. */
f22a77e1
RM
192#ifdef MACH_PORT_RECEIVE_STATUS_COUNT
193 {
194 const mach_port_limits_t lim = { mpl_qlimit: 1 };
195 assert (MACH_PORT_RECEIVE_STATUS_COUNT == sizeof lim / sizeof (natural_t));
196 err = __mach_port_set_attributes (__mach_task_self (), forward_sigexc,
197 MACH_PORT_RECEIVE_STATUS,
21297437
RM
198 (mach_port_info_t) &lim,
199 MACH_PORT_RECEIVE_STATUS_COUNT);
f22a77e1
RM
200 }
201#else
63f89404 202 err = __mach_port_set_qlimit (__mach_task_self (), forward_sigexc, 1);
f22a77e1 203#endif
a5a81fec 204 assert_perror (err);
28f540f4 205
63f89404
RM
206 /* This state will be restored when we fault.
207 It runs the function above. */
28f540f4
RM
208 memset (&state, 0, sizeof state);
209 MACHINE_THREAD_STATE_SET_PC (&state, faulted);
210 MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
211
a5a81fec
RM
212 err = __USEPORT
213 (PROC,
214 __proc_handle_exceptions (port,
215 sigexc,
216 forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
217 MACHINE_THREAD_STATE_FLAVOR,
218 (natural_t *) &state,
219 MACHINE_THREAD_STATE_COUNT));
220 assert_perror (err);
63f89404
RM
221
222 /* Direct signal thread exceptions to the proc server. */
7595ddb8 223#ifdef THREAD_EXCEPTION_PORT
63f89404
RM
224 err = __thread_set_special_port (_hurd_msgport_thread,
225 THREAD_EXCEPTION_PORT, sigexc);
7595ddb8
RM
226#elif defined (EXC_MASK_ALL)
227 __thread_set_exception_ports (_hurd_msgport_thread,
228 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
229 | EXC_MASK_MACH_SYSCALL
230 | EXC_MASK_RPC_ALERT),
231 sigexc,
f22a77e1
RM
232 EXCEPTION_STATE_IDENTITY,
233 MACHINE_THREAD_STATE);
7595ddb8
RM
234#else
235# error thread_set_exception_ports?
236#endif
63f89404
RM
237 __mach_port_deallocate (__mach_task_self (), sigexc);
238 assert_perror (err);
28f540f4 239}