support sigqueue

This commit is contained in:
Tomoki Shirasawa
2014-09-23 23:17:53 +09:00
parent 55aeceb1bf
commit 39f36120c1
12 changed files with 188 additions and 38 deletions

View File

@@ -405,7 +405,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 sig, void *regs); void set_signal(int sig, void *regs, struct siginfo *info);
void check_signal(unsigned long rc, void *regs); void check_signal(unsigned long rc, void *regs);
extern void tlb_flush_handler(int vector); extern void tlb_flush_handler(int vector);
@@ -452,10 +452,13 @@ void handle_interrupt(int vector, struct x86_regs *regs)
void gpe_handler(struct x86_regs *regs) void gpe_handler(struct x86_regs *regs)
{ {
struct siginfo info;
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); memset(&info, '\0', sizeof info);
set_signal(SIGILL, regs, &info);
check_signal(0, regs); check_signal(0, regs);
check_need_resched(); check_need_resched();
// panic("GPF"); // panic("GPF");

View File

@@ -36,13 +36,13 @@ struct sigaction {
sigset_t sa_mask; sigset_t sa_mask;
}; };
#define SA_NOCLDSTOP 0x00000001u #define SA_NOCLDSTOP 0x00000001U
#define SA_NOCLDWAIT 0x00000002u #define SA_NOCLDWAIT 0x00000002U
#define SA_NODEFER 0x40000000u #define SA_NODEFER 0x40000000U
#define SA_ONSTACK 0x08000000u #define SA_ONSTACK 0x08000000U
#define SA_RESETHAND 0x80000000u #define SA_RESETHAND 0x80000000U
#define SA_RESTART 0x10000000u #define SA_RESTART 0x10000000U
#define SA_SIGINFO 0x00000004u #define SA_SIGINFO 0x00000004U
struct k_sigaction { struct k_sigaction {
struct sigaction sa; struct sigaction sa;
@@ -71,6 +71,16 @@ typedef struct siginfo {
int si_errno; /* If non-zero, an errno value associated with int si_errno; /* If non-zero, an errno value associated with
this signal, as defined in <errno.h>. */ this signal, as defined in <errno.h>. */
int si_code; /* Signal code. */ int si_code; /* Signal code. */
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
#define SI_QUEUE -1 /* sent by sigqueue */
#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change
*/
#define SI_ASYNCIO -4 /* sent by AIO completion */
#define SI_SIGIO -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */
#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
union { union {
int _pad[__SI_PAD_SIZE]; int _pad[__SI_PAD_SIZE];
@@ -117,6 +127,29 @@ typedef struct siginfo {
} _sifields; } _sifields;
} siginfo_t; } siginfo_t;
struct signalfd_siginfo {
unsigned int ssi_signo;
int ssi_errno;
int ssi_code;
unsigned int ssi_pid;
unsigned int ssi_uid;
int ssi_fd;
unsigned int ssi_tid;
unsigned int ssi_band;
unsigned int ssi_overrun;
unsigned int ssi_trapno;
int ssi_status;
int ssi_int;
unsigned long ssi_ptr;
unsigned long ssi_utime;
unsigned long ssi_stime;
unsigned long ssi_addr;
unsigned short ssi_addr_lsb;
char __pad[46];
};
#define SIGHUP 1 #define SIGHUP 1
#define SIGINT 2 #define SIGINT 2
#define SIGQUIT 3 #define SIGQUIT 3

View File

@@ -84,6 +84,8 @@ SYSCALL_HANDLED(218, set_tid_address)
SYSCALL_HANDLED(231, exit_group) SYSCALL_HANDLED(231, exit_group)
SYSCALL_HANDLED(234, tgkill) SYSCALL_HANDLED(234, tgkill)
SYSCALL_HANDLED(273, set_robust_list) SYSCALL_HANDLED(273, set_robust_list)
SYSCALL_HANDLED(282, signalfd)
SYSCALL_HANDLED(289, signalfd4)
#ifdef DCFA_KMOD #ifdef DCFA_KMOD
SYSCALL_HANDLED(303, mod_call) SYSCALL_HANDLED(303, mod_call)
#endif #endif

View File

@@ -135,6 +135,7 @@ struct sigsp {
unsigned long sigrc; unsigned long sigrc;
unsigned long sigmask; unsigned long sigmask;
int ssflags; int ssflags;
siginfo_t info;
}; };
SYSCALL_DECLARE(rt_sigreturn) SYSCALL_DECLARE(rt_sigreturn)
@@ -157,7 +158,7 @@ SYSCALL_DECLARE(rt_sigreturn)
} }
extern struct cpu_local_var *clv; extern struct cpu_local_var *clv;
extern unsigned long do_kill(int pid, int tid, int sig); extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info);
extern void interrupt_syscall(int all, int pid); extern void interrupt_syscall(int all, int pid);
extern int num_processors; extern int num_processors;
@@ -253,12 +254,17 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
} }
sigsp->sigmask = mask; sigsp->sigmask = mask;
sigsp->ssflags = ssflags; sigsp->ssflags = ssflags;
memcpy(&sigsp->info, &pending->info, sizeof(siginfo_t));
usp = (unsigned long *)sigsp; usp = (unsigned long *)sigsp;
usp--; usp--;
*usp = (unsigned long)k->sa.sa_restorer; *usp = (unsigned long)k->sa.sa_restorer;
regs->rdi = (unsigned long)sig; regs->rdi = (unsigned long)sig;
if(k->sa.sa_flags & SA_SIGINFO){
regs->rsi = (unsigned long)&sigsp->info;
regs->rdx = 0;
}
regs->rip = (unsigned long)k->sa.sa_handler; regs->rip = (unsigned long)k->sa.sa_handler;
regs->rsp = (unsigned long)usp; regs->rsp = (unsigned long)usp;
@@ -374,7 +380,7 @@ check_signal(unsigned long rc, void *regs0)
} }
unsigned long unsigned long
do_kill(int pid, int tid, int sig) do_kill(int pid, int tid, int sig, siginfo_t *info)
{ {
struct cpu_local_var *v; struct cpu_local_var *v;
struct process *p; struct process *p;
@@ -435,9 +441,9 @@ do_kill(int pid, int tid, int sig)
ihk_mc_spinlock_unlock(&(v->runq_lock), irqstate); ihk_mc_spinlock_unlock(&(v->runq_lock), irqstate);
} }
for(i = 0; i < n; i++) for(i = 0; i < n; i++)
rc = do_kill(pids[i], -1, sig); rc = do_kill(pids[i], -1, sig, info);
if(sendme) if(sendme)
rc = do_kill(proc->pid, -1, sig); rc = do_kill(proc->pid, -1, sig, info);
kfree(pids); kfree(pids);
return rc; return rc;
@@ -563,11 +569,12 @@ do_kill(int pid, int tid, int sig)
if(pending == NULL){ if(pending == NULL){
doint = 1; doint = 1;
pending = kmalloc(sizeof(struct sig_pending), IHK_MC_AP_NOWAIT); pending = kmalloc(sizeof(struct sig_pending), IHK_MC_AP_NOWAIT);
pending->sigmask.__val[0] = mask;
if(!pending){ if(!pending){
rc = -ENOMEM; rc = -ENOMEM;
} }
else{ else{
pending->sigmask.__val[0] = mask;
memcpy(&pending->info, info, sizeof(siginfo_t));
list_add_tail(&pending->list, head); list_add_tail(&pending->list, head);
tproc->sigevent = 1; tproc->sigevent = 1;
} }
@@ -625,7 +632,7 @@ do_kill(int pid, int tid, int sig)
} }
void void
set_signal(int sig, void *regs0) set_signal(int sig, void *regs0, siginfo_t *info)
{ {
struct x86_regs *regs = regs0; struct x86_regs *regs = regs0;
struct process *proc = cpu_local_var(current); struct process *proc = cpu_local_var(current);
@@ -639,5 +646,5 @@ set_signal(int sig, void *regs0)
terminate(0, sig | 0x80, (ihk_mc_user_context_t *)regs->rsp); terminate(0, sig | 0x80, (ihk_mc_user_context_t *)regs->rsp);
} }
else else
do_kill(proc->pid, proc->tid, sig); do_kill(proc->pid, proc->tid, sig, info);
} }

View File

@@ -153,6 +153,7 @@ struct signal_desc {
int pid; int pid;
int tid; int tid;
int sig; int sig;
char info[128];
}; };
#endif #endif

View File

@@ -270,27 +270,57 @@ static long mcexec_start_image(ihk_os_t os,
return 0; return 0;
} }
static DECLARE_WAIT_QUEUE_HEAD(signalq);
static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam) static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam)
{ {
struct ikc_scd_packet isp; struct ikc_scd_packet isp;
struct mcctrl_channel *c; struct mcctrl_channel *c;
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os); struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
struct signal_desc sig; struct signal_desc sig;
struct mcctrl_signal msig[2];
struct mcctrl_signal *msigp;
int rc;
if (copy_from_user(&sig, sigparam, sizeof(struct signal_desc))) { if (copy_from_user(&sig, sigparam, sizeof(struct signal_desc))) {
return -EFAULT; return -EFAULT;
} }
msigp = msig;
if(((unsigned long)msig & 0xfffffffffffff000L) !=
((unsigned long)(msig + 1) & 0xfffffffffffff000L))
msigp++;
memset(msigp, '\0', sizeof msig);
msigp->sig = sig.sig;
msigp->pid = sig.pid;
msigp->tid = sig.tid;
memcpy(&msigp->info, &sig.info, 128);
c = usrdata->channels; c = usrdata->channels;
isp.msg = SCD_MSG_SEND_SIGNAL; isp.msg = SCD_MSG_SEND_SIGNAL;
isp.ref = sig.cpu; isp.ref = sig.cpu;
isp.pid = sig.pid; isp.pid = sig.pid;
isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL); isp.arg = virt_to_phys(msigp);
mcctrl_ikc_send(os, sig.cpu, &isp); if((rc = mcctrl_ikc_send(os, sig.cpu, &isp)) < 0){
printk("mcexec_send_signal: mcctrl_ikc_send ret=%d\n", rc);
return rc;
}
wait_event_interruptible(signalq, msigp->cond != 0);
return 0; return 0;
} }
void
sig_done(unsigned long arg, int err)
{
struct mcctrl_signal *msigp;
msigp = phys_to_virt(arg);
msigp->cond = 1;
wake_up_interruptible(&signalq);
}
static long mcexec_get_cpu(ihk_os_t os) static long mcexec_get_cpu(ihk_os_t os)
{ {
struct ihk_cpu_info *info; struct ihk_cpu_info *info;

View File

@@ -44,6 +44,7 @@ int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg);
void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg); void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg);
void procfs_delete(void *__os, int osnum, unsigned long arg); void procfs_delete(void *__os, int osnum, unsigned long arg);
void procfs_answer(unsigned long arg, int err); void procfs_answer(unsigned long arg, int err);
void sig_done(unsigned long arg, int err);
static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
void *__packet, void *__os) void *__packet, void *__os)
@@ -79,8 +80,11 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
case SCD_MSG_PROCFS_ANSWER: case SCD_MSG_PROCFS_ANSWER:
procfs_answer(pisp->arg, pisp->err); procfs_answer(pisp->arg, pisp->err);
break; break;
}
case SCD_MSG_SEND_SIGNAL:
sig_done(pisp->arg, pisp->err);
break;
}
return 0; return 0;
} }

View File

@@ -145,6 +145,14 @@ struct mcctrl_usrdata {
void **keys; void **keys;
}; };
struct mcctrl_signal {
int cond;
int sig;
int pid;
int tid;
char info[128];
};
int mcctrl_ikc_send(ihk_os_t os, int cpu, struct ikc_scd_packet *pisp); int mcctrl_ikc_send(ihk_os_t os, int cpu, struct ikc_scd_packet *pisp);
int mcctrl_ikc_send_msg(ihk_os_t os, int cpu, int msg, int ref, unsigned long arg); int mcctrl_ikc_send_msg(ihk_os_t os, int cpu, int msg, int ref, unsigned long arg);
int mcctrl_ikc_is_valid_thread(ihk_os_t os, int cpu); int mcctrl_ikc_is_valid_thread(ihk_os_t os, int cpu);

View File

@@ -820,6 +820,7 @@ sendsig(int sig, siginfo_t *siginfo, void *context)
sigdesc.pid = (int)pid; sigdesc.pid = (int)pid;
sigdesc.tid = remote_tid; sigdesc.tid = remote_tid;
sigdesc.sig = sig; sigdesc.sig = sig;
memcpy(&sigdesc.info, siginfo, 128);
if (ioctl(fd, MCEXEC_UP_SEND_SIGNAL, &sigdesc) != 0) { if (ioctl(fd, MCEXEC_UP_SEND_SIGNAL, &sigdesc) != 0) {
perror("send_signal"); perror("send_signal");
close(fd); close(fd);

View File

@@ -496,7 +496,7 @@ static void syscall_channel_send(struct ihk_ikc_channel_desc *c,
ihk_ikc_send(c, packet, 0); ihk_ikc_send(c, packet, 0);
} }
extern unsigned long do_kill(int, int, int); extern unsigned long do_kill(int, int, int, struct siginfo *);
extern void settid(struct process *proc, int mode, int newcpuid, int oldcpuid); extern void settid(struct process *proc, int mode, int newcpuid, int oldcpuid);
extern void process_procfs_request(unsigned long rarg); extern void process_procfs_request(unsigned long rarg);
@@ -508,6 +508,14 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
struct ikc_scd_packet pckt; struct ikc_scd_packet pckt;
int rc; int rc;
struct process *proc; struct process *proc;
struct mcctrl_signal {
int cond;
int sig;
int pid;
int tid;
struct siginfo info;
} *sp, info;
unsigned long pp;
switch (packet->msg) { switch (packet->msg) {
case SCD_MSG_INIT_CHANNEL_ACKED: case SCD_MSG_INIT_CHANNEL_ACKED:
@@ -540,8 +548,19 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
//cpu_local_var(next) = (struct process *)packet->arg; //cpu_local_var(next) = (struct process *)packet->arg;
return 0; return 0;
case SCD_MSG_SEND_SIGNAL: case SCD_MSG_SEND_SIGNAL:
rc = do_kill((int)packet->pid, (int)(packet->arg >> 32), packet->arg & 0x00000000ffffffffL); pp = ihk_mc_map_memory(NULL, packet->arg, sizeof(struct mcctrl_signal));
kprintf("SCD_MSG_SEND_SIGNAL: %lx, rc=%d\n", packet->arg, rc); sp = (struct mcctrl_signal *)ihk_mc_map_virtual(pp, 1, PTATTR_WRITABLE | PTATTR_ACTIVE);
memcpy(&info, sp, sizeof(struct mcctrl_signal));
ihk_mc_unmap_virtual(sp, 1, 0);
ihk_mc_unmap_memory(NULL, pp, sizeof(struct mcctrl_signal));
pckt.msg = SCD_MSG_SEND_SIGNAL;
pckt.err = 0;
pckt.ref = packet->ref;
pckt.arg = packet->arg;
syscall_channel_send(c, &pckt);
rc = do_kill(info.pid, info.tid, info.sig, &info.info);
kprintf("SCD_MSG_SEND_SIGNAL: do_kill(pid=%d, tid=%d, sig=%d)=%d\n", info.pid, info.tid, info.sig, rc);
return 0; return 0;
case SCD_MSG_PROCFS_REQUEST: case SCD_MSG_PROCFS_REQUEST:
process_procfs_request(packet->arg); process_procfs_request(packet->arg);

View File

@@ -168,7 +168,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = {
.priv = NULL, .priv = NULL,
}; };
void set_signal(int sig, void *regs); void set_signal(int sig, void *regs, struct siginfo *info);
void check_signal(unsigned long rc, void *regs); void check_signal(unsigned long rc, void *regs);
int gencore(struct process *, void *, struct coretable **, int *); int gencore(struct process *, void *, struct coretable **, int *);
void freecore(struct coretable **); void freecore(struct coretable **);
@@ -371,16 +371,19 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
error = page_fault_process(proc, fault_addr, reason); error = page_fault_process(proc, fault_addr, reason);
if (error) { if (error) {
struct siginfo info;
kprintf("[%d]page_fault_handler(%p,%lx,%p):" kprintf("[%d]page_fault_handler(%p,%lx,%p):"
"fault proc failed. %d\n", "fault proc failed. %d\n",
ihk_mc_get_processor_id(), fault_addr, ihk_mc_get_processor_id(), fault_addr,
reason, regs, error); reason, regs, error);
unhandled_page_fault(proc, fault_addr, regs); unhandled_page_fault(proc, fault_addr, regs);
memset(&info, '\0', sizeof info);
if (error == -ERANGE) { if (error == -ERANGE) {
set_signal(SIGBUS, regs); set_signal(SIGBUS, regs, &info);
} }
else { else {
set_signal(SIGSEGV, regs); set_signal(SIGSEGV, regs, &info);
} }
check_signal(0, regs); check_signal(0, regs);
goto out; goto out;

View File

@@ -95,7 +95,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
void check_signal(unsigned long rc, void *regs); void check_signal(unsigned long rc, void *regs);
void do_signal(long rc, void *regs, struct process *proc, struct sig_pending *pending); void do_signal(long rc, void *regs, struct process *proc, struct sig_pending *pending);
extern unsigned long do_kill(int pid, int tid, int sig); extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info);
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);
void do_setpgid(int, int); void do_setpgid(int, int);
@@ -460,7 +460,13 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
/* Signal parent if still attached */ /* Signal parent if still attached */
ihk_mc_spinlock_lock_noirq(&ftn->parent->lock); ihk_mc_spinlock_lock_noirq(&ftn->parent->lock);
if (ftn->parent->owner) { if (ftn->parent->owner) {
do_kill(ftn->parent->owner->pid, -1, SIGCHLD); struct siginfo info;
memset(&info, '\0', sizeof info);
info.si_signo = SIGCHLD;
info.si_code = sig? ((sig & 0x80)? 3: 2): 1;
info._sifields._sigchld.si_pid = proc->pid;
info._sifields._sigchld.si_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
do_kill(ftn->parent->owner->pid, -1, SIGCHLD, &info);
/* /*
sigchld_parent(ftn->parent->owner, 0); sigchld_parent(ftn->parent->owner, 0);
*/ */
@@ -1513,8 +1519,15 @@ SYSCALL_DECLARE(kill)
{ {
int pid = ihk_mc_syscall_arg0(ctx); int pid = ihk_mc_syscall_arg0(ctx);
int sig = ihk_mc_syscall_arg1(ctx); int sig = ihk_mc_syscall_arg1(ctx);
struct process *proc = cpu_local_var(current);
struct siginfo info;
return do_kill(pid, -1, sig); memset(&info, '\0', sizeof info);
info.si_signo = sig;
info.si_code = SI_USER;
info._sifields._kill.si_pid = proc->pid;
return do_kill(pid, -1, sig, &info);
} }
// see linux-2.6.34.13/kernel/signal.c // see linux-2.6.34.13/kernel/signal.c
@@ -1523,13 +1536,20 @@ SYSCALL_DECLARE(tgkill)
int tgid = ihk_mc_syscall_arg0(ctx); int tgid = ihk_mc_syscall_arg0(ctx);
int tid = ihk_mc_syscall_arg1(ctx); int tid = ihk_mc_syscall_arg1(ctx);
int sig = ihk_mc_syscall_arg2(ctx); int sig = ihk_mc_syscall_arg2(ctx);
struct process *proc = cpu_local_var(current);
struct siginfo info;
memset(&info, '\0', sizeof info);
info.si_signo = sig;
info.si_code = SI_TKILL;
info._sifields._kill.si_pid = proc->pid;
if(tid <= 0) if(tid <= 0)
return -EINVAL; return -EINVAL;
if(tgid <= 0 && tgid != -1) if(tgid <= 0 && tgid != -1)
return -EINVAL; return -EINVAL;
return do_kill(tgid, tid, sig); return do_kill(tgid, tid, sig, &info);
} }
SYSCALL_DECLARE(setpgid) SYSCALL_DECLARE(setpgid)
@@ -1650,6 +1670,16 @@ SYSCALL_DECLARE(rt_sigpending)
return 0; return 0;
} }
SYSCALL_DECLARE(signalfd)
{
return -EOPNOTSUPP;
}
SYSCALL_DECLARE(signalfd4)
{
return -EOPNOTSUPP;
}
SYSCALL_DECLARE(rt_sigtimedwait) SYSCALL_DECLARE(rt_sigtimedwait)
{ {
struct process *proc = cpu_local_var(current); struct process *proc = cpu_local_var(current);
@@ -1664,29 +1694,38 @@ SYSCALL_DECLARE(rt_sigtimedwait)
if (sigsetsize > sizeof(sigset_t)) if (sigsetsize > sizeof(sigset_t))
return -EINVAL; return -EINVAL;
if(set == NULL)
return -EFAULT;
memset(&winfo, '\0', sizeof winfo); memset(&winfo, '\0', sizeof winfo);
if(copy_from_user(proc, &wset, set, sizeof wset)) if(copy_from_user(proc, &wset, set, sizeof wset))
return -EFAULT; return -EFAULT;
if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout)) if(timeout)
return -EFAULT; if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout))
if(copy_to_user(proc, info, &winfo, sizeof winfo)) return -EFAULT;
return -EFAULT;
if(info)
if(copy_to_user(proc, info, &winfo, sizeof winfo))
return -EFAULT;
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
SYSCALL_DECLARE(rt_sigqueueinfo) SYSCALL_DECLARE(rt_sigqueueinfo)
{ {
struct process *proc = cpu_local_var(current);
int pid = (int)ihk_mc_syscall_arg0(ctx); int pid = (int)ihk_mc_syscall_arg0(ctx);
int sig = (int)ihk_mc_syscall_arg1(ctx); int sig = (int)ihk_mc_syscall_arg1(ctx);
siginfo_t *info = (siginfo_t *)ihk_mc_syscall_arg2(ctx); void *winfo = (void *)ihk_mc_syscall_arg2(ctx);
siginfo_t winfo; struct process *proc = cpu_local_var(current);
struct siginfo info;
if(copy_from_user(proc, &winfo, info, sizeof winfo)) if(pid <= 0)
return -ESRCH;
if(copy_from_user(proc, &info, winfo, sizeof info))
return -EFAULT; return -EFAULT;
return -EOPNOTSUPP; return do_kill(pid, -1, sig, &info);
} }
static int static int