31 #include <linux/sched.h>
33 #include <linux/kernel.h>
34 #include <linux/signal.h>
36 #include <linux/errno.h>
37 #include <linux/wait.h>
38 #include <linux/ptrace.h>
40 #include <linux/stddef.h>
42 #include <linux/personality.h>
43 #include <linux/tty.h>
44 #include <linux/binfmts.h>
45 #include <linux/module.h>
48 #include <asm/setup.h>
49 #include <asm/uaccess.h>
50 #include <asm/pgtable.h>
51 #include <asm/traps.h>
52 #include <asm/ucontext.h>
59 #ifdef CONFIG_COLDFIRE
64 #define FMT4SIZE sizeof(((struct frame *)0)->un.fmt4)
67 static const int frame_size_change[16] = {
69 [2] =
sizeof(((
struct frame *)0)->un.fmt2),
70 [3] =
sizeof(((
struct frame *)0)->
un.fmt3),
74 [7] =
sizeof(((
struct frame *)0)->un.fmt7),
76 [9] =
sizeof(((
struct frame *)0)->
un.fmt9),
77 [10] =
sizeof(((
struct frame *)0)->un.fmta),
78 [11] =
sizeof(((
struct frame *)0)->
un.fmtb),
85 static inline int frame_extra_sizes(
int f)
87 return frame_size_change[
f];
106 tregs->
sr = regs->
sr;
126 static inline void push_cache (
unsigned long vaddr)
140 __asm__ __volatile__ (
".chip 68040\n\t"
143 "movec %%mmusr,%0\n\t"
151 __asm__ __volatile__ (
".chip 68040\n\t"
153 "cpushl %%bc,(%0)\n\t"
159 __asm__ __volatile__ (
".chip 68060\n\t"
164 __asm__ __volatile__ (
".chip 68060\n\t"
165 "cpushl %%bc,(%0)\n\t"
175 asm volatile (
"movec %%cacr,%0" :
"=r" (
temp));
177 asm volatile (
"movec %0,%%caar\n\t"
179 : :
"r" (
vaddr),
"r" (temp));
180 asm volatile (
"movec %0,%%caar\n\t"
182 : :
"r" (vaddr + 4),
"r" (temp));
186 static inline void adjustformat(
struct pt_regs *regs)
199 static inline int frame_extra_sizes(
int f)
205 static inline void adjustformat(
struct pt_regs *regs)
220 static inline void push_cache(
unsigned long vaddr)
233 siginitset(&blocked, mask);
252 siginitset(&new_ka.
sa.sa_mask, mask);
260 __put_user(old_ka.
sa.sa_restorer, &oact->sa_restorer) ||
305 #define FPCONTEXT_SIZE 216
306 #define uc_fpstate uc_filler[0]
307 #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
308 #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
312 static unsigned char fpu_version;
314 static inline int restore_fpu_state(
struct sigcontext *
sc)
356 __asm__ volatile (
"fmovemd %0,%%fp0-%%fp1\n\t"
357 "fmovel %1,%%fpcr\n\t"
358 "fmovel %2,%%fpsr\n\t"
366 __asm__ volatile (
".chip 68k/68881\n\t"
367 "fmovemx %0,%%fp0-%%fp1\n\t"
368 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
379 __asm__ volatile (
".chip 68k/68881\n\t"
390 static inline int rt_restore_fpu_state(
struct ucontext __user *
uc)
400 uc->uc_mcontext.fpregs.f_fpcntl, 12))
404 uc->uc_mcontext.fpregs.f_fpregs, 96))
409 if (
__get_user(*(
long *)fpstate, (
long __user *)&uc->uc_fpstate))
413 context_size = fpstate[1];
416 (fpstate[0] != fpu_version))
420 !(context_size == 0x18 || context_size == 0xb4))
423 !(context_size == 0x38 || context_size == 0xd4))
426 if (!(context_size == 0x00 ||
427 context_size == 0x28 ||
428 context_size == 0x60))
431 if (!(fpstate[3] == 0x00 ||
432 fpstate[3] == 0x60 ||
436 if (!(fpstate[3] == 0x00 ||
437 fpstate[3] == 0x05 ||
447 __asm__ volatile (
"fmovemd %0,%%fp0-%%fp7\n\t"
448 "fmovel %1,%%fpcr\n\t"
449 "fmovel %2,%%fpsr\n\t"
457 __asm__ volatile (
".chip 68k/68881\n\t"
458 "fmovemx %0,%%fp0-%%fp7\n\t"
459 "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
472 __asm__ volatile (
"frestore %0" : :
"m" (*fpstate));
474 __asm__ volatile (
".chip 68k/68881\n\t"
501 __asm__ volatile (
".chip 68k/68881\n\t"
513 if (*(
unsigned short *) sc->
sc_fpstate == 0x1f38)
518 __asm__ volatile (
"fmovemd %%fp0-%%fp1,%0\n\t"
519 "fmovel %%fpcr,%1\n\t"
520 "fmovel %%fpsr,%2\n\t"
529 __asm__ volatile (
".chip 68k/68881\n\t"
530 "fmovemx %%fp0-%%fp1,%0\n\t"
531 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
541 static inline int rt_save_fpu_state(
struct ucontext __user *uc,
struct pt_regs *regs)
558 __asm__ volatile (
"fsave %0" : :
"m" (*fpstate) :
"memory");
560 __asm__ volatile (
".chip 68k/68881\n\t"
563 : :
"m" (*fpstate) :
"memory");
566 err |=
__put_user(*(
long *)fpstate, (
long __user *)&uc->uc_fpstate);
570 context_size = fpstate[1];
571 fpu_version = fpstate[0];
576 if (*(
unsigned short *) fpstate == 0x1f38)
577 fpstate[0x38] |= 1 << 3;
580 __asm__ volatile (
"fmovemd %%fp0-%%fp7,%0\n\t"
581 "fmovel %%fpcr,%1\n\t"
582 "fmovel %%fpsr,%2\n\t"
591 __asm__ volatile (
".chip 68k/68881\n\t"
592 "fmovemx %%fp0-%%fp7,%0\n\t"
593 "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
604 err |=
copy_to_user((
long __user *)&uc->uc_fpstate + 1, fpstate + 4,
614 static inline int restore_fpu_state(
struct sigcontext *sc)
619 static inline int rt_restore_fpu_state(
struct ucontext __user *uc)
628 static inline int rt_save_fpu_state(
struct ucontext __user *uc,
struct pt_regs *regs)
635 static int mangle_kernel_stack(
struct pt_regs *regs,
int formatvec,
638 int fsize = frame_extra_sizes(formatvec >> 12);
644 printk(
"user process returning with weird frame format\n");
649 regs->
format = formatvec >> 12;
650 regs->
vector = formatvec & 0xfff;
653 unsigned long buf[fsize / 2];
660 regs->
format = formatvec >> 12;
661 regs->
vector = formatvec & 0xfff;
662 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
664 #ifdef CONFIG_COLDFIRE
666 " bra ret_from_signal\n"
670 " movel %/a0,%/sp\n\t"
672 "1: movel %0@+,%/a0@+\n\t"
674 " lea %/sp@(%c3),%/a0\n\t"
678 "2: movel %4@+,%/a0@+\n\t"
680 " bral ret_from_signal\n"
683 :
"a" (sw),
"d" (fsize),
"d" (frame_offset/4-1),
684 "n" (frame_offset),
"a" (buf + fsize/4)
692 restore_sigcontext(
struct pt_regs *regs,
struct sigcontext __user *usc,
void __user *fp)
710 regs->
sr = (regs->
sr & 0xff00) | (
context.sc_sr & 0xff);
714 formatvec =
context.sc_formatvec;
716 err = restore_fpu_state(&
context);
718 if (err || mangle_kernel_stack(regs, formatvec, fp))
739 err =
__get_user(temp, &uc->uc_mcontext.version);
762 regs->
sr = (regs->
sr & 0xff00) | (temp & 0xff);
766 err |= rt_restore_fpu_state(uc);
771 if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
784 unsigned long usp = rdusp();
798 if (restore_sigcontext(regs, &frame->
sc, frame + 1))
811 unsigned long usp = rdusp();
822 if (rt_restore_ucontext(regs, sw, &frame->
uc))
843 save_a5_state(sc, regs);
844 save_fpu_state(sc, regs);
847 static inline int rt_setup_ucontext(
struct ucontext __user *uc,
struct pt_regs *regs)
873 err |= rt_save_fpu_state(uc, regs);
877 static inline void __user *
887 if (!sas_ss_flags(usp))
890 return (
void __user *)((usp - frame_size) & -8
UL);
897 int fsize = frame_extra_sizes(regs->
format);
903 printk (
"setup_frame: Unknown frame format %#x\n",
909 frame = get_sigframe(ka, regs,
sizeof(*frame) + fsize);
928 setup_sigcontext(&
context, regs,
set->sig[0]);
936 (
long __user *)(frame->
retcode));
944 push_cache ((
unsigned long) &frame->
retcode);
950 wrusp ((
unsigned long) frame);
951 regs->
pc = (
unsigned long) ka->
sa.sa_handler;
973 tregs->
pc = regs->
pc;
974 tregs->
sr = regs->
sr;
987 int fsize = frame_extra_sizes(regs->
format);
992 printk (
"setup_frame: Unknown frame format %#x\n",
998 frame = get_sigframe(ka, regs,
sizeof(*frame));
1017 &frame->
uc.uc_stack.ss_sp);
1019 &frame->
uc.uc_stack.ss_flags);
1021 err |= rt_setup_ucontext(&frame->
uc, regs);
1027 #ifdef __mcoldfire__
1031 (
long __user *)(frame->
retcode + 4));
1035 (
long __user *)(frame->
retcode + 0));
1045 push_cache ((
unsigned long) &frame->
retcode);
1051 wrusp ((
unsigned long) frame);
1052 regs->
pc = (
unsigned long) ka->
sa.sa_handler;
1074 tregs->
pc = regs->
pc;
1075 tregs->
sr = regs->
sr;
1124 sigset_t *oldset = sigmask_to_save();
1129 handle_restart(regs, ka, 1);
1133 err = setup_rt_frame(sig, ka, info, oldset, regs);
1135 err = setup_frame(sig, ka, oldset, regs);
1143 regs->
sr &= ~0x8000;
1164 handle_signal(signr, &ka, &info, regs);
1171 handle_restart(regs,
NULL, 0);
1174 restore_saved_sigmask();
1183 tracehook_notify_resume(regs);