simple signal handler and kill(2) support.
This commit is contained in:
18
arch/x86/kernel/include/signal.h
Normal file
18
arch/x86/kernel/include/signal.h
Normal file
@ -0,0 +1,18 @@
|
||||
#define _NSIG 64
|
||||
#define _NSIG_BPW 64
|
||||
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
|
||||
|
||||
typedef struct {
|
||||
unsigned long sig[_NSIG_WORDS];
|
||||
} sigset_t;
|
||||
|
||||
struct sigaction {
|
||||
void (*sa_handler)(int);
|
||||
unsigned long sa_flags;
|
||||
void (*sa_restorer)(int);
|
||||
sigset_t sa_mask;
|
||||
};
|
||||
|
||||
struct k_sigaction {
|
||||
struct sigaction sa;
|
||||
};
|
||||
@ -25,6 +25,7 @@ SYSCALL_HANDLED(11, munmap)
|
||||
SYSCALL_HANDLED(12, brk)
|
||||
SYSCALL_HANDLED(13, rt_sigaction)
|
||||
SYSCALL_HANDLED(14, rt_sigprocmask)
|
||||
SYSCALL_HANDLED(15, rt_sigreturn)
|
||||
SYSCALL_DELEGATED(16, ioctl)
|
||||
SYSCALL_DELEGATED(17, pread64)
|
||||
SYSCALL_DELEGATED(18, pwrite64)
|
||||
@ -35,6 +36,7 @@ SYSCALL_HANDLED(28, madvise)
|
||||
SYSCALL_HANDLED(39, getpid)
|
||||
SYSCALL_HANDLED(56, clone)
|
||||
SYSCALL_HANDLED(60, exit)
|
||||
SYSCALL_HANDLED(62, kill)
|
||||
SYSCALL_DELEGATED(63, uname)
|
||||
SYSCALL_DELEGATED(72, fcntl)
|
||||
SYSCALL_DELEGATED(79, getcwd)
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <ihk/mm.h>
|
||||
#include <ihk/atomic.h>
|
||||
#include <list.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define VR_NONE 0x0
|
||||
#define VR_STACK 0x1
|
||||
@ -53,6 +54,12 @@ struct vm_regions {
|
||||
|
||||
struct process_vm;
|
||||
|
||||
struct sig_handler {
|
||||
// TODO: lock;
|
||||
int use;
|
||||
struct k_sigaction action[_NSIG];
|
||||
};
|
||||
|
||||
struct process {
|
||||
int pid;
|
||||
int status;
|
||||
@ -74,6 +81,12 @@ struct process {
|
||||
int *clear_child_tid;
|
||||
unsigned long tlsblock_base, tlsblock_limit;
|
||||
} thread;
|
||||
|
||||
int signal;
|
||||
struct sig_handler *sighandler;
|
||||
ihk_mc_kernel_context_t sigctx;
|
||||
char sigstack[512];
|
||||
unsigned long sigrc; // return code of rt_sigreturn (x86_64: rax reg.)
|
||||
};
|
||||
|
||||
struct process_vm {
|
||||
|
||||
@ -73,6 +73,7 @@ void sbox_write(int offset, unsigned int value);
|
||||
|
||||
static void query_free_mem_interrupt_handler(void *priv)
|
||||
{
|
||||
#ifdef ATTACHED_MIC
|
||||
dkprintf("query free mem handler!\n");
|
||||
|
||||
int pages = ihk_pagealloc_query_free(pa_allocator);
|
||||
@ -81,6 +82,7 @@ static void query_free_mem_interrupt_handler(void *priv)
|
||||
|
||||
sbox_write(SBOX_SCRATCH0, pages);
|
||||
sbox_write(SBOX_SCRATCH1, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct ihk_mc_interrupt_handler query_free_mem_handler = {
|
||||
|
||||
@ -54,6 +54,14 @@ struct process *create_process(unsigned long user_pc)
|
||||
memset(proc, 0, sizeof(struct process));
|
||||
ihk_atomic_set(&proc->refcount, 2); /* one for exit, another for wait */
|
||||
|
||||
proc->sighandler = kmalloc(sizeof(struct sig_handler), IHK_MC_AP_NOWAIT);
|
||||
if(!proc->sighandler){
|
||||
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
||||
return NULL;
|
||||
}
|
||||
memset(proc->sighandler, '\0', sizeof(struct sig_handler));
|
||||
proc->sighandler->use = 1;
|
||||
|
||||
ihk_mc_init_user_process(&proc->ctx, &proc->uctx,
|
||||
((char *)proc) +
|
||||
KERNEL_STACK_NR_PAGES * PAGE_SIZE, user_pc, 0);
|
||||
@ -61,6 +69,7 @@ struct process *create_process(unsigned long user_pc)
|
||||
proc->vm = (struct process_vm *)(proc + 1);
|
||||
|
||||
if(init_process_vm(proc, proc->vm) != 0){
|
||||
kfree(proc->sighandler);
|
||||
ihk_mc_free_pages(proc, KERNEL_STACK_NR_PAGES);
|
||||
return NULL;
|
||||
}
|
||||
@ -95,6 +104,10 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
||||
ihk_atomic_inc(&org->vm->refcount);
|
||||
proc->vm = org->vm;
|
||||
|
||||
// TODO: lock
|
||||
proc->sighandler = org->sighandler;
|
||||
org->sighandler->use++;
|
||||
|
||||
ihk_mc_spinlock_init(&proc->spin_sleep_lock);
|
||||
proc->spin_sleep = 0;
|
||||
|
||||
|
||||
107
kernel/syscall.c
107
kernel/syscall.c
@ -813,6 +813,28 @@ SYSCALL_DECLARE(set_tid_address)
|
||||
return cpu_local_var(current)->pid;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(kill)
|
||||
{
|
||||
int pid = ihk_mc_syscall_arg0(ctx);
|
||||
int sig = ihk_mc_syscall_arg1(ctx);
|
||||
|
||||
struct process *proc = cpu_local_var(current);
|
||||
|
||||
if(proc->pid == pid){
|
||||
proc->signal = sig;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pid <= 0) { return -EINVAL; }
|
||||
// search pid
|
||||
// check kill permission
|
||||
if(sig == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
// see linux-2.6.34.13/kernel/signal.c
|
||||
SYSCALL_DECLARE(tgkill)
|
||||
{
|
||||
@ -835,11 +857,87 @@ SYSCALL_DECLARE(set_robust_list)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int
|
||||
do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current);
|
||||
struct k_sigaction *k;
|
||||
// TODO: sigmask
|
||||
|
||||
k = proc->sighandler->action + sig - 1;
|
||||
if(oact)
|
||||
memcpy(oact, k, sizeof(struct k_sigaction));
|
||||
if(act){
|
||||
memcpy(k, act, sizeof(struct k_sigaction));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(rt_sigaction)
|
||||
{
|
||||
// kprintf("sys_rt_sigaction called. returning zero...\n");
|
||||
return 0;
|
||||
int sig = ihk_mc_syscall_arg0(ctx);
|
||||
const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx);
|
||||
struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx);
|
||||
size_t sigsetsize = ihk_mc_syscall_arg3(ctx);
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int rc;
|
||||
|
||||
//if (sigsetsize != sizeof(sigset_t))
|
||||
//return -EINVAL;
|
||||
|
||||
if(act)
|
||||
memcpy(&new_sa.sa, act, sizeof new_sa.sa);
|
||||
rc = do_sigaction(sig, act? &new_sa: NULL, oact? &old_sa: NULL);
|
||||
if(oact)
|
||||
memcpy(oact, &old_sa.sa, sizeof old_sa.sa);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
check_signal(unsigned long rc)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current);
|
||||
struct k_sigaction *k;
|
||||
int sig = proc->signal;
|
||||
|
||||
proc->signal = 0;
|
||||
if(sig){
|
||||
k = proc->sighandler->action + sig - 1;
|
||||
if(k->sa.sa_handler){
|
||||
unsigned long *usp; /* user stack */
|
||||
char *kspbottom;
|
||||
long w;
|
||||
asm volatile ("movq %%gs:24,%0" : "=r" (usp));
|
||||
asm volatile ("movq %%gs:132,%0" : "=r" (kspbottom));
|
||||
memcpy(proc->sigstack, kspbottom - 120, 120);
|
||||
proc->sigrc = rc;
|
||||
usp--;
|
||||
*usp = (unsigned long)k->sa.sa_restorer;
|
||||
w = 56 + 3;
|
||||
asm volatile ("pushq %0" :: "r" (w));
|
||||
asm volatile ("pushq %0" :: "r" (usp));
|
||||
w = 1 << 9;
|
||||
asm volatile ("pushq %0" :: "r" (w));
|
||||
w = 48 + 3;
|
||||
asm volatile ("pushq %0" :: "r" (w));
|
||||
asm volatile ("pushq %0" :: "r" (k->sa.sa_handler));
|
||||
asm volatile ("iretq");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(rt_sigreturn)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current);
|
||||
char *kspbottom;
|
||||
asm volatile ("movq %%gs:132,%0" : "=r" (kspbottom));
|
||||
memcpy(kspbottom - 120, proc->sigstack, 120);
|
||||
|
||||
return proc->sigrc;
|
||||
}
|
||||
|
||||
|
||||
SYSCALL_DECLARE(rt_sigprocmask)
|
||||
{
|
||||
// kprintf("sys_rt_sigprocmask called. returning zero...\n");
|
||||
@ -1129,6 +1227,7 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
|
||||
cpu_enable_interrupt();
|
||||
|
||||
|
||||
#if 0
|
||||
if(num != 24) // if not sched_yield
|
||||
#endif
|
||||
@ -1170,7 +1269,9 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
ihk_mc_syscall_sp(ctx));
|
||||
l = syscall_generic_forwarding(num, ctx);
|
||||
}
|
||||
|
||||
|
||||
check_signal(l);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user