I was trying to add signalfd support on qemu-ppc (specifically, I'm doing a configure with "--enable-debug-tcg --enable-debug --disable-strip --disable-kvm --disable-bsd-user --disable-darwin-user --enable-profiler --target-list=ppc-linux-user --disable-curl --enable-nptl").
At first I thought that it should be straightforward, so I simply added the syscall to the "do_syscall" code. See the patch at the end. The test program used is the example that can be found on the signalfd(2) manpage. It fails with a "qemu: Unsupported syscall: 313"... but the syscall 313 IS supported (it's the splice syscall, which the configure detects and enables the CONFIG_SPLICE and it seems correct). I checked with a splice-specific test --it worked as it should. I debugged a bit and it seems that the switch ignores this syscall, but only when this 313 syscall is called from inside the signalfd syscall (it seems that internally signalfd calls a splice). I am completely lost, I was hoping that somebody could point me some directions. diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 2bf9e7e..bcf527f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -57,6 +57,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <sys/sysinfo.h> #include <sys/utsname.h> //#include <sys/user.h> +#include <sys/signalfd.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <linux/wireless.h> @@ -198,12 +199,14 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_inotify_init __NR_inotify_init #define __NR_sys_inotify_add_watch __NR_inotify_add_watch #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch +#define __NR_sys_signalfd __NR_signalfd #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \ defined(__s390x__) #define __NR__llseek __NR_lseek #endif +_syscall3(int, sys_signalfd, int, fd, const sigset_t * , mask , int, flags); #ifdef __NR_gettid _syscall0(int, gettid) #else @@ -8141,6 +8144,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; } #endif + case TARGET_NR_signalfd: + { + sigset_t set, *set_ptr; + + if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) + goto efault; + target_to_host_old_sigset(&set, p); + set_ptr = &set; + ret = get_errno(sys_signalfd(arg1,set_ptr,arg3) ); + break; + } default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num);