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