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 | 634 | queue_signal(info.si_signo, &info); |
635 | 635 | } |
636 | 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 | 645 | #endif |
638 | 646 | case EXCP_INTERRUPT: |
639 | 647 | /* just indicate that signals should be handled asap */ | ... | ... |
linux-user/qemu.h
... | ... | @@ -160,6 +160,9 @@ void save_v86_state(CPUX86State *env); |
160 | 160 | void handle_vm86_trap(CPUX86State *env, int trapno); |
161 | 161 | void handle_vm86_fault(CPUX86State *env); |
162 | 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 | 166 | #endif |
164 | 167 | |
165 | 168 | /* mmap.c */ | ... | ... |
linux-user/signal.c
... | ... | @@ -1443,6 +1443,9 @@ struct target_rt_signal_frame { |
1443 | 1443 | #define UREG_I0 0 |
1444 | 1444 | #define UREG_I1 1 |
1445 | 1445 | #define UREG_I2 2 |
1446 | +#define UREG_I3 3 | |
1447 | +#define UREG_I4 4 | |
1448 | +#define UREG_I5 5 | |
1446 | 1449 | #define UREG_I6 6 |
1447 | 1450 | #define UREG_I7 7 |
1448 | 1451 | #define UREG_L0 8 |
... | ... | @@ -1704,6 +1707,239 @@ long do_rt_sigreturn(CPUState *env) |
1704 | 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 | 1943 | #elif defined(TARGET_MIPS64) |
1708 | 1944 | |
1709 | 1945 | # warning signal handling not implemented | ... | ... |