diff options
Diffstat (limited to 'meta/packages/qemu/qemu-0.9.0+cvs20070613/12_signal_powerpc_support.patch')
-rw-r--r-- | meta/packages/qemu/qemu-0.9.0+cvs20070613/12_signal_powerpc_support.patch | 401 |
1 files changed, 0 insertions, 401 deletions
diff --git a/meta/packages/qemu/qemu-0.9.0+cvs20070613/12_signal_powerpc_support.patch b/meta/packages/qemu/qemu-0.9.0+cvs20070613/12_signal_powerpc_support.patch deleted file mode 100644 index d8d4198784..0000000000 --- a/meta/packages/qemu/qemu-0.9.0+cvs20070613/12_signal_powerpc_support.patch +++ /dev/null | |||
@@ -1,401 +0,0 @@ | |||
1 | #DPATCHLEVEL=1 | ||
2 | --- | ||
3 | # linux-user/signal.c | 371 ++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
4 | # 1 file changed, 371 insertions(+) | ||
5 | # | ||
6 | Index: qemu/linux-user/signal.c | ||
7 | =================================================================== | ||
8 | --- qemu.orig/linux-user/signal.c 2007-06-13 11:51:54.000000000 +0100 | ||
9 | +++ qemu/linux-user/signal.c 2007-06-13 11:51:54.000000000 +0100 | ||
10 | @@ -2,6 +2,7 @@ | ||
11 | * Emulation of Linux signals | ||
12 | * | ||
13 | * Copyright (c) 2003 Fabrice Bellard | ||
14 | + * Copyright (c) 2005 Josh Triplett <josh@psas.pdx.edu> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | @@ -16,6 +17,12 @@ | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | + * | ||
23 | + * Various portions adapted from the Linux kernel: | ||
24 | + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
25 | + * Derived from "arch/i386/kernel/signal.c" | ||
26 | + * Copyright (C) 1991, 1992 Linus Torvalds | ||
27 | + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson | ||
28 | */ | ||
29 | #include <stdlib.h> | ||
30 | #include <stdio.h> | ||
31 | @@ -1964,6 +1971,370 @@ long do_rt_sigreturn(CPUState *env) | ||
32 | return -ENOSYS; | ||
33 | } | ||
34 | |||
35 | +#elif defined(TARGET_PPC) | ||
36 | +/* Adapted from the Linux kernel: | ||
37 | + * arch/ppc/kernel/signal.c | ||
38 | + * include/asm-ppc/elf.h | ||
39 | + * include/asm-ppc/ptrace.h | ||
40 | + * include/asm-ppc/sigcontext.h | ||
41 | + * include/asm-ppc/ucontext.h | ||
42 | + */ | ||
43 | + | ||
44 | +/* | ||
45 | + * When we have signals to deliver, we set up on the | ||
46 | + * user stack, going down from the original stack pointer: | ||
47 | + * a sigregs struct | ||
48 | + * a sigcontext struct | ||
49 | + * a gap of __SIGNAL_FRAMESIZE bytes | ||
50 | + * | ||
51 | + * Each of these things must be a multiple of 16 bytes in size. | ||
52 | + * | ||
53 | + */ | ||
54 | + | ||
55 | +#define TARGET_ELF_NGREG 48 /* includes nip, msr, lr, etc. */ | ||
56 | +#define TARGET_ELF_NFPREG 33 /* includes fpscr */ | ||
57 | +#define TARGET_ELF_NVRREG 33 /* includes vscr */ | ||
58 | + | ||
59 | +/* General registers */ | ||
60 | +typedef unsigned long target_elf_greg_t; | ||
61 | +typedef target_elf_greg_t target_elf_gregset_t[TARGET_ELF_NGREG]; | ||
62 | + | ||
63 | +/* Floating point registers */ | ||
64 | +typedef double target_elf_fpreg_t; | ||
65 | +typedef target_elf_fpreg_t target_elf_fpregset_t[TARGET_ELF_NFPREG]; | ||
66 | + | ||
67 | +/* Altivec registers */ | ||
68 | +/* FIXME: Altivec not supported yet. */ | ||
69 | +/* typedef __vector128 elf_vrreg_t; */ | ||
70 | +typedef uint64_t target_elf_vrreg_t[2]; | ||
71 | +typedef target_elf_vrreg_t target_elf_vrregset_t[TARGET_ELF_NVRREG]; | ||
72 | + | ||
73 | +struct target_mcontext { | ||
74 | + target_elf_gregset_t mc_gregs; | ||
75 | + target_elf_fpregset_t mc_fregs; | ||
76 | + /* The kernel calls this mc_pad, but does #define tramp mc_pad */ | ||
77 | + target_ulong tramp[2]; | ||
78 | + target_elf_vrregset_t mc_vregs __attribute__((__aligned__(16))); | ||
79 | +}; | ||
80 | + | ||
81 | +struct target_sigregs { | ||
82 | + struct target_mcontext mctx; /* all the register values */ | ||
83 | + /* Programs using the rs6000/xcoff abi can save up to 19 gp regs | ||
84 | + and 18 fp regs below sp before decrementing it. */ | ||
85 | + int abigap[56]; | ||
86 | +}; | ||
87 | + | ||
88 | +struct target_sigcontext { | ||
89 | + target_ulong _unused[4]; | ||
90 | + uint32_t signal; | ||
91 | + target_ulong handler; | ||
92 | + target_ulong oldmask; | ||
93 | + struct target_pt_regs *regs; | ||
94 | +}; | ||
95 | + | ||
96 | +#define __SIGNAL_FRAMESIZE 64 | ||
97 | + | ||
98 | +static int | ||
99 | +save_user_regs(CPUState *env, struct target_mcontext *frame, int sigret) | ||
100 | +{ | ||
101 | + /* save general and floating-point registers */ | ||
102 | +#if 0 /* FIXME: handle floating-point, Altivec, SPE */ | ||
103 | + CHECK_FULL_REGS(regs); | ||
104 | + preempt_disable(); | ||
105 | + if (regs->msr & MSR_FP) | ||
106 | + giveup_fpu(current); | ||
107 | +#ifdef CONFIG_ALTIVEC | ||
108 | + if (current->thread.used_vr && (regs->msr & MSR_VEC)) | ||
109 | + giveup_altivec(current); | ||
110 | +#endif /* CONFIG_ALTIVEC */ | ||
111 | +#ifdef CONFIG_SPE | ||
112 | + if (current->thread.used_spe && (regs->msr & MSR_SPE)) | ||
113 | + giveup_spe(current); | ||
114 | +#endif /* CONFIG_ALTIVEC */ | ||
115 | + preempt_enable(); | ||
116 | +#endif /* 0 */ | ||
117 | + | ||
118 | + /* Note: this needs to be in the same order as target_pt_regs */ | ||
119 | + if(!memcpy(&frame->mc_gregs, env->gpr, | ||
120 | + 32*sizeof(target_elf_greg_t)) | ||
121 | + || __put_user(env->nip, &frame->mc_gregs[32]) | ||
122 | + || __put_user(do_load_msr(env), &frame->mc_gregs[33]) | ||
123 | + /* FIXME: || __put_user(orig_gpr3, &frame->mc_gregs[34]) */ | ||
124 | + || __put_user(env->ctr, &frame->mc_gregs[35]) | ||
125 | + || __put_user(env->lr, &frame->mc_gregs[36]) | ||
126 | + || __put_user(do_load_xer(env), &frame->mc_gregs[37]) | ||
127 | + || __put_user(do_load_cr(env), &frame->mc_gregs[38]) | ||
128 | + || __put_user(env->spr[SPR_MQ], &frame->mc_gregs[39]) | ||
129 | + /* FIXME: || __put_user(trap, &frame->mc_gregs[40]) */ | ||
130 | + || __put_user(env->spr[SPR_DAR], &frame->mc_gregs[41]) | ||
131 | + || __put_user(env->spr[SPR_DSISR], &frame->mc_gregs[42]) | ||
132 | + /* FIXME: || __put_user(result, &frame->mc_gregs[43]) */) | ||
133 | + return 1; | ||
134 | + | ||
135 | + if(!memcpy(&frame->mc_fregs, env->fpr, | ||
136 | + 32*sizeof(target_elf_fpreg_t)) | ||
137 | + || __put_user(do_load_fpscr(env), &frame->mc_fregs[32])) | ||
138 | + | ||
139 | + do_store_fpscr(env, 0, 0xFF); /* turn off all fp exceptions */ | ||
140 | + | ||
141 | +#if 0 /* FIXME: handle Altivec, SPE */ | ||
142 | +#ifdef CONFIG_ALTIVEC | ||
143 | + /* save altivec registers */ | ||
144 | + if (current->thread.used_vr) { | ||
145 | + if (!memcpy(&frame->mc_vregs, current->thread.vr, | ||
146 | + ELF_NVRREG * sizeof(vector128))) | ||
147 | + return 1; | ||
148 | + /* set MSR_VEC in the saved MSR value to indicate that | ||
149 | + frame->mc_vregs contains valid data */ | ||
150 | + if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR])) | ||
151 | + return 1; | ||
152 | + } | ||
153 | + /* else assert((regs->msr & MSR_VEC) == 0) */ | ||
154 | + | ||
155 | + /* We always copy to/from vrsave, it's 0 if we don't have or don't | ||
156 | + * use altivec. Since VSCR only contains 32 bits saved in the least | ||
157 | + * significant bits of a vector, we "cheat" and stuff VRSAVE in the | ||
158 | + * most significant bits of that same vector. --BenH | ||
159 | + */ | ||
160 | + if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32])) | ||
161 | + return 1; | ||
162 | +#endif /* CONFIG_ALTIVEC */ | ||
163 | + | ||
164 | +#ifdef CONFIG_SPE | ||
165 | + /* save spe registers */ | ||
166 | + if (current->thread.used_spe) { | ||
167 | + if (!memcpy(&frame->mc_vregs, current->thread.evr, | ||
168 | + ELF_NEVRREG * sizeof(u32))) | ||
169 | + return 1; | ||
170 | + /* set MSR_SPE in the saved MSR value to indicate that | ||
171 | + frame->mc_vregs contains valid data */ | ||
172 | + if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR])) | ||
173 | + return 1; | ||
174 | + } | ||
175 | + /* else assert((regs->msr & MSR_SPE) == 0) */ | ||
176 | + | ||
177 | + /* We always copy to/from spefscr */ | ||
178 | + if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG)) | ||
179 | + return 1; | ||
180 | +#endif /* CONFIG_SPE */ | ||
181 | +#endif /* 0 */ | ||
182 | + | ||
183 | + if (sigret) { | ||
184 | + /* Set up the sigreturn trampoline: li r0,sigret; sc */ | ||
185 | + if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) | ||
186 | + || __put_user(0x44000002UL, &frame->tramp[1])) | ||
187 | + return 1; | ||
188 | +#if 0 | ||
189 | + flush_icache_range((unsigned long) &frame->tramp[0], | ||
190 | + (unsigned long) &frame->tramp[2]); | ||
191 | +#endif | ||
192 | + } | ||
193 | + | ||
194 | + return 0; | ||
195 | +} | ||
196 | + | ||
197 | +static int | ||
198 | +restore_user_regs(CPUState *env, struct target_mcontext *sr, int sig) | ||
199 | +{ | ||
200 | + target_ulong save_r2 = 0; | ||
201 | + target_ulong saved_xer; | ||
202 | + target_ulong saved_cr; | ||
203 | + double saved_fpscr; | ||
204 | + | ||
205 | +#if 0 /* FIXME: handle Altivec, SPE */ | ||
206 | +#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) | ||
207 | + unsigned long msr; | ||
208 | +#endif | ||
209 | +#endif /* 0 */ | ||
210 | + | ||
211 | + /* backup/restore the TLS as we don't want it to be modified */ | ||
212 | + if (!sig) | ||
213 | + save_r2 = env->gpr[2]; | ||
214 | + | ||
215 | + /* Copy all registers except MSR */ | ||
216 | + /* Note: this needs to be in the same order as target_pt_regs */ | ||
217 | + if(!memcpy(env->gpr, &sr->mc_gregs, | ||
218 | + 32*sizeof(target_elf_greg_t)) | ||
219 | + || __get_user(env->nip, &sr->mc_gregs[32]) | ||
220 | + /* FIXME: || __get_user(orig_gpr3, &sr->mc_gregs[34]) */ | ||
221 | + || __get_user(env->ctr, &sr->mc_gregs[35]) | ||
222 | + || __get_user(env->lr, &sr->mc_gregs[36]) | ||
223 | + || __get_user(saved_xer, &sr->mc_gregs[37]) | ||
224 | + || __get_user(saved_cr, &sr->mc_gregs[38]) | ||
225 | + || __get_user(env->spr[SPR_MQ], &sr->mc_gregs[39]) | ||
226 | + /* FIXME: || __get_user(trap, &sr->mc_gregs[40]) */ | ||
227 | + || __get_user(env->spr[SPR_DAR], &sr->mc_gregs[41]) | ||
228 | + || __get_user(env->spr[SPR_DSISR], &sr->mc_gregs[42]) | ||
229 | + /* FIXME: || __get_user(result, &sr->mc_gregs[43]) */) | ||
230 | + return 1; | ||
231 | + do_store_xer(env, saved_xer); | ||
232 | + do_store_cr(env, saved_cr, 0xFF); | ||
233 | + | ||
234 | + if (!sig) | ||
235 | + env->gpr[2] = save_r2; | ||
236 | + | ||
237 | + /* The kernel delays restoring the floating-point registers until the | ||
238 | + * thread uses floating-point again. For simplicity, just restore the | ||
239 | + * registers now. */ | ||
240 | + if(!memcpy(env->fpr, &sr->mc_fregs, | ||
241 | + 32*sizeof(target_elf_fpreg_t)) | ||
242 | + || __get_user(saved_fpscr, &sr->mc_fregs[32])) | ||
243 | + return 1; | ||
244 | + do_store_fpscr(env, saved_fpscr, 0xFF); | ||
245 | + | ||
246 | +#if 0 /* FIXME: handle Altivec, SPE */ | ||
247 | +#ifdef CONFIG_ALTIVEC | ||
248 | + /* force the process to reload the altivec registers from | ||
249 | + current->thread when it next does altivec instructions */ | ||
250 | + regs->msr &= ~MSR_VEC; | ||
251 | + if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { | ||
252 | + /* restore altivec registers from the stack */ | ||
253 | + if (!memcpy(current->thread.vr, &sr->mc_vregs, | ||
254 | + sizeof(sr->mc_vregs))) | ||
255 | + return 1; | ||
256 | + } else if (current->thread.used_vr) | ||
257 | + memset(¤t->thread.vr, 0, ELF_NVRREG * sizeof(vector128)); | ||
258 | + | ||
259 | + /* Always get VRSAVE back */ | ||
260 | + if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32])) | ||
261 | + return 1; | ||
262 | +#endif /* CONFIG_ALTIVEC */ | ||
263 | + | ||
264 | +#ifdef CONFIG_SPE | ||
265 | + /* force the process to reload the spe registers from | ||
266 | + current->thread when it next does spe instructions */ | ||
267 | + regs->msr &= ~MSR_SPE; | ||
268 | + if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { | ||
269 | + /* restore spe registers from the stack */ | ||
270 | + if (!memcpy(current->thread.evr, &sr->mc_vregs, | ||
271 | + ELF_NEVRREG * sizeof(u32))) | ||
272 | + return 1; | ||
273 | + } else if (current->thread.used_spe) | ||
274 | + memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); | ||
275 | + | ||
276 | + /* Always get SPEFSCR back */ | ||
277 | + if (__get_user(current->thread.spefscr, (u32 *)&sr->mc_vregs + ELF_NEVRREG)) | ||
278 | + return 1; | ||
279 | +#endif /* CONFIG_SPE */ | ||
280 | +#endif /* 0 */ | ||
281 | + | ||
282 | +#if 0 /* FIXME: handle floating-point, Altivec, SPE */ | ||
283 | +#ifndef CONFIG_SMP | ||
284 | + preempt_disable(); | ||
285 | + if (last_task_used_math == current) | ||
286 | + last_task_used_math = NULL; | ||
287 | + if (last_task_used_altivec == current) | ||
288 | + last_task_used_altivec = NULL; | ||
289 | + if (last_task_used_spe == current) | ||
290 | + last_task_used_spe = NULL; | ||
291 | + preempt_enable(); | ||
292 | +#endif | ||
293 | +#endif /* 0 */ | ||
294 | + return 0; | ||
295 | +} | ||
296 | + | ||
297 | +static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
298 | + target_sigset_t *oldset, CPUState *env) | ||
299 | +{ | ||
300 | + struct target_sigcontext *sc; | ||
301 | + struct target_sigregs *frame; | ||
302 | + target_ulong origsp = env->gpr[1]; | ||
303 | + target_ulong newsp = origsp; | ||
304 | + | ||
305 | + /* Set up Signal Frame */ | ||
306 | + newsp -= sizeof(struct target_sigregs); | ||
307 | + frame = (struct target_sigregs *) newsp; | ||
308 | + | ||
309 | + /* Put a sigcontext on the stack */ | ||
310 | + newsp -= sizeof(*sc); | ||
311 | + sc = (struct target_sigcontext *) newsp; | ||
312 | + | ||
313 | + /* create a stack frame for the caller of the handler */ | ||
314 | + newsp -= __SIGNAL_FRAMESIZE; | ||
315 | + | ||
316 | + if (!access_ok(VERIFY_WRITE, (void *) newsp, origsp - newsp)) | ||
317 | + goto badframe; | ||
318 | + | ||
319 | +#if TARGET_NSIG != 64 | ||
320 | +#error "Please adjust handle_signal()" | ||
321 | +#endif | ||
322 | + if (__put_user((target_ulong) ka->sa._sa_handler, &sc->handler) | ||
323 | + || __put_user(oldset->sig[0], &sc->oldmask) | ||
324 | + || __put_user(oldset->sig[1], &sc->_unused[3]) | ||
325 | + || __put_user(frame, (target_ulong *)&sc->regs) | ||
326 | + || __put_user(sig, &sc->signal)) | ||
327 | + goto badframe; | ||
328 | + | ||
329 | + if (save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn)) | ||
330 | + goto badframe; | ||
331 | + | ||
332 | + if (put_user(env->gpr[1], (unsigned long *)newsp)) | ||
333 | + goto badframe; | ||
334 | + env->gpr[1] = newsp; | ||
335 | + env->gpr[3] = sig; | ||
336 | + env->gpr[4] = (unsigned long) sc; | ||
337 | + env->nip = (unsigned long) ka->sa._sa_handler; | ||
338 | + env->lr = (unsigned long) frame->mctx.tramp; | ||
339 | + /* FIXME: env->trap = 0; */ | ||
340 | + | ||
341 | + return; | ||
342 | + | ||
343 | +badframe: | ||
344 | +#ifdef DEBUG_SIGNAL | ||
345 | + fprintf(stderr, | ||
346 | + "badframe in handle_signal, frame=%p newsp=%lx\n", | ||
347 | + frame, newsp); | ||
348 | +#endif | ||
349 | + force_sig(TARGET_SIGSEGV); | ||
350 | +} | ||
351 | + | ||
352 | +static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
353 | + target_siginfo_t *info, | ||
354 | + target_sigset_t *set, CPUState *env) | ||
355 | +{ | ||
356 | + fprintf(stderr, "setup_rt_frame: not implemented\n"); | ||
357 | +} | ||
358 | + | ||
359 | +long do_sigreturn(CPUState *env) | ||
360 | +{ | ||
361 | + struct target_sigcontext *sc; | ||
362 | + struct target_sigcontext sigctx; | ||
363 | + struct target_mcontext *sr; | ||
364 | + target_sigset_t set; | ||
365 | + sigset_t host_set; | ||
366 | + | ||
367 | + /* Always make any pending restarted system calls return -EINTR */ | ||
368 | +#if 0 /* FIXME */ | ||
369 | + current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
370 | +#endif | ||
371 | + | ||
372 | + sc = (struct target_sigcontext *)(env->gpr[1] + __SIGNAL_FRAMESIZE); | ||
373 | + if (!memcpy(&sigctx, sc, sizeof(sigctx))) | ||
374 | + goto badframe; | ||
375 | + | ||
376 | + set.sig[0] = sigctx.oldmask; | ||
377 | + set.sig[1] = sigctx._unused[3]; | ||
378 | + target_to_host_sigset_internal(&host_set, &set); | ||
379 | + sigprocmask(SIG_SETMASK, &host_set, NULL); | ||
380 | + | ||
381 | + sr = (struct target_mcontext *) tswapl((target_ulong)sigctx.regs); | ||
382 | + if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) | ||
383 | + || restore_user_regs(env, sr, 1)) | ||
384 | + goto badframe; | ||
385 | + | ||
386 | + return 0; | ||
387 | + | ||
388 | +badframe: | ||
389 | + force_sig(TARGET_SIGSEGV); | ||
390 | + return 0; | ||
391 | +} | ||
392 | + | ||
393 | +long do_rt_sigreturn(CPUState *env) | ||
394 | +{ | ||
395 | + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); | ||
396 | + return -ENOSYS; | ||
397 | +} | ||
398 | + | ||
399 | #else | ||
400 | |||
401 | static void setup_frame(int sig, struct emulated_sigaction *ka, | ||