signal part 4 (sigsuspend etc)
This commit is contained in:
@@ -368,7 +368,7 @@ void setup_x86_ap(void (*next_func)(void))
|
|||||||
}
|
}
|
||||||
|
|
||||||
void arch_show_interrupt_context(const void *reg);
|
void arch_show_interrupt_context(const void *reg);
|
||||||
void set_signal(int, void *, int);
|
void set_signal(int, void *);
|
||||||
void check_signal(long, void *);
|
void check_signal(long, void *);
|
||||||
|
|
||||||
void handle_interrupt(int vector, struct x86_regs *regs)
|
void handle_interrupt(int vector, struct x86_regs *regs)
|
||||||
@@ -409,7 +409,7 @@ void gpe_handler(struct x86_regs *regs)
|
|||||||
kprintf("General protection fault (err: %lx, %lx:%lx)\n",
|
kprintf("General protection fault (err: %lx, %lx:%lx)\n",
|
||||||
regs->error, regs->cs, regs->rip);
|
regs->error, regs->cs, regs->rip);
|
||||||
arch_show_interrupt_context(regs);
|
arch_show_interrupt_context(regs);
|
||||||
set_signal(SIGILL, regs, 1);
|
set_signal(SIGILL, regs);
|
||||||
check_signal(0, regs);
|
check_signal(0, regs);
|
||||||
// panic("GPF");
|
// panic("GPF");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,16 @@ struct sigaction {
|
|||||||
sigset_t sa_mask;
|
sigset_t sa_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//// work in progress
|
||||||
|
struct sigbackup {
|
||||||
|
unsigned long rc; // return code of rt_sigreturn (rax)
|
||||||
|
void *uctx;
|
||||||
|
sigset_t mask;
|
||||||
|
double fpregs[16];
|
||||||
|
|
||||||
|
};
|
||||||
|
////
|
||||||
|
|
||||||
struct k_sigaction {
|
struct k_sigaction {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ SYSCALL_DELEGATED(20, writev)
|
|||||||
SYSCALL_DELEGATED(21, access)
|
SYSCALL_DELEGATED(21, access)
|
||||||
SYSCALL_HANDLED(24, sched_yield)
|
SYSCALL_HANDLED(24, sched_yield)
|
||||||
SYSCALL_HANDLED(28, madvise)
|
SYSCALL_HANDLED(28, madvise)
|
||||||
|
SYSCALL_HANDLED(34, pause)
|
||||||
SYSCALL_HANDLED(39, getpid)
|
SYSCALL_HANDLED(39, getpid)
|
||||||
SYSCALL_HANDLED(56, clone)
|
SYSCALL_HANDLED(56, clone)
|
||||||
SYSCALL_HANDLED(59, execve)
|
SYSCALL_HANDLED(59, execve)
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ SYSCALL_DECLARE(rt_sigreturn)
|
|||||||
regs -= 16;
|
regs -= 16;
|
||||||
memcpy(regs, proc->sigstack, 128);
|
memcpy(regs, proc->sigstack, 128);
|
||||||
|
|
||||||
|
proc->sigmask.__val[0] = proc->supmask.__val[0];
|
||||||
|
|
||||||
return proc->sigrc;
|
return proc->sigrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,58 +106,18 @@ extern void interrupt_syscall(int all);
|
|||||||
extern int num_processors;
|
extern int num_processors;
|
||||||
|
|
||||||
void
|
void
|
||||||
check_signal(unsigned long rc, unsigned long *regs)
|
do_signal(unsigned long rc, unsigned long *regs, struct process *proc, struct sig_pending *pending)
|
||||||
{
|
{
|
||||||
struct process *proc;
|
|
||||||
struct k_sigaction *k;
|
struct k_sigaction *k;
|
||||||
int sig;
|
int sig;
|
||||||
struct sig_pending *pending;
|
|
||||||
struct sig_pending *next;
|
|
||||||
struct list_head *head;
|
|
||||||
ihk_spinlock_t *lock;
|
|
||||||
__sigset_t w;
|
__sigset_t w;
|
||||||
int irqstate;
|
int irqstate;
|
||||||
|
|
||||||
if(clv == NULL)
|
|
||||||
return;
|
|
||||||
proc = cpu_local_var(current);
|
|
||||||
if(proc == NULL || proc->pid == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
w = proc->sigmask.__val[0];
|
|
||||||
lock = &proc->sigshared->lock;
|
|
||||||
head = &proc->sigshared->sigpending;
|
|
||||||
pending = NULL;
|
|
||||||
irqstate = ihk_mc_spinlock_lock(lock);
|
|
||||||
list_for_each_entry_safe(pending, next, head, list){
|
|
||||||
if(!(pending->sigmask.__val[0] & w)){
|
|
||||||
list_del(&pending->list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(&pending->list == head)
|
|
||||||
pending = NULL;
|
|
||||||
ihk_mc_spinlock_unlock(lock, irqstate);
|
|
||||||
|
|
||||||
if(!pending){
|
|
||||||
lock = &proc->sigpendinglock;
|
|
||||||
head = &proc->sigpending;
|
|
||||||
irqstate = ihk_mc_spinlock_lock(lock);
|
|
||||||
list_for_each_entry_safe(pending, next, head, list){
|
|
||||||
if(!(pending->sigmask.__val[0] & w)){
|
|
||||||
list_del(&pending->list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(&pending->list == head)
|
|
||||||
pending = NULL;
|
|
||||||
ihk_mc_spinlock_unlock(lock, irqstate);
|
|
||||||
}
|
|
||||||
if(!pending)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||||
|
|
||||||
|
if(sig == SIGKILL || sig == SIGTERM)
|
||||||
|
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
||||||
|
|
||||||
irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock);
|
||||||
if(regs == NULL){ /* call from syscall */
|
if(regs == NULL){ /* call from syscall */
|
||||||
asm volatile ("movq %%gs:132,%0" : "=r" (regs));
|
asm volatile ("movq %%gs:132,%0" : "=r" (regs));
|
||||||
@@ -174,14 +136,6 @@ check_signal(unsigned long rc, unsigned long *regs)
|
|||||||
else if(k->sa.sa_handler){
|
else if(k->sa.sa_handler){
|
||||||
unsigned long *usp; /* user stack */
|
unsigned long *usp; /* user stack */
|
||||||
|
|
||||||
if(regs[14] & 0x8000000000000000){ // kernel addr
|
|
||||||
int flag = ihk_mc_spinlock_lock(lock);
|
|
||||||
list_add(&pending->list, head);
|
|
||||||
ihk_mc_spinlock_unlock(lock, flag);
|
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
usp = (void *)regs[14];
|
usp = (void *)regs[14];
|
||||||
memcpy(proc->sigstack, regs, 128);
|
memcpy(proc->sigstack, regs, 128);
|
||||||
proc->sigrc = rc;
|
proc->sigrc = rc;
|
||||||
@@ -192,6 +146,7 @@ check_signal(unsigned long rc, unsigned long *regs)
|
|||||||
regs[11] = (unsigned long)k->sa.sa_handler;
|
regs[11] = (unsigned long)k->sa.sa_handler;
|
||||||
regs[14] = (unsigned long)usp;
|
regs[14] = (unsigned long)usp;
|
||||||
kfree(pending);
|
kfree(pending);
|
||||||
|
proc->sigmask.__val[0] |= pending->sigmask.__val[0];
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -203,6 +158,63 @@ check_signal(unsigned long rc, unsigned long *regs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_signal(unsigned long rc, unsigned long *regs)
|
||||||
|
{
|
||||||
|
struct process *proc;
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct sig_pending *next;
|
||||||
|
struct list_head *head;
|
||||||
|
ihk_spinlock_t *lock;
|
||||||
|
__sigset_t w;
|
||||||
|
int irqstate;
|
||||||
|
|
||||||
|
if(clv == NULL)
|
||||||
|
return;
|
||||||
|
proc = cpu_local_var(current);
|
||||||
|
if(proc == NULL || proc->pid == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(regs != NULL && (regs[14] & 0x8000000000000000))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
w = proc->sigmask.__val[0];
|
||||||
|
lock = &proc->sigshared->lock;
|
||||||
|
head = &proc->sigshared->sigpending;
|
||||||
|
pending = NULL;
|
||||||
|
irqstate = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry_safe(pending, next, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & w)){
|
||||||
|
list_del(&pending->list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(&pending->list == head)
|
||||||
|
pending = NULL;
|
||||||
|
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||||
|
|
||||||
|
if(!pending){
|
||||||
|
lock = &proc->sigpendinglock;
|
||||||
|
head = &proc->sigpending;
|
||||||
|
irqstate = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry_safe(pending, next, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & w)){
|
||||||
|
list_del(&pending->list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(&pending->list == head)
|
||||||
|
pending = NULL;
|
||||||
|
ihk_mc_spinlock_unlock(lock, irqstate);
|
||||||
|
}
|
||||||
|
if(!pending)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do_signal(rc, regs, proc, pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long
|
unsigned long
|
||||||
do_kill(int pid, int tid, int sig)
|
do_kill(int pid, int tid, int sig)
|
||||||
{
|
{
|
||||||
@@ -284,6 +296,7 @@ do_kill(int pid, int tid, int sig)
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
list_add_tail(&pending->list, head);
|
list_add_tail(&pending->list, head);
|
||||||
|
proc->sigevent = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(tid == -1){
|
if(tid == -1){
|
||||||
@@ -297,17 +310,16 @@ do_kill(int pid, int tid, int sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_signal(int sig, unsigned long *regs, int nonmaskable)
|
set_signal(int sig, unsigned long *regs)
|
||||||
{
|
{
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
|
|
||||||
if(proc == NULL || proc->pid == 0)
|
if(proc == NULL || proc->pid == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(__sigmask(sig) & proc->sigmask.__val[0]){
|
if((__sigmask(sig) & proc->sigmask.__val[0]) ||
|
||||||
if(nonmaskable){
|
(regs[14] & 0x8000000000000000))
|
||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
terminate(0, sig, (ihk_mc_user_context_t *)regs[14]);
|
||||||
}
|
else
|
||||||
}
|
do_kill(proc->pid, proc->tid, sig);
|
||||||
do_kill(proc->pid, proc->tid, sig);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = {
|
|||||||
.priv = NULL,
|
.priv = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_signal(int, unsigned long *, int);
|
void set_signal(int, unsigned long *);
|
||||||
void check_signal(long, unsigned long *);
|
void check_signal(long, unsigned long *);
|
||||||
|
|
||||||
static void unhandled_page_fault(struct process *proc, void *fault_addr, void *regs)
|
static void unhandled_page_fault(struct process *proc, void *fault_addr, void *regs)
|
||||||
@@ -234,10 +234,10 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
|
|||||||
reason, regs, error);
|
reason, regs, error);
|
||||||
unhandled_page_fault(proc, fault_addr, regs);
|
unhandled_page_fault(proc, fault_addr, regs);
|
||||||
if (error == -ERANGE) {
|
if (error == -ERANGE) {
|
||||||
set_signal(SIGBUS, regs, 1);
|
set_signal(SIGBUS, regs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_signal(SIGSEGV, regs, 1);
|
set_signal(SIGSEGV, regs);
|
||||||
}
|
}
|
||||||
check_signal(0, regs);
|
check_signal(0, regs);
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
134
kernel/syscall.c
134
kernel/syscall.c
@@ -93,6 +93,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void check_signal(long rc, unsigned long *regs);
|
void check_signal(long rc, unsigned long *regs);
|
||||||
|
void do_signal(long rc, unsigned long *regs, struct process *proc, struct sig_pending *pending);
|
||||||
int copy_from_user(struct process *, void *, const void *, size_t);
|
int copy_from_user(struct process *, void *, const void *, size_t);
|
||||||
int copy_to_user(struct process *, void *, const void *, size_t);
|
int copy_to_user(struct process *, void *, const void *, size_t);
|
||||||
|
|
||||||
@@ -1154,37 +1155,132 @@ SYSCALL_DECLARE(rt_sigpending)
|
|||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigtimedwait)
|
SYSCALL_DECLARE(rt_sigtimedwait)
|
||||||
{
|
{
|
||||||
/*
|
struct process *proc = cpu_local_var(current);
|
||||||
sigset_t *
|
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg0(ctx);
|
||||||
siginfo_t *
|
siginfo_t *info = (siginfo_t *)ihk_mc_syscall_arg1(ctx);
|
||||||
struct timespec *
|
void *timeout = (void *)ihk_mc_syscall_arg2(ctx);
|
||||||
size_t
|
size_t sigsetsize = (size_t)ihk_mc_syscall_arg3(ctx);
|
||||||
*/
|
siginfo_t winfo;
|
||||||
return 0;
|
__sigset_t wset;
|
||||||
|
long wtimeout[2];
|
||||||
|
|
||||||
|
if (sigsetsize > sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&winfo, '\0', sizeof winfo);
|
||||||
|
if(copy_from_user(proc, &wset, set, sizeof wset))
|
||||||
|
return -EFAULT;
|
||||||
|
if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout))
|
||||||
|
return -EFAULT;
|
||||||
|
if(copy_to_user(proc, info, &winfo, sizeof winfo))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigqueueinfo)
|
SYSCALL_DECLARE(rt_sigqueueinfo)
|
||||||
{
|
{
|
||||||
/*
|
struct process *proc = cpu_local_var(current);
|
||||||
pid_t
|
int pid = (int)ihk_mc_syscall_arg0(ctx);
|
||||||
int
|
int sig = (int)ihk_mc_syscall_arg1(ctx);
|
||||||
siginfo_t *
|
siginfo_t *info = (siginfo_t *)ihk_mc_syscall_arg2(ctx);
|
||||||
*/
|
siginfo_t winfo;
|
||||||
return 0;
|
|
||||||
|
if(copy_from_user(proc, &winfo, info, sizeof winfo))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_sigsuspend(struct process *proc, const sigset_t *set)
|
||||||
|
{
|
||||||
|
__sigset_t wset;
|
||||||
|
int flag;
|
||||||
|
struct sig_pending *pending;
|
||||||
|
struct list_head *head;
|
||||||
|
ihk_spinlock_t *lock;
|
||||||
|
|
||||||
|
wset = set->__val[0];
|
||||||
|
wset &= ~__sigmask(SIGKILL);
|
||||||
|
wset &= ~__sigmask(SIGTERM);
|
||||||
|
proc->sigmask.__val[0] = wset;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
while(proc->sigevent == 0);
|
||||||
|
proc->sigevent = 0;
|
||||||
|
|
||||||
|
lock = &proc->sigshared->lock;
|
||||||
|
head = &proc->sigshared->sigpending;
|
||||||
|
flag = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry(pending, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & wset))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(&pending->list == head){
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
|
||||||
|
lock = &proc->sigpendinglock;
|
||||||
|
head = &proc->sigpending;
|
||||||
|
flag = ihk_mc_spinlock_lock(lock);
|
||||||
|
list_for_each_entry(pending, head, list){
|
||||||
|
if(!(pending->sigmask.__val[0] & wset))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(&pending->list == head){
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_del(&pending->list);
|
||||||
|
ihk_mc_spinlock_unlock(lock, flag);
|
||||||
|
do_signal(-EINTR, NULL, proc, pending);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SYSCALL_DECLARE(pause)
|
||||||
|
{
|
||||||
|
struct process *proc = cpu_local_var(current);
|
||||||
|
|
||||||
|
return do_sigsuspend(proc, &proc->sigmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(rt_sigsuspend)
|
SYSCALL_DECLARE(rt_sigsuspend)
|
||||||
{
|
{
|
||||||
/*
|
struct process *proc = cpu_local_var(current);
|
||||||
sigset_t *
|
const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg0(ctx);
|
||||||
size_t
|
size_t sigsetsize = (size_t)ihk_mc_syscall_arg1(ctx);
|
||||||
*/
|
sigset_t wset;
|
||||||
return 0;
|
|
||||||
|
if (sigsetsize > sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
if(copy_from_user(proc, &wset, set, sizeof wset))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return do_sigsuspend(proc, &wset);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(sigaltstack)
|
SYSCALL_DECLARE(sigaltstack)
|
||||||
{
|
{
|
||||||
return 0;
|
struct process *proc = cpu_local_var(current);
|
||||||
|
const stack_t *ss = (const stack_t *)ihk_mc_syscall_arg0(ctx);
|
||||||
|
stack_t *oss = (stack_t *)ihk_mc_syscall_arg1(ctx);
|
||||||
|
stack_t wss;
|
||||||
|
|
||||||
|
memset(&wss, '\0', sizeof wss);
|
||||||
|
if(oss)
|
||||||
|
if(copy_to_user(proc, oss, &wss, sizeof wss))
|
||||||
|
return -EFAULT;
|
||||||
|
if(ss)
|
||||||
|
if(copy_from_user(proc, &wss, ss, sizeof wss))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DECLARE(madvise)
|
SYSCALL_DECLARE(madvise)
|
||||||
|
|||||||
Reference in New Issue
Block a user