aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-05 17:01:51 +0000
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-05 17:01:51 +0000
commit5bfb56b264d18be57f16c519464fc1919db44372 (patch)
tree6ebf801cf88366386721708218b2c5d1e25ee113 /linux-user
parent65f9ee8d670e12a396857affb36920afd48f5e64 (diff)
Implement sparc64_[gs]et_context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3334 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c8
-rw-r--r--linux-user/qemu.h3
-rw-r--r--linux-user/signal.c236
3 files changed, 247 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 9c3d67d497..127ae109a8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -634,6 +634,14 @@ void cpu_loop (CPUSPARCState *env)
queue_signal(info.si_signo, &info);
}
break;
+ case 0x16e:
+ flush_windows(env);
+ sparc64_get_context(env);
+ break;
+ case 0x16f:
+ flush_windows(env);
+ sparc64_set_context(env);
+ break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index e07ac7b4dc..defa6b71e7 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -160,6 +160,9 @@ void save_v86_state(CPUX86State *env);
void handle_vm86_trap(CPUX86State *env, int trapno);
void handle_vm86_fault(CPUX86State *env);
int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr);
+#elif defined(TARGET_SPARC64)
+void sparc64_set_context(CPUSPARCState *env);
+void sparc64_get_context(CPUSPARCState *env);
#endif
/* mmap.c */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index d17c506d2d..52041dafdf 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1443,6 +1443,9 @@ struct target_rt_signal_frame {
#define UREG_I0 0
#define UREG_I1 1
#define UREG_I2 2
+#define UREG_I3 3
+#define UREG_I4 4
+#define UREG_I5 5
#define UREG_I6 6
#define UREG_I7 7
#define UREG_L0 8
@@ -1704,6 +1707,239 @@ long do_rt_sigreturn(CPUState *env)
return -ENOSYS;
}
+#ifdef TARGET_SPARC64
+#define MC_TSTATE 0
+#define MC_PC 1
+#define MC_NPC 2
+#define MC_Y 3
+#define MC_G1 4
+#define MC_G2 5
+#define MC_G3 6
+#define MC_G4 7
+#define MC_G5 8
+#define MC_G6 9
+#define MC_G7 10
+#define MC_O0 11
+#define MC_O1 12
+#define MC_O2 13
+#define MC_O3 14
+#define MC_O4 15
+#define MC_O5 16
+#define MC_O6 17
+#define MC_O7 18
+#define MC_NGREG 19
+
+typedef target_ulong target_mc_greg_t;
+typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
+
+struct target_mc_fq {
+ target_ulong *mcfq_addr;
+ uint32_t mcfq_insn;
+};
+
+struct target_mc_fpu {
+ union {
+ uint32_t sregs[32];
+ uint64_t dregs[32];
+ //uint128_t qregs[16];
+ } mcfpu_fregs;
+ target_ulong mcfpu_fsr;
+ target_ulong mcfpu_fprs;
+ target_ulong mcfpu_gsr;
+ struct target_mc_fq *mcfpu_fq;
+ unsigned char mcfpu_qcnt;
+ unsigned char mcfpu_qentsz;
+ unsigned char mcfpu_enab;
+};
+typedef struct target_mc_fpu target_mc_fpu_t;
+
+typedef struct {
+ target_mc_gregset_t mc_gregs;
+ target_mc_greg_t mc_fp;
+ target_mc_greg_t mc_i7;
+ target_mc_fpu_t mc_fpregs;
+} target_mcontext_t;
+
+struct target_ucontext {
+ struct target_ucontext *uc_link;
+ target_ulong uc_flags;
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+};
+
+/* A V9 register window */
+struct target_reg_window {
+ target_ulong locals[8];
+ target_ulong ins[8];
+};
+
+#define TARGET_STACK_BIAS 2047
+
+/* {set, get}context() needed for 64-bit SparcLinux userland. */
+void sparc64_set_context(CPUSPARCState *env)
+{
+ struct target_ucontext *ucp = (struct target_ucontext *)
+ env->regwptr[UREG_I0];
+ target_mc_gregset_t *grp;
+ target_ulong pc, npc, tstate;
+ target_ulong fp, i7;
+ unsigned char fenab;
+ int err;
+ unsigned int i;
+ target_ulong *src, *dst;
+
+ grp = &ucp->uc_mcontext.mc_gregs;
+ err = get_user(pc, &((*grp)[MC_PC]));
+ err |= get_user(npc, &((*grp)[MC_NPC]));
+ if (err || ((pc | npc) & 3))
+ goto do_sigsegv;
+ if (env->regwptr[UREG_I1]) {
+ target_sigset_t target_set;
+ sigset_t set;
+
+ if (TARGET_NSIG_WORDS == 1) {
+ if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
+ goto do_sigsegv;
+ } else {
+ src = &ucp->uc_sigmask;
+ dst = &target_set;
+ for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong);
+ i++, dst++, src++)
+ err |= get_user(dst, src);
+ if (err)
+ goto do_sigsegv;
+ }
+ target_to_host_sigset_internal(&set, &target_set);
+ sigprocmask(SIG_SETMASK, &set, NULL);
+ }
+ env->pc = pc;
+ env->npc = npc;
+ err |= get_user(env->y, &((*grp)[MC_Y]));
+ err |= get_user(tstate, &((*grp)[MC_TSTATE]));
+ env->asi = (tstate >> 24) & 0xff;
+ PUT_CCR(env, tstate >> 32);
+ PUT_CWP64(env, tstate & 0x1f);
+ err |= get_user(env->gregs[1], (&(*grp)[MC_G1]));
+ err |= get_user(env->gregs[2], (&(*grp)[MC_G2]));
+ err |= get_user(env->gregs[3], (&(*grp)[MC_G3]));
+ err |= get_user(env->gregs[4], (&(*grp)[MC_G4]));
+ err |= get_user(env->gregs[5], (&(*grp)[MC_G5]));
+ err |= get_user(env->gregs[6], (&(*grp)[MC_G6]));
+ err |= get_user(env->gregs[7], (&(*grp)[MC_G7]));
+ err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
+ err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
+ err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
+ err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
+ err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
+ err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
+ err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
+ err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
+
+ err |= get_user(fp, &(ucp->uc_mcontext.mc_fp));
+ err |= get_user(i7, &(ucp->uc_mcontext.mc_i7));
+ err |= put_user(fp,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+ err |= put_user(i7,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+
+ err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
+ err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
+ src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+ dst = &env->fpr;
+ for (i = 0; i < 64; i++, dst++, src++)
+ err |= get_user(dst, src);
+ err |= get_user(env->fsr,
+ &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
+ err |= get_user(env->gsr,
+ &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
+ if (err)
+ goto do_sigsegv;
+
+ return;
+ do_sigsegv:
+ force_sig(SIGSEGV);
+}
+
+void sparc64_get_context(CPUSPARCState *env)
+{
+ struct target_ucontext *ucp = (struct target_ucontext *)
+ env->regwptr[UREG_I0];
+ target_mc_gregset_t *grp;
+ target_mcontext_t *mcp;
+ target_ulong fp, i7;
+ int err;
+ unsigned int i;
+ target_ulong *src, *dst;
+ target_sigset_t target_set;
+ sigset_t set;
+
+ mcp = &ucp->uc_mcontext;
+ grp = &mcp->mc_gregs;
+
+ /* Skip over the trap instruction, first. */
+ env->pc = env->npc;
+ env->npc += 4;
+
+ err = 0;
+
+ sigprocmask(0, NULL, &set);
+ host_to_target_sigset_internal(&target_set, &set);
+ if (TARGET_NSIG_WORDS == 1)
+ err |= put_user(target_set.sig[0],
+ (target_ulong *)&ucp->uc_sigmask);
+ else {
+ src = &target_set;
+ dst = &ucp->uc_sigmask;
+ for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong);
+ i++, dst++, src++)
+ err |= put_user(src, dst);
+ if (err)
+ goto do_sigsegv;
+ }
+
+ err |= put_user(env->tstate, &((*grp)[MC_TSTATE]));
+ err |= put_user(env->pc, &((*grp)[MC_PC]));
+ err |= put_user(env->npc, &((*grp)[MC_NPC]));
+ err |= put_user(env->y, &((*grp)[MC_Y]));
+ err |= put_user(env->gregs[1], &((*grp)[MC_G1]));
+ err |= put_user(env->gregs[2], &((*grp)[MC_G2]));
+ err |= put_user(env->gregs[3], &((*grp)[MC_G3]));
+ err |= put_user(env->gregs[4], &((*grp)[MC_G4]));
+ err |= put_user(env->gregs[5], &((*grp)[MC_G5]));
+ err |= put_user(env->gregs[6], &((*grp)[MC_G6]));
+ err |= put_user(env->gregs[7], &((*grp)[MC_G7]));
+ err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
+ err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
+ err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
+ err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
+ err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
+ err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
+ err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
+ err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
+
+ err |= get_user(fp,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+ err |= get_user(i7,
+ (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+ err |= put_user(fp, &(mcp->mc_fp));
+ err |= put_user(i7, &(mcp->mc_i7));
+
+ src = &env->fpr;
+ dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+ for (i = 0; i < 64; i++, dst++, src++)
+ err |= put_user(src, dst);
+ err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
+ err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
+ err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+
+ if (err)
+ goto do_sigsegv;
+
+ return;
+ do_sigsegv:
+ force_sig(SIGSEGV);
+}
+#endif
#elif defined(TARGET_MIPS64)
# warning signal handling not implemented