2 * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU Lesser General Public License 2.1.
7 * Please see the COPYING-LGPL-2.1 file for details.
10 #include <l4/sys/thread>
11 #include <l4/sys/debugger.h>
12 #include <l4/cxx/ipc_server>
14 #include <l4/re/debug>
15 #include <l4/util/util.h>
16 #include <l4/libc_backends/sig.h>
26 #include <sys/types.h>
28 #include <pthread-l4.h>
34 // handlers registered with 'signal'
35 struct sigaction sigactions[_NSIG];
37 L4::Cap<L4::Thread> thcap;
40 struct itimerval current_itimerval;
41 l4_cpu_time_t alarm_timeout;
45 void ping_exc_handler();
46 l4_addr_t get_handler(int signum);
47 int get_any_async_handler();
48 bool is_async_sig(int sig);
49 sighandler_t signal(int signum, sighandler_t handler) throw();
50 int sigaction(int signum, const struct sigaction *act,
51 struct sigaction *oldact) throw();
52 int setitimer(__itimer_which_t __which,
53 __const struct itimerval *__restrict __new,
54 struct itimerval *__restrict __old) throw();
57 int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
58 int handle_exception(l4_umword_t obj, L4::Ipc::Iostream &ios);
63 // -----------------------------------------------------------------------
67 Sig_handling::get_handler(int signum)
71 if ( (sigactions[signum].sa_flags & SA_SIGINFO)
72 && sigactions[signum].sa_sigaction)
73 return (l4_addr_t)sigactions[signum].sa_sigaction;
74 else if (sigactions[signum].sa_handler)
75 return (l4_addr_t)sigactions[signum].sa_handler;
80 Sig_handling::is_async_sig(int sig)
91 case SIGSYS: return true;
92 default: return false;
97 Sig_handling::get_any_async_handler()
99 for (int i = 0; i < _NSIG; ++i)
100 if (is_async_sig(i) && get_handler(i))
107 ".global libc_be_sig_return_trap \n\t"
108 "libc_be_sig_return_trap: \n\t"
109 #if defined(ARCH_x86) || defined(ARCH_amd64)
111 #elif defined(ARCH_arm)
113 "word: .long 0xe1600070 \n\t" // smc
114 #elif defined(ARCH_ppc32)
116 #elif defined(ARCH_sparc)
119 #error Unsupported arch!
124 extern char libc_be_sig_return_trap[];
126 static bool range_ok(l4_addr_t start, unsigned long size)
130 L4::Cap<L4Re::Dataspace> ds;
132 return !L4Re::Env::env()->rm()->find(&start, &size, &offset, &flags, &ds)
133 && !(flags & L4Re::Rm::Read_only);
136 static void dump_rm()
138 L4::Cap<L4Re::Debug_obj> d(L4Re::Env::env()->rm().cap());
142 static bool setup_sig_frame(l4_exc_regs_t *u, int signum)
144 // put state + pointer to it on stack
145 ucontext_t *ucf = (ucontext_t *)(u->sp - sizeof(*ucf));
147 /* Check if memory access is fine */
148 if (!range_ok((l4_addr_t)ucf, sizeof(*ucf)))
151 fill_ucontext_frame(ucf, u);
154 u->sp = (l4_umword_t)ucf;
156 u->r[1] = 0; // siginfo_t pointer, we do not have one right currently
157 u->r[2] = (l4_umword_t)ucf;
158 u->ulr = (unsigned long)libc_be_sig_return_trap;
160 u->sp = (l4_umword_t)ucf - sizeof(void *);
161 *(l4_umword_t *)u->sp = (l4_umword_t)ucf;
163 // siginfo_t pointer, we do not have one right currently
164 u->sp -= sizeof(siginfo_t *);
165 *(l4_umword_t *)u->sp = 0;
167 // both types get the signum as the first argument
168 u->sp -= sizeof(l4_umword_t);
169 *(l4_umword_t *)u->sp = signum;
171 u->sp -= sizeof(l4_umword_t);
172 *(unsigned long *)u->sp = (unsigned long)libc_be_sig_return_trap;
178 int Sig_handling::handle_exception(l4_umword_t, L4::Ipc::Iostream &ios)
181 l4_exc_regs_t *u = &_u;
192 if ((u->err >> 26) == 0x3e)
193 #elif defined(ARCH_ppc32)
194 if ((u->err & 3) == 4)
196 if (u->trapno == 0xff)
199 //printf("SIGALRM\n");
201 int sig = get_any_async_handler();
205 printf("No signal handler found\n");
209 if ( !(handler = get_handler(sig))
210 || !setup_sig_frame(u, sig))
212 printf("Invalid user memory for sigframe...\n");
217 l4_utcb_exc_pc_set(u, handler);
218 ios.put(*u); // expensive? how to set amount of words in tag without copy?
223 if (l4_utcb_exc_pc(u) + pc_delta == (l4_addr_t)libc_be_sig_return_trap)
226 //printf("Sigreturn\n");
229 ucontext_t *ucf = (ucontext_t *)u->sp;
231 ucontext_t *ucf = (ucontext_t *)(u->sp + sizeof(l4_umword_t) * 3);
234 if (!range_ok((l4_addr_t)ucf, sizeof(*ucf)))
237 printf("Invalid memory...\n");
241 fill_utcb_exc(u, ucf);
245 ios.put(*u); // expensive? how to set amount of words in tag without copy?
249 if (!(handler = get_handler(SIGSEGV)))
251 printf("No signal handler found\n");
256 printf("Doing SIGSEGV\n");
258 if (!setup_sig_frame(u, SIGSEGV))
260 printf("Invalid user memory for sigframe...\n");
266 l4_utcb_exc_pc_set(u, handler);
267 ios.put(*u); // expensive? how to set amount of words in tag without copy?
269 //printf("and back\n");
273 int Sig_handling::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
280 case L4_PROTO_EXCEPTION:
281 return handle_exception(obj, ios);
287 static Sig_handling _sig_handling;
292 public L4::Ipc_svr::Compound_reply,
293 public L4::Ipc_svr::Default_setup_wait
295 static l4_timeout_t timeout()
297 if (_sig_handling.alarm_timeout)
300 l4_rcv_timeout(l4_timeout_abs(_sig_handling.alarm_timeout, 1), &t);
301 _sig_handling.alarm_timeout = 0;
305 if (_sig_handling.current_itimerval.it_value.tv_sec == 0
306 && _sig_handling.current_itimerval.it_value.tv_usec == 0)
308 return l4_timeout(L4_IPC_TIMEOUT_NEVER,
309 l4util_micros2l4to(_sig_handling.current_itimerval.it_value.tv_sec * 1000000 +
310 _sig_handling.current_itimerval.it_value.tv_usec));
313 void error(l4_msgtag_t res, L4::Ipc::Istream &s)
315 long ipc_error = l4_ipc_error(res, s.utcb());
317 if (ipc_error == L4_IPC_RETIMEOUT)
321 // any thread is ok, right?!
322 t = L4Re::Env::env()->main_thread()
323 ->ex_regs(~0UL, ~0UL,
324 L4_THREAD_EX_REGS_TRIGGER_EXCEPTION);
326 printf("ex_regs error\n");
331 _sig_handling.current_itimerval.it_value = _sig_handling.current_itimerval.it_interval;
335 printf("(unsupported/strange) loopabort: %lx\n", ipc_error);
340 static void *__handler_main(void *)
342 L4::Server<Loop_hooks> srv(l4_utcb());
343 srv.loop_noexc(&_sig_handling);
348 Sig_handling::Sig_handling()
350 if (pthread_create(&pthread, 0, __handler_main, 0))
352 fprintf(stderr, "libsig: Failed to create handler thread\n");
356 thcap = L4::Cap<L4::Thread>(pthread_getl4cap(pthread));
358 l4_debugger_set_object_name(thcap.cap(), "&-");
360 libsig_be_add_thread(l4re_env()->main_thread);
365 void libsig_be_set_dbg_name(const char *n)
368 snprintf(s, sizeof(s) - 1, "&%s", n);
369 s[sizeof(s) - 1] = 0;
370 l4_debugger_set_object_name(_sig_handling.thcap.cap(), s);
373 void libsig_be_add_thread(l4_cap_idx_t t)
375 L4::Cap<L4::Thread> tt(t);
377 a.exc_handler(_sig_handling.thcap);
378 if (int e = l4_error(tt->control(a)))
379 fprintf(stderr, "libsig: thread-control error: %d\n", e);
380 //printf("Set exc-handler %lx for %lx\n", thcap.cap(), t);
384 void Sig_handling::ping_exc_handler() throw()
386 l4_ipc_call(thcap.cap(), l4_utcb(), l4_msgtag(0, 0, 0, 0), L4_IPC_NEVER);
391 Sig_handling::signal(int signum, sighandler_t handler) throw()
395 sighandler_t old = sigactions[signum].sa_handler;
396 sigactions[signum].sa_handler = handler;
404 sighandler_t signal(int signum, sighandler_t handler) L4_NOTHROW
406 //printf("Called: %s(%d, %p)\n", __func__, signum, handler);
407 return _sig_handling.signal(signum, handler);
412 Sig_handling::sigaction(int signum, const struct sigaction *act,
413 struct sigaction *oldact) throw()
415 if (signum == SIGKILL || signum == SIGSTOP)
421 *oldact = sigactions[signum];
423 sigactions[signum] = *act;
431 int sigaction(int signum, const struct sigaction *act,
432 struct sigaction *oldact) L4_NOTHROW
434 //printf("Called: %s(%d, %p, %p)\n", __func__, signum, act, oldact);
435 int err = _sig_handling.sigaction(signum, act, oldact);
446 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) throw()
448 printf("%s(%d, %p, %p): Unimplemented\n", __func__, how, set, oldset);
454 int sigpending(sigset_t *set) throw()
456 printf("%s(%p): Unimplemented\n", __func__, set);
461 int sigsuspend(const sigset_t *mask) throw()
463 printf("%s(%p): Unimplemented\n", __func__, mask);
469 int killpg(int pgrp, int sig) throw()
471 printf("%s(%d, %d): Unimplemented\n", __func__, pgrp, sig);
477 unsigned int alarm(unsigned int seconds) L4_NOTHROW
479 //printf("unimplemented: alarm(%u)\n", seconds);
481 _sig_handling.alarm_timeout = l4_kip_clock(l4re_kip()) + seconds * 1000000;
483 _sig_handling.ping_exc_handler();
488 pid_t wait(void *status)
490 printf("unimplemented: wait(%p)\n", status);
496 int getitimer(__itimer_which_t __which,
497 struct itimerval *__value) L4_NOTHROW
499 if (__which != ITIMER_REAL)
505 *__value = _sig_handling.current_itimerval;
507 _sig_handling.ping_exc_handler();
513 Sig_handling::setitimer(__itimer_which_t __which,
514 __const struct itimerval *__restrict __new,
515 struct itimerval *__restrict __old) throw()
517 printf("called %s(..)\n", __func__);
519 if (__which != ITIMER_REAL)
526 *__old = current_itimerval;
528 if (__new->it_value.tv_usec < 0
529 || __new->it_value.tv_usec > 999999
530 || __new->it_interval.tv_usec < 0
531 || __new->it_interval.tv_usec > 999999)
537 printf("%s: setting stuff\n", __func__);
538 current_itimerval = *__new;
544 int setitimer(__itimer_which_t __which,
545 __const struct itimerval *__restrict __new,
546 struct itimerval *__restrict __old) L4_NOTHROW
548 int err = _sig_handling.setitimer(__which, __new, __old);