aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/signal-common.h150
-rw-r--r--arch/mips/kernel/signal.c139
2 files changed, 153 insertions, 136 deletions
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index bb3c631b808e..03d2b603fb84 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -8,145 +8,23 @@
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */ 9 */
10 10
11#ifndef __SIGNAL_COMMON_H
12#define __SIGNAL_COMMON_H
11 13
12static inline int 14/*
13setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 15 * handle hardware context
14{ 16 */
15 int err = 0; 17extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
16 int i; 18extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
17
18 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
19
20 err |= __put_user(0, &sc->sc_regs[0]);
21 for (i = 1; i < 32; i++)
22 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
23
24 err |= __put_user(regs->hi, &sc->sc_mdhi);
25 err |= __put_user(regs->lo, &sc->sc_mdlo);
26 if (cpu_has_dsp) {
27 err |= __put_user(mfhi1(), &sc->sc_hi1);
28 err |= __put_user(mflo1(), &sc->sc_lo1);
29 err |= __put_user(mfhi2(), &sc->sc_hi2);
30 err |= __put_user(mflo2(), &sc->sc_lo2);
31 err |= __put_user(mfhi3(), &sc->sc_hi3);
32 err |= __put_user(mflo3(), &sc->sc_lo3);
33 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
34 }
35
36 err |= __put_user(!!used_math(), &sc->sc_used_math);
37
38 if (used_math()) {
39 /*
40 * Save FPU state to signal context. Signal handler
41 * will "inherit" current FPU state.
42 */
43 preempt_disable();
44
45 if (!is_fpu_owner()) {
46 own_fpu();
47 restore_fp(current);
48 }
49 err |= save_fp_context(sc);
50
51 preempt_enable();
52 }
53 return err;
54}
55
56static inline int
57restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
58{
59 unsigned int used_math;
60 unsigned long treg;
61 int err = 0;
62 int i;
63
64 /* Always make any pending restarted system calls return -EINTR */
65 current_thread_info()->restart_block.fn = do_no_restart_syscall;
66
67 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
68 err |= __get_user(regs->hi, &sc->sc_mdhi);
69 err |= __get_user(regs->lo, &sc->sc_mdlo);
70 if (cpu_has_dsp) {
71 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
72 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
73 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
74 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
75 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
76 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
77 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
78 }
79
80 for (i = 1; i < 32; i++)
81 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
82
83 err |= __get_user(used_math, &sc->sc_used_math);
84 conditional_used_math(used_math);
85
86 preempt_disable();
87
88 if (used_math()) {
89 /* restore fpu context if we have used it before */
90 own_fpu();
91 err |= restore_fp_context(sc);
92 } else {
93 /* signal handler may have used FPU. Give it up. */
94 lose_fpu();
95 }
96
97 preempt_enable();
98
99 return err;
100}
101 19
102/* 20/*
103 * Determine which stack to use.. 21 * Determine which stack to use..
104 */ 22 */
105static inline void __user * 23extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
106get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 24 size_t frame_size);
107{ 25/*
108 unsigned long sp; 26 * install trampoline code to get back from the sig handler
109 27 */
110 /* Default to using normal stack */ 28extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);
111 sp = regs->regs[29];
112
113 /*
114 * FPU emulator may have it's own trampoline active just
115 * above the user stack, 16-bytes before the next lowest
116 * 16 byte boundary. Try to avoid trashing it.
117 */
118 sp -= 32;
119
120 /* This is the X/Open sanctioned signal stack switching. */
121 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
122 sp = current->sas_ss_sp + current->sas_ss_size;
123
124 return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
125}
126
127static inline int install_sigtramp(unsigned int __user *tramp,
128 unsigned int syscall)
129{
130 int err;
131
132 /*
133 * Set up the return code ...
134 *
135 * li v0, __NR__foo_sigreturn
136 * syscall
137 */
138
139 err = __put_user(0x24020000 + syscall, tramp + 0);
140 err |= __put_user(0x0000000c , tramp + 1);
141 if (ICACHE_REFILLS_WORKAROUND_WAR) {
142 err |= __put_user(0, tramp + 2);
143 err |= __put_user(0, tramp + 3);
144 err |= __put_user(0, tramp + 4);
145 err |= __put_user(0, tramp + 5);
146 err |= __put_user(0, tramp + 6);
147 err |= __put_user(0, tramp + 7);
148 }
149 flush_cache_sigtramp((unsigned long) tramp);
150 29
151 return err; 30#endif /* __SIGNAL_COMMON_H */
152}
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9a44053cd9f1..7d5a631d6cab 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -39,6 +39,145 @@
39#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 39#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
40 40
41/* 41/*
42 * Helper routines
43 */
44int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
45{
46 int err = 0;
47 int i;
48
49 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
50
51 err |= __put_user(0, &sc->sc_regs[0]);
52 for (i = 1; i < 32; i++)
53 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
54
55 err |= __put_user(regs->hi, &sc->sc_mdhi);
56 err |= __put_user(regs->lo, &sc->sc_mdlo);
57 if (cpu_has_dsp) {
58 err |= __put_user(mfhi1(), &sc->sc_hi1);
59 err |= __put_user(mflo1(), &sc->sc_lo1);
60 err |= __put_user(mfhi2(), &sc->sc_hi2);
61 err |= __put_user(mflo2(), &sc->sc_lo2);
62 err |= __put_user(mfhi3(), &sc->sc_hi3);
63 err |= __put_user(mflo3(), &sc->sc_lo3);
64 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
65 }
66
67 err |= __put_user(!!used_math(), &sc->sc_used_math);
68
69 if (used_math()) {
70 /*
71 * Save FPU state to signal context. Signal handler
72 * will "inherit" current FPU state.
73 */
74 preempt_disable();
75
76 if (!is_fpu_owner()) {
77 own_fpu();
78 restore_fp(current);
79 }
80 err |= save_fp_context(sc);
81
82 preempt_enable();
83 }
84 return err;
85}
86
87int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
88{
89 unsigned int used_math;
90 unsigned long treg;
91 int err = 0;
92 int i;
93
94 /* Always make any pending restarted system calls return -EINTR */
95 current_thread_info()->restart_block.fn = do_no_restart_syscall;
96
97 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
98 err |= __get_user(regs->hi, &sc->sc_mdhi);
99 err |= __get_user(regs->lo, &sc->sc_mdlo);
100 if (cpu_has_dsp) {
101 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
102 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
103 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
104 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
105 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
106 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
107 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
108 }
109
110 for (i = 1; i < 32; i++)
111 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
112
113 err |= __get_user(used_math, &sc->sc_used_math);
114 conditional_used_math(used_math);
115
116 preempt_disable();
117
118 if (used_math()) {
119 /* restore fpu context if we have used it before */
120 own_fpu();
121 err |= restore_fp_context(sc);
122 } else {
123 /* signal handler may have used FPU. Give it up. */
124 lose_fpu();
125 }
126
127 preempt_enable();
128
129 return err;
130}
131
132void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
133 size_t frame_size)
134{
135 unsigned long sp;
136
137 /* Default to using normal stack */
138 sp = regs->regs[29];
139
140 /*
141 * FPU emulator may have it's own trampoline active just
142 * above the user stack, 16-bytes before the next lowest
143 * 16 byte boundary. Try to avoid trashing it.
144 */
145 sp -= 32;
146
147 /* This is the X/Open sanctioned signal stack switching. */
148 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
149 sp = current->sas_ss_sp + current->sas_ss_size;
150
151 return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
152}
153
154int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
155{
156 int err;
157
158 /*
159 * Set up the return code ...
160 *
161 * li v0, __NR__foo_sigreturn
162 * syscall
163 */
164
165 err = __put_user(0x24020000 + syscall, tramp + 0);
166 err |= __put_user(0x0000000c , tramp + 1);
167 if (ICACHE_REFILLS_WORKAROUND_WAR) {
168 err |= __put_user(0, tramp + 2);
169 err |= __put_user(0, tramp + 3);
170 err |= __put_user(0, tramp + 4);
171 err |= __put_user(0, tramp + 5);
172 err |= __put_user(0, tramp + 6);
173 err |= __put_user(0, tramp + 7);
174 }
175 flush_cache_sigtramp((unsigned long) tramp);
176
177 return err;
178}
179
180/*
42 * Atomically swap in the new signal mask, and wait for a signal. 181 * Atomically swap in the new signal mask, and wait for a signal.
43 */ 182 */
44 183