]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ux/usermode.cpp
9c57df96d6f5b9667898d6a631704744c48f550f
[l4.git] / kernel / fiasco / src / kern / ux / usermode.cpp
1
2 INTERFACE:
3
4 #include <csignal>                              // for siginfo_t
5 #include "initcalls.h"
6 #include "types.h"
7
8 class Usermode
9 {};
10
11 IMPLEMENTATION:
12
13 #include <cassert>
14 #include <cerrno>
15 #include <climits>
16 #include <cstdarg>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <fcntl.h>
21 #include <panic.h>
22 #include <ucontext.h>
23 #include <unistd.h>
24 #include <asm/unistd.h>
25 #include <sys/mman.h>
26 #include <sys/ptrace.h>
27 #include <sys/types.h>
28 #include <sys/user.h>
29 #include <sys/wait.h>
30 #include "undef_page.h"
31
32 #include "boot_info.h"
33 #include "config.h"
34 #include "config_tcbsize.h"
35 #include "context.h"
36 #include "emulation.h"
37 #include "fpu.h"
38 #include "globals.h"
39 #include "mem_layout.h"
40 #include "pic.h"
41 #include "processor.h"
42 #include "regdefs.h"
43 #include "task.h"
44 #include "thread.h"
45 #include "thread_state.h"
46
47 PRIVATE static
48 Mword
49 Usermode::peek_at_addr (pid_t pid, Address addr, unsigned n)
50 {
51   Mword val;
52
53   if ((addr & sizeof (Mword) - 1) + n > sizeof (Mword))
54     val = ptrace (PTRACE_PEEKTEXT, pid, addr, NULL);
55   else
56     val = ptrace (PTRACE_PEEKTEXT, pid, addr & ~(sizeof (Mword) - 1), NULL) >>
57           CHAR_BIT * (addr & sizeof (Mword) - 1);
58
59   return val & (Mword) -1 >> CHAR_BIT * (sizeof (Mword) - n);
60 }
61
62 /**
63  * Wait for host process to stop.
64  * @param pid process id to wait for.
65  * @return signal the host process stopped with.
66  */
67 PRIVATE static inline NOEXPORT
68 int
69 Usermode::wait_for_stop (pid_t pid)
70 {
71   int status;
72
73   check (waitpid (pid, &status, 0) == pid && WIFSTOPPED (status));
74
75   return WSTOPSIG (status);
76 }
77
78 /**
79  * Set emulated internal processor interrupt state.
80  * @param mask signal mask to modify
81  * @param eflags processor flags register
82  */
83 PRIVATE static inline NOEXPORT
84 void
85 Usermode::sync_interrupt_state (sigset_t *mask, Mword eflags)
86 {
87   Proc::ux_set_virtual_processor_state (eflags);
88
89   if (!mask)
90     return;
91
92   if (eflags & EFLAGS_IF)
93     sigdelset (mask, SIGIO);
94   else
95     sigaddset (mask, SIGIO);
96 }
97
98 /**
99  * Cancel a native system call in the host.
100  * @param pid process id of the host process.
101  * @param regs register set at the time of the system call.
102  */
103 PRIVATE static inline NOEXPORT
104 void
105 Usermode::cancel_syscall (pid_t pid, struct user_regs_struct *regs)
106 {
107   ptrace (PTRACE_POKEUSER, pid, offsetof (struct user, regs.orig_eax), -1);
108   ptrace (PTRACE_SYSCALL, pid, NULL, NULL);
109
110   wait_for_stop (pid);
111
112   regs->eax = regs->orig_eax;
113   ptrace (PTRACE_POKEUSER, pid, offsetof (struct user, regs.eax), regs->eax);
114 }
115
116 /**
117  * Read debug register
118  * @param pid process id of the host process.
119  * @param reg number of debug register (0..7)
120  * @param value reference to register value
121  * @return 0 is ok
122  */
123 PUBLIC static
124 int
125 Usermode::read_debug_register (pid_t pid, Mword reg, Mword &value)
126 {
127   if (reg > 7)
128     return 0;
129
130   int ret = ptrace (PTRACE_PEEKUSER, pid,
131                    ((struct user *) 0)->u_debugreg + reg, NULL);
132
133   if (ret == -1 && errno == -1)
134     return 0;
135
136   value = ret;
137
138   return 1;
139 }
140
141 /**
142  * Write debug register
143  * @param pid process id of the host process.
144  * @param reg number of debug register (0..7)
145  * @param value register value to be written.
146  * @return 0 is ok
147  */
148 PUBLIC static
149 int
150 Usermode::write_debug_register (pid_t pid, Mword reg, Mword value)
151 {
152   if (reg > 7)
153     return 0;
154
155   if (ptrace (PTRACE_POKEUSER, pid,
156              ((struct user *) 0)->u_debugreg + reg, value) == -1)
157     return 0;
158
159   return 1;
160 }
161
162 /**
163  * Set up kernel stack for kernel entry through an interrupt gate.
164  * We are running on the signal stack and modifying the interrupted context
165  * on the signal stack to allow us to return anywhere.
166  * Depending on the value of the code segment (CS) we set up a processor
167  * context of 3 (kernel mode) or 5 (user mode) words on the respective kernel
168  * stack, which is the current stack (kernel mode) or the stack determined by
169  * the Task State Segment (user mode). For some traps we need to put an
170  * additional error code on the stack.
171  * This is precisely what an ia32 processor does in hardware.
172  * @param context Interrupted context on signal stack
173  * @param trap Trap number that caused kernel entry (0xffffffff == shutdown)
174  * @param xss Stack Segment
175  * @param esp Stack Pointer
176  * @param efl EFLAGS
177  * @param xcs Code Segment
178  * @param eip Instruction Pointer
179  * @param err Error Code
180  * @param cr2 Page Fault Address (if applicable)
181  */
182 PRIVATE static
183 void
184 Usermode::kernel_entry (unsigned _cpu,
185                         struct ucontext *context,
186                         Mword trap,
187                         Mword xss,
188                         Mword esp,
189                         Mword efl,
190                         Mword xcs,
191                         Mword eip,
192                         Mword err,
193                         Mword cr2)
194 {
195   Mword *kesp = (xcs & 3) == 3
196               ? (Mword *) Cpu::cpus.cpu(_cpu).kernel_sp() - 5
197               : (Mword *) context->uc_mcontext.gregs[REG_ESP] - 3;
198
199   if (!Thread::is_tcb_address((Address)kesp))
200     {
201       printf("KERNEL BUG at EIP:%08x ESP:%08x -- PFA:%08lx kesp=%p trap=%lx xcs=%lx @ %p %lx\n",
202              context->uc_mcontext.gregs[REG_EIP],
203              context->uc_mcontext.gregs[REG_ESP],
204              context->uc_mcontext.cr2, kesp, trap, xcs, &Cpu::cpus.cpu(_cpu).kernel_sp(), Cpu::cpus.cpu(_cpu).kernel_sp());
205       abort();
206     }
207
208   // Make sure the kernel stack is sane
209   assert (Thread::is_tcb_address((Address)kesp));
210
211   // Make sure the kernel stack has enough space
212   if ((Mword) kesp % THREAD_BLOCK_SIZE <= 512)
213     {
214       printf("KERNEL BUG: Kernel stack of thread ");
215       printf("DBGID=%lx\n", static_cast<Thread*>(context_of(kesp))->dbg_info()->dbg_id());
216       panic(" exceeded (%p, %c). \n"
217             "            As a workaround, please make sure that you built \n"
218             "            Fiasco-UX with enabled CONTEXT_4K.",
219             kesp, (xcs & 3) == 2 ? 'k' : 'u');
220     }
221
222   efl &= ~EFLAGS_IF;
223
224   switch (xcs & 3)
225     {
226       case 3:
227         *(kesp + 4) = xss;
228         *(kesp + 3) = esp;
229
230       case 0:
231         *(kesp + 2) = efl | (Proc::processor_state() & EFLAGS_IF);
232         *(kesp + 1) = xcs & ~1; // trap on iret
233         *(kesp + 0) = eip;
234     }
235
236   switch (trap)
237     {
238       case 0xe:                                 // Page Fault
239         Emulation::set_page_fault_addr (cr2);
240       case 0x8:                                 // Double Fault
241       case 0xa:                                 // Invalid TSS
242       case 0xb:                                 // Segment Not Present
243       case 0xc:                                 // Stack Fault
244       case 0xd:                                 // General Protection Fault
245       case 0x11:                                // Alignment Check
246         *--kesp = err;
247     }
248
249   context->uc_mcontext.gregs[REG_ESP] = (Mword) kesp;
250   context->uc_mcontext.gregs[REG_EIP] = Emulation::idt_vector (trap, false);
251   context->uc_mcontext.gregs[REG_EFL] = efl & ~(EFLAGS_TF | EFLAGS_NT | EFLAGS_RF | EFLAGS_VM);
252   sync_interrupt_state (&context->uc_sigmask, efl);
253
254   // Make sure interrupts are off
255   assert (!Proc::interrupts());
256 }
257
258 PRIVATE static inline NOEXPORT
259 Mword
260 Usermode::kip_syscall (Address eip)
261 {
262   if ((eip & Config::PAGE_MASK) != Mem_layout::Syscalls || eip & 0xff)
263     return 0;
264
265   Mword trap = 0x30 + (eip - Mem_layout::Syscalls >> 8);
266
267   return Emulation::idt_vector (trap, true) ? trap : 0;
268 }
269
270 PRIVATE static inline NOEXPORT
271 Mword
272 Usermode::l4_syscall (Mword opcode)
273 {
274   if (EXPECT_FALSE ((opcode & 0xff) != 0xcd))
275     return 0;
276
277   Mword trap = opcode >> 8;
278
279   return Emulation::idt_vector (trap, true) ? trap : 0;
280 }
281
282 PRIVATE static inline NOEXPORT NEEDS["thread_state.h"]
283 bool
284 Usermode::user_exception (unsigned _cpu, pid_t pid, struct ucontext *context,
285                           struct user_regs_struct *regs)
286 {
287   Mword trap, error = 0, addr = 0;
288
289   if (EXPECT_FALSE ((trap = kip_syscall (regs->eip))))
290     {
291       Context *t = context_of(((Mword *)Cpu::cpus.cpu(_cpu).kernel_sp()) - 1);
292
293       /* The alien syscall code in entry-*.S substracts 2 bytes from the
294        * EIP to put the EIP back on the instruction to reexecute it.
295        * 'int X' and sysenter etc. are 2 byte instructions.
296        * So we add 2 here to have the EIP in the right position afterwards.
297        *
298        * Furthermore we leave ESP and EIP (with the adjustment) where they
299        * are so that the syscall can be re-executed.
300        *
301        * This is not a problem for native as it does not trap on the
302        * 'call 0xea......' itself there but on the real int/sysenter/etc.
303        * instructions in the syscall page.
304        */
305       if (EXPECT_FALSE((t->state() & (Thread_alien | Thread_dis_alien))
306                        == Thread_alien || t->space_ref()->user_mode()))
307         regs->eip += 2;
308       else
309         {
310           regs->eip  = peek_at_addr (pid, regs->esp, 4);
311           regs->esp += 4;
312         }
313     }
314
315   else if ((trap = l4_syscall (peek_at_addr (pid, regs->eip, 2))))
316     regs->eip += 2;
317
318   else
319     {
320       struct ucontext *exception_context;
321
322       memcpy ((void *) Mem_layout::kernel_trampoline_page,
323               (void *) &Mem_layout::task_sighandler_start,
324               &Mem_layout::task_sighandler_end -
325               &Mem_layout::task_sighandler_start);
326
327       ptrace (PTRACE_CONT, pid, NULL, SIGSEGV);
328
329       wait_for_stop (pid);
330
331       // See corresponding code in sighandler.S
332       exception_context = reinterpret_cast<struct ucontext *>
333                           (Mem_layout::kernel_trampoline_page +
334                          *reinterpret_cast<Address *>
335                           (Mem_layout::kernel_trampoline_page + 0x100));
336
337       addr  = exception_context->uc_mcontext.cr2;
338       trap  = exception_context->uc_mcontext.gregs[REG_TRAPNO];
339       error = exception_context->uc_mcontext.gregs[REG_ERR];
340
341       switch (trap)
342         {
343           case 0xd:
344             if (Boot_info::emulate_clisti())
345               switch (peek_at_addr (pid, regs->eip, 1))
346                 {
347                   case 0xfa:    // cli
348                     Pic::set_owner (Boot_info::pid());
349                     regs->eip++;
350                     regs->eflags &= ~EFLAGS_IF;
351                     sync_interrupt_state (0, regs->eflags);
352                     check(ptrace (PTRACE_SETREGS, pid, NULL, regs));
353                     return false;
354
355                   case 0xfb:    // sti
356                     Pic::set_owner (pid);
357                     regs->eip++;
358                     regs->eflags |= EFLAGS_IF;
359                     sync_interrupt_state (0, regs->eflags);
360                     check(ptrace (PTRACE_SETREGS, pid, NULL, regs));
361                     return false;
362                 }
363             break;
364
365           case 0xe:
366             error |= PF_ERR_USERADDR;
367             break;
368         }
369     }
370
371   kernel_entry (_cpu, context, trap,
372                 regs->xss,      /* XSS */
373                 regs->esp,      /* ESP */
374                 regs->eflags,   /* EFL */
375                 regs->xcs,      /* XCS */
376                 regs->eip,      /* EIP */
377                 error,          /* ERR */
378                 addr);          /* CR2 */
379
380   return true;
381 }
382
383 PRIVATE static inline NOEXPORT
384 bool
385 Usermode::user_emulation (unsigned _cpu, int stop, pid_t pid,
386                           struct ucontext *context,
387                           struct user_regs_struct *regs)
388 {
389   Mword trap, error = 0;
390
391   switch (stop)
392     {
393       case SIGSEGV:
394         return user_exception (_cpu, pid, context, regs);
395
396       case SIGIO:
397         int irq_pend;
398         if ((irq_pend = Pic::irq_pending()) == -1)
399           return false;
400         Pic::eat (irq_pend);
401         trap = Pic::map_irq_to_gate (irq_pend);
402         break;
403
404       case SIGTRAP:
405         if (peek_at_addr (pid, regs->eip - 1, 1) == 0xcc)
406           {
407             trap = 0x3;
408             break;
409           }
410         else if (peek_at_addr (pid, regs->eip - 2, 2) == 0x80cd)
411           {
412             cancel_syscall (pid, regs);
413             trap       = 0xd;
414             error      = 0x80 << 3 | 2;
415             regs->eip -= 2;
416             break;
417           }
418         trap = 0x1;
419         break;
420
421       case SIGILL:
422         trap = 0x6;
423         break;
424
425       case SIGFPE:
426         trap = 0x10;
427         break;
428
429       default:
430         trap = 0x1;
431         break;
432     }
433
434   kernel_entry (_cpu, context, trap,
435                 regs->xss,      /* XSS */
436                 regs->esp,      /* ESP */
437                 regs->eflags,   /* EFL */
438                 regs->xcs,      /* XCS */
439                 regs->eip,      /* EIP */
440                 error,          /* ERR */
441                 0);             /* CR2 */
442
443   return true;
444 }
445
446 /**
447  * IRET to a user context.
448  * We restore the saved context on the stack, namely EIP, CS, EFLAGS, ESP, SS.
449  * Additionally all register values are transferred to the task's register set.
450  * @param ctx Kern context during iret
451  */
452 PRIVATE static inline NOEXPORT
453 void
454 Usermode::iret_to_user_mode (unsigned _cpu,
455                              struct ucontext *context, Mword *kesp)
456 {
457   struct user_regs_struct regs;
458   int irq_pend;
459   Context *t = context_of (kesp);
460   pid_t pid = t->vcpu_aware_space()->pid();
461
462   Pic::set_owner (pid);
463
464   /*
465    * If there are any interrupts pending up to this point, don't start the task
466    * but let it enter kernel immediately. Any interrupts occuring beyond this
467    * point will go directly to the task.
468    */
469   if ((irq_pend = Pic::irq_pending()) != -1)
470     {
471       Pic::eat (irq_pend);
472
473       Pic::set_owner (Boot_info::pid());
474
475       kernel_entry (_cpu, context,
476                     Pic::map_irq_to_gate (irq_pend),
477                     *(kesp + 4),    /* XSS */
478                     *(kesp + 3),    /* ESP */
479                     *(kesp + 2),    /* EFL */
480                     *(kesp + 1) | 3,/* XCS */
481                     *(kesp + 0),    /* EIP */
482                     0,              /* ERR */
483                     0);             /* CR2 */
484       return;
485     }
486
487   // Restore these from the kernel stack (iret context)
488   regs.eip    = *(kesp + 0);
489   regs.xcs    = *(kesp + 1) | 3;
490   regs.eflags = *(kesp + 2);
491   regs.esp    = *(kesp + 3);
492   regs.xss    = *(kesp + 4);
493
494   // Copy these from the kernel
495   regs.eax    = context->uc_mcontext.gregs[REG_EAX];
496   regs.ebx    = context->uc_mcontext.gregs[REG_EBX];
497   regs.ecx    = context->uc_mcontext.gregs[REG_ECX];
498   regs.edx    = context->uc_mcontext.gregs[REG_EDX];
499   regs.esi    = context->uc_mcontext.gregs[REG_ESI];
500   regs.edi    = context->uc_mcontext.gregs[REG_EDI];
501   regs.ebp    = context->uc_mcontext.gregs[REG_EBP];
502   regs.xds    = context->uc_mcontext.gregs[REG_DS];
503   regs.xes    = context->uc_mcontext.gregs[REG_ES];
504   regs.xfs    = Cpu::get_fs();
505   regs.xgs    = Cpu::get_gs();
506
507   // ptrace will return with an error if we try to load invalid values to
508   // segment registers
509   int r = ptrace (PTRACE_SETREGS, pid, NULL, &regs);
510   if (EXPECT_FALSE(r == -EPERM))
511     {
512       WARN("Failure setting registers, probably invalid segment values.\n"
513            "        Fixing up!\n");
514       regs.xds = Cpu::kern_ds();
515       regs.xes = Cpu::kern_es();
516       regs.xgs = 0;
517       check(ptrace (PTRACE_SETREGS, pid, NULL, &regs));
518     }
519   else
520     assert(r == 0);
521
522   Fpu::restore_state (t->fpu_state());
523
524   for (;;)
525     {
526       ptrace (t->is_native() ? PTRACE_CONT :  PTRACE_SYSCALL, pid, NULL, NULL);
527
528       int stop = wait_for_stop (pid);
529
530       if (EXPECT_FALSE (stop == SIGWINCH || stop == SIGTERM || stop == SIGINT))
531         continue;
532
533       check(ptrace (PTRACE_GETREGS, pid, NULL, &regs) == 0);
534
535       if (EXPECT_TRUE (user_emulation (_cpu, stop, pid, context, &regs)))
536         break;
537     }
538
539   Pic::set_owner (Boot_info::pid());
540
541   if (Pic::irq_pending() != -1)
542     kill (Boot_info::pid(), SIGIO);
543
544   context->uc_mcontext.gregs[REG_EAX] = regs.eax;
545   context->uc_mcontext.gregs[REG_EBX] = regs.ebx;
546   context->uc_mcontext.gregs[REG_ECX] = regs.ecx;
547   context->uc_mcontext.gregs[REG_EDX] = regs.edx;
548   context->uc_mcontext.gregs[REG_ESI] = regs.esi;
549   context->uc_mcontext.gregs[REG_EDI] = regs.edi;
550   context->uc_mcontext.gregs[REG_EBP] = regs.ebp;
551   context->uc_mcontext.gregs[REG_DS]  = regs.xds;
552   context->uc_mcontext.gregs[REG_ES]  = regs.xes;
553   Cpu::set_fs(regs.xfs);
554   Cpu::set_gs(regs.xgs);
555
556   Fpu::save_state (t->fpu_state());
557 }
558
559 /**
560  * IRET to a kernel context.
561  * We restore the saved context on the stack, namely EIP and EFLAGS.
562  * We do NOT restore CS, because the kernel thinks it has privilege level 0
563  * but in usermode it has to have privilege level 3. We also adjust ESP by
564  * 3 words, thus clearing the context from the stack.
565  * @param ctx Kern context during iret
566  */
567 PRIVATE static inline NOEXPORT
568 void
569 Usermode::iret_to_kern_mode (struct ucontext *context, Mword *kesp)
570 {
571   context->uc_mcontext.gregs[REG_EIP]  = *(kesp + 0);
572   context->uc_mcontext.gregs[REG_EFL]  = *(kesp + 2);
573   context->uc_mcontext.gregs[REG_ESP] += 3 * sizeof (Mword);
574 }
575
576 /**
577  * Emulate IRET instruction.
578  * Depending on the value of the saved code segment (CS) on the kernel stack
579  * we return to kernel mode (CPL == 0) or user mode (CPL == 2).
580  * @param ctx Kern context during iret
581  */
582 PRIVATE static inline NOEXPORT
583 void
584 Usermode::iret (unsigned _cpu, struct ucontext *context)
585 {
586   Mword *kesp = (Mword *) context->uc_mcontext.gregs[REG_ESP];
587
588   sync_interrupt_state (&context->uc_sigmask, *(kesp + 2));
589
590   switch (*(kesp + 1) & 3)
591     {
592       case 0:                   /* CPL 0 -> Kernel */
593         iret_to_kern_mode (context, kesp);
594         break;
595
596       case 2:                   /* CPL 2 -> User */
597         iret_to_user_mode (_cpu, context, kesp);
598         break;
599
600       default:
601         assert(0);
602     }
603 }
604
605 PRIVATE static
606 void
607 Usermode::emu_handler (int, siginfo_t *, void *ctx)
608 {
609   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
610   unsigned int trap = context->uc_mcontext.gregs[REG_TRAPNO];
611
612   unsigned _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct()));
613
614   if (trap == 0xd)      /* General protection fault */
615     {
616       unsigned char opcode = *reinterpret_cast<unsigned char *>
617                              (context->uc_mcontext.gregs[REG_EIP]);
618
619       switch (opcode)
620         {
621           case 0xfa:                                    /* cli */
622             context->uc_mcontext.gregs[REG_EIP]++;
623             context->uc_mcontext.gregs[REG_EFL] &= ~EFLAGS_IF;
624             sync_interrupt_state (&context->uc_sigmask,
625                                    context->uc_mcontext.gregs[REG_EFL]);
626             return;
627
628           case 0xfb:                                    /* sti */
629             context->uc_mcontext.gregs[REG_EIP]++;
630             context->uc_mcontext.gregs[REG_EFL] |= EFLAGS_IF;
631             sync_interrupt_state (&context->uc_sigmask,
632                                    context->uc_mcontext.gregs[REG_EFL]);
633             return;
634
635           case 0xcf:                                    /* iret */
636             iret (_cpu, context);
637             return;
638         }
639     }
640
641   kernel_entry (_cpu, context, trap,
642                 context->uc_mcontext.gregs[REG_SS],
643                 context->uc_mcontext.gregs[REG_ESP],
644                 context->uc_mcontext.gregs[REG_EFL],
645                 context->uc_mcontext.gregs[REG_CS] & ~3,
646                 context->uc_mcontext.gregs[REG_EIP],
647                 context->uc_mcontext.gregs[REG_ERR] & ~PF_ERR_USERMODE,
648                 context->uc_mcontext.cr2);
649 }
650
651 PRIVATE static
652 void
653 Usermode::int_handler (int, siginfo_t *, void *ctx)
654 {
655   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
656   int irq;
657   unsigned long gate;
658
659   if ((irq = Pic::irq_pending()) == -1)
660     return;
661
662   if (Pic::get_ipi_gate(irq, gate) == false)
663     gate = Pic::map_irq_to_gate(irq);
664
665   Pic::eat (irq);
666
667   kernel_entry (Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct())),
668                 context,
669                 gate,
670                 context->uc_mcontext.gregs[REG_SS],     /* XSS */
671                 context->uc_mcontext.gregs[REG_ESP],    /* ESP */
672                 context->uc_mcontext.gregs[REG_EFL],    /* EFL */
673                 context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */
674                 context->uc_mcontext.gregs[REG_EIP],    /* EIP */
675                 0,                                      /* ERR */
676                 0);                                     /* CR2 */
677 }
678
679 PRIVATE static
680 void
681 Usermode::jdb_handler (int sig, siginfo_t *, void *ctx)
682 {
683   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
684
685   if (!Thread::is_tcb_address(context->uc_mcontext.gregs[REG_ESP]))
686     return;
687
688   /*
689    * If a SIGSEGV is pending at the same time as SIGINT, i.e. because
690    * someone pressed Ctrl-C on an sti instruction, SIGINT will be delivered
691    * first. Since we warp to a different execution path the pending SIGSEGV
692    * will then hit an innocent instruction elsewhere with fatal consequences.
693    * Therefore a pending SIGSEGV must be cancelled - it will later reoccur.
694    */
695
696   signal (SIGSEGV, SIG_IGN);    // Cancel signal
697   set_signal (SIGSEGV);         // Reinstall handler
698
699   kernel_entry (Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct())),
700                 context, sig == SIGTRAP ? 3 : 1,
701                 context->uc_mcontext.gregs[REG_SS],     /* XSS */
702                 context->uc_mcontext.gregs[REG_ESP],    /* ESP */
703                 context->uc_mcontext.gregs[REG_EFL],    /* EFL */
704                 context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */
705                 context->uc_mcontext.gregs[REG_EIP],    /* EIP */
706                 0,                                      /* ERR */
707                 0);                                     /* CR2 */
708 }
709
710 PUBLIC static
711 void
712 Usermode::set_signal (int sig)
713 {
714   void (*func)(int, siginfo_t *, void *);
715   struct sigaction action;
716
717   switch (sig)
718     {
719       case SIGIO:       func = int_handler;     break;
720       case SIGSEGV:     func = emu_handler;     break;
721       default:          func = jdb_handler;     break;
722     }
723
724   sigfillset (&action.sa_mask);         /* No other signals while we run */
725   action.sa_sigaction = func;
726   action.sa_flags     = SA_RESTART | SA_ONSTACK | SA_SIGINFO;
727
728   check (sigaction (sig, &action, NULL) == 0);
729 }
730
731 PUBLIC static FIASCO_INIT_CPU
732 void
733 Usermode::init(unsigned cpu)
734 {
735   stack_t stack;
736
737   /* We want signals, aka interrupts to be delivered on an alternate stack */
738   if (cpu == 0)
739     stack.ss_sp  = (void *) Mem_layout::phys_to_pmem
740                                 (Mem_layout::Sigstack_cpu0_start_frame);
741   else
742     stack.ss_sp = Kmem_alloc::allocator()->alloc(Mem_layout::Sigstack_log2_size);
743   stack.ss_size  =  Mem_layout::Sigstack_size;
744   stack.ss_flags = 0;
745
746   check (sigaltstack (&stack, NULL) == 0);
747
748   signal (SIGWINCH, SIG_IGN);
749   signal (SIGPROF,  SIG_IGN);
750   signal (SIGHUP,   SIG_IGN);
751   signal (SIGUSR1,  SIG_IGN);
752   signal (SIGUSR2,  SIG_IGN);
753
754   set_signal (SIGSEGV);
755   set_signal (SIGIO);
756   if (cpu == 0)
757     set_signal (SIGINT);
758   else
759     signal (SIGINT, SIG_IGN);
760   set_signal (SIGTRAP);
761   set_signal (SIGTERM);
762   set_signal (SIGXCPU);
763 }