1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "qemu.h"
21#include "signal-common.h"
22#include "linux-user/trace.h"
23
24#define __SUNOS_MAXWIN 31
25
26
27struct target_sigcontext {
28 abi_ulong sigc_onstack;
29
30 abi_ulong sigc_mask;
31 abi_ulong sigc_sp;
32 abi_ulong sigc_pc;
33 abi_ulong sigc_npc;
34 abi_ulong sigc_psr;
35 abi_ulong sigc_g1;
36 abi_ulong sigc_o0;
37
38
39
40
41 abi_ulong sigc_oswins;
42
43
44 char *sigc_spbuf[__SUNOS_MAXWIN];
45
46
47 struct {
48 abi_ulong locals[8];
49 abi_ulong ins[8];
50 } sigc_wbuf[__SUNOS_MAXWIN];
51};
52
53struct sparc_stackf {
54 abi_ulong locals[8];
55 abi_ulong ins[8];
56
57
58
59 char *structptr;
60 abi_ulong xargs[6];
61 abi_ulong xxargs[1];
62};
63
64typedef struct {
65 struct {
66 abi_ulong psr;
67 abi_ulong pc;
68 abi_ulong npc;
69 abi_ulong y;
70 abi_ulong u_regs[16];
71 } si_regs;
72 int si_mask;
73} __siginfo_t;
74
75typedef struct {
76 abi_ulong si_float_regs[32];
77 unsigned long si_fsr;
78 unsigned long si_fpqdepth;
79 struct {
80 unsigned long *insn_addr;
81 unsigned long insn;
82 } si_fpqueue [16];
83} qemu_siginfo_fpu_t;
84
85
86struct target_signal_frame {
87 struct sparc_stackf ss;
88 __siginfo_t info;
89 abi_ulong fpu_save;
90 abi_ulong insns[2] __attribute__ ((aligned (8)));
91 abi_ulong extramask[TARGET_NSIG_WORDS - 1];
92 abi_ulong extra_size;
93 qemu_siginfo_fpu_t fpu_state;
94};
95struct target_rt_signal_frame {
96 struct sparc_stackf ss;
97 siginfo_t info;
98 abi_ulong regs[20];
99 sigset_t mask;
100 abi_ulong fpu_save;
101 unsigned int insns[2];
102 stack_t stack;
103 unsigned int extra_size;
104 qemu_siginfo_fpu_t fpu_state;
105};
106
107#define UREG_O0 16
108#define UREG_O6 22
109#define UREG_I0 0
110#define UREG_I1 1
111#define UREG_I2 2
112#define UREG_I3 3
113#define UREG_I4 4
114#define UREG_I5 5
115#define UREG_I6 6
116#define UREG_I7 7
117#define UREG_L0 8
118#define UREG_FP UREG_I6
119#define UREG_SP UREG_O6
120
121static inline abi_ulong get_sigframe(struct target_sigaction *sa,
122 CPUSPARCState *env,
123 unsigned long framesize)
124{
125 abi_ulong sp = get_sp_from_cpustate(env);
126
127
128
129
130
131 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) {
132 return -1;
133 }
134
135
136 sp = target_sigsp(sp, sa) - framesize;
137
138
139
140
141
142
143
144 sp &= ~15UL;
145
146 return sp;
147}
148
149static int
150setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
151{
152 int err = 0, i;
153
154 __put_user(env->psr, &si->si_regs.psr);
155 __put_user(env->pc, &si->si_regs.pc);
156 __put_user(env->npc, &si->si_regs.npc);
157 __put_user(env->y, &si->si_regs.y);
158 for (i=0; i < 8; i++) {
159 __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
160 }
161 for (i=0; i < 8; i++) {
162 __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
163 }
164 __put_user(mask, &si->si_mask);
165 return err;
166}
167
168#if 0
169static int
170setup_sigcontext(struct target_sigcontext *sc,
171 CPUSPARCState *env, unsigned long mask)
172{
173 int err = 0;
174
175 __put_user(mask, &sc->sigc_mask);
176 __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
177 __put_user(env->pc, &sc->sigc_pc);
178 __put_user(env->npc, &sc->sigc_npc);
179 __put_user(env->psr, &sc->sigc_psr);
180 __put_user(env->gregs[1], &sc->sigc_g1);
181 __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
182
183 return err;
184}
185#endif
186#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
187
188void setup_frame(int sig, struct target_sigaction *ka,
189 target_sigset_t *set, CPUSPARCState *env)
190{
191 abi_ulong sf_addr;
192 struct target_signal_frame *sf;
193 int sigframe_size, err, i;
194
195
196
197
198 sigframe_size = NF_ALIGNEDSZ;
199 sf_addr = get_sigframe(ka, env, sigframe_size);
200 trace_user_setup_frame(env, sf_addr);
201
202 sf = lock_user(VERIFY_WRITE, sf_addr,
203 sizeof(struct target_signal_frame), 0);
204 if (!sf) {
205 goto sigsegv;
206 }
207#if 0
208 if (invalid_frame_pointer(sf, sigframe_size))
209 goto sigill_and_return;
210#endif
211
212 err = setup___siginfo(&sf->info, env, set->sig[0]);
213 __put_user(0, &sf->extra_size);
214
215
216
217
218 __put_user(set->sig[0], &sf->info.si_mask);
219 for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
220 __put_user(set->sig[i + 1], &sf->extramask[i]);
221 }
222
223 for (i = 0; i < 8; i++) {
224 __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
225 }
226 for (i = 0; i < 8; i++) {
227 __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
228 }
229 if (err)
230 goto sigsegv;
231
232
233 env->regwptr[UREG_FP] = sf_addr;
234 env->regwptr[UREG_I0] = sig;
235 env->regwptr[UREG_I1] = sf_addr +
236 offsetof(struct target_signal_frame, info);
237 env->regwptr[UREG_I2] = sf_addr +
238 offsetof(struct target_signal_frame, info);
239
240
241 env->pc = ka->_sa_handler;
242 env->npc = (env->pc + 4);
243
244 if (ka->ka_restorer) {
245 env->regwptr[UREG_I7] = ka->ka_restorer;
246 } else {
247 uint32_t val32;
248
249 env->regwptr[UREG_I7] = sf_addr +
250 offsetof(struct target_signal_frame, insns) - 2 * 4;
251
252
253 val32 = 0x821020d8;
254 __put_user(val32, &sf->insns[0]);
255
256
257 val32 = 0x91d02010;
258 __put_user(val32, &sf->insns[1]);
259 }
260 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
261 return;
262#if 0
263sigill_and_return:
264 force_sig(TARGET_SIGILL);
265#endif
266sigsegv:
267 unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
268 force_sigsegv(sig);
269}
270
271void setup_rt_frame(int sig, struct target_sigaction *ka,
272 target_siginfo_t *info,
273 target_sigset_t *set, CPUSPARCState *env)
274{
275 qemu_log_mask(LOG_UNIMP, "setup_rt_frame: not implemented\n");
276}
277
278long do_sigreturn(CPUSPARCState *env)
279{
280 abi_ulong sf_addr;
281 struct target_signal_frame *sf;
282 uint32_t up_psr, pc, npc;
283 target_sigset_t set;
284 sigset_t host_set;
285 int i;
286
287 sf_addr = env->regwptr[UREG_FP];
288 trace_user_do_sigreturn(env, sf_addr);
289 if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
290 goto segv_and_exit;
291 }
292
293
294
295 if (sf_addr & 3)
296 goto segv_and_exit;
297
298 __get_user(pc, &sf->info.si_regs.pc);
299 __get_user(npc, &sf->info.si_regs.npc);
300
301 if ((pc | npc) & 3) {
302 goto segv_and_exit;
303 }
304
305
306 __get_user(up_psr, &sf->info.si_regs.psr);
307
308
309 env->psr = (up_psr & (PSR_ICC ))
310 | (env->psr & ~(PSR_ICC ));
311
312 env->pc = pc;
313 env->npc = npc;
314 __get_user(env->y, &sf->info.si_regs.y);
315 for (i=0; i < 8; i++) {
316 __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
317 }
318 for (i=0; i < 8; i++) {
319 __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334 __get_user(set.sig[0], &sf->info.si_mask);
335 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
336 __get_user(set.sig[i], &sf->extramask[i - 1]);
337 }
338
339 target_to_host_sigset_internal(&host_set, &set);
340 set_sigmask(&host_set);
341
342 unlock_user_struct(sf, sf_addr, 0);
343 return -TARGET_QEMU_ESIGRETURN;
344
345segv_and_exit:
346 unlock_user_struct(sf, sf_addr, 0);
347 force_sig(TARGET_SIGSEGV);
348 return -TARGET_QEMU_ESIGRETURN;
349}
350
351long do_rt_sigreturn(CPUSPARCState *env)
352{
353 trace_user_do_rt_sigreturn(env, 0);
354 qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n");
355 return -TARGET_ENOSYS;
356}
357
358#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
359#define SPARC_MC_TSTATE 0
360#define SPARC_MC_PC 1
361#define SPARC_MC_NPC 2
362#define SPARC_MC_Y 3
363#define SPARC_MC_G1 4
364#define SPARC_MC_G2 5
365#define SPARC_MC_G3 6
366#define SPARC_MC_G4 7
367#define SPARC_MC_G5 8
368#define SPARC_MC_G6 9
369#define SPARC_MC_G7 10
370#define SPARC_MC_O0 11
371#define SPARC_MC_O1 12
372#define SPARC_MC_O2 13
373#define SPARC_MC_O3 14
374#define SPARC_MC_O4 15
375#define SPARC_MC_O5 16
376#define SPARC_MC_O6 17
377#define SPARC_MC_O7 18
378#define SPARC_MC_NGREG 19
379
380typedef abi_ulong target_mc_greg_t;
381typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG];
382
383struct target_mc_fq {
384 abi_ulong *mcfq_addr;
385 uint32_t mcfq_insn;
386};
387
388struct target_mc_fpu {
389 union {
390 uint32_t sregs[32];
391 uint64_t dregs[32];
392
393 } mcfpu_fregs;
394 abi_ulong mcfpu_fsr;
395 abi_ulong mcfpu_fprs;
396 abi_ulong mcfpu_gsr;
397 struct target_mc_fq *mcfpu_fq;
398 unsigned char mcfpu_qcnt;
399 unsigned char mcfpu_qentsz;
400 unsigned char mcfpu_enab;
401};
402typedef struct target_mc_fpu target_mc_fpu_t;
403
404typedef struct {
405 target_mc_gregset_t mc_gregs;
406 target_mc_greg_t mc_fp;
407 target_mc_greg_t mc_i7;
408 target_mc_fpu_t mc_fpregs;
409} target_mcontext_t;
410
411struct target_ucontext {
412 struct target_ucontext *tuc_link;
413 abi_ulong tuc_flags;
414 target_sigset_t tuc_sigmask;
415 target_mcontext_t tuc_mcontext;
416};
417
418
419struct target_reg_window {
420 abi_ulong locals[8];
421 abi_ulong ins[8];
422};
423
424#define TARGET_STACK_BIAS 2047
425
426
427void sparc64_set_context(CPUSPARCState *env)
428{
429 abi_ulong ucp_addr;
430 struct target_ucontext *ucp;
431 target_mc_gregset_t *grp;
432 abi_ulong pc, npc, tstate;
433 abi_ulong fp, i7, w_addr;
434 unsigned int i;
435
436 ucp_addr = env->regwptr[UREG_I0];
437 if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
438 goto do_sigsegv;
439 }
440 grp = &ucp->tuc_mcontext.mc_gregs;
441 __get_user(pc, &((*grp)[SPARC_MC_PC]));
442 __get_user(npc, &((*grp)[SPARC_MC_NPC]));
443 if ((pc | npc) & 3) {
444 goto do_sigsegv;
445 }
446 if (env->regwptr[UREG_I1]) {
447 target_sigset_t target_set;
448 sigset_t set;
449
450 if (TARGET_NSIG_WORDS == 1) {
451 __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]);
452 } else {
453 abi_ulong *src, *dst;
454 src = ucp->tuc_sigmask.sig;
455 dst = target_set.sig;
456 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
457 __get_user(*dst, src);
458 }
459 }
460 target_to_host_sigset_internal(&set, &target_set);
461 set_sigmask(&set);
462 }
463 env->pc = pc;
464 env->npc = npc;
465 __get_user(env->y, &((*grp)[SPARC_MC_Y]));
466 __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
467 env->asi = (tstate >> 24) & 0xff;
468 cpu_put_ccr(env, tstate >> 32);
469 cpu_put_cwp64(env, tstate & 0x1f);
470 __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
471 __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
472 __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
473 __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
474 __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
475 __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
476 __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
477 __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
478 __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
479 __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
480 __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
481 __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
482 __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
483 __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
484 __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
485
486 __get_user(fp, &(ucp->tuc_mcontext.mc_fp));
487 __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
488
489 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
490 if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
491 abi_ulong) != 0) {
492 goto do_sigsegv;
493 }
494 if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
495 abi_ulong) != 0) {
496 goto do_sigsegv;
497 }
498
499
500
501
502
503 __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
504 {
505 uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
506 for (i = 0; i < 64; i++, src++) {
507 if (i & 1) {
508 __get_user(env->fpr[i/2].l.lower, src);
509 } else {
510 __get_user(env->fpr[i/2].l.upper, src);
511 }
512 }
513 }
514 __get_user(env->fsr,
515 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
516 __get_user(env->gsr,
517 &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
518 unlock_user_struct(ucp, ucp_addr, 0);
519 return;
520do_sigsegv:
521 unlock_user_struct(ucp, ucp_addr, 0);
522 force_sig(TARGET_SIGSEGV);
523}
524
525void sparc64_get_context(CPUSPARCState *env)
526{
527 abi_ulong ucp_addr;
528 struct target_ucontext *ucp;
529 target_mc_gregset_t *grp;
530 target_mcontext_t *mcp;
531 abi_ulong fp, i7, w_addr;
532 int err;
533 unsigned int i;
534 target_sigset_t target_set;
535 sigset_t set;
536
537 ucp_addr = env->regwptr[UREG_I0];
538 if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
539 goto do_sigsegv;
540 }
541
542 mcp = &ucp->tuc_mcontext;
543 grp = &mcp->mc_gregs;
544
545
546 env->pc = env->npc;
547 env->npc += 4;
548
549
550
551
552
553
554 err = do_sigprocmask(0, NULL, &set);
555 assert(err == 0);
556 host_to_target_sigset_internal(&target_set, &set);
557 if (TARGET_NSIG_WORDS == 1) {
558 __put_user(target_set.sig[0],
559 (abi_ulong *)&ucp->tuc_sigmask);
560 } else {
561 abi_ulong *src, *dst;
562 src = target_set.sig;
563 dst = ucp->tuc_sigmask.sig;
564 for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
565 __put_user(*src, dst);
566 }
567 if (err)
568 goto do_sigsegv;
569 }
570
571
572
573 __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
574 __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
575 __put_user(env->y, &((*grp)[SPARC_MC_Y]));
576 __put_user(env->gregs[1], &((*grp)[SPARC_MC_G1]));
577 __put_user(env->gregs[2], &((*grp)[SPARC_MC_G2]));
578 __put_user(env->gregs[3], &((*grp)[SPARC_MC_G3]));
579 __put_user(env->gregs[4], &((*grp)[SPARC_MC_G4]));
580 __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
581 __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
582 __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
583 __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
584 __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
585 __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
586 __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
587 __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
588 __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
589 __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
590 __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
591
592 w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
593 fp = i7 = 0;
594 if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
595 abi_ulong) != 0) {
596 goto do_sigsegv;
597 }
598 if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
599 abi_ulong) != 0) {
600 goto do_sigsegv;
601 }
602 __put_user(fp, &(mcp->mc_fp));
603 __put_user(i7, &(mcp->mc_i7));
604
605 {
606 uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
607 for (i = 0; i < 64; i++, dst++) {
608 if (i & 1) {
609 __put_user(env->fpr[i/2].l.lower, dst);
610 } else {
611 __put_user(env->fpr[i/2].l.upper, dst);
612 }
613 }
614 }
615 __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
616 __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
617 __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
618
619 if (err)
620 goto do_sigsegv;
621 unlock_user_struct(ucp, ucp_addr, 1);
622 return;
623do_sigsegv:
624 unlock_user_struct(ucp, ucp_addr, 1);
625 force_sig(TARGET_SIGSEGV);
626}
627#endif
628