]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ux/usermode.cpp
update
[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   if (trap == 0x38) trap = 0x39;
267
268   return Emulation::idt_vector (trap, true) ? trap : 0;
269 }
270
271 PRIVATE static inline NOEXPORT
272 Mword
273 Usermode::l4_syscall (Mword opcode)
274 {
275   if (EXPECT_FALSE ((opcode & 0xff) != 0xcd))
276     return 0;
277
278   Mword trap = opcode >> 8;
279
280   return Emulation::idt_vector (trap, true) ? trap : 0;
281 }
282
283 PRIVATE static inline NOEXPORT NEEDS["thread_state.h"]
284 bool
285 Usermode::user_exception (unsigned _cpu, pid_t pid, struct ucontext *context,
286                           struct user_regs_struct *regs)
287 {
288   Mword trap, error = 0, addr = 0;
289
290   if (EXPECT_FALSE ((trap = kip_syscall (regs->eip))))
291     {
292       Context *t = context_of(((Mword *)Cpu::cpus.cpu(_cpu).kernel_sp()) - 1);
293
294       /* The alien syscall code in entry-*.S substracts 2 bytes from the
295        * EIP to put the EIP back on the instruction to reexecute it.
296        * 'int X' and sysenter etc. are 2 byte instructions.
297        * So we add 2 here to have the EIP in the right position afterwards.
298        *
299        * Furthermore we leave ESP and EIP (with the adjustment) where they
300        * are so that the syscall can be re-executed.
301        *
302        * This is not a problem for native as it does not trap on the
303        * 'call 0xea......' itself there but on the real int/sysenter/etc.
304        * instructions in the syscall page.
305        */
306       if (EXPECT_FALSE((t->state() & (Thread_alien | Thread_dis_alien))
307                        == Thread_alien || t->space_ref()->user_mode()))
308         regs->eip += 2;
309       else
310         {
311           regs->eip  = peek_at_addr (pid, regs->esp, 4);
312           regs->esp += 4;
313         }
314     }
315
316   else if ((trap = l4_syscall (peek_at_addr (pid, regs->eip, 2))))
317     regs->eip += 2;
318
319   else
320     {
321       struct ucontext *exception_context;
322
323       memcpy ((void *) Mem_layout::kernel_trampoline_page,
324               (void *) &Mem_layout::task_sighandler_start,
325               &Mem_layout::task_sighandler_end -
326               &Mem_layout::task_sighandler_start);
327
328       ptrace (PTRACE_CONT, pid, NULL, SIGSEGV);
329
330       wait_for_stop (pid);
331
332       // See corresponding code in sighandler.S
333       exception_context = reinterpret_cast<struct ucontext *>
334                           (Mem_layout::kernel_trampoline_page +
335                          *reinterpret_cast<Address *>
336                           (Mem_layout::kernel_trampoline_page + 0x100));
337
338       addr  = exception_context->uc_mcontext.cr2;
339       trap  = exception_context->uc_mcontext.gregs[REG_TRAPNO];
340       error = exception_context->uc_mcontext.gregs[REG_ERR];
341
342       switch (trap)
343         {
344           case 0xd:
345             if (Boot_info::emulate_clisti())
346               switch (peek_at_addr (pid, regs->eip, 1))
347                 {
348                   case 0xfa:    // cli
349                     Pic::set_owner (Boot_info::pid());
350                     regs->eip++;
351                     regs->eflags &= ~EFLAGS_IF;
352                     sync_interrupt_state (0, regs->eflags);
353                     check(ptrace (PTRACE_SETREGS, pid, NULL, regs));
354                     return false;
355
356                   case 0xfb:    // sti
357                     Pic::set_owner (pid);
358                     regs->eip++;
359                     regs->eflags |= EFLAGS_IF;
360                     sync_interrupt_state (0, regs->eflags);
361                     check(ptrace (PTRACE_SETREGS, pid, NULL, regs));
362                     return false;
363                 }
364             break;
365
366           case 0xe:
367             error |= PF_ERR_USERADDR;
368             break;
369         }
370     }
371
372   kernel_entry (_cpu, context, trap,
373                 regs->xss,      /* XSS */
374                 regs->esp,      /* ESP */
375                 regs->eflags,   /* EFL */
376                 regs->xcs,      /* XCS */
377                 regs->eip,      /* EIP */
378                 error,          /* ERR */
379                 addr);          /* CR2 */
380
381   return true;
382 }
383
384 PRIVATE static inline NOEXPORT
385 bool
386 Usermode::user_emulation (unsigned _cpu, int stop, pid_t pid,
387                           struct ucontext *context,
388                           struct user_regs_struct *regs)
389 {
390   Mword trap, error = 0;
391
392   switch (stop)
393     {
394       case SIGSEGV:
395         return user_exception (_cpu, pid, context, regs);
396
397       case SIGIO:
398         int irq_pend;
399         if ((irq_pend = Pic::irq_pending()) == -1)
400           return false;
401         Pic::eat (irq_pend);
402         trap = Pic::map_irq_to_gate (irq_pend);
403         break;
404
405       case SIGTRAP:
406         if (peek_at_addr (pid, regs->eip - 1, 1) == 0xcc)
407           {
408             trap = 0x3;
409             break;
410           }
411         else if (peek_at_addr (pid, regs->eip - 2, 2) == 0x80cd)
412           {
413             cancel_syscall (pid, regs);
414             trap       = 0xd;
415             error      = 0x80 << 3 | 2;
416             regs->eip -= 2;
417             break;
418           }
419         trap = 0x1;
420         break;
421
422       case SIGILL:
423         trap = 0x6;
424         break;
425
426       case SIGFPE:
427         trap = 0x10;
428         break;
429
430       default:
431         trap = 0x1;
432         break;
433     }
434
435   kernel_entry (_cpu, context, trap,
436                 regs->xss,      /* XSS */
437                 regs->esp,      /* ESP */
438                 regs->eflags,   /* EFL */
439                 regs->xcs,      /* XCS */
440                 regs->eip,      /* EIP */
441                 error,          /* ERR */
442                 0);             /* CR2 */
443
444   return true;
445 }
446
447 /**
448  * IRET to a user context.
449  * We restore the saved context on the stack, namely EIP, CS, EFLAGS, ESP, SS.
450  * Additionally all register values are transferred to the task's register set.
451  * @param ctx Kern context during iret
452  */
453 PRIVATE static inline NOEXPORT
454 void
455 Usermode::iret_to_user_mode (unsigned _cpu,
456                              struct ucontext *context, Mword *kesp)
457 {
458   struct user_regs_struct regs;
459   int stop, irq_pend;
460   Context *t = context_of (kesp);
461   pid_t pid = t->vcpu_aware_space()->pid();
462
463   Pic::set_owner (pid);
464
465   /*
466    * If there are any interrupts pending up to this point, don't start the task
467    * but let it enter kernel immediately. Any interrupts occuring beyond this
468    * point will go directly to the task.
469    */
470   if ((irq_pend = Pic::irq_pending()) != -1)
471     {
472       Pic::eat (irq_pend);
473
474       Pic::set_owner (Boot_info::pid());
475
476       kernel_entry (_cpu, context,
477                     Pic::map_irq_to_gate (irq_pend),
478                     *(kesp + 4),    /* XSS */
479                     *(kesp + 3),    /* ESP */
480                     *(kesp + 2),    /* EFL */
481                     *(kesp + 1) | 3,/* XCS */
482                     *(kesp + 0),    /* EIP */
483                     0,              /* ERR */
484                     0);             /* CR2 */
485       return;
486     }
487
488   // Restore these from the kernel stack (iret context)
489   regs.eip    = *(kesp + 0);
490   regs.xcs    = *(kesp + 1) | 3;
491   regs.eflags = *(kesp + 2);
492   regs.esp    = *(kesp + 3);
493   regs.xss    = *(kesp + 4);
494
495   // Copy these from the kernel
496   regs.eax    = context->uc_mcontext.gregs[REG_EAX];
497   regs.ebx    = context->uc_mcontext.gregs[REG_EBX];
498   regs.ecx    = context->uc_mcontext.gregs[REG_ECX];
499   regs.edx    = context->uc_mcontext.gregs[REG_EDX];
500   regs.esi    = context->uc_mcontext.gregs[REG_ESI];
501   regs.edi    = context->uc_mcontext.gregs[REG_EDI];
502   regs.ebp    = context->uc_mcontext.gregs[REG_EBP];
503   regs.xds    = context->uc_mcontext.gregs[REG_DS];
504   regs.xes    = context->uc_mcontext.gregs[REG_ES];
505   regs.xfs    = Cpu::get_fs();
506   regs.xgs    = Cpu::get_gs();
507
508   // ptrace will return with an error if we try to load invalid values to
509   // segment registers
510   int r = ptrace (PTRACE_SETREGS, pid, NULL, &regs);
511   if (EXPECT_FALSE(r == -EPERM))
512     {
513       WARN("Failure setting registers, probably invalid segment values.\n"
514            "        Fixing up!\n");
515       regs.xds = Cpu::kern_ds();
516       regs.xes = Cpu::kern_es();
517       regs.xgs = 0;
518       check(ptrace (PTRACE_SETREGS, pid, NULL, &regs));
519     }
520   else
521     assert(r == 0);
522
523   Fpu::restore_state (t->fpu_state());
524
525   for (;;)
526     {
527       ptrace (t->is_native() ? PTRACE_CONT :  PTRACE_SYSCALL, pid, NULL, NULL);
528
529       stop = wait_for_stop (pid);
530
531       if (EXPECT_FALSE (stop == SIGWINCH || stop == SIGTERM || stop == SIGINT))
532         continue;
533
534       check(ptrace (PTRACE_GETREGS, pid, NULL, &regs) == 0);
535
536       if (EXPECT_TRUE (user_emulation (_cpu, stop, pid, context, &regs)))
537         break;
538     }
539
540   Pic::set_owner (Boot_info::pid());
541
542   if (Pic::irq_pending() != -1)
543     kill (Boot_info::pid(), SIGIO);
544
545   context->uc_mcontext.gregs[REG_EAX] = regs.eax;
546   context->uc_mcontext.gregs[REG_EBX] = regs.ebx;
547   context->uc_mcontext.gregs[REG_ECX] = regs.ecx;
548   context->uc_mcontext.gregs[REG_EDX] = regs.edx;
549   context->uc_mcontext.gregs[REG_ESI] = regs.esi;
550   context->uc_mcontext.gregs[REG_EDI] = regs.edi;
551   context->uc_mcontext.gregs[REG_EBP] = regs.ebp;
552   context->uc_mcontext.gregs[REG_DS]  = regs.xds;
553   context->uc_mcontext.gregs[REG_ES]  = regs.xes;
554   Cpu::set_fs(regs.xfs);
555   Cpu::set_gs(regs.xgs);
556
557   Fpu::save_state (t->fpu_state());
558 }
559
560 /**
561  * IRET to a kernel context.
562  * We restore the saved context on the stack, namely EIP and EFLAGS.
563  * We do NOT restore CS, because the kernel thinks it has privilege level 0
564  * but in usermode it has to have privilege level 3. We also adjust ESP by
565  * 3 words, thus clearing the context from the stack.
566  * @param ctx Kern context during iret
567  */
568 PRIVATE static inline NOEXPORT
569 void
570 Usermode::iret_to_kern_mode (struct ucontext *context, Mword *kesp)
571 {
572   context->uc_mcontext.gregs[REG_EIP]  = *(kesp + 0);
573   context->uc_mcontext.gregs[REG_EFL]  = *(kesp + 2);
574   context->uc_mcontext.gregs[REG_ESP] += 3 * sizeof (Mword);
575 }
576
577 /**
578  * Emulate IRET instruction.
579  * Depending on the value of the saved code segment (CS) on the kernel stack
580  * we return to kernel mode (CPL == 0) or user mode (CPL == 2).
581  * @param ctx Kern context during iret
582  */
583 PRIVATE static inline NOEXPORT
584 void
585 Usermode::iret (unsigned _cpu, struct ucontext *context)
586 {
587   Mword *kesp = (Mword *) context->uc_mcontext.gregs[REG_ESP];
588
589   sync_interrupt_state (&context->uc_sigmask, *(kesp + 2));
590
591   switch (*(kesp + 1) & 3)
592     {
593       case 0:                   /* CPL 0 -> Kernel */
594         iret_to_kern_mode (context, kesp);
595         break;
596
597       case 2:                   /* CPL 2 -> User */
598         iret_to_user_mode (_cpu, context, kesp);
599         break;
600
601       default:
602         assert(0);
603     }
604 }
605
606 PRIVATE static
607 void
608 Usermode::emu_handler (int, siginfo_t *, void *ctx)
609 {
610   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
611   unsigned int trap = context->uc_mcontext.gregs[REG_TRAPNO];
612
613   unsigned _cpu = Cpu::p2l(Cpu::phys_id_direct());
614
615   if (trap == 0xd)      /* General protection fault */
616     {
617       unsigned char opcode = *reinterpret_cast<unsigned char *>
618                              (context->uc_mcontext.gregs[REG_EIP]);
619
620       switch (opcode)
621         {
622           case 0xfa:                                    /* cli */
623             context->uc_mcontext.gregs[REG_EIP]++;
624             context->uc_mcontext.gregs[REG_EFL] &= ~EFLAGS_IF;
625             sync_interrupt_state (&context->uc_sigmask,
626                                    context->uc_mcontext.gregs[REG_EFL]);
627             return;
628
629           case 0xfb:                                    /* sti */
630             context->uc_mcontext.gregs[REG_EIP]++;
631             context->uc_mcontext.gregs[REG_EFL] |= EFLAGS_IF;
632             sync_interrupt_state (&context->uc_sigmask,
633                                    context->uc_mcontext.gregs[REG_EFL]);
634             return;
635
636           case 0xcf:                                    /* iret */
637             iret (_cpu, context);
638             return;
639         }
640     }
641
642   kernel_entry (_cpu, context, trap,
643                 context->uc_mcontext.gregs[REG_SS],
644                 context->uc_mcontext.gregs[REG_ESP],
645                 context->uc_mcontext.gregs[REG_EFL],
646                 context->uc_mcontext.gregs[REG_CS] & ~3,
647                 context->uc_mcontext.gregs[REG_EIP],
648                 context->uc_mcontext.gregs[REG_ERR] & ~PF_ERR_USERMODE,
649                 context->uc_mcontext.cr2);
650 }
651
652 PRIVATE static
653 void
654 Usermode::int_handler (int, siginfo_t *, void *ctx)
655 {
656   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
657   int irq;
658   unsigned long gate;
659
660   if ((irq = Pic::irq_pending()) == -1)
661     return;
662
663   if (Pic::get_ipi_gate(irq, gate) == false)
664     gate = Pic::map_irq_to_gate(irq);
665
666   Pic::eat (irq);
667
668   kernel_entry (Cpu::p2l(Cpu::phys_id_direct()),
669                 context,
670                 gate,
671                 context->uc_mcontext.gregs[REG_SS],     /* XSS */
672                 context->uc_mcontext.gregs[REG_ESP],    /* ESP */
673                 context->uc_mcontext.gregs[REG_EFL],    /* EFL */
674                 context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */
675                 context->uc_mcontext.gregs[REG_EIP],    /* EIP */
676                 0,                                      /* ERR */
677                 0);                                     /* CR2 */
678 }
679
680 PRIVATE static
681 void
682 Usermode::jdb_handler (int sig, siginfo_t *, void *ctx)
683 {
684   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
685
686   if (!Thread::is_tcb_address(context->uc_mcontext.gregs[REG_ESP]))
687     return;
688
689   /*
690    * If a SIGSEGV is pending at the same time as SIGINT, i.e. because
691    * someone pressed Ctrl-C on an sti instruction, SIGINT will be delivered
692    * first. Since we warp to a different execution path the pending SIGSEGV
693    * will then hit an innocent instruction elsewhere with fatal consequences.
694    * Therefore a pending SIGSEGV must be cancelled - it will later reoccur.
695    */
696
697   signal (SIGSEGV, SIG_IGN);    // Cancel signal
698   set_signal (SIGSEGV);         // Reinstall handler
699
700   kernel_entry (Cpu::p2l(Cpu::phys_id_direct()),
701                 context, sig == SIGTRAP ? 3 : 1,
702                 context->uc_mcontext.gregs[REG_SS],     /* XSS */
703                 context->uc_mcontext.gregs[REG_ESP],    /* ESP */
704                 context->uc_mcontext.gregs[REG_EFL],    /* EFL */
705                 context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */
706                 context->uc_mcontext.gregs[REG_EIP],    /* EIP */
707                 0,                                      /* ERR */
708                 0);                                     /* CR2 */
709 }
710
711 PUBLIC static
712 void
713 Usermode::set_signal (int sig)
714 {
715   void (*func)(int, siginfo_t *, void *);
716   struct sigaction action;
717
718   switch (sig)
719     {
720       case SIGIO:       func = int_handler;     break;
721       case SIGSEGV:     func = emu_handler;     break;
722       default:          func = jdb_handler;     break;
723     }
724
725   sigfillset (&action.sa_mask);         /* No other signals while we run */
726   action.sa_sigaction = func;
727   action.sa_flags     = SA_RESTART | SA_ONSTACK | SA_SIGINFO;
728
729   check (sigaction (sig, &action, NULL) == 0);
730 }
731
732 PUBLIC static FIASCO_INIT_CPU
733 void
734 Usermode::init(unsigned cpu)
735 {
736   stack_t stack;
737
738   /* We want signals, aka interrupts to be delivered on an alternate stack */
739   if (cpu == 0)
740     stack.ss_sp  = (void *) Mem_layout::phys_to_pmem
741                                 (Mem_layout::Sigstack_cpu0_start_frame);
742   else
743     stack.ss_sp = Mapped_allocator::allocator()->alloc(Mem_layout::Sigstack_log2_size);
744   stack.ss_size  =  Mem_layout::Sigstack_size;
745   stack.ss_flags = 0;
746
747   check (sigaltstack (&stack, NULL) == 0);
748
749   signal (SIGWINCH, SIG_IGN);
750   signal (SIGPROF,  SIG_IGN);
751   signal (SIGHUP,   SIG_IGN);
752   signal (SIGUSR1,  SIG_IGN);
753   signal (SIGUSR2,  SIG_IGN);
754
755   set_signal (SIGSEGV);
756   set_signal (SIGIO);
757   if (cpu == 0)
758     set_signal (SIGINT);
759   else
760     signal (SIGINT, SIG_IGN);
761   set_signal (SIGTRAP);
762   set_signal (SIGTERM);
763   set_signal (SIGXCPU);
764 }