131e31b8aSbellard /* 266fb9763Sbellard * Emulation of Linux signals 331e31b8aSbellard * 431e31b8aSbellard * Copyright (c) 2003 Fabrice Bellard 531e31b8aSbellard * 631e31b8aSbellard * This program is free software; you can redistribute it and/or modify 731e31b8aSbellard * it under the terms of the GNU General Public License as published by 831e31b8aSbellard * the Free Software Foundation; either version 2 of the License, or 931e31b8aSbellard * (at your option) any later version. 1031e31b8aSbellard * 1131e31b8aSbellard * This program is distributed in the hope that it will be useful, 1231e31b8aSbellard * but WITHOUT ANY WARRANTY; without even the implied warranty of 1331e31b8aSbellard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1431e31b8aSbellard * GNU General Public License for more details. 1531e31b8aSbellard * 1631e31b8aSbellard * You should have received a copy of the GNU General Public License 1731e31b8aSbellard * along with this program; if not, write to the Free Software 1831e31b8aSbellard * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1931e31b8aSbellard */ 2031e31b8aSbellard #include <stdlib.h> 2131e31b8aSbellard #include <stdio.h> 2266fb9763Sbellard #include <string.h> 2331e31b8aSbellard #include <stdarg.h> 242677e107Sbellard #include <unistd.h> 2531e31b8aSbellard #include <signal.h> 2666fb9763Sbellard #include <errno.h> 2731e31b8aSbellard #include <sys/ucontext.h> 2831e31b8aSbellard 290d330196Sbellard #ifdef __ia64__ 300d330196Sbellard #undef uc_mcontext 310d330196Sbellard #undef uc_sigmask 320d330196Sbellard #undef uc_stack 330d330196Sbellard #undef uc_link 340d330196Sbellard #endif 350d330196Sbellard 363ef693a0Sbellard #include "qemu.h" 3766fb9763Sbellard 3866fb9763Sbellard //#define DEBUG_SIGNAL 3966fb9763Sbellard 4066fb9763Sbellard #define MAX_SIGQUEUE_SIZE 1024 4166fb9763Sbellard 4266fb9763Sbellard struct sigqueue { 4366fb9763Sbellard struct sigqueue *next; 449de5e440Sbellard target_siginfo_t info; 4566fb9763Sbellard }; 4631e31b8aSbellard 4731e31b8aSbellard struct emulated_sigaction { 4831e31b8aSbellard struct target_sigaction sa; 4966fb9763Sbellard int pending; /* true if signal is pending */ 5066fb9763Sbellard struct sigqueue *first; 5166fb9763Sbellard struct sigqueue info; /* in order to always have memory for the 5266fb9763Sbellard first signal, we put it here */ 5331e31b8aSbellard }; 5431e31b8aSbellard 5566fb9763Sbellard static struct emulated_sigaction sigact_table[TARGET_NSIG]; 5666fb9763Sbellard static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ 5766fb9763Sbellard static struct sigqueue *first_free; /* first free siginfo queue entry */ 5866fb9763Sbellard static int signal_pending; /* non zero if a signal may be pending */ 5931e31b8aSbellard 6066fb9763Sbellard static void host_signal_handler(int host_signum, siginfo_t *info, 6166fb9763Sbellard void *puc); 6266fb9763Sbellard 639e5f5284Sbellard static uint8_t host_to_target_signal_table[65] = { 649e5f5284Sbellard [SIGHUP] = TARGET_SIGHUP, 659e5f5284Sbellard [SIGINT] = TARGET_SIGINT, 669e5f5284Sbellard [SIGQUIT] = TARGET_SIGQUIT, 679e5f5284Sbellard [SIGILL] = TARGET_SIGILL, 689e5f5284Sbellard [SIGTRAP] = TARGET_SIGTRAP, 699e5f5284Sbellard [SIGABRT] = TARGET_SIGABRT, 7001e3b763Sbellard /* [SIGIOT] = TARGET_SIGIOT,*/ 719e5f5284Sbellard [SIGBUS] = TARGET_SIGBUS, 729e5f5284Sbellard [SIGFPE] = TARGET_SIGFPE, 739e5f5284Sbellard [SIGKILL] = TARGET_SIGKILL, 749e5f5284Sbellard [SIGUSR1] = TARGET_SIGUSR1, 759e5f5284Sbellard [SIGSEGV] = TARGET_SIGSEGV, 769e5f5284Sbellard [SIGUSR2] = TARGET_SIGUSR2, 779e5f5284Sbellard [SIGPIPE] = TARGET_SIGPIPE, 789e5f5284Sbellard [SIGALRM] = TARGET_SIGALRM, 799e5f5284Sbellard [SIGTERM] = TARGET_SIGTERM, 809e5f5284Sbellard #ifdef SIGSTKFLT 819e5f5284Sbellard [SIGSTKFLT] = TARGET_SIGSTKFLT, 829e5f5284Sbellard #endif 839e5f5284Sbellard [SIGCHLD] = TARGET_SIGCHLD, 849e5f5284Sbellard [SIGCONT] = TARGET_SIGCONT, 859e5f5284Sbellard [SIGSTOP] = TARGET_SIGSTOP, 869e5f5284Sbellard [SIGTSTP] = TARGET_SIGTSTP, 879e5f5284Sbellard [SIGTTIN] = TARGET_SIGTTIN, 889e5f5284Sbellard [SIGTTOU] = TARGET_SIGTTOU, 899e5f5284Sbellard [SIGURG] = TARGET_SIGURG, 909e5f5284Sbellard [SIGXCPU] = TARGET_SIGXCPU, 919e5f5284Sbellard [SIGXFSZ] = TARGET_SIGXFSZ, 929e5f5284Sbellard [SIGVTALRM] = TARGET_SIGVTALRM, 939e5f5284Sbellard [SIGPROF] = TARGET_SIGPROF, 949e5f5284Sbellard [SIGWINCH] = TARGET_SIGWINCH, 959e5f5284Sbellard [SIGIO] = TARGET_SIGIO, 969e5f5284Sbellard [SIGPWR] = TARGET_SIGPWR, 979e5f5284Sbellard [SIGSYS] = TARGET_SIGSYS, 989e5f5284Sbellard /* next signals stay the same */ 999e5f5284Sbellard }; 1009e5f5284Sbellard static uint8_t target_to_host_signal_table[65]; 1019e5f5284Sbellard 10231e31b8aSbellard static inline int host_to_target_signal(int sig) 10331e31b8aSbellard { 1049e5f5284Sbellard return host_to_target_signal_table[sig]; 10531e31b8aSbellard } 10631e31b8aSbellard 10731e31b8aSbellard static inline int target_to_host_signal(int sig) 10831e31b8aSbellard { 1099e5f5284Sbellard return target_to_host_signal_table[sig]; 11031e31b8aSbellard } 11131e31b8aSbellard 1129e5f5284Sbellard void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) 11366fb9763Sbellard { 11466fb9763Sbellard int i; 1159e5f5284Sbellard unsigned long sigmask; 1169e5f5284Sbellard uint32_t target_sigmask; 1179e5f5284Sbellard 1189e5f5284Sbellard sigmask = ((unsigned long *)s)[0]; 1199e5f5284Sbellard target_sigmask = 0; 1209e5f5284Sbellard for(i = 0; i < 32; i++) { 1219e5f5284Sbellard if (sigmask & (1 << i)) 1229e5f5284Sbellard target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1); 1239e5f5284Sbellard } 1249e5f5284Sbellard #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 1259e5f5284Sbellard d->sig[0] = tswapl(target_sigmask); 1269e5f5284Sbellard for(i = 1;i < TARGET_NSIG_WORDS; i++) { 12766fb9763Sbellard d->sig[i] = tswapl(((unsigned long *)s)[i]); 12866fb9763Sbellard } 1299e5f5284Sbellard #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 1309e5f5284Sbellard d->sig[0] = tswapl(target_sigmask); 1319e5f5284Sbellard d->sig[1] = tswapl(sigmask >> 32); 1329e5f5284Sbellard #else 1339e5f5284Sbellard #error host_to_target_sigset 1349e5f5284Sbellard #endif 13566fb9763Sbellard } 13666fb9763Sbellard 1379e5f5284Sbellard void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) 13866fb9763Sbellard { 13966fb9763Sbellard int i; 1409e5f5284Sbellard unsigned long sigmask; 1419e5f5284Sbellard target_ulong target_sigmask; 1429e5f5284Sbellard 1439e5f5284Sbellard target_sigmask = tswapl(s->sig[0]); 1449e5f5284Sbellard sigmask = 0; 1459e5f5284Sbellard for(i = 0; i < 32; i++) { 1469e5f5284Sbellard if (target_sigmask & (1 << i)) 1479e5f5284Sbellard sigmask |= 1 << (target_to_host_signal(i + 1) - 1); 1489e5f5284Sbellard } 1499e5f5284Sbellard #if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32 1509e5f5284Sbellard ((unsigned long *)d)[0] = sigmask; 1519e5f5284Sbellard for(i = 1;i < TARGET_NSIG_WORDS; i++) { 15266fb9763Sbellard ((unsigned long *)d)[i] = tswapl(s->sig[i]); 15366fb9763Sbellard } 1549e5f5284Sbellard #elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 1559dfa5b42Sbellard ((unsigned long *)d)[0] = sigmask | ((unsigned long)tswapl(s->sig[1]) << 32); 1569e5f5284Sbellard #else 1579e5f5284Sbellard #error target_to_host_sigset 1589e5f5284Sbellard #endif /* TARGET_LONG_BITS */ 15966fb9763Sbellard } 16066fb9763Sbellard 16166fb9763Sbellard void host_to_target_old_sigset(target_ulong *old_sigset, 16266fb9763Sbellard const sigset_t *sigset) 16366fb9763Sbellard { 1649e5f5284Sbellard target_sigset_t d; 1659e5f5284Sbellard host_to_target_sigset(&d, sigset); 1669e5f5284Sbellard *old_sigset = d.sig[0]; 16766fb9763Sbellard } 16866fb9763Sbellard 16966fb9763Sbellard void target_to_host_old_sigset(sigset_t *sigset, 17066fb9763Sbellard const target_ulong *old_sigset) 17166fb9763Sbellard { 1729e5f5284Sbellard target_sigset_t d; 1739e5f5284Sbellard int i; 1749e5f5284Sbellard 1759e5f5284Sbellard d.sig[0] = *old_sigset; 1769e5f5284Sbellard for(i = 1;i < TARGET_NSIG_WORDS; i++) 1779e5f5284Sbellard d.sig[i] = 0; 1789e5f5284Sbellard target_to_host_sigset(sigset, &d); 17966fb9763Sbellard } 18066fb9763Sbellard 1819de5e440Sbellard /* siginfo conversion */ 1829de5e440Sbellard 1839de5e440Sbellard static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, 1849de5e440Sbellard const siginfo_t *info) 18566fb9763Sbellard { 1869de5e440Sbellard int sig; 1879de5e440Sbellard sig = host_to_target_signal(info->si_signo); 1889de5e440Sbellard tinfo->si_signo = sig; 1899de5e440Sbellard tinfo->si_errno = 0; 1909de5e440Sbellard tinfo->si_code = 0; 191447db213Sbellard if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || 192447db213Sbellard sig == SIGBUS || sig == SIGTRAP) { 1939de5e440Sbellard /* should never come here, but who knows. The information for 1949de5e440Sbellard the target is irrelevant */ 1959de5e440Sbellard tinfo->_sifields._sigfault._addr = 0; 1969de5e440Sbellard } else if (sig >= TARGET_SIGRTMIN) { 1979de5e440Sbellard tinfo->_sifields._rt._pid = info->si_pid; 1989de5e440Sbellard tinfo->_sifields._rt._uid = info->si_uid; 1999de5e440Sbellard /* XXX: potential problem if 64 bit */ 2009de5e440Sbellard tinfo->_sifields._rt._sigval.sival_ptr = 2019de5e440Sbellard (target_ulong)info->si_value.sival_ptr; 2029de5e440Sbellard } 20366fb9763Sbellard } 20466fb9763Sbellard 2059de5e440Sbellard static void tswap_siginfo(target_siginfo_t *tinfo, 2069de5e440Sbellard const target_siginfo_t *info) 2079de5e440Sbellard { 2089de5e440Sbellard int sig; 2099de5e440Sbellard sig = info->si_signo; 2109de5e440Sbellard tinfo->si_signo = tswap32(sig); 2119de5e440Sbellard tinfo->si_errno = tswap32(info->si_errno); 2129de5e440Sbellard tinfo->si_code = tswap32(info->si_code); 213447db213Sbellard if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || 214447db213Sbellard sig == SIGBUS || sig == SIGTRAP) { 2159de5e440Sbellard tinfo->_sifields._sigfault._addr = 2169de5e440Sbellard tswapl(info->_sifields._sigfault._addr); 2179de5e440Sbellard } else if (sig >= TARGET_SIGRTMIN) { 2189de5e440Sbellard tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid); 2199de5e440Sbellard tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid); 2209de5e440Sbellard tinfo->_sifields._rt._sigval.sival_ptr = 2219de5e440Sbellard tswapl(info->_sifields._rt._sigval.sival_ptr); 2229de5e440Sbellard } 2239de5e440Sbellard } 2249de5e440Sbellard 2259de5e440Sbellard 2269de5e440Sbellard void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) 2279de5e440Sbellard { 2289de5e440Sbellard host_to_target_siginfo_noswap(tinfo, info); 2299de5e440Sbellard tswap_siginfo(tinfo, tinfo); 2309de5e440Sbellard } 2319de5e440Sbellard 2329de5e440Sbellard /* XXX: we support only POSIX RT signals are used. */ 2339de5e440Sbellard /* XXX: find a solution for 64 bit (additionnal malloced data is needed) */ 2349de5e440Sbellard void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) 23566fb9763Sbellard { 23666fb9763Sbellard info->si_signo = tswap32(tinfo->si_signo); 23766fb9763Sbellard info->si_errno = tswap32(tinfo->si_errno); 23866fb9763Sbellard info->si_code = tswap32(tinfo->si_code); 2399de5e440Sbellard info->si_pid = tswap32(tinfo->_sifields._rt._pid); 2409de5e440Sbellard info->si_uid = tswap32(tinfo->_sifields._rt._uid); 2419de5e440Sbellard info->si_value.sival_ptr = 2429de5e440Sbellard (void *)tswapl(tinfo->_sifields._rt._sigval.sival_ptr); 24366fb9763Sbellard } 24466fb9763Sbellard 24531e31b8aSbellard void signal_init(void) 24631e31b8aSbellard { 24731e31b8aSbellard struct sigaction act; 2489e5f5284Sbellard int i, j; 2499e5f5284Sbellard 2509e5f5284Sbellard /* generate signal conversion tables */ 2519e5f5284Sbellard for(i = 1; i <= 64; i++) { 2529e5f5284Sbellard if (host_to_target_signal_table[i] == 0) 2539e5f5284Sbellard host_to_target_signal_table[i] = i; 2549e5f5284Sbellard } 2559e5f5284Sbellard for(i = 1; i <= 64; i++) { 2569e5f5284Sbellard j = host_to_target_signal_table[i]; 2579e5f5284Sbellard target_to_host_signal_table[j] = i; 2589e5f5284Sbellard } 25931e31b8aSbellard 2609de5e440Sbellard /* set all host signal handlers. ALL signals are blocked during 2619de5e440Sbellard the handlers to serialize them. */ 2629de5e440Sbellard sigfillset(&act.sa_mask); 26331e31b8aSbellard act.sa_flags = SA_SIGINFO; 26431e31b8aSbellard act.sa_sigaction = host_signal_handler; 26531e31b8aSbellard for(i = 1; i < NSIG; i++) { 26666fb9763Sbellard sigaction(i, &act, NULL); 26731e31b8aSbellard } 26831e31b8aSbellard 26931e31b8aSbellard memset(sigact_table, 0, sizeof(sigact_table)); 27066fb9763Sbellard 27166fb9763Sbellard first_free = &sigqueue_table[0]; 27266fb9763Sbellard for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) 27366fb9763Sbellard sigqueue_table[i].next = &sigqueue_table[i + 1]; 27466fb9763Sbellard sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL; 27531e31b8aSbellard } 27631e31b8aSbellard 27766fb9763Sbellard /* signal queue handling */ 27866fb9763Sbellard 27966fb9763Sbellard static inline struct sigqueue *alloc_sigqueue(void) 28066fb9763Sbellard { 28166fb9763Sbellard struct sigqueue *q = first_free; 28266fb9763Sbellard if (!q) 28366fb9763Sbellard return NULL; 28466fb9763Sbellard first_free = q->next; 28566fb9763Sbellard return q; 28666fb9763Sbellard } 28766fb9763Sbellard 28866fb9763Sbellard static inline void free_sigqueue(struct sigqueue *q) 28966fb9763Sbellard { 29066fb9763Sbellard q->next = first_free; 29166fb9763Sbellard first_free = q; 29266fb9763Sbellard } 29366fb9763Sbellard 2949de5e440Sbellard /* abort execution with signal */ 2959de5e440Sbellard void __attribute((noreturn)) force_sig(int sig) 29666fb9763Sbellard { 2979de5e440Sbellard int host_sig; 2989de5e440Sbellard host_sig = target_to_host_signal(sig); 299bc8a22ccSbellard fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", 3009de5e440Sbellard sig, strsignal(host_sig)); 3019de5e440Sbellard #if 1 3029de5e440Sbellard _exit(-host_sig); 3039de5e440Sbellard #else 3049de5e440Sbellard { 3059de5e440Sbellard struct sigaction act; 3069de5e440Sbellard sigemptyset(&act.sa_mask); 3079de5e440Sbellard act.sa_flags = SA_SIGINFO; 3089de5e440Sbellard act.sa_sigaction = SIG_DFL; 3099de5e440Sbellard sigaction(SIGABRT, &act, NULL); 3109de5e440Sbellard abort(); 3119de5e440Sbellard } 3129de5e440Sbellard #endif 3139de5e440Sbellard } 31466fb9763Sbellard 3159de5e440Sbellard /* queue a signal so that it will be send to the virtual CPU as soon 3169de5e440Sbellard as possible */ 3179de5e440Sbellard int queue_signal(int sig, target_siginfo_t *info) 3189de5e440Sbellard { 3199de5e440Sbellard struct emulated_sigaction *k; 3209de5e440Sbellard struct sigqueue *q, **pq; 3219de5e440Sbellard target_ulong handler; 3229de5e440Sbellard 3239de5e440Sbellard #if defined(DEBUG_SIGNAL) 324bc8a22ccSbellard fprintf(stderr, "queue_signal: sig=%d\n", 3259de5e440Sbellard sig); 3269de5e440Sbellard #endif 3279de5e440Sbellard k = &sigact_table[sig - 1]; 3289de5e440Sbellard handler = k->sa._sa_handler; 3299de5e440Sbellard if (handler == TARGET_SIG_DFL) { 3309de5e440Sbellard /* default handler : ignore some signal. The other are fatal */ 3319de5e440Sbellard if (sig != TARGET_SIGCHLD && 3329de5e440Sbellard sig != TARGET_SIGURG && 3339de5e440Sbellard sig != TARGET_SIGWINCH) { 3349de5e440Sbellard force_sig(sig); 3359de5e440Sbellard } else { 3369de5e440Sbellard return 0; /* indicate ignored */ 3379de5e440Sbellard } 3389de5e440Sbellard } else if (handler == TARGET_SIG_IGN) { 3399de5e440Sbellard /* ignore signal */ 3409de5e440Sbellard return 0; 3419de5e440Sbellard } else if (handler == TARGET_SIG_ERR) { 3429de5e440Sbellard force_sig(sig); 3439de5e440Sbellard } else { 34466fb9763Sbellard pq = &k->first; 3459de5e440Sbellard if (sig < TARGET_SIGRTMIN) { 3469de5e440Sbellard /* if non real time signal, we queue exactly one signal */ 3479de5e440Sbellard if (!k->pending) 3489de5e440Sbellard q = &k->info; 3499de5e440Sbellard else 3509de5e440Sbellard return 0; 3519de5e440Sbellard } else { 3529de5e440Sbellard if (!k->pending) { 3539de5e440Sbellard /* first signal */ 35466fb9763Sbellard q = &k->info; 35566fb9763Sbellard } else { 35666fb9763Sbellard q = alloc_sigqueue(); 35766fb9763Sbellard if (!q) 35866fb9763Sbellard return -EAGAIN; 35966fb9763Sbellard while (*pq != NULL) 36066fb9763Sbellard pq = &(*pq)->next; 36166fb9763Sbellard } 3629de5e440Sbellard } 36366fb9763Sbellard *pq = q; 36466fb9763Sbellard q->info = *info; 36566fb9763Sbellard q->next = NULL; 36666fb9763Sbellard k->pending = 1; 36766fb9763Sbellard /* signal that a new signal is pending */ 36866fb9763Sbellard signal_pending = 1; 3699de5e440Sbellard return 1; /* indicates that the signal was queued */ 3709de5e440Sbellard } 37166fb9763Sbellard } 37266fb9763Sbellard 37331e31b8aSbellard static void host_signal_handler(int host_signum, siginfo_t *info, 37431e31b8aSbellard void *puc) 37531e31b8aSbellard { 37666fb9763Sbellard int sig; 3779de5e440Sbellard target_siginfo_t tinfo; 3789de5e440Sbellard 3799de5e440Sbellard /* the CPU emulator uses some host signals to detect exceptions, 3809de5e440Sbellard we we forward to it some signals */ 3819de5e440Sbellard if (host_signum == SIGSEGV || host_signum == SIGBUS) { 382b346ff46Sbellard if (cpu_signal_handler(host_signum, info, puc)) 3839de5e440Sbellard return; 3849de5e440Sbellard } 38566fb9763Sbellard 38631e31b8aSbellard /* get target signal number */ 38766fb9763Sbellard sig = host_to_target_signal(host_signum); 38866fb9763Sbellard if (sig < 1 || sig > TARGET_NSIG) 38931e31b8aSbellard return; 3909de5e440Sbellard #if defined(DEBUG_SIGNAL) 391bc8a22ccSbellard fprintf(stderr, "qemu: got signal %d\n", sig); 39266fb9763Sbellard #endif 3939de5e440Sbellard host_to_target_siginfo_noswap(&tinfo, info); 3949de5e440Sbellard if (queue_signal(sig, &tinfo) == 1) { 3959de5e440Sbellard /* interrupt the virtual CPU as soon as possible */ 39668a79315Sbellard cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); 39766fb9763Sbellard } 39831e31b8aSbellard } 39931e31b8aSbellard 40066fb9763Sbellard int do_sigaction(int sig, const struct target_sigaction *act, 40166fb9763Sbellard struct target_sigaction *oact) 40231e31b8aSbellard { 40366fb9763Sbellard struct emulated_sigaction *k; 404*773b93eeSbellard struct sigaction act1; 405*773b93eeSbellard int host_sig; 40631e31b8aSbellard 40766fb9763Sbellard if (sig < 1 || sig > TARGET_NSIG) 40866fb9763Sbellard return -EINVAL; 40966fb9763Sbellard k = &sigact_table[sig - 1]; 410*773b93eeSbellard #if defined(DEBUG_SIGNAL) 41166fb9763Sbellard fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n", 41266fb9763Sbellard sig, (int)act, (int)oact); 41366fb9763Sbellard #endif 41466fb9763Sbellard if (oact) { 41566fb9763Sbellard oact->_sa_handler = tswapl(k->sa._sa_handler); 41666fb9763Sbellard oact->sa_flags = tswapl(k->sa.sa_flags); 41766fb9763Sbellard oact->sa_restorer = tswapl(k->sa.sa_restorer); 41866fb9763Sbellard oact->sa_mask = k->sa.sa_mask; 41966fb9763Sbellard } 42066fb9763Sbellard if (act) { 42166fb9763Sbellard k->sa._sa_handler = tswapl(act->_sa_handler); 42266fb9763Sbellard k->sa.sa_flags = tswapl(act->sa_flags); 42366fb9763Sbellard k->sa.sa_restorer = tswapl(act->sa_restorer); 42466fb9763Sbellard k->sa.sa_mask = act->sa_mask; 425*773b93eeSbellard 426*773b93eeSbellard /* we update the host linux signal state */ 427*773b93eeSbellard host_sig = target_to_host_signal(sig); 428*773b93eeSbellard if (host_sig != SIGSEGV && host_sig != SIGBUS) { 429*773b93eeSbellard sigfillset(&act1.sa_mask); 430*773b93eeSbellard act1.sa_flags = SA_SIGINFO; 431*773b93eeSbellard if (k->sa.sa_flags & TARGET_SA_RESTART) 432*773b93eeSbellard act1.sa_flags |= SA_RESTART; 433*773b93eeSbellard /* NOTE: it is important to update the host kernel signal 434*773b93eeSbellard ignore state to avoid getting unexpected interrupted 435*773b93eeSbellard syscalls */ 436*773b93eeSbellard if (k->sa._sa_handler == TARGET_SIG_IGN) { 437*773b93eeSbellard act1.sa_sigaction = (void *)SIG_IGN; 438*773b93eeSbellard } else if (k->sa._sa_handler == TARGET_SIG_DFL) { 439*773b93eeSbellard act1.sa_sigaction = (void *)SIG_DFL; 440*773b93eeSbellard } else { 441*773b93eeSbellard act1.sa_sigaction = host_signal_handler; 442*773b93eeSbellard } 443*773b93eeSbellard sigaction(host_sig, &act1, NULL); 444*773b93eeSbellard } 44566fb9763Sbellard } 44666fb9763Sbellard return 0; 44766fb9763Sbellard } 44866fb9763Sbellard 44943fff238Sbellard #define __put_user(x,ptr)\ 45043fff238Sbellard ({\ 45143fff238Sbellard int size = sizeof(*ptr);\ 45243fff238Sbellard switch(size) {\ 45343fff238Sbellard case 1:\ 45443fff238Sbellard stb(ptr, (typeof(*ptr))(x));\ 45543fff238Sbellard break;\ 45643fff238Sbellard case 2:\ 45743fff238Sbellard stw(ptr, (typeof(*ptr))(x));\ 45843fff238Sbellard break;\ 45943fff238Sbellard case 4:\ 46043fff238Sbellard stl(ptr, (typeof(*ptr))(x));\ 46143fff238Sbellard break;\ 46243fff238Sbellard case 8:\ 46343fff238Sbellard stq(ptr, (typeof(*ptr))(x));\ 46443fff238Sbellard break;\ 46543fff238Sbellard default:\ 46643fff238Sbellard abort();\ 46743fff238Sbellard }\ 46843fff238Sbellard 0;\ 46943fff238Sbellard }) 47043fff238Sbellard 47143fff238Sbellard #define __get_user(x, ptr) \ 47243fff238Sbellard ({\ 47343fff238Sbellard int size = sizeof(*ptr);\ 47443fff238Sbellard switch(size) {\ 47543fff238Sbellard case 1:\ 47643fff238Sbellard x = (typeof(*ptr))ldub(ptr);\ 47743fff238Sbellard break;\ 47843fff238Sbellard case 2:\ 47943fff238Sbellard x = (typeof(*ptr))lduw(ptr);\ 48043fff238Sbellard break;\ 48143fff238Sbellard case 4:\ 48243fff238Sbellard x = (typeof(*ptr))ldl(ptr);\ 48343fff238Sbellard break;\ 48443fff238Sbellard case 8:\ 48543fff238Sbellard x = (typeof(*ptr))ldq(ptr);\ 48643fff238Sbellard break;\ 48743fff238Sbellard default:\ 48843fff238Sbellard abort();\ 48943fff238Sbellard }\ 49043fff238Sbellard 0;\ 49143fff238Sbellard }) 49243fff238Sbellard 49343fff238Sbellard 49443fff238Sbellard #define __copy_to_user(dst, src, size)\ 49543fff238Sbellard ({\ 49643fff238Sbellard memcpy(dst, src, size);\ 49743fff238Sbellard 0;\ 49843fff238Sbellard }) 49943fff238Sbellard 50043fff238Sbellard #define __copy_from_user(dst, src, size)\ 50143fff238Sbellard ({\ 50243fff238Sbellard memcpy(dst, src, size);\ 50343fff238Sbellard 0;\ 50443fff238Sbellard }) 50543fff238Sbellard 50643fff238Sbellard #define __clear_user(dst, size)\ 50743fff238Sbellard ({\ 50843fff238Sbellard memset(dst, 0, size);\ 50943fff238Sbellard 0;\ 51043fff238Sbellard }) 51143fff238Sbellard 51243fff238Sbellard #ifndef offsetof 51343fff238Sbellard #define offsetof(type, field) ((size_t) &((type *)0)->field) 51443fff238Sbellard #endif 51543fff238Sbellard 51643fff238Sbellard static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, 51743fff238Sbellard const target_siginfo_t *info) 51843fff238Sbellard { 51943fff238Sbellard tswap_siginfo(tinfo, info); 52043fff238Sbellard return 0; 52143fff238Sbellard } 52243fff238Sbellard 52366fb9763Sbellard #ifdef TARGET_I386 52466fb9763Sbellard 52566fb9763Sbellard /* from the Linux kernel */ 52666fb9763Sbellard 52766fb9763Sbellard struct target_fpreg { 52866fb9763Sbellard uint16_t significand[4]; 52966fb9763Sbellard uint16_t exponent; 53066fb9763Sbellard }; 53166fb9763Sbellard 53266fb9763Sbellard struct target_fpxreg { 53366fb9763Sbellard uint16_t significand[4]; 53466fb9763Sbellard uint16_t exponent; 53566fb9763Sbellard uint16_t padding[3]; 53666fb9763Sbellard }; 53766fb9763Sbellard 53866fb9763Sbellard struct target_xmmreg { 53966fb9763Sbellard target_ulong element[4]; 54066fb9763Sbellard }; 54166fb9763Sbellard 54266fb9763Sbellard struct target_fpstate { 54366fb9763Sbellard /* Regular FPU environment */ 54466fb9763Sbellard target_ulong cw; 54566fb9763Sbellard target_ulong sw; 54666fb9763Sbellard target_ulong tag; 54766fb9763Sbellard target_ulong ipoff; 54866fb9763Sbellard target_ulong cssel; 54966fb9763Sbellard target_ulong dataoff; 55066fb9763Sbellard target_ulong datasel; 55166fb9763Sbellard struct target_fpreg _st[8]; 55266fb9763Sbellard uint16_t status; 55366fb9763Sbellard uint16_t magic; /* 0xffff = regular FPU data only */ 55466fb9763Sbellard 55566fb9763Sbellard /* FXSR FPU environment */ 55666fb9763Sbellard target_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */ 55766fb9763Sbellard target_ulong mxcsr; 55866fb9763Sbellard target_ulong reserved; 55966fb9763Sbellard struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ 56066fb9763Sbellard struct target_xmmreg _xmm[8]; 56166fb9763Sbellard target_ulong padding[56]; 56266fb9763Sbellard }; 56366fb9763Sbellard 56466fb9763Sbellard #define X86_FXSR_MAGIC 0x0000 56566fb9763Sbellard 56666fb9763Sbellard struct target_sigcontext { 56766fb9763Sbellard uint16_t gs, __gsh; 56866fb9763Sbellard uint16_t fs, __fsh; 56966fb9763Sbellard uint16_t es, __esh; 57066fb9763Sbellard uint16_t ds, __dsh; 57166fb9763Sbellard target_ulong edi; 57266fb9763Sbellard target_ulong esi; 57366fb9763Sbellard target_ulong ebp; 57466fb9763Sbellard target_ulong esp; 57566fb9763Sbellard target_ulong ebx; 57666fb9763Sbellard target_ulong edx; 57766fb9763Sbellard target_ulong ecx; 57866fb9763Sbellard target_ulong eax; 57966fb9763Sbellard target_ulong trapno; 58066fb9763Sbellard target_ulong err; 58166fb9763Sbellard target_ulong eip; 58266fb9763Sbellard uint16_t cs, __csh; 58366fb9763Sbellard target_ulong eflags; 58466fb9763Sbellard target_ulong esp_at_signal; 58566fb9763Sbellard uint16_t ss, __ssh; 58666fb9763Sbellard target_ulong fpstate; /* pointer */ 58766fb9763Sbellard target_ulong oldmask; 58866fb9763Sbellard target_ulong cr2; 58966fb9763Sbellard }; 59066fb9763Sbellard 59166fb9763Sbellard typedef struct target_sigaltstack { 59266fb9763Sbellard target_ulong ss_sp; 59366fb9763Sbellard int ss_flags; 59466fb9763Sbellard target_ulong ss_size; 59566fb9763Sbellard } target_stack_t; 59666fb9763Sbellard 59766fb9763Sbellard struct target_ucontext { 59866fb9763Sbellard target_ulong uc_flags; 59966fb9763Sbellard target_ulong uc_link; 60066fb9763Sbellard target_stack_t uc_stack; 60166fb9763Sbellard struct target_sigcontext uc_mcontext; 60266fb9763Sbellard target_sigset_t uc_sigmask; /* mask last for extensibility */ 60366fb9763Sbellard }; 60466fb9763Sbellard 60566fb9763Sbellard struct sigframe 60666fb9763Sbellard { 60766fb9763Sbellard target_ulong pretcode; 60866fb9763Sbellard int sig; 60966fb9763Sbellard struct target_sigcontext sc; 61066fb9763Sbellard struct target_fpstate fpstate; 61166fb9763Sbellard target_ulong extramask[TARGET_NSIG_WORDS-1]; 61266fb9763Sbellard char retcode[8]; 61366fb9763Sbellard }; 61466fb9763Sbellard 61566fb9763Sbellard struct rt_sigframe 61666fb9763Sbellard { 61766fb9763Sbellard target_ulong pretcode; 61866fb9763Sbellard int sig; 61966fb9763Sbellard target_ulong pinfo; 62066fb9763Sbellard target_ulong puc; 62166fb9763Sbellard struct target_siginfo info; 62266fb9763Sbellard struct target_ucontext uc; 62366fb9763Sbellard struct target_fpstate fpstate; 62466fb9763Sbellard char retcode[8]; 62566fb9763Sbellard }; 62666fb9763Sbellard 62766fb9763Sbellard /* 62866fb9763Sbellard * Set up a signal frame. 62966fb9763Sbellard */ 63066fb9763Sbellard 63166fb9763Sbellard /* XXX: save x87 state */ 63266fb9763Sbellard static int 63366fb9763Sbellard setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, 63466fb9763Sbellard CPUX86State *env, unsigned long mask) 63566fb9763Sbellard { 63666fb9763Sbellard int err = 0; 63766fb9763Sbellard 638a52c757cSbellard err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); 639a52c757cSbellard err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); 640a52c757cSbellard err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); 641a52c757cSbellard err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); 64266fb9763Sbellard err |= __put_user(env->regs[R_EDI], &sc->edi); 64366fb9763Sbellard err |= __put_user(env->regs[R_ESI], &sc->esi); 64466fb9763Sbellard err |= __put_user(env->regs[R_EBP], &sc->ebp); 64566fb9763Sbellard err |= __put_user(env->regs[R_ESP], &sc->esp); 64666fb9763Sbellard err |= __put_user(env->regs[R_EBX], &sc->ebx); 64766fb9763Sbellard err |= __put_user(env->regs[R_EDX], &sc->edx); 64866fb9763Sbellard err |= __put_user(env->regs[R_ECX], &sc->ecx); 64966fb9763Sbellard err |= __put_user(env->regs[R_EAX], &sc->eax); 65066099dd9Sbellard err |= __put_user(env->exception_index, &sc->trapno); 65166099dd9Sbellard err |= __put_user(env->error_code, &sc->err); 65266fb9763Sbellard err |= __put_user(env->eip, &sc->eip); 653a52c757cSbellard err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); 65466fb9763Sbellard err |= __put_user(env->eflags, &sc->eflags); 65566fb9763Sbellard err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); 656a52c757cSbellard err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); 657ed2dcdf6Sbellard 658ed2dcdf6Sbellard cpu_x86_fsave(env, (void *)fpstate, 1); 659ed2dcdf6Sbellard fpstate->status = fpstate->sw; 660ed2dcdf6Sbellard err |= __put_user(0xffff, &fpstate->magic); 661ed2dcdf6Sbellard err |= __put_user(fpstate, &sc->fpstate); 662ed2dcdf6Sbellard 66366fb9763Sbellard /* non-iBCS2 extensions.. */ 66466fb9763Sbellard err |= __put_user(mask, &sc->oldmask); 665a52c757cSbellard err |= __put_user(env->cr[2], &sc->cr2); 66666fb9763Sbellard return err; 66766fb9763Sbellard } 66866fb9763Sbellard 66966fb9763Sbellard /* 67066fb9763Sbellard * Determine which stack to use.. 67166fb9763Sbellard */ 67266fb9763Sbellard 67366fb9763Sbellard static inline void * 67466fb9763Sbellard get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) 67566fb9763Sbellard { 67666fb9763Sbellard unsigned long esp; 67766fb9763Sbellard 67866fb9763Sbellard /* Default to using normal stack */ 67966fb9763Sbellard esp = env->regs[R_ESP]; 68066fb9763Sbellard #if 0 68166fb9763Sbellard /* This is the X/Open sanctioned signal stack switching. */ 68266fb9763Sbellard if (ka->sa.sa_flags & SA_ONSTACK) { 68366fb9763Sbellard if (sas_ss_flags(esp) == 0) 68466fb9763Sbellard esp = current->sas_ss_sp + current->sas_ss_size; 68566fb9763Sbellard } 68666fb9763Sbellard 68766fb9763Sbellard /* This is the legacy signal stack switching. */ 688a52c757cSbellard else 689a52c757cSbellard #endif 690a52c757cSbellard if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && 691a52c757cSbellard !(ka->sa.sa_flags & TARGET_SA_RESTORER) && 69266fb9763Sbellard ka->sa.sa_restorer) { 69366fb9763Sbellard esp = (unsigned long) ka->sa.sa_restorer; 69466fb9763Sbellard } 69566fb9763Sbellard return (void *)((esp - frame_size) & -8ul); 69666fb9763Sbellard } 69766fb9763Sbellard 69866fb9763Sbellard static void setup_frame(int sig, struct emulated_sigaction *ka, 69966fb9763Sbellard target_sigset_t *set, CPUX86State *env) 70066fb9763Sbellard { 70166fb9763Sbellard struct sigframe *frame; 70266fb9763Sbellard int err = 0; 70366fb9763Sbellard 70466fb9763Sbellard frame = get_sigframe(ka, env, sizeof(*frame)); 70566fb9763Sbellard 70666fb9763Sbellard #if 0 70766fb9763Sbellard if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 70866fb9763Sbellard goto give_sigsegv; 70966fb9763Sbellard #endif 71066fb9763Sbellard err |= __put_user((/*current->exec_domain 71166fb9763Sbellard && current->exec_domain->signal_invmap 71266fb9763Sbellard && sig < 32 71366fb9763Sbellard ? current->exec_domain->signal_invmap[sig] 71466fb9763Sbellard : */ sig), 71566fb9763Sbellard &frame->sig); 71666fb9763Sbellard if (err) 71766fb9763Sbellard goto give_sigsegv; 71866fb9763Sbellard 71966fb9763Sbellard setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0]); 72066fb9763Sbellard if (err) 72166fb9763Sbellard goto give_sigsegv; 72266fb9763Sbellard 72366fb9763Sbellard if (TARGET_NSIG_WORDS > 1) { 72466fb9763Sbellard err |= __copy_to_user(frame->extramask, &set->sig[1], 72566fb9763Sbellard sizeof(frame->extramask)); 72666fb9763Sbellard } 72766fb9763Sbellard if (err) 72866fb9763Sbellard goto give_sigsegv; 72966fb9763Sbellard 73066fb9763Sbellard /* Set up to return from userspace. If provided, use a stub 73166fb9763Sbellard already in userspace. */ 73266fb9763Sbellard if (ka->sa.sa_flags & TARGET_SA_RESTORER) { 73366fb9763Sbellard err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 73466fb9763Sbellard } else { 73566fb9763Sbellard err |= __put_user(frame->retcode, &frame->pretcode); 73666fb9763Sbellard /* This is popl %eax ; movl $,%eax ; int $0x80 */ 73766fb9763Sbellard err |= __put_user(0xb858, (short *)(frame->retcode+0)); 73866fb9763Sbellard err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); 73966fb9763Sbellard err |= __put_user(0x80cd, (short *)(frame->retcode+6)); 74066fb9763Sbellard } 74166fb9763Sbellard 74266fb9763Sbellard if (err) 74366fb9763Sbellard goto give_sigsegv; 74466fb9763Sbellard 74566fb9763Sbellard /* Set up registers for signal handler */ 74666fb9763Sbellard env->regs[R_ESP] = (unsigned long) frame; 74766fb9763Sbellard env->eip = (unsigned long) ka->sa._sa_handler; 74866fb9763Sbellard 74966fb9763Sbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 75066fb9763Sbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 75166fb9763Sbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 75266fb9763Sbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 75366fb9763Sbellard env->eflags &= ~TF_MASK; 75466fb9763Sbellard 75566fb9763Sbellard return; 75666fb9763Sbellard 75766fb9763Sbellard give_sigsegv: 75866fb9763Sbellard if (sig == TARGET_SIGSEGV) 75966fb9763Sbellard ka->sa._sa_handler = TARGET_SIG_DFL; 76066fb9763Sbellard force_sig(TARGET_SIGSEGV /* , current */); 76166fb9763Sbellard } 76266fb9763Sbellard 7639de5e440Sbellard static void setup_rt_frame(int sig, struct emulated_sigaction *ka, 7649de5e440Sbellard target_siginfo_t *info, 76566fb9763Sbellard target_sigset_t *set, CPUX86State *env) 76666fb9763Sbellard { 76766fb9763Sbellard struct rt_sigframe *frame; 76866fb9763Sbellard int err = 0; 76966fb9763Sbellard 77066fb9763Sbellard frame = get_sigframe(ka, env, sizeof(*frame)); 77166fb9763Sbellard 77266fb9763Sbellard #if 0 77366fb9763Sbellard if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 77466fb9763Sbellard goto give_sigsegv; 77566fb9763Sbellard #endif 77666fb9763Sbellard 77766fb9763Sbellard err |= __put_user((/*current->exec_domain 77866fb9763Sbellard && current->exec_domain->signal_invmap 77966fb9763Sbellard && sig < 32 78066fb9763Sbellard ? current->exec_domain->signal_invmap[sig] 78166fb9763Sbellard : */sig), 78266fb9763Sbellard &frame->sig); 78366fb9763Sbellard err |= __put_user((target_ulong)&frame->info, &frame->pinfo); 78466fb9763Sbellard err |= __put_user((target_ulong)&frame->uc, &frame->puc); 78566fb9763Sbellard err |= copy_siginfo_to_user(&frame->info, info); 78666fb9763Sbellard if (err) 78766fb9763Sbellard goto give_sigsegv; 78866fb9763Sbellard 78966fb9763Sbellard /* Create the ucontext. */ 79066fb9763Sbellard err |= __put_user(0, &frame->uc.uc_flags); 79166fb9763Sbellard err |= __put_user(0, &frame->uc.uc_link); 79266fb9763Sbellard err |= __put_user(/*current->sas_ss_sp*/ 0, &frame->uc.uc_stack.ss_sp); 79366fb9763Sbellard err |= __put_user(/* sas_ss_flags(regs->esp) */ 0, 79466fb9763Sbellard &frame->uc.uc_stack.ss_flags); 79566fb9763Sbellard err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size); 79666fb9763Sbellard err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, 79766fb9763Sbellard env, set->sig[0]); 79866fb9763Sbellard err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 79966fb9763Sbellard if (err) 80066fb9763Sbellard goto give_sigsegv; 80166fb9763Sbellard 80266fb9763Sbellard /* Set up to return from userspace. If provided, use a stub 80366fb9763Sbellard already in userspace. */ 80466fb9763Sbellard if (ka->sa.sa_flags & TARGET_SA_RESTORER) { 80566fb9763Sbellard err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 80666fb9763Sbellard } else { 80766fb9763Sbellard err |= __put_user(frame->retcode, &frame->pretcode); 80866fb9763Sbellard /* This is movl $,%eax ; int $0x80 */ 80966fb9763Sbellard err |= __put_user(0xb8, (char *)(frame->retcode+0)); 81066fb9763Sbellard err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); 81166fb9763Sbellard err |= __put_user(0x80cd, (short *)(frame->retcode+5)); 81266fb9763Sbellard } 81366fb9763Sbellard 81466fb9763Sbellard if (err) 81566fb9763Sbellard goto give_sigsegv; 81666fb9763Sbellard 81766fb9763Sbellard /* Set up registers for signal handler */ 81866fb9763Sbellard env->regs[R_ESP] = (unsigned long) frame; 81966fb9763Sbellard env->eip = (unsigned long) ka->sa._sa_handler; 82066fb9763Sbellard 82166fb9763Sbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 82266fb9763Sbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 82366fb9763Sbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 82466fb9763Sbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 82566fb9763Sbellard env->eflags &= ~TF_MASK; 82666fb9763Sbellard 82766fb9763Sbellard return; 82866fb9763Sbellard 82966fb9763Sbellard give_sigsegv: 83066fb9763Sbellard if (sig == TARGET_SIGSEGV) 83166fb9763Sbellard ka->sa._sa_handler = TARGET_SIG_DFL; 83266fb9763Sbellard force_sig(TARGET_SIGSEGV /* , current */); 83366fb9763Sbellard } 83466fb9763Sbellard 83566fb9763Sbellard static int 83666fb9763Sbellard restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) 83766fb9763Sbellard { 83866fb9763Sbellard unsigned int err = 0; 83966fb9763Sbellard 84066fb9763Sbellard cpu_x86_load_seg(env, R_GS, lduw(&sc->gs)); 84166fb9763Sbellard cpu_x86_load_seg(env, R_FS, lduw(&sc->fs)); 84266fb9763Sbellard cpu_x86_load_seg(env, R_ES, lduw(&sc->es)); 84366fb9763Sbellard cpu_x86_load_seg(env, R_DS, lduw(&sc->ds)); 84466fb9763Sbellard 84566fb9763Sbellard env->regs[R_EDI] = ldl(&sc->edi); 84666fb9763Sbellard env->regs[R_ESI] = ldl(&sc->esi); 84766fb9763Sbellard env->regs[R_EBP] = ldl(&sc->ebp); 84866fb9763Sbellard env->regs[R_ESP] = ldl(&sc->esp); 84966fb9763Sbellard env->regs[R_EBX] = ldl(&sc->ebx); 85066fb9763Sbellard env->regs[R_EDX] = ldl(&sc->edx); 85166fb9763Sbellard env->regs[R_ECX] = ldl(&sc->ecx); 85266fb9763Sbellard env->eip = ldl(&sc->eip); 85366fb9763Sbellard 85466fb9763Sbellard cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); 85566fb9763Sbellard cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3); 85666fb9763Sbellard 85766fb9763Sbellard { 85866fb9763Sbellard unsigned int tmpflags; 85966fb9763Sbellard tmpflags = ldl(&sc->eflags); 86066fb9763Sbellard env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); 86166fb9763Sbellard // regs->orig_eax = -1; /* disable syscall checks */ 86266fb9763Sbellard } 86366fb9763Sbellard 86466fb9763Sbellard { 86566fb9763Sbellard struct _fpstate * buf; 866ed2dcdf6Sbellard buf = (void *)ldl(&sc->fpstate); 86766fb9763Sbellard if (buf) { 868ed2dcdf6Sbellard #if 0 86966fb9763Sbellard if (verify_area(VERIFY_READ, buf, sizeof(*buf))) 87066fb9763Sbellard goto badframe; 87166fb9763Sbellard #endif 872ed2dcdf6Sbellard cpu_x86_frstor(env, (void *)buf, 1); 873ed2dcdf6Sbellard } 874ed2dcdf6Sbellard } 875ed2dcdf6Sbellard 87666fb9763Sbellard *peax = ldl(&sc->eax); 87766fb9763Sbellard return err; 87866fb9763Sbellard #if 0 87966fb9763Sbellard badframe: 88066fb9763Sbellard return 1; 88166fb9763Sbellard #endif 88266fb9763Sbellard } 88366fb9763Sbellard 88466fb9763Sbellard long do_sigreturn(CPUX86State *env) 88566fb9763Sbellard { 88666fb9763Sbellard struct sigframe *frame = (struct sigframe *)(env->regs[R_ESP] - 8); 88766fb9763Sbellard target_sigset_t target_set; 88866fb9763Sbellard sigset_t set; 88966fb9763Sbellard int eax, i; 89066fb9763Sbellard 891447db213Sbellard #if defined(DEBUG_SIGNAL) 892447db213Sbellard fprintf(stderr, "do_sigreturn\n"); 893447db213Sbellard #endif 89466fb9763Sbellard /* set blocked signals */ 89566fb9763Sbellard target_set.sig[0] = frame->sc.oldmask; 89666fb9763Sbellard for(i = 1; i < TARGET_NSIG_WORDS; i++) 89766fb9763Sbellard target_set.sig[i] = frame->extramask[i - 1]; 89866fb9763Sbellard 89966fb9763Sbellard target_to_host_sigset(&set, &target_set); 90066fb9763Sbellard sigprocmask(SIG_SETMASK, &set, NULL); 90166fb9763Sbellard 90266fb9763Sbellard /* restore registers */ 90366fb9763Sbellard if (restore_sigcontext(env, &frame->sc, &eax)) 90466fb9763Sbellard goto badframe; 90566fb9763Sbellard return eax; 90666fb9763Sbellard 90766fb9763Sbellard badframe: 90866fb9763Sbellard force_sig(TARGET_SIGSEGV); 90966fb9763Sbellard return 0; 91066fb9763Sbellard } 91166fb9763Sbellard 91266fb9763Sbellard long do_rt_sigreturn(CPUX86State *env) 91366fb9763Sbellard { 91466fb9763Sbellard struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); 91566fb9763Sbellard target_sigset_t target_set; 91666fb9763Sbellard sigset_t set; 91766fb9763Sbellard // stack_t st; 91866fb9763Sbellard int eax; 91966fb9763Sbellard 92066fb9763Sbellard #if 0 92166fb9763Sbellard if (verify_area(VERIFY_READ, frame, sizeof(*frame))) 92266fb9763Sbellard goto badframe; 92366fb9763Sbellard #endif 92466fb9763Sbellard memcpy(&target_set, &frame->uc.uc_sigmask, sizeof(target_sigset_t)); 92566fb9763Sbellard 92666fb9763Sbellard target_to_host_sigset(&set, &target_set); 92766fb9763Sbellard sigprocmask(SIG_SETMASK, &set, NULL); 92866fb9763Sbellard 92966fb9763Sbellard if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax)) 93066fb9763Sbellard goto badframe; 93166fb9763Sbellard 93266fb9763Sbellard #if 0 93366fb9763Sbellard if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) 93466fb9763Sbellard goto badframe; 93566fb9763Sbellard /* It is more difficult to avoid calling this function than to 93666fb9763Sbellard call it and ignore errors. */ 93766fb9763Sbellard do_sigaltstack(&st, NULL, regs->esp); 93866fb9763Sbellard #endif 93966fb9763Sbellard return eax; 94066fb9763Sbellard 94166fb9763Sbellard badframe: 94266fb9763Sbellard force_sig(TARGET_SIGSEGV); 94366fb9763Sbellard return 0; 94466fb9763Sbellard } 94566fb9763Sbellard 94643fff238Sbellard #elif defined(TARGET_ARM) 94743fff238Sbellard 94843fff238Sbellard struct target_sigcontext { 94943fff238Sbellard target_ulong trap_no; 95043fff238Sbellard target_ulong error_code; 95143fff238Sbellard target_ulong oldmask; 95243fff238Sbellard target_ulong arm_r0; 95343fff238Sbellard target_ulong arm_r1; 95443fff238Sbellard target_ulong arm_r2; 95543fff238Sbellard target_ulong arm_r3; 95643fff238Sbellard target_ulong arm_r4; 95743fff238Sbellard target_ulong arm_r5; 95843fff238Sbellard target_ulong arm_r6; 95943fff238Sbellard target_ulong arm_r7; 96043fff238Sbellard target_ulong arm_r8; 96143fff238Sbellard target_ulong arm_r9; 96243fff238Sbellard target_ulong arm_r10; 96343fff238Sbellard target_ulong arm_fp; 96443fff238Sbellard target_ulong arm_ip; 96543fff238Sbellard target_ulong arm_sp; 96643fff238Sbellard target_ulong arm_lr; 96743fff238Sbellard target_ulong arm_pc; 96843fff238Sbellard target_ulong arm_cpsr; 96943fff238Sbellard target_ulong fault_address; 97043fff238Sbellard }; 97143fff238Sbellard 97243fff238Sbellard typedef struct target_sigaltstack { 97343fff238Sbellard target_ulong ss_sp; 97443fff238Sbellard int ss_flags; 97543fff238Sbellard target_ulong ss_size; 97643fff238Sbellard } target_stack_t; 97743fff238Sbellard 97843fff238Sbellard struct target_ucontext { 97943fff238Sbellard target_ulong uc_flags; 98043fff238Sbellard target_ulong uc_link; 98143fff238Sbellard target_stack_t uc_stack; 98243fff238Sbellard struct target_sigcontext uc_mcontext; 98343fff238Sbellard target_sigset_t uc_sigmask; /* mask last for extensibility */ 98443fff238Sbellard }; 98543fff238Sbellard 98643fff238Sbellard struct sigframe 98743fff238Sbellard { 98843fff238Sbellard struct target_sigcontext sc; 98943fff238Sbellard target_ulong extramask[TARGET_NSIG_WORDS-1]; 99043fff238Sbellard target_ulong retcode; 99143fff238Sbellard }; 99243fff238Sbellard 99343fff238Sbellard struct rt_sigframe 99443fff238Sbellard { 99543fff238Sbellard struct target_siginfo *pinfo; 99643fff238Sbellard void *puc; 99743fff238Sbellard struct target_siginfo info; 99843fff238Sbellard struct target_ucontext uc; 99943fff238Sbellard target_ulong retcode; 100043fff238Sbellard }; 100143fff238Sbellard 100243fff238Sbellard #define TARGET_CONFIG_CPU_32 1 100343fff238Sbellard 100443fff238Sbellard /* 100543fff238Sbellard * For ARM syscalls, we encode the syscall number into the instruction. 100643fff238Sbellard */ 100743fff238Sbellard #define SWI_SYS_SIGRETURN (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE)) 100843fff238Sbellard #define SWI_SYS_RT_SIGRETURN (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE)) 100943fff238Sbellard 101043fff238Sbellard /* 101143fff238Sbellard * For Thumb syscalls, we pass the syscall number via r7. We therefore 101243fff238Sbellard * need two 16-bit instructions. 101343fff238Sbellard */ 101443fff238Sbellard #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn)) 101543fff238Sbellard #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn)) 101643fff238Sbellard 101743fff238Sbellard static const target_ulong retcodes[4] = { 101843fff238Sbellard SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, 101943fff238Sbellard SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN 102043fff238Sbellard }; 102143fff238Sbellard 102243fff238Sbellard 102343fff238Sbellard #define __put_user_error(x,p,e) __put_user(x, p) 102443fff238Sbellard #define __get_user_error(x,p,e) __get_user(x, p) 102543fff238Sbellard 102643fff238Sbellard static inline int valid_user_regs(CPUState *regs) 102743fff238Sbellard { 102843fff238Sbellard return 1; 102943fff238Sbellard } 103043fff238Sbellard 103143fff238Sbellard static int 103243fff238Sbellard setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ 103343fff238Sbellard CPUState *env, unsigned long mask) 103443fff238Sbellard { 103543fff238Sbellard int err = 0; 103643fff238Sbellard 103743fff238Sbellard __put_user_error(env->regs[0], &sc->arm_r0, err); 103843fff238Sbellard __put_user_error(env->regs[1], &sc->arm_r1, err); 103943fff238Sbellard __put_user_error(env->regs[2], &sc->arm_r2, err); 104043fff238Sbellard __put_user_error(env->regs[3], &sc->arm_r3, err); 104143fff238Sbellard __put_user_error(env->regs[4], &sc->arm_r4, err); 104243fff238Sbellard __put_user_error(env->regs[5], &sc->arm_r5, err); 104343fff238Sbellard __put_user_error(env->regs[6], &sc->arm_r6, err); 104443fff238Sbellard __put_user_error(env->regs[7], &sc->arm_r7, err); 104543fff238Sbellard __put_user_error(env->regs[8], &sc->arm_r8, err); 104643fff238Sbellard __put_user_error(env->regs[9], &sc->arm_r9, err); 104743fff238Sbellard __put_user_error(env->regs[10], &sc->arm_r10, err); 104843fff238Sbellard __put_user_error(env->regs[11], &sc->arm_fp, err); 104943fff238Sbellard __put_user_error(env->regs[12], &sc->arm_ip, err); 105043fff238Sbellard __put_user_error(env->regs[13], &sc->arm_sp, err); 105143fff238Sbellard __put_user_error(env->regs[14], &sc->arm_lr, err); 105243fff238Sbellard __put_user_error(env->regs[15], &sc->arm_pc, err); 105343fff238Sbellard #ifdef TARGET_CONFIG_CPU_32 105443fff238Sbellard __put_user_error(env->cpsr, &sc->arm_cpsr, err); 105543fff238Sbellard #endif 105643fff238Sbellard 105743fff238Sbellard __put_user_error(/* current->thread.trap_no */ 0, &sc->trap_no, err); 105843fff238Sbellard __put_user_error(/* current->thread.error_code */ 0, &sc->error_code, err); 105943fff238Sbellard __put_user_error(/* current->thread.address */ 0, &sc->fault_address, err); 106043fff238Sbellard __put_user_error(mask, &sc->oldmask, err); 106143fff238Sbellard 106243fff238Sbellard return err; 106343fff238Sbellard } 106443fff238Sbellard 106543fff238Sbellard static inline void * 106643fff238Sbellard get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) 106743fff238Sbellard { 106843fff238Sbellard unsigned long sp = regs->regs[13]; 106943fff238Sbellard 107043fff238Sbellard #if 0 107143fff238Sbellard /* 107243fff238Sbellard * This is the X/Open sanctioned signal stack switching. 107343fff238Sbellard */ 107443fff238Sbellard if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) 107543fff238Sbellard sp = current->sas_ss_sp + current->sas_ss_size; 107643fff238Sbellard #endif 107743fff238Sbellard /* 107843fff238Sbellard * ATPCS B01 mandates 8-byte alignment 107943fff238Sbellard */ 108043fff238Sbellard return (void *)((sp - framesize) & ~7); 108143fff238Sbellard } 108243fff238Sbellard 108343fff238Sbellard static int 108443fff238Sbellard setup_return(CPUState *env, struct emulated_sigaction *ka, 108543fff238Sbellard target_ulong *rc, void *frame, int usig) 108643fff238Sbellard { 108743fff238Sbellard target_ulong handler = (target_ulong)ka->sa._sa_handler; 108843fff238Sbellard target_ulong retcode; 108943fff238Sbellard int thumb = 0; 109043fff238Sbellard #if defined(TARGET_CONFIG_CPU_32) 109143fff238Sbellard target_ulong cpsr = env->cpsr; 109243fff238Sbellard 109343fff238Sbellard #if 0 109443fff238Sbellard /* 109543fff238Sbellard * Maybe we need to deliver a 32-bit signal to a 26-bit task. 109643fff238Sbellard */ 109743fff238Sbellard if (ka->sa.sa_flags & SA_THIRTYTWO) 109843fff238Sbellard cpsr = (cpsr & ~MODE_MASK) | USR_MODE; 109943fff238Sbellard 110043fff238Sbellard #ifdef CONFIG_ARM_THUMB 110143fff238Sbellard if (elf_hwcap & HWCAP_THUMB) { 110243fff238Sbellard /* 110343fff238Sbellard * The LSB of the handler determines if we're going to 110443fff238Sbellard * be using THUMB or ARM mode for this signal handler. 110543fff238Sbellard */ 110643fff238Sbellard thumb = handler & 1; 110743fff238Sbellard 110843fff238Sbellard if (thumb) 110943fff238Sbellard cpsr |= T_BIT; 111043fff238Sbellard else 111143fff238Sbellard cpsr &= ~T_BIT; 111243fff238Sbellard } 111343fff238Sbellard #endif 111443fff238Sbellard #endif 111543fff238Sbellard #endif /* TARGET_CONFIG_CPU_32 */ 111643fff238Sbellard 111743fff238Sbellard if (ka->sa.sa_flags & TARGET_SA_RESTORER) { 111843fff238Sbellard retcode = (target_ulong)ka->sa.sa_restorer; 111943fff238Sbellard } else { 112043fff238Sbellard unsigned int idx = thumb; 112143fff238Sbellard 112243fff238Sbellard if (ka->sa.sa_flags & TARGET_SA_SIGINFO) 112343fff238Sbellard idx += 2; 112443fff238Sbellard 112543fff238Sbellard if (__put_user(retcodes[idx], rc)) 112643fff238Sbellard return 1; 112743fff238Sbellard #if 0 112843fff238Sbellard flush_icache_range((target_ulong)rc, 112943fff238Sbellard (target_ulong)(rc + 1)); 113043fff238Sbellard #endif 113143fff238Sbellard retcode = ((target_ulong)rc) + thumb; 113243fff238Sbellard } 113343fff238Sbellard 113443fff238Sbellard env->regs[0] = usig; 113543fff238Sbellard env->regs[13] = (target_ulong)frame; 113643fff238Sbellard env->regs[14] = retcode; 113743fff238Sbellard env->regs[15] = handler & (thumb ? ~1 : ~3); 113843fff238Sbellard 113943fff238Sbellard #ifdef TARGET_CONFIG_CPU_32 114043fff238Sbellard env->cpsr = cpsr; 114143fff238Sbellard #endif 114243fff238Sbellard 114343fff238Sbellard return 0; 114443fff238Sbellard } 114543fff238Sbellard 114643fff238Sbellard static void setup_frame(int usig, struct emulated_sigaction *ka, 114743fff238Sbellard target_sigset_t *set, CPUState *regs) 114843fff238Sbellard { 114943fff238Sbellard struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); 115043fff238Sbellard int err = 0; 115143fff238Sbellard 115243fff238Sbellard err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); 115343fff238Sbellard 115443fff238Sbellard if (TARGET_NSIG_WORDS > 1) { 115543fff238Sbellard err |= __copy_to_user(frame->extramask, &set->sig[1], 115643fff238Sbellard sizeof(frame->extramask)); 115743fff238Sbellard } 115843fff238Sbellard 115943fff238Sbellard if (err == 0) 116043fff238Sbellard err = setup_return(regs, ka, &frame->retcode, frame, usig); 116143fff238Sbellard // return err; 116243fff238Sbellard } 116343fff238Sbellard 116443fff238Sbellard static void setup_rt_frame(int usig, struct emulated_sigaction *ka, 116543fff238Sbellard target_siginfo_t *info, 116643fff238Sbellard target_sigset_t *set, CPUState *env) 116743fff238Sbellard { 116843fff238Sbellard struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); 116943fff238Sbellard int err = 0; 117043fff238Sbellard 117143fff238Sbellard #if 0 117243fff238Sbellard if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 117343fff238Sbellard return 1; 117443fff238Sbellard #endif 117543fff238Sbellard __put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err); 117643fff238Sbellard __put_user_error(&frame->uc, (target_ulong *)&frame->puc, err); 117743fff238Sbellard err |= copy_siginfo_to_user(&frame->info, info); 117843fff238Sbellard 117943fff238Sbellard /* Clear all the bits of the ucontext we don't use. */ 118043fff238Sbellard err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); 118143fff238Sbellard 118243fff238Sbellard err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ 118343fff238Sbellard env, set->sig[0]); 118443fff238Sbellard err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 118543fff238Sbellard 118643fff238Sbellard if (err == 0) 118743fff238Sbellard err = setup_return(env, ka, &frame->retcode, frame, usig); 118843fff238Sbellard 118943fff238Sbellard if (err == 0) { 119043fff238Sbellard /* 119143fff238Sbellard * For realtime signals we must also set the second and third 119243fff238Sbellard * arguments for the signal handler. 119343fff238Sbellard * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 119443fff238Sbellard */ 119543fff238Sbellard env->regs[1] = (target_ulong)frame->pinfo; 119643fff238Sbellard env->regs[2] = (target_ulong)frame->puc; 119743fff238Sbellard } 119843fff238Sbellard 119943fff238Sbellard // return err; 120043fff238Sbellard } 120143fff238Sbellard 120243fff238Sbellard static int 120343fff238Sbellard restore_sigcontext(CPUState *env, struct target_sigcontext *sc) 120443fff238Sbellard { 120543fff238Sbellard int err = 0; 120643fff238Sbellard 120743fff238Sbellard __get_user_error(env->regs[0], &sc->arm_r0, err); 120843fff238Sbellard __get_user_error(env->regs[1], &sc->arm_r1, err); 120943fff238Sbellard __get_user_error(env->regs[2], &sc->arm_r2, err); 121043fff238Sbellard __get_user_error(env->regs[3], &sc->arm_r3, err); 121143fff238Sbellard __get_user_error(env->regs[4], &sc->arm_r4, err); 121243fff238Sbellard __get_user_error(env->regs[5], &sc->arm_r5, err); 121343fff238Sbellard __get_user_error(env->regs[6], &sc->arm_r6, err); 121443fff238Sbellard __get_user_error(env->regs[7], &sc->arm_r7, err); 121543fff238Sbellard __get_user_error(env->regs[8], &sc->arm_r8, err); 121643fff238Sbellard __get_user_error(env->regs[9], &sc->arm_r9, err); 121743fff238Sbellard __get_user_error(env->regs[10], &sc->arm_r10, err); 121843fff238Sbellard __get_user_error(env->regs[11], &sc->arm_fp, err); 121943fff238Sbellard __get_user_error(env->regs[12], &sc->arm_ip, err); 122043fff238Sbellard __get_user_error(env->regs[13], &sc->arm_sp, err); 122143fff238Sbellard __get_user_error(env->regs[14], &sc->arm_lr, err); 122243fff238Sbellard __get_user_error(env->regs[15], &sc->arm_pc, err); 122343fff238Sbellard #ifdef TARGET_CONFIG_CPU_32 122443fff238Sbellard __get_user_error(env->cpsr, &sc->arm_cpsr, err); 122543fff238Sbellard #endif 122643fff238Sbellard 122743fff238Sbellard err |= !valid_user_regs(env); 122843fff238Sbellard 122943fff238Sbellard return err; 123043fff238Sbellard } 123143fff238Sbellard 123243fff238Sbellard long do_sigreturn(CPUState *env) 123343fff238Sbellard { 123443fff238Sbellard struct sigframe *frame; 123543fff238Sbellard target_sigset_t set; 123643fff238Sbellard sigset_t host_set; 123743fff238Sbellard 123843fff238Sbellard /* 123943fff238Sbellard * Since we stacked the signal on a 64-bit boundary, 124043fff238Sbellard * then 'sp' should be word aligned here. If it's 124143fff238Sbellard * not, then the user is trying to mess with us. 124243fff238Sbellard */ 124343fff238Sbellard if (env->regs[13] & 7) 124443fff238Sbellard goto badframe; 124543fff238Sbellard 124643fff238Sbellard frame = (struct sigframe *)env->regs[13]; 124743fff238Sbellard 124843fff238Sbellard #if 0 124943fff238Sbellard if (verify_area(VERIFY_READ, frame, sizeof (*frame))) 125043fff238Sbellard goto badframe; 125143fff238Sbellard #endif 125243fff238Sbellard if (__get_user(set.sig[0], &frame->sc.oldmask) 125343fff238Sbellard || (TARGET_NSIG_WORDS > 1 125443fff238Sbellard && __copy_from_user(&set.sig[1], &frame->extramask, 125543fff238Sbellard sizeof(frame->extramask)))) 125643fff238Sbellard goto badframe; 125743fff238Sbellard 125843fff238Sbellard target_to_host_sigset(&host_set, &set); 125943fff238Sbellard sigprocmask(SIG_SETMASK, &host_set, NULL); 126043fff238Sbellard 126143fff238Sbellard if (restore_sigcontext(env, &frame->sc)) 126243fff238Sbellard goto badframe; 126343fff238Sbellard 126443fff238Sbellard #if 0 126543fff238Sbellard /* Send SIGTRAP if we're single-stepping */ 126643fff238Sbellard if (ptrace_cancel_bpt(current)) 126743fff238Sbellard send_sig(SIGTRAP, current, 1); 126843fff238Sbellard #endif 126943fff238Sbellard return env->regs[0]; 127043fff238Sbellard 127143fff238Sbellard badframe: 127243fff238Sbellard force_sig(SIGSEGV /* , current */); 127343fff238Sbellard return 0; 127443fff238Sbellard } 127543fff238Sbellard 127643fff238Sbellard long do_rt_sigreturn(CPUState *env) 127743fff238Sbellard { 127843fff238Sbellard struct rt_sigframe *frame; 127943fff238Sbellard target_sigset_t set; 128043fff238Sbellard sigset_t host_set; 128143fff238Sbellard 128243fff238Sbellard /* 128343fff238Sbellard * Since we stacked the signal on a 64-bit boundary, 128443fff238Sbellard * then 'sp' should be word aligned here. If it's 128543fff238Sbellard * not, then the user is trying to mess with us. 128643fff238Sbellard */ 128743fff238Sbellard if (env->regs[13] & 7) 128843fff238Sbellard goto badframe; 128943fff238Sbellard 129043fff238Sbellard frame = (struct rt_sigframe *)env->regs[13]; 129143fff238Sbellard 129243fff238Sbellard #if 0 129343fff238Sbellard if (verify_area(VERIFY_READ, frame, sizeof (*frame))) 129443fff238Sbellard goto badframe; 129543fff238Sbellard #endif 129643fff238Sbellard if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 129743fff238Sbellard goto badframe; 129843fff238Sbellard 129943fff238Sbellard target_to_host_sigset(&host_set, &set); 130043fff238Sbellard sigprocmask(SIG_SETMASK, &host_set, NULL); 130143fff238Sbellard 130243fff238Sbellard if (restore_sigcontext(env, &frame->uc.uc_mcontext)) 130343fff238Sbellard goto badframe; 130443fff238Sbellard 130543fff238Sbellard #if 0 130643fff238Sbellard /* Send SIGTRAP if we're single-stepping */ 130743fff238Sbellard if (ptrace_cancel_bpt(current)) 130843fff238Sbellard send_sig(SIGTRAP, current, 1); 130943fff238Sbellard #endif 131043fff238Sbellard return env->regs[0]; 131143fff238Sbellard 131243fff238Sbellard badframe: 131343fff238Sbellard force_sig(SIGSEGV /* , current */); 131443fff238Sbellard return 0; 131543fff238Sbellard } 131643fff238Sbellard 1317b346ff46Sbellard #else 1318b346ff46Sbellard 1319b346ff46Sbellard static void setup_frame(int sig, struct emulated_sigaction *ka, 1320b346ff46Sbellard target_sigset_t *set, CPUState *env) 1321b346ff46Sbellard { 1322b346ff46Sbellard fprintf(stderr, "setup_frame: not implemented\n"); 1323b346ff46Sbellard } 1324b346ff46Sbellard 1325b346ff46Sbellard static void setup_rt_frame(int sig, struct emulated_sigaction *ka, 1326b346ff46Sbellard target_siginfo_t *info, 1327b346ff46Sbellard target_sigset_t *set, CPUState *env) 1328b346ff46Sbellard { 1329b346ff46Sbellard fprintf(stderr, "setup_rt_frame: not implemented\n"); 1330b346ff46Sbellard } 1331b346ff46Sbellard 1332b346ff46Sbellard long do_sigreturn(CPUState *env) 1333b346ff46Sbellard { 1334b346ff46Sbellard fprintf(stderr, "do_sigreturn: not implemented\n"); 1335b346ff46Sbellard return -ENOSYS; 1336b346ff46Sbellard } 1337b346ff46Sbellard 1338b346ff46Sbellard long do_rt_sigreturn(CPUState *env) 1339b346ff46Sbellard { 1340b346ff46Sbellard fprintf(stderr, "do_rt_sigreturn: not implemented\n"); 1341b346ff46Sbellard return -ENOSYS; 1342b346ff46Sbellard } 1343b346ff46Sbellard 134466fb9763Sbellard #endif 134566fb9763Sbellard 134666fb9763Sbellard void process_pending_signals(void *cpu_env) 134766fb9763Sbellard { 134866fb9763Sbellard int sig; 134966fb9763Sbellard target_ulong handler; 13509de5e440Sbellard sigset_t set, old_set; 13519de5e440Sbellard target_sigset_t target_old_set; 135266fb9763Sbellard struct emulated_sigaction *k; 135366fb9763Sbellard struct sigqueue *q; 135431e31b8aSbellard 135531e31b8aSbellard if (!signal_pending) 135631e31b8aSbellard return; 135731e31b8aSbellard 135866fb9763Sbellard k = sigact_table; 135966fb9763Sbellard for(sig = 1; sig <= TARGET_NSIG; sig++) { 136066fb9763Sbellard if (k->pending) 136131e31b8aSbellard goto handle_signal; 136266fb9763Sbellard k++; 136331e31b8aSbellard } 136431e31b8aSbellard /* if no signal is pending, just return */ 136531e31b8aSbellard signal_pending = 0; 136631e31b8aSbellard return; 136766fb9763Sbellard 136831e31b8aSbellard handle_signal: 136966fb9763Sbellard #ifdef DEBUG_SIGNAL 1370bc8a22ccSbellard fprintf(stderr, "qemu: process signal %d\n", sig); 137166fb9763Sbellard #endif 137266fb9763Sbellard /* dequeue signal */ 137366fb9763Sbellard q = k->first; 137466fb9763Sbellard k->first = q->next; 137566fb9763Sbellard if (!k->first) 137666fb9763Sbellard k->pending = 0; 137766fb9763Sbellard 137866fb9763Sbellard handler = k->sa._sa_handler; 137966fb9763Sbellard if (handler == TARGET_SIG_DFL) { 138066fb9763Sbellard /* default handler : ignore some signal. The other are fatal */ 138166fb9763Sbellard if (sig != TARGET_SIGCHLD && 138266fb9763Sbellard sig != TARGET_SIGURG && 138366fb9763Sbellard sig != TARGET_SIGWINCH) { 138466fb9763Sbellard force_sig(sig); 138566fb9763Sbellard } 138666fb9763Sbellard } else if (handler == TARGET_SIG_IGN) { 138766fb9763Sbellard /* ignore sig */ 138866fb9763Sbellard } else if (handler == TARGET_SIG_ERR) { 138966fb9763Sbellard force_sig(sig); 139066fb9763Sbellard } else { 13919de5e440Sbellard /* compute the blocked signals during the handler execution */ 13929de5e440Sbellard target_to_host_sigset(&set, &k->sa.sa_mask); 13939de5e440Sbellard /* SA_NODEFER indicates that the current signal should not be 13949de5e440Sbellard blocked during the handler */ 13959de5e440Sbellard if (!(k->sa.sa_flags & TARGET_SA_NODEFER)) 13969de5e440Sbellard sigaddset(&set, target_to_host_signal(sig)); 13979de5e440Sbellard 13989de5e440Sbellard /* block signals in the handler using Linux */ 13999de5e440Sbellard sigprocmask(SIG_BLOCK, &set, &old_set); 14009de5e440Sbellard /* save the previous blocked signal state to restore it at the 14019de5e440Sbellard end of the signal execution (see do_sigreturn) */ 14029de5e440Sbellard host_to_target_sigset(&target_old_set, &old_set); 14039de5e440Sbellard 1404bc8a22ccSbellard /* if the CPU is in VM86 mode, we restore the 32 bit values */ 1405bc8a22ccSbellard #ifdef TARGET_I386 1406bc8a22ccSbellard { 1407bc8a22ccSbellard CPUX86State *env = cpu_env; 1408bc8a22ccSbellard if (env->eflags & VM_MASK) 1409bc8a22ccSbellard save_v86_state(env); 1410bc8a22ccSbellard } 1411bc8a22ccSbellard #endif 14129de5e440Sbellard /* prepare the stack frame of the virtual CPU */ 141366fb9763Sbellard if (k->sa.sa_flags & TARGET_SA_SIGINFO) 14149de5e440Sbellard setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env); 141566fb9763Sbellard else 14169de5e440Sbellard setup_frame(sig, k, &target_old_set, cpu_env); 141766fb9763Sbellard if (k->sa.sa_flags & TARGET_SA_RESETHAND) 141866fb9763Sbellard k->sa._sa_handler = TARGET_SIG_DFL; 141966fb9763Sbellard } 142066fb9763Sbellard if (q != &k->info) 142166fb9763Sbellard free_sigqueue(q); 142231e31b8aSbellard } 142331e31b8aSbellard 142431e31b8aSbellard 1425