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 | ... | ... |