Commit 459a40172e7ee1be269771c355dbb3ef3c3903db
1 parent
eeeac3f3
removed warnings - improved sparc32/64 signal frame setup - disabled x86 frame setup for x86_64
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3608 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
92 additions
and
59 deletions
linux-user/signal.c
| ... | ... | @@ -143,7 +143,7 @@ static void host_to_target_sigset_internal(target_sigset_t *d, |
| 143 | 143 | d->sig[0] = target_sigmask; |
| 144 | 144 | d->sig[1] = sigmask >> 32; |
| 145 | 145 | #else |
| 146 | -#warning host_to_target_sigset | |
| 146 | + /* XXX: do it */ | |
| 147 | 147 | #endif |
| 148 | 148 | } |
| 149 | 149 | |
| ... | ... | @@ -177,7 +177,7 @@ void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) |
| 177 | 177 | #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 |
| 178 | 178 | ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32); |
| 179 | 179 | #else |
| 180 | -#warning target_to_host_sigset | |
| 180 | + /* XXX: do it */ | |
| 181 | 181 | #endif /* TARGET_ABI_BITS */ |
| 182 | 182 | } |
| 183 | 183 | |
| ... | ... | @@ -233,7 +233,7 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, |
| 233 | 233 | tinfo->_sifields._rt._uid = info->si_uid; |
| 234 | 234 | /* XXX: potential problem if 64 bit */ |
| 235 | 235 | tinfo->_sifields._rt._sigval.sival_ptr = |
| 236 | - (abi_ulong)info->si_value.sival_ptr; | |
| 236 | + (abi_ulong)(unsigned long)info->si_value.sival_ptr; | |
| 237 | 237 | } |
| 238 | 238 | } |
| 239 | 239 | |
| ... | ... | @@ -276,7 +276,7 @@ void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) |
| 276 | 276 | info->si_pid = tswap32(tinfo->_sifields._rt._pid); |
| 277 | 277 | info->si_uid = tswap32(tinfo->_sifields._rt._uid); |
| 278 | 278 | info->si_value.sival_ptr = |
| 279 | - (void *)tswapl(tinfo->_sifields._rt._sigval.sival_ptr); | |
| 279 | + (void *)(long)tswapl(tinfo->_sifields._rt._sigval.sival_ptr); | |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | 282 | void signal_init(void) |
| ... | ... | @@ -562,7 +562,7 @@ static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, |
| 562 | 562 | return 0; |
| 563 | 563 | } |
| 564 | 564 | |
| 565 | -#ifdef TARGET_I386 | |
| 565 | +#if defined(TARGET_I386) && TARGET_ABI_BITS == 32 | |
| 566 | 566 | |
| 567 | 567 | /* from the Linux kernel */ |
| 568 | 568 | |
| ... | ... | @@ -773,11 +773,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 773 | 773 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ |
| 774 | 774 | val16 = 0xb858; |
| 775 | 775 | err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); |
| 776 | -#if defined(TARGET_X86_64) | |
| 777 | -#warning "Fix this !" | |
| 778 | -#else | |
| 779 | 776 | err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); |
| 780 | -#endif | |
| 781 | 777 | val16 = 0x80cd; |
| 782 | 778 | err |= __put_user(val16, (uint16_t *)(frame->retcode+6)); |
| 783 | 779 | } |
| ... | ... | @@ -1486,9 +1482,10 @@ struct target_rt_signal_frame { |
| 1486 | 1482 | #define UREG_FP UREG_I6 |
| 1487 | 1483 | #define UREG_SP UREG_O6 |
| 1488 | 1484 | |
| 1489 | -static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, unsigned long framesize) | |
| 1485 | +static inline abi_ulong get_sigframe(struct emulated_sigaction *sa, | |
| 1486 | + CPUState *env, unsigned long framesize) | |
| 1490 | 1487 | { |
| 1491 | - unsigned long sp; | |
| 1488 | + abi_ulong sp; | |
| 1492 | 1489 | |
| 1493 | 1490 | sp = env->regwptr[UREG_FP]; |
| 1494 | 1491 | |
| ... | ... | @@ -1498,7 +1495,7 @@ static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, u |
| 1498 | 1495 | && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) |
| 1499 | 1496 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| 1500 | 1497 | } |
| 1501 | - return g2h(sp - framesize); | |
| 1498 | + return sp - framesize; | |
| 1502 | 1499 | } |
| 1503 | 1500 | |
| 1504 | 1501 | static int |
| ... | ... | @@ -1543,6 +1540,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ |
| 1543 | 1540 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1544 | 1541 | target_sigset_t *set, CPUState *env) |
| 1545 | 1542 | { |
| 1543 | + abi_ulong sf_addr; | |
| 1546 | 1544 | struct target_signal_frame *sf; |
| 1547 | 1545 | int sigframe_size, err, i; |
| 1548 | 1546 | |
| ... | ... | @@ -1550,10 +1548,13 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1550 | 1548 | //synchronize_user_stack(); |
| 1551 | 1549 | |
| 1552 | 1550 | sigframe_size = NF_ALIGNEDSZ; |
| 1551 | + sf_addr = get_sigframe(ka, env, sigframe_size); | |
| 1553 | 1552 | |
| 1554 | - sf = (struct target_signal_frame *) | |
| 1555 | - get_sigframe(ka, env, sigframe_size); | |
| 1556 | - | |
| 1553 | + sf = lock_user(VERIFY_WRITE, sf_addr, | |
| 1554 | + sizeof(struct target_signal_frame), 0); | |
| 1555 | + if (!sf) | |
| 1556 | + goto sigsegv; | |
| 1557 | + | |
| 1557 | 1558 | //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); |
| 1558 | 1559 | #if 0 |
| 1559 | 1560 | if (invalid_frame_pointer(sf, sigframe_size)) |
| ... | ... | @@ -1581,20 +1582,24 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1581 | 1582 | goto sigsegv; |
| 1582 | 1583 | |
| 1583 | 1584 | /* 3. signal handler back-trampoline and parameters */ |
| 1584 | - env->regwptr[UREG_FP] = h2g(sf); | |
| 1585 | + env->regwptr[UREG_FP] = sf_addr; | |
| 1585 | 1586 | env->regwptr[UREG_I0] = sig; |
| 1586 | - env->regwptr[UREG_I1] = h2g(&sf->info); | |
| 1587 | - env->regwptr[UREG_I2] = h2g(&sf->info); | |
| 1587 | + env->regwptr[UREG_I1] = sf_addr + | |
| 1588 | + offsetof(struct target_signal_frame, info); | |
| 1589 | + env->regwptr[UREG_I2] = sf_addr + | |
| 1590 | + offsetof(struct target_signal_frame, info); | |
| 1588 | 1591 | |
| 1589 | 1592 | /* 4. signal handler */ |
| 1590 | - env->pc = (unsigned long) ka->sa._sa_handler; | |
| 1593 | + env->pc = ka->sa._sa_handler; | |
| 1591 | 1594 | env->npc = (env->pc + 4); |
| 1592 | 1595 | /* 5. return to kernel instructions */ |
| 1593 | 1596 | if (ka->sa.sa_restorer) |
| 1594 | - env->regwptr[UREG_I7] = (unsigned long)ka->sa.sa_restorer; | |
| 1597 | + env->regwptr[UREG_I7] = ka->sa.sa_restorer; | |
| 1595 | 1598 | else { |
| 1596 | 1599 | uint32_t val32; |
| 1597 | - env->regwptr[UREG_I7] = h2g(&(sf->insns[0]) - 2); | |
| 1600 | + | |
| 1601 | + env->regwptr[UREG_I7] = sf_addr + | |
| 1602 | + offsetof(struct target_signal_frame, insns) - 2 * 4; | |
| 1598 | 1603 | |
| 1599 | 1604 | /* mov __NR_sigreturn, %g1 */ |
| 1600 | 1605 | val32 = 0x821020d8; |
| ... | ... | @@ -1610,12 +1615,15 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1610 | 1615 | //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); |
| 1611 | 1616 | // tb_flush(env); |
| 1612 | 1617 | } |
| 1618 | + unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); | |
| 1613 | 1619 | return; |
| 1614 | - | |
| 1615 | - //sigill_and_return: | |
| 1620 | +#if 0 | |
| 1621 | +sigill_and_return: | |
| 1616 | 1622 | force_sig(TARGET_SIGILL); |
| 1623 | +#endif | |
| 1617 | 1624 | sigsegv: |
| 1618 | 1625 | //fprintf(stderr, "force_sig\n"); |
| 1626 | + unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); | |
| 1619 | 1627 | force_sig(TARGET_SIGSEGV); |
| 1620 | 1628 | } |
| 1621 | 1629 | static inline int |
| ... | ... | @@ -1744,7 +1752,7 @@ long do_rt_sigreturn(CPUState *env) |
| 1744 | 1752 | return -ENOSYS; |
| 1745 | 1753 | } |
| 1746 | 1754 | |
| 1747 | -#ifdef TARGET_SPARC64 | |
| 1755 | +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) | |
| 1748 | 1756 | #define MC_TSTATE 0 |
| 1749 | 1757 | #define MC_PC 1 |
| 1750 | 1758 | #define MC_NPC 2 |
| ... | ... | @@ -1815,16 +1823,18 @@ struct target_reg_window { |
| 1815 | 1823 | /* {set, get}context() needed for 64-bit SparcLinux userland. */ |
| 1816 | 1824 | void sparc64_set_context(CPUSPARCState *env) |
| 1817 | 1825 | { |
| 1818 | - struct target_ucontext *ucp = (struct target_ucontext *) | |
| 1819 | - env->regwptr[UREG_I0]; | |
| 1826 | + abi_ulong ucp_addr; | |
| 1827 | + struct target_ucontext *ucp; | |
| 1820 | 1828 | target_mc_gregset_t *grp; |
| 1821 | 1829 | abi_ulong pc, npc, tstate; |
| 1822 | - abi_ulong fp, i7; | |
| 1830 | + abi_ulong fp, i7, w_addr; | |
| 1823 | 1831 | unsigned char fenab; |
| 1824 | 1832 | int err; |
| 1825 | 1833 | unsigned int i; |
| 1826 | - abi_ulong *src, *dst; | |
| 1827 | 1834 | |
| 1835 | + ucp_addr = env->regwptr[UREG_I0]; | |
| 1836 | + if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) | |
| 1837 | + goto do_sigsegv; | |
| 1828 | 1838 | grp = &ucp->uc_mcontext.mc_gregs; |
| 1829 | 1839 | err = __get_user(pc, &((*grp)[MC_PC])); |
| 1830 | 1840 | err |= __get_user(npc, &((*grp)[MC_NPC])); |
| ... | ... | @@ -1838,11 +1848,12 @@ void sparc64_set_context(CPUSPARCState *env) |
| 1838 | 1848 | if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) |
| 1839 | 1849 | goto do_sigsegv; |
| 1840 | 1850 | } else { |
| 1841 | - src = &ucp->uc_sigmask; | |
| 1842 | - dst = &target_set; | |
| 1851 | + abi_ulong *src, *dst; | |
| 1852 | + src = ucp->uc_sigmask.sig; | |
| 1853 | + dst = target_set.sig; | |
| 1843 | 1854 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
| 1844 | 1855 | i++, dst++, src++) |
| 1845 | - err |= __get_user(dst, src); | |
| 1856 | + err |= __get_user(*dst, src); | |
| 1846 | 1857 | if (err) |
| 1847 | 1858 | goto do_sigsegv; |
| 1848 | 1859 | } |
| ... | ... | @@ -1874,42 +1885,53 @@ void sparc64_set_context(CPUSPARCState *env) |
| 1874 | 1885 | |
| 1875 | 1886 | err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); |
| 1876 | 1887 | err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); |
| 1877 | - err |= __put_user(fp, | |
| 1878 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
| 1879 | - err |= __put_user(i7, | |
| 1880 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
| 1881 | 1888 | |
| 1889 | + w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6]; | |
| 1890 | + if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), | |
| 1891 | + abi_ulong) != 0) | |
| 1892 | + goto do_sigsegv; | |
| 1893 | + if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), | |
| 1894 | + abi_ulong) != 0) | |
| 1895 | + goto do_sigsegv; | |
| 1882 | 1896 | err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); |
| 1883 | 1897 | err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); |
| 1884 | - src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); | |
| 1885 | - dst = &env->fpr; | |
| 1886 | - for (i = 0; i < 64; i++, dst++, src++) | |
| 1887 | - err |= __get_user(dst, src); | |
| 1898 | + { | |
| 1899 | + uint32_t *src, *dst; | |
| 1900 | + src = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs; | |
| 1901 | + dst = env->fpr; | |
| 1902 | + /* XXX: check that the CPU storage is the same as user context */ | |
| 1903 | + for (i = 0; i < 64; i++, dst++, src++) | |
| 1904 | + err |= __get_user(*dst, src); | |
| 1905 | + } | |
| 1888 | 1906 | err |= __get_user(env->fsr, |
| 1889 | 1907 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); |
| 1890 | 1908 | err |= __get_user(env->gsr, |
| 1891 | 1909 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); |
| 1892 | 1910 | if (err) |
| 1893 | 1911 | goto do_sigsegv; |
| 1894 | - | |
| 1912 | + unlock_user_struct(ucp, ucp_addr, 0); | |
| 1895 | 1913 | return; |
| 1896 | 1914 | do_sigsegv: |
| 1915 | + unlock_user_struct(ucp, ucp_addr, 0); | |
| 1897 | 1916 | force_sig(SIGSEGV); |
| 1898 | 1917 | } |
| 1899 | 1918 | |
| 1900 | 1919 | void sparc64_get_context(CPUSPARCState *env) |
| 1901 | 1920 | { |
| 1902 | - struct target_ucontext *ucp = (struct target_ucontext *) | |
| 1903 | - env->regwptr[UREG_I0]; | |
| 1921 | + abi_ulong ucp_addr; | |
| 1922 | + struct target_ucontext *ucp; | |
| 1904 | 1923 | target_mc_gregset_t *grp; |
| 1905 | 1924 | target_mcontext_t *mcp; |
| 1906 | - abi_ulong fp, i7; | |
| 1925 | + abi_ulong fp, i7, w_addr; | |
| 1907 | 1926 | int err; |
| 1908 | 1927 | unsigned int i; |
| 1909 | - abi_ulong *src, *dst; | |
| 1910 | 1928 | target_sigset_t target_set; |
| 1911 | 1929 | sigset_t set; |
| 1912 | 1930 | |
| 1931 | + ucp_addr = env->regwptr[UREG_I0]; | |
| 1932 | + if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) | |
| 1933 | + goto do_sigsegv; | |
| 1934 | + | |
| 1913 | 1935 | mcp = &ucp->uc_mcontext; |
| 1914 | 1936 | grp = &mcp->mc_gregs; |
| 1915 | 1937 | |
| ... | ... | @@ -1921,20 +1943,22 @@ void sparc64_get_context(CPUSPARCState *env) |
| 1921 | 1943 | |
| 1922 | 1944 | sigprocmask(0, NULL, &set); |
| 1923 | 1945 | host_to_target_sigset_internal(&target_set, &set); |
| 1924 | - if (TARGET_NSIG_WORDS == 1) | |
| 1946 | + if (TARGET_NSIG_WORDS == 1) { | |
| 1925 | 1947 | err |= __put_user(target_set.sig[0], |
| 1926 | 1948 | (abi_ulong *)&ucp->uc_sigmask); |
| 1927 | - else { | |
| 1928 | - src = &target_set; | |
| 1929 | - dst = &ucp->uc_sigmask; | |
| 1949 | + } else { | |
| 1950 | + abi_ulong *src, *dst; | |
| 1951 | + src = target_set.sig; | |
| 1952 | + dst = ucp->uc_sigmask.sig; | |
| 1930 | 1953 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
| 1931 | 1954 | i++, dst++, src++) |
| 1932 | - err |= __put_user(src, dst); | |
| 1955 | + err |= __put_user(*src, dst); | |
| 1933 | 1956 | if (err) |
| 1934 | 1957 | goto do_sigsegv; |
| 1935 | 1958 | } |
| 1936 | 1959 | |
| 1937 | - err |= __put_user(env->tstate, &((*grp)[MC_TSTATE])); | |
| 1960 | + /* XXX: tstate must be saved properly */ | |
| 1961 | + // err |= __put_user(env->tstate, &((*grp)[MC_TSTATE])); | |
| 1938 | 1962 | err |= __put_user(env->pc, &((*grp)[MC_PC])); |
| 1939 | 1963 | err |= __put_user(env->npc, &((*grp)[MC_NPC])); |
| 1940 | 1964 | err |= __put_user(env->y, &((*grp)[MC_Y])); |
| ... | ... | @@ -1954,26 +1978,35 @@ void sparc64_get_context(CPUSPARCState *env) |
| 1954 | 1978 | err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); |
| 1955 | 1979 | err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); |
| 1956 | 1980 | |
| 1957 | - err |= __get_user(fp, | |
| 1958 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
| 1959 | - err |= __get_user(i7, | |
| 1960 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
| 1981 | + w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6]; | |
| 1982 | + fp = i7 = 0; | |
| 1983 | + if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), | |
| 1984 | + abi_ulong) != 0) | |
| 1985 | + goto do_sigsegv; | |
| 1986 | + if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), | |
| 1987 | + abi_ulong) != 0) | |
| 1988 | + goto do_sigsegv; | |
| 1961 | 1989 | err |= __put_user(fp, &(mcp->mc_fp)); |
| 1962 | 1990 | err |= __put_user(i7, &(mcp->mc_i7)); |
| 1963 | 1991 | |
| 1964 | - src = &env->fpr; | |
| 1965 | - dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); | |
| 1966 | - for (i = 0; i < 64; i++, dst++, src++) | |
| 1967 | - err |= __put_user(src, dst); | |
| 1992 | + { | |
| 1993 | + uint32_t *src, *dst; | |
| 1994 | + src = env->fpr; | |
| 1995 | + dst = ucp->uc_mcontext.mc_fpregs.mcfpu_fregs.sregs; | |
| 1996 | + /* XXX: check that the CPU storage is the same as user context */ | |
| 1997 | + for (i = 0; i < 64; i++, dst++, src++) | |
| 1998 | + err |= __put_user(*src, dst); | |
| 1999 | + } | |
| 1968 | 2000 | err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); |
| 1969 | 2001 | err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); |
| 1970 | 2002 | err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); |
| 1971 | 2003 | |
| 1972 | 2004 | if (err) |
| 1973 | 2005 | goto do_sigsegv; |
| 1974 | - | |
| 2006 | + unlock_user_struct(ucp, ucp_addr, 1); | |
| 1975 | 2007 | return; |
| 1976 | 2008 | do_sigsegv: |
| 2009 | + unlock_user_struct(ucp, ucp_addr, 1); | |
| 1977 | 2010 | force_sig(SIGSEGV); |
| 1978 | 2011 | } |
| 1979 | 2012 | #endif | ... | ... |