Commit 5bfb56b264d18be57f16c519464fc1919db44372
1 parent
65f9ee8d
Implement sparc64_[gs]et_context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3334 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
247 additions
and
0 deletions
linux-user/main.c
| @@ -634,6 +634,14 @@ void cpu_loop (CPUSPARCState *env) | @@ -634,6 +634,14 @@ void cpu_loop (CPUSPARCState *env) | ||
| 634 | queue_signal(info.si_signo, &info); | 634 | queue_signal(info.si_signo, &info); |
| 635 | } | 635 | } |
| 636 | break; | 636 | break; |
| 637 | + case 0x16e: | ||
| 638 | + flush_windows(env); | ||
| 639 | + sparc64_get_context(env); | ||
| 640 | + break; | ||
| 641 | + case 0x16f: | ||
| 642 | + flush_windows(env); | ||
| 643 | + sparc64_set_context(env); | ||
| 644 | + break; | ||
| 637 | #endif | 645 | #endif |
| 638 | case EXCP_INTERRUPT: | 646 | case EXCP_INTERRUPT: |
| 639 | /* just indicate that signals should be handled asap */ | 647 | /* just indicate that signals should be handled asap */ |
linux-user/qemu.h
| @@ -160,6 +160,9 @@ void save_v86_state(CPUX86State *env); | @@ -160,6 +160,9 @@ void save_v86_state(CPUX86State *env); | ||
| 160 | void handle_vm86_trap(CPUX86State *env, int trapno); | 160 | void handle_vm86_trap(CPUX86State *env, int trapno); |
| 161 | void handle_vm86_fault(CPUX86State *env); | 161 | void handle_vm86_fault(CPUX86State *env); |
| 162 | int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr); | 162 | int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr); |
| 163 | +#elif defined(TARGET_SPARC64) | ||
| 164 | +void sparc64_set_context(CPUSPARCState *env); | ||
| 165 | +void sparc64_get_context(CPUSPARCState *env); | ||
| 163 | #endif | 166 | #endif |
| 164 | 167 | ||
| 165 | /* mmap.c */ | 168 | /* mmap.c */ |
linux-user/signal.c
| @@ -1443,6 +1443,9 @@ struct target_rt_signal_frame { | @@ -1443,6 +1443,9 @@ struct target_rt_signal_frame { | ||
| 1443 | #define UREG_I0 0 | 1443 | #define UREG_I0 0 |
| 1444 | #define UREG_I1 1 | 1444 | #define UREG_I1 1 |
| 1445 | #define UREG_I2 2 | 1445 | #define UREG_I2 2 |
| 1446 | +#define UREG_I3 3 | ||
| 1447 | +#define UREG_I4 4 | ||
| 1448 | +#define UREG_I5 5 | ||
| 1446 | #define UREG_I6 6 | 1449 | #define UREG_I6 6 |
| 1447 | #define UREG_I7 7 | 1450 | #define UREG_I7 7 |
| 1448 | #define UREG_L0 8 | 1451 | #define UREG_L0 8 |
| @@ -1704,6 +1707,239 @@ long do_rt_sigreturn(CPUState *env) | @@ -1704,6 +1707,239 @@ long do_rt_sigreturn(CPUState *env) | ||
| 1704 | return -ENOSYS; | 1707 | return -ENOSYS; |
| 1705 | } | 1708 | } |
| 1706 | 1709 | ||
| 1710 | +#ifdef TARGET_SPARC64 | ||
| 1711 | +#define MC_TSTATE 0 | ||
| 1712 | +#define MC_PC 1 | ||
| 1713 | +#define MC_NPC 2 | ||
| 1714 | +#define MC_Y 3 | ||
| 1715 | +#define MC_G1 4 | ||
| 1716 | +#define MC_G2 5 | ||
| 1717 | +#define MC_G3 6 | ||
| 1718 | +#define MC_G4 7 | ||
| 1719 | +#define MC_G5 8 | ||
| 1720 | +#define MC_G6 9 | ||
| 1721 | +#define MC_G7 10 | ||
| 1722 | +#define MC_O0 11 | ||
| 1723 | +#define MC_O1 12 | ||
| 1724 | +#define MC_O2 13 | ||
| 1725 | +#define MC_O3 14 | ||
| 1726 | +#define MC_O4 15 | ||
| 1727 | +#define MC_O5 16 | ||
| 1728 | +#define MC_O6 17 | ||
| 1729 | +#define MC_O7 18 | ||
| 1730 | +#define MC_NGREG 19 | ||
| 1731 | + | ||
| 1732 | +typedef target_ulong target_mc_greg_t; | ||
| 1733 | +typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG]; | ||
| 1734 | + | ||
| 1735 | +struct target_mc_fq { | ||
| 1736 | + target_ulong *mcfq_addr; | ||
| 1737 | + uint32_t mcfq_insn; | ||
| 1738 | +}; | ||
| 1739 | + | ||
| 1740 | +struct target_mc_fpu { | ||
| 1741 | + union { | ||
| 1742 | + uint32_t sregs[32]; | ||
| 1743 | + uint64_t dregs[32]; | ||
| 1744 | + //uint128_t qregs[16]; | ||
| 1745 | + } mcfpu_fregs; | ||
| 1746 | + target_ulong mcfpu_fsr; | ||
| 1747 | + target_ulong mcfpu_fprs; | ||
| 1748 | + target_ulong mcfpu_gsr; | ||
| 1749 | + struct target_mc_fq *mcfpu_fq; | ||
| 1750 | + unsigned char mcfpu_qcnt; | ||
| 1751 | + unsigned char mcfpu_qentsz; | ||
| 1752 | + unsigned char mcfpu_enab; | ||
| 1753 | +}; | ||
| 1754 | +typedef struct target_mc_fpu target_mc_fpu_t; | ||
| 1755 | + | ||
| 1756 | +typedef struct { | ||
| 1757 | + target_mc_gregset_t mc_gregs; | ||
| 1758 | + target_mc_greg_t mc_fp; | ||
| 1759 | + target_mc_greg_t mc_i7; | ||
| 1760 | + target_mc_fpu_t mc_fpregs; | ||
| 1761 | +} target_mcontext_t; | ||
| 1762 | + | ||
| 1763 | +struct target_ucontext { | ||
| 1764 | + struct target_ucontext *uc_link; | ||
| 1765 | + target_ulong uc_flags; | ||
| 1766 | + target_sigset_t uc_sigmask; | ||
| 1767 | + target_mcontext_t uc_mcontext; | ||
| 1768 | +}; | ||
| 1769 | + | ||
| 1770 | +/* A V9 register window */ | ||
| 1771 | +struct target_reg_window { | ||
| 1772 | + target_ulong locals[8]; | ||
| 1773 | + target_ulong ins[8]; | ||
| 1774 | +}; | ||
| 1775 | + | ||
| 1776 | +#define TARGET_STACK_BIAS 2047 | ||
| 1777 | + | ||
| 1778 | +/* {set, get}context() needed for 64-bit SparcLinux userland. */ | ||
| 1779 | +void sparc64_set_context(CPUSPARCState *env) | ||
| 1780 | +{ | ||
| 1781 | + struct target_ucontext *ucp = (struct target_ucontext *) | ||
| 1782 | + env->regwptr[UREG_I0]; | ||
| 1783 | + target_mc_gregset_t *grp; | ||
| 1784 | + target_ulong pc, npc, tstate; | ||
| 1785 | + target_ulong fp, i7; | ||
| 1786 | + unsigned char fenab; | ||
| 1787 | + int err; | ||
| 1788 | + unsigned int i; | ||
| 1789 | + target_ulong *src, *dst; | ||
| 1790 | + | ||
| 1791 | + grp = &ucp->uc_mcontext.mc_gregs; | ||
| 1792 | + err = get_user(pc, &((*grp)[MC_PC])); | ||
| 1793 | + err |= get_user(npc, &((*grp)[MC_NPC])); | ||
| 1794 | + if (err || ((pc | npc) & 3)) | ||
| 1795 | + goto do_sigsegv; | ||
| 1796 | + if (env->regwptr[UREG_I1]) { | ||
| 1797 | + target_sigset_t target_set; | ||
| 1798 | + sigset_t set; | ||
| 1799 | + | ||
| 1800 | + if (TARGET_NSIG_WORDS == 1) { | ||
| 1801 | + if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) | ||
| 1802 | + goto do_sigsegv; | ||
| 1803 | + } else { | ||
| 1804 | + src = &ucp->uc_sigmask; | ||
| 1805 | + dst = &target_set; | ||
| 1806 | + for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong); | ||
| 1807 | + i++, dst++, src++) | ||
| 1808 | + err |= get_user(dst, src); | ||
| 1809 | + if (err) | ||
| 1810 | + goto do_sigsegv; | ||
| 1811 | + } | ||
| 1812 | + target_to_host_sigset_internal(&set, &target_set); | ||
| 1813 | + sigprocmask(SIG_SETMASK, &set, NULL); | ||
| 1814 | + } | ||
| 1815 | + env->pc = pc; | ||
| 1816 | + env->npc = npc; | ||
| 1817 | + err |= get_user(env->y, &((*grp)[MC_Y])); | ||
| 1818 | + err |= get_user(tstate, &((*grp)[MC_TSTATE])); | ||
| 1819 | + env->asi = (tstate >> 24) & 0xff; | ||
| 1820 | + PUT_CCR(env, tstate >> 32); | ||
| 1821 | + PUT_CWP64(env, tstate & 0x1f); | ||
| 1822 | + err |= get_user(env->gregs[1], (&(*grp)[MC_G1])); | ||
| 1823 | + err |= get_user(env->gregs[2], (&(*grp)[MC_G2])); | ||
| 1824 | + err |= get_user(env->gregs[3], (&(*grp)[MC_G3])); | ||
| 1825 | + err |= get_user(env->gregs[4], (&(*grp)[MC_G4])); | ||
| 1826 | + err |= get_user(env->gregs[5], (&(*grp)[MC_G5])); | ||
| 1827 | + err |= get_user(env->gregs[6], (&(*grp)[MC_G6])); | ||
| 1828 | + err |= get_user(env->gregs[7], (&(*grp)[MC_G7])); | ||
| 1829 | + err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); | ||
| 1830 | + err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); | ||
| 1831 | + err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); | ||
| 1832 | + err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); | ||
| 1833 | + err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); | ||
| 1834 | + err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); | ||
| 1835 | + err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); | ||
| 1836 | + err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); | ||
| 1837 | + | ||
| 1838 | + err |= get_user(fp, &(ucp->uc_mcontext.mc_fp)); | ||
| 1839 | + err |= get_user(i7, &(ucp->uc_mcontext.mc_i7)); | ||
| 1840 | + err |= put_user(fp, | ||
| 1841 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | ||
| 1842 | + err |= put_user(i7, | ||
| 1843 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | ||
| 1844 | + | ||
| 1845 | + err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); | ||
| 1846 | + err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); | ||
| 1847 | + src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); | ||
| 1848 | + dst = &env->fpr; | ||
| 1849 | + for (i = 0; i < 64; i++, dst++, src++) | ||
| 1850 | + err |= get_user(dst, src); | ||
| 1851 | + err |= get_user(env->fsr, | ||
| 1852 | + &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); | ||
| 1853 | + err |= get_user(env->gsr, | ||
| 1854 | + &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); | ||
| 1855 | + if (err) | ||
| 1856 | + goto do_sigsegv; | ||
| 1857 | + | ||
| 1858 | + return; | ||
| 1859 | + do_sigsegv: | ||
| 1860 | + force_sig(SIGSEGV); | ||
| 1861 | +} | ||
| 1862 | + | ||
| 1863 | +void sparc64_get_context(CPUSPARCState *env) | ||
| 1864 | +{ | ||
| 1865 | + struct target_ucontext *ucp = (struct target_ucontext *) | ||
| 1866 | + env->regwptr[UREG_I0]; | ||
| 1867 | + target_mc_gregset_t *grp; | ||
| 1868 | + target_mcontext_t *mcp; | ||
| 1869 | + target_ulong fp, i7; | ||
| 1870 | + int err; | ||
| 1871 | + unsigned int i; | ||
| 1872 | + target_ulong *src, *dst; | ||
| 1873 | + target_sigset_t target_set; | ||
| 1874 | + sigset_t set; | ||
| 1875 | + | ||
| 1876 | + mcp = &ucp->uc_mcontext; | ||
| 1877 | + grp = &mcp->mc_gregs; | ||
| 1878 | + | ||
| 1879 | + /* Skip over the trap instruction, first. */ | ||
| 1880 | + env->pc = env->npc; | ||
| 1881 | + env->npc += 4; | ||
| 1882 | + | ||
| 1883 | + err = 0; | ||
| 1884 | + | ||
| 1885 | + sigprocmask(0, NULL, &set); | ||
| 1886 | + host_to_target_sigset_internal(&target_set, &set); | ||
| 1887 | + if (TARGET_NSIG_WORDS == 1) | ||
| 1888 | + err |= put_user(target_set.sig[0], | ||
| 1889 | + (target_ulong *)&ucp->uc_sigmask); | ||
| 1890 | + else { | ||
| 1891 | + src = &target_set; | ||
| 1892 | + dst = &ucp->uc_sigmask; | ||
| 1893 | + for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong); | ||
| 1894 | + i++, dst++, src++) | ||
| 1895 | + err |= put_user(src, dst); | ||
| 1896 | + if (err) | ||
| 1897 | + goto do_sigsegv; | ||
| 1898 | + } | ||
| 1899 | + | ||
| 1900 | + err |= put_user(env->tstate, &((*grp)[MC_TSTATE])); | ||
| 1901 | + err |= put_user(env->pc, &((*grp)[MC_PC])); | ||
| 1902 | + err |= put_user(env->npc, &((*grp)[MC_NPC])); | ||
| 1903 | + err |= put_user(env->y, &((*grp)[MC_Y])); | ||
| 1904 | + err |= put_user(env->gregs[1], &((*grp)[MC_G1])); | ||
| 1905 | + err |= put_user(env->gregs[2], &((*grp)[MC_G2])); | ||
| 1906 | + err |= put_user(env->gregs[3], &((*grp)[MC_G3])); | ||
| 1907 | + err |= put_user(env->gregs[4], &((*grp)[MC_G4])); | ||
| 1908 | + err |= put_user(env->gregs[5], &((*grp)[MC_G5])); | ||
| 1909 | + err |= put_user(env->gregs[6], &((*grp)[MC_G6])); | ||
| 1910 | + err |= put_user(env->gregs[7], &((*grp)[MC_G7])); | ||
| 1911 | + err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); | ||
| 1912 | + err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); | ||
| 1913 | + err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); | ||
| 1914 | + err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); | ||
| 1915 | + err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); | ||
| 1916 | + err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); | ||
| 1917 | + err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); | ||
| 1918 | + err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); | ||
| 1919 | + | ||
| 1920 | + err |= get_user(fp, | ||
| 1921 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | ||
| 1922 | + err |= get_user(i7, | ||
| 1923 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | ||
| 1924 | + err |= put_user(fp, &(mcp->mc_fp)); | ||
| 1925 | + err |= put_user(i7, &(mcp->mc_i7)); | ||
| 1926 | + | ||
| 1927 | + src = &env->fpr; | ||
| 1928 | + dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); | ||
| 1929 | + for (i = 0; i < 64; i++, dst++, src++) | ||
| 1930 | + err |= put_user(src, dst); | ||
| 1931 | + err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); | ||
| 1932 | + err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); | ||
| 1933 | + err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); | ||
| 1934 | + | ||
| 1935 | + if (err) | ||
| 1936 | + goto do_sigsegv; | ||
| 1937 | + | ||
| 1938 | + return; | ||
| 1939 | + do_sigsegv: | ||
| 1940 | + force_sig(SIGSEGV); | ||
| 1941 | +} | ||
| 1942 | +#endif | ||
| 1707 | #elif defined(TARGET_MIPS64) | 1943 | #elif defined(TARGET_MIPS64) |
| 1708 | 1944 | ||
| 1709 | # warning signal handling not implemented | 1945 | # warning signal handling not implemented |