AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
signal.c File Reference

x86: signals, on the way back to user mode, and a handler's frame. More...

#include <core/system.h>
#include <core/arch.h>
#include <core/string.h>
#include <cpu/cpu.h>
#include <ds/hashmap.h>
#include <mm/mm.h>
#include <mm/pmap.h>
#include <mm/vm.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/signal.h>
#include <sys/uaccess.h>
#include <aquila/syscall.h>

Go to the source code of this file.

Data Structures

struct  sigframe
 A signal handler's frame, on the user stack. More...

Macros

#define REG_IP(r)
#define REG_SP(r)
#define REG_AX(r)
#define REG_FLAGS(r)
#define USER_FLAGS   0x00240DD5UL
#define I386_ARGS   20

Functions

static int vm_page_eq (void *a, void *b)
 Compares a page with an offset, for the sigcode object's hashmap.
static struct vm_page * sigcode_in (struct vm_object *vm_object, size_t off)
 Makes the sigcode page, the first time a process touches it.
int arch_sigcode_map (struct proc *proc)
 Maps the page with the code that calls sigreturn() (the sigcode) into a process's new address space.
static void deliver (struct x86_regs *r, int sig)
 Makes the handler of sig run when the context r is returned to: writes its frame on the user stack, and points r at the handler.
void x86_return_to_user (struct x86_regs *r, int syscall)
 Delivers the current process's pending signals on the way back to user mode: stops and default actions, a handler, and the restart (or EINTR) of a system call that a signal interrupted.
void arch_sigreturn (void)
 Returns from a signal handler, for sigreturn(): restores the registers, the signal mask and the FPU state that the handler's frame saved.

Variables

static const uint8_t sigcode []
static struct vm_pager sigcode_pager
static struct vm_object sigcode_object

Detailed Description

x86: signals, on the way back to user mode, and a handler's frame.

Every return to user mode (from a system call, an interrupt or an exception) goes through x86_return_to_user(). There the process takes its signals (signal_take(): stops, default actions), a system call that a signal interrupted is restarted or fails with EINTR, and a handler is made to run by rewriting the user context saved on the kernel stack. Signals come nowhere else, so the kernel never leaves anything halfway.

A handler's frame, on the user stack, is what the handler returns to (the sigcode page) and its arguments (in registers on x86_64), then a struct sigframe: the siginfo, the mask to restore, and the interrupted registers and FPU state.

The handler returns into the sigcode page, mapped in every process (SIGCODE_ADDR, shared, read and execute), which makes the sigreturn system call. It reads the frame back, checks its registers (user segments, no privileged flags), and restores the mask and the FPU state.

The frame is made in the kernel and written with copyout(), and read back with copyin(): a stack that isn't there is the process's fault (SIGSEGV), not the kernel's.

Definition in file signal.c.

Macro Definition Documentation

◆ I386_ARGS

#define I386_ARGS   20

Definition at line 72 of file signal.c.

Referenced by arch_sigreturn(), and deliver().

◆ REG_AX

#define REG_AX ( r)
Value:
((r)->rax)

Definition at line 51 of file signal.c.

Referenced by x86_return_to_user().

◆ REG_FLAGS

#define REG_FLAGS ( r)
Value:
((r)->rflags)

Definition at line 52 of file signal.c.

Referenced by arch_sigreturn(), and deliver().

◆ REG_IP

#define REG_IP ( r)
Value:
((r)->rip)

Definition at line 49 of file signal.c.

Referenced by deliver(), and x86_return_to_user().

◆ REG_SP

#define REG_SP ( r)
Value:
((r)->rsp)

Definition at line 50 of file signal.c.

Referenced by arch_sigreturn(), and deliver().

◆ USER_FLAGS

#define USER_FLAGS   0x00240DD5UL

Definition at line 57 of file signal.c.

Function Documentation

◆ arch_sigcode_map()

int arch_sigcode_map ( struct proc * proc)

Maps the page with the code that calls sigreturn() (the sigcode) into a process's new address space.

Parameters
procthe process
Returns
0, or a negative errno (-ENOMEM if there was no memory)

Definition at line 129 of file signal.c.

References arch_sigcode_map(), vm_entry::base, vm_entry::flags, kfree(), kmalloc(), M_ZERO, PAGE_SIZE, vm_object::pages, SIGCODE_ADDR, sigcode_object, vm_entry::size, vm_entry::vm_object, vm_object_incref(), vm_page_eq(), proc::vm_space, vm_space_insert(), and VM_URX.

◆ arch_sigreturn()

void arch_sigreturn ( void )

Returns from a signal handler, for sigreturn(): restores the registers, the signal mask and the FPU state that the handler's frame saved.

A bad frame gets SIGSEGV.

Definition at line 291 of file signal.c.

References arch_sigreturn(), x86_regs::cs, curproc, curthread, sigframe::fpu, sigframe::fxsave, I386_ARGS, sigframe::mask, REG_FLAGS, REG_SP, sigframe::regs, x86_thread::regs, SIG_UNMASKABLE, signal_force(), x86_regs::ss, USER_FLAGS, X86_CS, X86_EFLAGS, x86_fpu_load_from(), and X86_SS.

◆ deliver()

void deliver ( struct x86_regs * r,
int sig )
static

◆ sigcode_in()

struct vm_page * sigcode_in ( struct vm_object * vm_object,
size_t off )
static

Makes the sigcode page, the first time a process touches it.

The object keeps it, and every process maps the same page.

Definition at line 91 of file signal.c.

References kfree(), kmalloc(), M_ZERO, memcpy(), mm_page_alloc(), mm_page_dealloc(), NULL, vm_page::off, vm_page::paddr, PAGE_SIZE, pmap_page_write(), vm_page::ref, sigcode, sigcode_in(), vm_page::vm_object, and vm_object_page_insert().

◆ vm_page_eq()

int vm_page_eq ( void * a,
void * b )
static

Compares a page with an offset, for the sigcode object's hashmap.

Definition at line 84 of file signal.c.

References vm_page_eq().

◆ x86_return_to_user()

void x86_return_to_user ( struct x86_regs * r,
int syscall )

Delivers the current process's pending signals on the way back to user mode: stops and default actions, a handler, and the restart (or EINTR) of a system call that a signal interrupted.

Parameters
rthe user context about to be returned to
syscallwhether r is returning from a system call (one that may need restarting)

Definition at line 246 of file signal.c.

References thread::arch, x86_regs::cs, curthread, deliver(), ERESTARTNOHAND, ERESTARTSYS, thread::owner, REG_AX, REG_IP, thread::restarting, thread::sig_oldmask, thread::sig_oldmask_set, proc::sigaction, proc::sigmask, signal_take(), thread::syscall_nr, and x86_return_to_user().

Referenced by arch_syscall(), irq_dispatch(), isr_dispatch(), and x86_return_to_user().

Variable Documentation

◆ sigcode

const uint8_t sigcode[]
static
Initial value:
= {
0xB8, SYS_sigreturn & 0xff, (SYS_sigreturn >> 8) & 0xff, 0, 0,
0xCD, 0x80,
0x0F, 0x0B,
}

Definition at line 77 of file signal.c.

◆ sigcode_object

struct vm_object sigcode_object
static
Initial value:
= {
.pager = &sigcode_pager,
.ref = 1,
}
static struct vm_pager sigcode_pager
Definition signal.c:95

Definition at line 121 of file signal.c.

◆ sigcode_pager

struct vm_pager sigcode_pager
static
Initial value:
= {
.in = sigcode_in,
}
static struct vm_page * sigcode_in(struct vm_object *vm_object, size_t off)
Makes the sigcode page, the first time a process touches it.
Definition signal.c:64

Definition at line 117 of file signal.c.