diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b057e6852a7d..f7fa395b9fb5 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -337,14 +337,16 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
337 | int sigret) | 337 | int sigret) |
338 | { | 338 | { |
339 | unsigned long msr = regs->msr; | 339 | unsigned long msr = regs->msr; |
340 | #ifdef CONFIG_VSX | ||
341 | double buf[32]; | ||
342 | int i; | ||
343 | #endif | ||
340 | 344 | ||
341 | /* Make sure floating point registers are stored in regs */ | 345 | /* Make sure floating point registers are stored in regs */ |
342 | flush_fp_to_thread(current); | 346 | flush_fp_to_thread(current); |
343 | 347 | ||
344 | /* save general and floating-point registers */ | 348 | /* save general registers */ |
345 | if (save_general_regs(regs, frame) || | 349 | if (save_general_regs(regs, frame)) |
346 | __copy_to_user(&frame->mc_fregs, current->thread.fpr, | ||
347 | ELF_NFPREG * sizeof(double))) | ||
348 | return 1; | 350 | return 1; |
349 | 351 | ||
350 | #ifdef CONFIG_ALTIVEC | 352 | #ifdef CONFIG_ALTIVEC |
@@ -368,7 +370,20 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
368 | if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32])) | 370 | if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32])) |
369 | return 1; | 371 | return 1; |
370 | #endif /* CONFIG_ALTIVEC */ | 372 | #endif /* CONFIG_ALTIVEC */ |
371 | 373 | #ifdef CONFIG_VSX | |
374 | /* save FPR copy to local buffer then write to the thread_struct */ | ||
375 | flush_fp_to_thread(current); | ||
376 | for (i = 0; i < 32 ; i++) | ||
377 | buf[i] = current->thread.TS_FPR(i); | ||
378 | memcpy(&buf[i], ¤t->thread.fpscr, sizeof(double)); | ||
379 | if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double))) | ||
380 | return 1; | ||
381 | #else | ||
382 | /* save floating-point registers */ | ||
383 | if (__copy_to_user(&frame->mc_fregs, current->thread.fpr, | ||
384 | ELF_NFPREG * sizeof(double))) | ||
385 | return 1; | ||
386 | #endif /* CONFIG_VSX */ | ||
372 | #ifdef CONFIG_SPE | 387 | #ifdef CONFIG_SPE |
373 | /* save spe registers */ | 388 | /* save spe registers */ |
374 | if (current->thread.used_spe) { | 389 | if (current->thread.used_spe) { |
@@ -411,6 +426,10 @@ static long restore_user_regs(struct pt_regs *regs, | |||
411 | long err; | 426 | long err; |
412 | unsigned int save_r2 = 0; | 427 | unsigned int save_r2 = 0; |
413 | unsigned long msr; | 428 | unsigned long msr; |
429 | #ifdef CONFIG_VSX | ||
430 | double buf[32]; | ||
431 | int i; | ||
432 | #endif | ||
414 | 433 | ||
415 | /* | 434 | /* |
416 | * restore general registers but not including MSR or SOFTE. Also | 435 | * restore general registers but not including MSR or SOFTE. Also |
@@ -438,16 +457,11 @@ static long restore_user_regs(struct pt_regs *regs, | |||
438 | */ | 457 | */ |
439 | discard_lazy_cpu_state(); | 458 | discard_lazy_cpu_state(); |
440 | 459 | ||
441 | /* force the process to reload the FP registers from | ||
442 | current->thread when it next does FP instructions */ | ||
443 | regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); | ||
444 | if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, | ||
445 | sizeof(sr->mc_fregs))) | ||
446 | return 1; | ||
447 | |||
448 | #ifdef CONFIG_ALTIVEC | 460 | #ifdef CONFIG_ALTIVEC |
449 | /* force the process to reload the altivec registers from | 461 | /* |
450 | current->thread when it next does altivec instructions */ | 462 | * Force the process to reload the altivec registers from |
463 | * current->thread when it next does altivec instructions | ||
464 | */ | ||
451 | regs->msr &= ~MSR_VEC; | 465 | regs->msr &= ~MSR_VEC; |
452 | if (msr & MSR_VEC) { | 466 | if (msr & MSR_VEC) { |
453 | /* restore altivec registers from the stack */ | 467 | /* restore altivec registers from the stack */ |
@@ -462,6 +476,23 @@ static long restore_user_regs(struct pt_regs *regs, | |||
462 | return 1; | 476 | return 1; |
463 | #endif /* CONFIG_ALTIVEC */ | 477 | #endif /* CONFIG_ALTIVEC */ |
464 | 478 | ||
479 | #ifdef CONFIG_VSX | ||
480 | if (__copy_from_user(buf, &sr->mc_fregs,sizeof(sr->mc_fregs))) | ||
481 | return 1; | ||
482 | for (i = 0; i < 32 ; i++) | ||
483 | current->thread.TS_FPR(i) = buf[i]; | ||
484 | memcpy(¤t->thread.fpscr, &buf[i], sizeof(double)); | ||
485 | #else | ||
486 | if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, | ||
487 | sizeof(sr->mc_fregs))) | ||
488 | return 1; | ||
489 | #endif /* CONFIG_VSX */ | ||
490 | /* | ||
491 | * force the process to reload the FP registers from | ||
492 | * current->thread when it next does FP instructions | ||
493 | */ | ||
494 | regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); | ||
495 | |||
465 | #ifdef CONFIG_SPE | 496 | #ifdef CONFIG_SPE |
466 | /* force the process to reload the spe registers from | 497 | /* force the process to reload the spe registers from |
467 | current->thread when it next does spe instructions */ | 498 | current->thread when it next does spe instructions */ |