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 |