Commit 106ec87921a41752777781f073092301d4477567
1 parent
951f1351
initial MIPS signal handling (initial patch by Raphael Rigo)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2031 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
376 additions
and
3 deletions
linux-user/main.c
@@ -1302,6 +1302,7 @@ void cpu_loop(CPUMIPSState *env) | @@ -1302,6 +1302,7 @@ void cpu_loop(CPUMIPSState *env) | ||
1302 | case EXCP_SYSCALL: | 1302 | case EXCP_SYSCALL: |
1303 | { | 1303 | { |
1304 | syscall_num = env->gpr[2] - 4000; | 1304 | syscall_num = env->gpr[2] - 4000; |
1305 | + env->PC += 4; | ||
1305 | if (syscall_num >= sizeof(mips_syscall_args)) { | 1306 | if (syscall_num >= sizeof(mips_syscall_args)) { |
1306 | ret = -ENOSYS; | 1307 | ret = -ENOSYS; |
1307 | } else { | 1308 | } else { |
@@ -1328,7 +1329,6 @@ void cpu_loop(CPUMIPSState *env) | @@ -1328,7 +1329,6 @@ void cpu_loop(CPUMIPSState *env) | ||
1328 | arg5, | 1329 | arg5, |
1329 | arg6); | 1330 | arg6); |
1330 | } | 1331 | } |
1331 | - env->PC += 4; | ||
1332 | if ((unsigned int)ret >= (unsigned int)(-1133)) { | 1332 | if ((unsigned int)ret >= (unsigned int)(-1133)) { |
1333 | env->gpr[7] = 1; /* error flag */ | 1333 | env->gpr[7] = 1; /* error flag */ |
1334 | ret = -ret; | 1334 | ret = -ret; |
@@ -1347,6 +1347,9 @@ void cpu_loop(CPUMIPSState *env) | @@ -1347,6 +1347,9 @@ void cpu_loop(CPUMIPSState *env) | ||
1347 | info.si_code = 0; | 1347 | info.si_code = 0; |
1348 | queue_signal(info.si_signo, &info); | 1348 | queue_signal(info.si_signo, &info); |
1349 | break; | 1349 | break; |
1350 | + case EXCP_INTERRUPT: | ||
1351 | + /* just indicate that signals should be handled asap */ | ||
1352 | + break; | ||
1350 | default: | 1353 | default: |
1351 | // error: | 1354 | // error: |
1352 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | 1355 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", |
linux-user/signal.c
@@ -432,13 +432,17 @@ int do_sigaction(int sig, const struct target_sigaction *act, | @@ -432,13 +432,17 @@ int do_sigaction(int sig, const struct target_sigaction *act, | ||
432 | if (oact) { | 432 | if (oact) { |
433 | oact->_sa_handler = tswapl(k->sa._sa_handler); | 433 | oact->_sa_handler = tswapl(k->sa._sa_handler); |
434 | oact->sa_flags = tswapl(k->sa.sa_flags); | 434 | oact->sa_flags = tswapl(k->sa.sa_flags); |
435 | - oact->sa_restorer = tswapl(k->sa.sa_restorer); | 435 | + #if !defined(TARGET_MIPS) |
436 | + oact->sa_restorer = tswapl(k->sa.sa_restorer); | ||
437 | + #endif | ||
436 | oact->sa_mask = k->sa.sa_mask; | 438 | oact->sa_mask = k->sa.sa_mask; |
437 | } | 439 | } |
438 | if (act) { | 440 | if (act) { |
439 | k->sa._sa_handler = tswapl(act->_sa_handler); | 441 | k->sa._sa_handler = tswapl(act->_sa_handler); |
440 | k->sa.sa_flags = tswapl(act->sa_flags); | 442 | k->sa.sa_flags = tswapl(act->sa_flags); |
441 | - k->sa.sa_restorer = tswapl(act->sa_restorer); | 443 | + #if !defined(TARGET_MIPS) |
444 | + k->sa.sa_restorer = tswapl(act->sa_restorer); | ||
445 | + #endif | ||
442 | k->sa.sa_mask = act->sa_mask; | 446 | k->sa.sa_mask = act->sa_mask; |
443 | 447 | ||
444 | /* we update the host linux signal state */ | 448 | /* we update the host linux signal state */ |
@@ -1618,6 +1622,334 @@ long do_rt_sigreturn(CPUState *env) | @@ -1618,6 +1622,334 @@ long do_rt_sigreturn(CPUState *env) | ||
1618 | return -ENOSYS; | 1622 | return -ENOSYS; |
1619 | } | 1623 | } |
1620 | 1624 | ||
1625 | +#elif defined(TARGET_MIPS) | ||
1626 | + | ||
1627 | +struct target_sigcontext { | ||
1628 | + uint32_t sc_regmask; /* Unused */ | ||
1629 | + uint32_t sc_status; | ||
1630 | + uint64_t sc_pc; | ||
1631 | + uint64_t sc_regs[32]; | ||
1632 | + uint64_t sc_fpregs[32]; | ||
1633 | + uint32_t sc_ownedfp; /* Unused */ | ||
1634 | + uint32_t sc_fpc_csr; | ||
1635 | + uint32_t sc_fpc_eir; /* Unused */ | ||
1636 | + uint32_t sc_used_math; | ||
1637 | + uint32_t sc_dsp; /* dsp status, was sc_ssflags */ | ||
1638 | + uint64_t sc_mdhi; | ||
1639 | + uint64_t sc_mdlo; | ||
1640 | + target_ulong sc_hi1; /* Was sc_cause */ | ||
1641 | + target_ulong sc_lo1; /* Was sc_badvaddr */ | ||
1642 | + target_ulong sc_hi2; /* Was sc_sigset[4] */ | ||
1643 | + target_ulong sc_lo2; | ||
1644 | + target_ulong sc_hi3; | ||
1645 | + target_ulong sc_lo3; | ||
1646 | +}; | ||
1647 | + | ||
1648 | +struct sigframe { | ||
1649 | + uint32_t sf_ass[4]; /* argument save space for o32 */ | ||
1650 | + uint32_t sf_code[2]; /* signal trampoline */ | ||
1651 | + struct target_sigcontext sf_sc; | ||
1652 | + target_sigset_t sf_mask; | ||
1653 | +}; | ||
1654 | + | ||
1655 | +/* Install trampoline to jump back from signal handler */ | ||
1656 | +static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall) | ||
1657 | +{ | ||
1658 | + int err; | ||
1659 | + | ||
1660 | + /* | ||
1661 | + * Set up the return code ... | ||
1662 | + * | ||
1663 | + * li v0, __NR__foo_sigreturn | ||
1664 | + * syscall | ||
1665 | + */ | ||
1666 | + | ||
1667 | + err = __put_user(0x24020000 + syscall, tramp + 0); | ||
1668 | + err |= __put_user(0x0000000c , tramp + 1); | ||
1669 | + /* flush_cache_sigtramp((unsigned long) tramp); */ | ||
1670 | + return err; | ||
1671 | +} | ||
1672 | + | ||
1673 | +static inline int | ||
1674 | +setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) | ||
1675 | +{ | ||
1676 | + int err = 0; | ||
1677 | + | ||
1678 | + err |= __put_user(regs->PC, &sc->sc_pc); | ||
1679 | + | ||
1680 | + #define save_gp_reg(i) do { \ | ||
1681 | + err |= __put_user(regs->gpr[i], &sc->sc_regs[i]); \ | ||
1682 | + } while(0) | ||
1683 | + __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); | ||
1684 | + save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); | ||
1685 | + save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); | ||
1686 | + save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); | ||
1687 | + save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); | ||
1688 | + save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); | ||
1689 | + save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); | ||
1690 | + save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); | ||
1691 | + save_gp_reg(31); | ||
1692 | + #undef save_gp_reg | ||
1693 | + | ||
1694 | + err |= __put_user(regs->HI, &sc->sc_mdhi); | ||
1695 | + err |= __put_user(regs->LO, &sc->sc_mdlo); | ||
1696 | + | ||
1697 | + /* Not used yet, but might be useful if we ever have DSP suppport */ | ||
1698 | +#if 0 | ||
1699 | + if (cpu_has_dsp) { | ||
1700 | + err |= __put_user(mfhi1(), &sc->sc_hi1); | ||
1701 | + err |= __put_user(mflo1(), &sc->sc_lo1); | ||
1702 | + err |= __put_user(mfhi2(), &sc->sc_hi2); | ||
1703 | + err |= __put_user(mflo2(), &sc->sc_lo2); | ||
1704 | + err |= __put_user(mfhi3(), &sc->sc_hi3); | ||
1705 | + err |= __put_user(mflo3(), &sc->sc_lo3); | ||
1706 | + err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
1707 | + } | ||
1708 | + /* same with 64 bit */ | ||
1709 | + #ifdef CONFIG_64BIT | ||
1710 | + err |= __put_user(regs->hi, &sc->sc_hi[0]); | ||
1711 | + err |= __put_user(regs->lo, &sc->sc_lo[0]); | ||
1712 | + if (cpu_has_dsp) { | ||
1713 | + err |= __put_user(mfhi1(), &sc->sc_hi[1]); | ||
1714 | + err |= __put_user(mflo1(), &sc->sc_lo[1]); | ||
1715 | + err |= __put_user(mfhi2(), &sc->sc_hi[2]); | ||
1716 | + err |= __put_user(mflo2(), &sc->sc_lo[2]); | ||
1717 | + err |= __put_user(mfhi3(), &sc->sc_hi[3]); | ||
1718 | + err |= __put_user(mflo3(), &sc->sc_lo[3]); | ||
1719 | + err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
1720 | + } | ||
1721 | + #endif | ||
1722 | + | ||
1723 | + | ||
1724 | + #endif | ||
1725 | + | ||
1726 | + | ||
1727 | + #if 0 | ||
1728 | + err |= __put_user(!!used_math(), &sc->sc_used_math); | ||
1729 | + | ||
1730 | + if (!used_math()) | ||
1731 | + goto out; | ||
1732 | + | ||
1733 | + /* | ||
1734 | + * Save FPU state to signal context. Signal handler will "inherit" | ||
1735 | + * current FPU state. | ||
1736 | + */ | ||
1737 | + preempt_disable(); | ||
1738 | + | ||
1739 | + if (!is_fpu_owner()) { | ||
1740 | + own_fpu(); | ||
1741 | + restore_fp(current); | ||
1742 | + } | ||
1743 | + err |= save_fp_context(sc); | ||
1744 | + | ||
1745 | + preempt_enable(); | ||
1746 | + out: | ||
1747 | +#endif | ||
1748 | + return err; | ||
1749 | +} | ||
1750 | + | ||
1751 | +static inline int | ||
1752 | +restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) | ||
1753 | +{ | ||
1754 | + int err = 0; | ||
1755 | + | ||
1756 | + err |= __get_user(regs->CP0_EPC, &sc->sc_pc); | ||
1757 | + | ||
1758 | + err |= __get_user(regs->HI, &sc->sc_mdhi); | ||
1759 | + err |= __get_user(regs->LO, &sc->sc_mdlo); | ||
1760 | + | ||
1761 | + #define restore_gp_reg(i) do { \ | ||
1762 | + err |= __get_user(regs->gpr[i], &sc->sc_regs[i]); \ | ||
1763 | + } while(0) | ||
1764 | + restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); | ||
1765 | + restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); | ||
1766 | + restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); | ||
1767 | + restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12); | ||
1768 | + restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15); | ||
1769 | + restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18); | ||
1770 | + restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21); | ||
1771 | + restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24); | ||
1772 | + restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27); | ||
1773 | + restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30); | ||
1774 | + restore_gp_reg(31); | ||
1775 | + #undef restore_gp_reg | ||
1776 | + | ||
1777 | +#if 0 | ||
1778 | + if (cpu_has_dsp) { | ||
1779 | + err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | ||
1780 | + err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | ||
1781 | + err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | ||
1782 | + err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | ||
1783 | + err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | ||
1784 | + err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | ||
1785 | + err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
1786 | + } | ||
1787 | + #ifdef CONFIG_64BIT | ||
1788 | + err |= __get_user(regs->hi, &sc->sc_hi[0]); | ||
1789 | + err |= __get_user(regs->lo, &sc->sc_lo[0]); | ||
1790 | + if (cpu_has_dsp) { | ||
1791 | + err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg); | ||
1792 | + err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg); | ||
1793 | + err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg); | ||
1794 | + err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg); | ||
1795 | + err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg); | ||
1796 | + err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg); | ||
1797 | + err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
1798 | + } | ||
1799 | + #endif | ||
1800 | + | ||
1801 | + err |= __get_user(used_math, &sc->sc_used_math); | ||
1802 | + conditional_used_math(used_math); | ||
1803 | + | ||
1804 | + preempt_disable(); | ||
1805 | + | ||
1806 | + if (used_math()) { | ||
1807 | + /* restore fpu context if we have used it before */ | ||
1808 | + own_fpu(); | ||
1809 | + err |= restore_fp_context(sc); | ||
1810 | + } else { | ||
1811 | + /* signal handler may have used FPU. Give it up. */ | ||
1812 | + lose_fpu(); | ||
1813 | + } | ||
1814 | + | ||
1815 | + preempt_enable(); | ||
1816 | +#endif | ||
1817 | + return err; | ||
1818 | +} | ||
1819 | +/* | ||
1820 | + * Determine which stack to use.. | ||
1821 | + */ | ||
1822 | +static inline void * | ||
1823 | +get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) | ||
1824 | +{ | ||
1825 | + unsigned long sp; | ||
1826 | + | ||
1827 | + /* Default to using normal stack */ | ||
1828 | + sp = regs->gpr[29]; | ||
1829 | + | ||
1830 | + /* | ||
1831 | + * FPU emulator may have it's own trampoline active just | ||
1832 | + * above the user stack, 16-bytes before the next lowest | ||
1833 | + * 16 byte boundary. Try to avoid trashing it. | ||
1834 | + */ | ||
1835 | + sp -= 32; | ||
1836 | + | ||
1837 | +#if 0 | ||
1838 | + /* This is the X/Open sanctioned signal stack switching. */ | ||
1839 | + if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) | ||
1840 | + sp = current->sas_ss_sp + current->sas_ss_size; | ||
1841 | +#endif | ||
1842 | + | ||
1843 | + return g2h((sp - frame_size) & ~7); | ||
1844 | +} | ||
1845 | + | ||
1846 | +static void setup_frame(int sig, struct emulated_sigaction * ka, | ||
1847 | + target_sigset_t *set, CPUState *regs) | ||
1848 | +{ | ||
1849 | + struct sigframe *frame; | ||
1850 | + int i; | ||
1851 | + | ||
1852 | + frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
1853 | + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | ||
1854 | + goto give_sigsegv; | ||
1855 | + | ||
1856 | + install_sigtramp(frame->sf_code, TARGET_NR_sigreturn); | ||
1857 | + | ||
1858 | + if(setup_sigcontext(regs, &frame->sf_sc)) | ||
1859 | + goto give_sigsegv; | ||
1860 | + | ||
1861 | + for(i = 0; i < TARGET_NSIG_WORDS; i++) { | ||
1862 | + if(__put_user(set->sig[i], &frame->sf_mask.sig[i])) | ||
1863 | + goto give_sigsegv; | ||
1864 | + } | ||
1865 | + | ||
1866 | + /* | ||
1867 | + * Arguments to signal handler: | ||
1868 | + * | ||
1869 | + * a0 = signal number | ||
1870 | + * a1 = 0 (should be cause) | ||
1871 | + * a2 = pointer to struct sigcontext | ||
1872 | + * | ||
1873 | + * $25 and PC point to the signal handler, $29 points to the | ||
1874 | + * struct sigframe. | ||
1875 | + */ | ||
1876 | + regs->gpr[ 4] = sig; | ||
1877 | + regs->gpr[ 5] = 0; | ||
1878 | + regs->gpr[ 6] = h2g(&frame->sf_sc); | ||
1879 | + regs->gpr[29] = h2g(frame); | ||
1880 | + regs->gpr[31] = h2g(frame->sf_code); | ||
1881 | + /* The original kernel code sets CP0_EPC to the handler | ||
1882 | + * since it returns to userland using eret | ||
1883 | + * we cannot do this here, and we must set PC directly */ | ||
1884 | + regs->PC = regs->gpr[25] = ka->sa._sa_handler; | ||
1885 | + return; | ||
1886 | + | ||
1887 | +give_sigsegv: | ||
1888 | + force_sig(TARGET_SIGSEGV/*, current*/); | ||
1889 | + return; | ||
1890 | +} | ||
1891 | + | ||
1892 | +long do_sigreturn(CPUState *regs) | ||
1893 | +{ | ||
1894 | + struct sigframe *frame; | ||
1895 | + sigset_t blocked; | ||
1896 | + target_sigset_t target_set; | ||
1897 | + int i; | ||
1898 | + | ||
1899 | +#if defined(DEBUG_SIGNAL) | ||
1900 | + fprintf(stderr, "do_sigreturn\n"); | ||
1901 | +#endif | ||
1902 | + frame = (struct sigframe *) regs->gpr[29]; | ||
1903 | + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
1904 | + goto badframe; | ||
1905 | + | ||
1906 | + for(i = 0; i < TARGET_NSIG_WORDS; i++) { | ||
1907 | + if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i])) | ||
1908 | + goto badframe; | ||
1909 | + } | ||
1910 | + | ||
1911 | + target_to_host_sigset_internal(&blocked, &target_set); | ||
1912 | + sigprocmask(SIG_SETMASK, &blocked, NULL); | ||
1913 | + | ||
1914 | + if (restore_sigcontext(regs, &frame->sf_sc)) | ||
1915 | + goto badframe; | ||
1916 | + | ||
1917 | +#if 0 | ||
1918 | + /* | ||
1919 | + * Don't let your children do this ... | ||
1920 | + */ | ||
1921 | + __asm__ __volatile__( | ||
1922 | + "move\t$29, %0\n\t" | ||
1923 | + "j\tsyscall_exit" | ||
1924 | + :/* no outputs */ | ||
1925 | + :"r" (®s)); | ||
1926 | + /* Unreached */ | ||
1927 | +#endif | ||
1928 | + | ||
1929 | + regs->PC = regs->CP0_EPC; | ||
1930 | + /* I am not sure this is right, but it seems to work | ||
1931 | + * maybe a problem with nested signals ? */ | ||
1932 | + regs->CP0_EPC = 0; | ||
1933 | + return 0; | ||
1934 | + | ||
1935 | +badframe: | ||
1936 | + force_sig(TARGET_SIGSEGV/*, current*/); | ||
1937 | + return 0; | ||
1938 | + | ||
1939 | +} | ||
1940 | + | ||
1941 | +static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
1942 | + target_siginfo_t *info, | ||
1943 | + target_sigset_t *set, CPUState *env) | ||
1944 | +{ | ||
1945 | + fprintf(stderr, "setup_rt_frame: not implemented\n"); | ||
1946 | +} | ||
1947 | + | ||
1948 | +long do_rt_sigreturn(CPUState *env) | ||
1949 | +{ | ||
1950 | + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); | ||
1951 | + return -ENOSYS; | ||
1952 | +} | ||
1621 | 1953 | ||
1622 | #else | 1954 | #else |
1623 | 1955 |
linux-user/syscall.c
@@ -2246,6 +2246,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2246,6 +2246,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2246 | break; | 2246 | break; |
2247 | case TARGET_NR_sigaction: | 2247 | case TARGET_NR_sigaction: |
2248 | { | 2248 | { |
2249 | + #if !defined(TARGET_MIPS) | ||
2249 | struct target_old_sigaction *old_act; | 2250 | struct target_old_sigaction *old_act; |
2250 | struct target_sigaction act, oact, *pact; | 2251 | struct target_sigaction act, oact, *pact; |
2251 | if (arg2) { | 2252 | if (arg2) { |
@@ -2268,6 +2269,33 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2268,6 +2269,33 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2268 | old_act->sa_restorer = oact.sa_restorer; | 2269 | old_act->sa_restorer = oact.sa_restorer; |
2269 | unlock_user_struct(old_act, arg3, 1); | 2270 | unlock_user_struct(old_act, arg3, 1); |
2270 | } | 2271 | } |
2272 | + #else | ||
2273 | + struct target_sigaction act, oact, *pact, *old_act; | ||
2274 | + | ||
2275 | + if (arg2) { | ||
2276 | + lock_user_struct(old_act, arg2, 1); | ||
2277 | + act._sa_handler = old_act->_sa_handler; | ||
2278 | + target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); | ||
2279 | + act.sa_flags = old_act->sa_flags; | ||
2280 | + unlock_user_struct(old_act, arg2, 0); | ||
2281 | + pact = &act; | ||
2282 | + } else { | ||
2283 | + pact = NULL; | ||
2284 | + } | ||
2285 | + | ||
2286 | + ret = get_errno(do_sigaction(arg1, pact, &oact)); | ||
2287 | + | ||
2288 | + if (!is_error(ret) && arg3) { | ||
2289 | + lock_user_struct(old_act, arg3, 0); | ||
2290 | + old_act->_sa_handler = oact._sa_handler; | ||
2291 | + old_act->sa_flags = oact.sa_flags; | ||
2292 | + old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; | ||
2293 | + old_act->sa_mask.sig[1] = 0; | ||
2294 | + old_act->sa_mask.sig[2] = 0; | ||
2295 | + old_act->sa_mask.sig[3] = 0; | ||
2296 | + unlock_user_struct(old_act, arg3, 1); | ||
2297 | + } | ||
2298 | + #endif | ||
2271 | } | 2299 | } |
2272 | break; | 2300 | break; |
2273 | case TARGET_NR_rt_sigaction: | 2301 | case TARGET_NR_rt_sigaction: |
linux-user/syscall_defs.h
@@ -448,6 +448,15 @@ int do_sigaction(int sig, const struct target_sigaction *act, | @@ -448,6 +448,15 @@ int do_sigaction(int sig, const struct target_sigaction *act, | ||
448 | 448 | ||
449 | #endif | 449 | #endif |
450 | 450 | ||
451 | +#if defined(TARGET_MIPS) | ||
452 | + | ||
453 | +struct target_sigaction { | ||
454 | + target_ulong sa_flags; | ||
455 | + target_ulong _sa_handler; | ||
456 | + target_sigset_t sa_mask; | ||
457 | +}; | ||
458 | + | ||
459 | +#else | ||
451 | struct target_old_sigaction { | 460 | struct target_old_sigaction { |
452 | target_ulong _sa_handler; | 461 | target_ulong _sa_handler; |
453 | target_ulong sa_mask; | 462 | target_ulong sa_mask; |
@@ -461,6 +470,7 @@ struct target_sigaction { | @@ -461,6 +470,7 @@ struct target_sigaction { | ||
461 | target_ulong sa_restorer; | 470 | target_ulong sa_restorer; |
462 | target_sigset_t sa_mask; | 471 | target_sigset_t sa_mask; |
463 | }; | 472 | }; |
473 | +#endif | ||
464 | 474 | ||
465 | typedef union target_sigval { | 475 | typedef union target_sigval { |
466 | int sival_int; | 476 | int sival_int; |