Revision 459a4017
b/linux-user/signal.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
Also available in: Unified diff