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,7 +143,7 @@ static void host_to_target_sigset_internal(target_sigset_t *d, | ||
| 143 | d->sig[0] = target_sigmask; | 143 | d->sig[0] = target_sigmask; |
| 144 | d->sig[1] = sigmask >> 32; | 144 | d->sig[1] = sigmask >> 32; |
| 145 | #else | 145 | #else |
| 146 | -#warning host_to_target_sigset | 146 | + /* XXX: do it */ |
| 147 | #endif | 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,7 +177,7 @@ void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) | ||
| 177 | #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 | 177 | #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2 |
| 178 | ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32); | 178 | ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32); |
| 179 | #else | 179 | #else |
| 180 | -#warning target_to_host_sigset | 180 | + /* XXX: do it */ |
| 181 | #endif /* TARGET_ABI_BITS */ | 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,7 +233,7 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, | ||
| 233 | tinfo->_sifields._rt._uid = info->si_uid; | 233 | tinfo->_sifields._rt._uid = info->si_uid; |
| 234 | /* XXX: potential problem if 64 bit */ | 234 | /* XXX: potential problem if 64 bit */ |
| 235 | tinfo->_sifields._rt._sigval.sival_ptr = | 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,7 +276,7 @@ void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) | ||
| 276 | info->si_pid = tswap32(tinfo->_sifields._rt._pid); | 276 | info->si_pid = tswap32(tinfo->_sifields._rt._pid); |
| 277 | info->si_uid = tswap32(tinfo->_sifields._rt._uid); | 277 | info->si_uid = tswap32(tinfo->_sifields._rt._uid); |
| 278 | info->si_value.sival_ptr = | 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 | void signal_init(void) | 282 | void signal_init(void) |
| @@ -562,7 +562,7 @@ static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, | @@ -562,7 +562,7 @@ static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, | ||
| 562 | return 0; | 562 | return 0; |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | -#ifdef TARGET_I386 | 565 | +#if defined(TARGET_I386) && TARGET_ABI_BITS == 32 |
| 566 | 566 | ||
| 567 | /* from the Linux kernel */ | 567 | /* from the Linux kernel */ |
| 568 | 568 | ||
| @@ -773,11 +773,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -773,11 +773,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 773 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ | 773 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ |
| 774 | val16 = 0xb858; | 774 | val16 = 0xb858; |
| 775 | err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); | 775 | err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); |
| 776 | -#if defined(TARGET_X86_64) | ||
| 777 | -#warning "Fix this !" | ||
| 778 | -#else | ||
| 779 | err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); | 776 | err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); |
| 780 | -#endif | ||
| 781 | val16 = 0x80cd; | 777 | val16 = 0x80cd; |
| 782 | err |= __put_user(val16, (uint16_t *)(frame->retcode+6)); | 778 | err |= __put_user(val16, (uint16_t *)(frame->retcode+6)); |
| 783 | } | 779 | } |
| @@ -1486,9 +1482,10 @@ struct target_rt_signal_frame { | @@ -1486,9 +1482,10 @@ struct target_rt_signal_frame { | ||
| 1486 | #define UREG_FP UREG_I6 | 1482 | #define UREG_FP UREG_I6 |
| 1487 | #define UREG_SP UREG_O6 | 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 | sp = env->regwptr[UREG_FP]; | 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,7 +1495,7 @@ static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, u | ||
| 1498 | && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) | 1495 | && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) |
| 1499 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; | 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 | static int | 1501 | static int |
| @@ -1543,6 +1540,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ | @@ -1543,6 +1540,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ | ||
| 1543 | static void setup_frame(int sig, struct emulated_sigaction *ka, | 1540 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1544 | target_sigset_t *set, CPUState *env) | 1541 | target_sigset_t *set, CPUState *env) |
| 1545 | { | 1542 | { |
| 1543 | + abi_ulong sf_addr; | ||
| 1546 | struct target_signal_frame *sf; | 1544 | struct target_signal_frame *sf; |
| 1547 | int sigframe_size, err, i; | 1545 | int sigframe_size, err, i; |
| 1548 | 1546 | ||
| @@ -1550,10 +1548,13 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -1550,10 +1548,13 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 1550 | //synchronize_user_stack(); | 1548 | //synchronize_user_stack(); |
| 1551 | 1549 | ||
| 1552 | sigframe_size = NF_ALIGNEDSZ; | 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 | //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); | 1558 | //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); |
| 1558 | #if 0 | 1559 | #if 0 |
| 1559 | if (invalid_frame_pointer(sf, sigframe_size)) | 1560 | if (invalid_frame_pointer(sf, sigframe_size)) |
| @@ -1581,20 +1582,24 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -1581,20 +1582,24 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 1581 | goto sigsegv; | 1582 | goto sigsegv; |
| 1582 | 1583 | ||
| 1583 | /* 3. signal handler back-trampoline and parameters */ | 1584 | /* 3. signal handler back-trampoline and parameters */ |
| 1584 | - env->regwptr[UREG_FP] = h2g(sf); | 1585 | + env->regwptr[UREG_FP] = sf_addr; |
| 1585 | env->regwptr[UREG_I0] = sig; | 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 | /* 4. signal handler */ | 1592 | /* 4. signal handler */ |
| 1590 | - env->pc = (unsigned long) ka->sa._sa_handler; | 1593 | + env->pc = ka->sa._sa_handler; |
| 1591 | env->npc = (env->pc + 4); | 1594 | env->npc = (env->pc + 4); |
| 1592 | /* 5. return to kernel instructions */ | 1595 | /* 5. return to kernel instructions */ |
| 1593 | if (ka->sa.sa_restorer) | 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 | else { | 1598 | else { |
| 1596 | uint32_t val32; | 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 | /* mov __NR_sigreturn, %g1 */ | 1604 | /* mov __NR_sigreturn, %g1 */ |
| 1600 | val32 = 0x821020d8; | 1605 | val32 = 0x821020d8; |
| @@ -1610,12 +1615,15 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -1610,12 +1615,15 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 1610 | //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); | 1615 | //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); |
| 1611 | // tb_flush(env); | 1616 | // tb_flush(env); |
| 1612 | } | 1617 | } |
| 1618 | + unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); | ||
| 1613 | return; | 1619 | return; |
| 1614 | - | ||
| 1615 | - //sigill_and_return: | 1620 | +#if 0 |
| 1621 | +sigill_and_return: | ||
| 1616 | force_sig(TARGET_SIGILL); | 1622 | force_sig(TARGET_SIGILL); |
| 1623 | +#endif | ||
| 1617 | sigsegv: | 1624 | sigsegv: |
| 1618 | //fprintf(stderr, "force_sig\n"); | 1625 | //fprintf(stderr, "force_sig\n"); |
| 1626 | + unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); | ||
| 1619 | force_sig(TARGET_SIGSEGV); | 1627 | force_sig(TARGET_SIGSEGV); |
| 1620 | } | 1628 | } |
| 1621 | static inline int | 1629 | static inline int |
| @@ -1744,7 +1752,7 @@ long do_rt_sigreturn(CPUState *env) | @@ -1744,7 +1752,7 @@ long do_rt_sigreturn(CPUState *env) | ||
| 1744 | return -ENOSYS; | 1752 | return -ENOSYS; |
| 1745 | } | 1753 | } |
| 1746 | 1754 | ||
| 1747 | -#ifdef TARGET_SPARC64 | 1755 | +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) |
| 1748 | #define MC_TSTATE 0 | 1756 | #define MC_TSTATE 0 |
| 1749 | #define MC_PC 1 | 1757 | #define MC_PC 1 |
| 1750 | #define MC_NPC 2 | 1758 | #define MC_NPC 2 |
| @@ -1815,16 +1823,18 @@ struct target_reg_window { | @@ -1815,16 +1823,18 @@ struct target_reg_window { | ||
| 1815 | /* {set, get}context() needed for 64-bit SparcLinux userland. */ | 1823 | /* {set, get}context() needed for 64-bit SparcLinux userland. */ |
| 1816 | void sparc64_set_context(CPUSPARCState *env) | 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 | target_mc_gregset_t *grp; | 1828 | target_mc_gregset_t *grp; |
| 1821 | abi_ulong pc, npc, tstate; | 1829 | abi_ulong pc, npc, tstate; |
| 1822 | - abi_ulong fp, i7; | 1830 | + abi_ulong fp, i7, w_addr; |
| 1823 | unsigned char fenab; | 1831 | unsigned char fenab; |
| 1824 | int err; | 1832 | int err; |
| 1825 | unsigned int i; | 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 | grp = &ucp->uc_mcontext.mc_gregs; | 1838 | grp = &ucp->uc_mcontext.mc_gregs; |
| 1829 | err = __get_user(pc, &((*grp)[MC_PC])); | 1839 | err = __get_user(pc, &((*grp)[MC_PC])); |
| 1830 | err |= __get_user(npc, &((*grp)[MC_NPC])); | 1840 | err |= __get_user(npc, &((*grp)[MC_NPC])); |
| @@ -1838,11 +1848,12 @@ void sparc64_set_context(CPUSPARCState *env) | @@ -1838,11 +1848,12 @@ void sparc64_set_context(CPUSPARCState *env) | ||
| 1838 | if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) | 1848 | if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) |
| 1839 | goto do_sigsegv; | 1849 | goto do_sigsegv; |
| 1840 | } else { | 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 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); | 1854 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
| 1844 | i++, dst++, src++) | 1855 | i++, dst++, src++) |
| 1845 | - err |= __get_user(dst, src); | 1856 | + err |= __get_user(*dst, src); |
| 1846 | if (err) | 1857 | if (err) |
| 1847 | goto do_sigsegv; | 1858 | goto do_sigsegv; |
| 1848 | } | 1859 | } |
| @@ -1874,42 +1885,53 @@ void sparc64_set_context(CPUSPARCState *env) | @@ -1874,42 +1885,53 @@ void sparc64_set_context(CPUSPARCState *env) | ||
| 1874 | 1885 | ||
| 1875 | err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); | 1886 | err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); |
| 1876 | err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); | 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 | err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); | 1896 | err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); |
| 1883 | err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); | 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 | err |= __get_user(env->fsr, | 1906 | err |= __get_user(env->fsr, |
| 1889 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); | 1907 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); |
| 1890 | err |= __get_user(env->gsr, | 1908 | err |= __get_user(env->gsr, |
| 1891 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); | 1909 | &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); |
| 1892 | if (err) | 1910 | if (err) |
| 1893 | goto do_sigsegv; | 1911 | goto do_sigsegv; |
| 1894 | - | 1912 | + unlock_user_struct(ucp, ucp_addr, 0); |
| 1895 | return; | 1913 | return; |
| 1896 | do_sigsegv: | 1914 | do_sigsegv: |
| 1915 | + unlock_user_struct(ucp, ucp_addr, 0); | ||
| 1897 | force_sig(SIGSEGV); | 1916 | force_sig(SIGSEGV); |
| 1898 | } | 1917 | } |
| 1899 | 1918 | ||
| 1900 | void sparc64_get_context(CPUSPARCState *env) | 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 | target_mc_gregset_t *grp; | 1923 | target_mc_gregset_t *grp; |
| 1905 | target_mcontext_t *mcp; | 1924 | target_mcontext_t *mcp; |
| 1906 | - abi_ulong fp, i7; | 1925 | + abi_ulong fp, i7, w_addr; |
| 1907 | int err; | 1926 | int err; |
| 1908 | unsigned int i; | 1927 | unsigned int i; |
| 1909 | - abi_ulong *src, *dst; | ||
| 1910 | target_sigset_t target_set; | 1928 | target_sigset_t target_set; |
| 1911 | sigset_t set; | 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 | mcp = &ucp->uc_mcontext; | 1935 | mcp = &ucp->uc_mcontext; |
| 1914 | grp = &mcp->mc_gregs; | 1936 | grp = &mcp->mc_gregs; |
| 1915 | 1937 | ||
| @@ -1921,20 +1943,22 @@ void sparc64_get_context(CPUSPARCState *env) | @@ -1921,20 +1943,22 @@ void sparc64_get_context(CPUSPARCState *env) | ||
| 1921 | 1943 | ||
| 1922 | sigprocmask(0, NULL, &set); | 1944 | sigprocmask(0, NULL, &set); |
| 1923 | host_to_target_sigset_internal(&target_set, &set); | 1945 | host_to_target_sigset_internal(&target_set, &set); |
| 1924 | - if (TARGET_NSIG_WORDS == 1) | 1946 | + if (TARGET_NSIG_WORDS == 1) { |
| 1925 | err |= __put_user(target_set.sig[0], | 1947 | err |= __put_user(target_set.sig[0], |
| 1926 | (abi_ulong *)&ucp->uc_sigmask); | 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 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); | 1953 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
| 1931 | i++, dst++, src++) | 1954 | i++, dst++, src++) |
| 1932 | - err |= __put_user(src, dst); | 1955 | + err |= __put_user(*src, dst); |
| 1933 | if (err) | 1956 | if (err) |
| 1934 | goto do_sigsegv; | 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 | err |= __put_user(env->pc, &((*grp)[MC_PC])); | 1962 | err |= __put_user(env->pc, &((*grp)[MC_PC])); |
| 1939 | err |= __put_user(env->npc, &((*grp)[MC_NPC])); | 1963 | err |= __put_user(env->npc, &((*grp)[MC_NPC])); |
| 1940 | err |= __put_user(env->y, &((*grp)[MC_Y])); | 1964 | err |= __put_user(env->y, &((*grp)[MC_Y])); |
| @@ -1954,26 +1978,35 @@ void sparc64_get_context(CPUSPARCState *env) | @@ -1954,26 +1978,35 @@ void sparc64_get_context(CPUSPARCState *env) | ||
| 1954 | err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); | 1978 | err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); |
| 1955 | err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); | 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 | err |= __put_user(fp, &(mcp->mc_fp)); | 1989 | err |= __put_user(fp, &(mcp->mc_fp)); |
| 1962 | err |= __put_user(i7, &(mcp->mc_i7)); | 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 | err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); | 2000 | err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); |
| 1969 | err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); | 2001 | err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); |
| 1970 | err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); | 2002 | err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); |
| 1971 | 2003 | ||
| 1972 | if (err) | 2004 | if (err) |
| 1973 | goto do_sigsegv; | 2005 | goto do_sigsegv; |
| 1974 | - | 2006 | + unlock_user_struct(ucp, ucp_addr, 1); |
| 1975 | return; | 2007 | return; |
| 1976 | do_sigsegv: | 2008 | do_sigsegv: |
| 2009 | + unlock_user_struct(ucp, ucp_addr, 1); | ||
| 1977 | force_sig(SIGSEGV); | 2010 | force_sig(SIGSEGV); |
| 1978 | } | 2011 | } |
| 1979 | #endif | 2012 | #endif |