diff options
author | Michael Neuling <mikey@neuling.org> | 2008-06-25 00:07:18 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-06-30 21:28:50 -0400 |
commit | ce48b2100785e5ca629fb3aa8e3b50aca808f692 (patch) | |
tree | 63532ff7cc68b18ca4902bd10e03fcbaaf01cade /arch/powerpc/kernel/ptrace.c | |
parent | 72ffff5b1792b0fa4d40a8e2f3276fff999820ec (diff) |
powerpc: Add VSX context save/restore, ptrace and signal support
This patch extends the floating point save and restore code to use the
VSX load/stores when VSX is available. This will make FP context
save/restore marginally slower on FP only code, when VSX is available,
as it has to load/store 128bits rather than just 64bits.
Mixing FP, VMX and VSX code will get constant architected state.
The signals interface is extended to enable access to VSR 0-31
doubleword 1 after discussions with tool chain maintainers. Backward
compatibility is maintained.
The ptrace interface is also extended to allow access to VSR 0-31 full
registers.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 70fbde84b83f..4e203a89e189 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -350,6 +350,51 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset, | |||
350 | } | 350 | } |
351 | #endif /* CONFIG_ALTIVEC */ | 351 | #endif /* CONFIG_ALTIVEC */ |
352 | 352 | ||
353 | #ifdef CONFIG_VSX | ||
354 | /* | ||
355 | * Currently to set and and get all the vsx state, you need to call | ||
356 | * the fp and VMX calls aswell. This only get/sets the lower 32 | ||
357 | * 128bit VSX registers. | ||
358 | */ | ||
359 | |||
360 | static int vsr_active(struct task_struct *target, | ||
361 | const struct user_regset *regset) | ||
362 | { | ||
363 | flush_vsx_to_thread(target); | ||
364 | return target->thread.used_vsr ? regset->n : 0; | ||
365 | } | ||
366 | |||
367 | static int vsr_get(struct task_struct *target, const struct user_regset *regset, | ||
368 | unsigned int pos, unsigned int count, | ||
369 | void *kbuf, void __user *ubuf) | ||
370 | { | ||
371 | int ret; | ||
372 | |||
373 | flush_vsx_to_thread(target); | ||
374 | |||
375 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
376 | target->thread.fpr, 0, | ||
377 | 32 * sizeof(vector128)); | ||
378 | |||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int vsr_set(struct task_struct *target, const struct user_regset *regset, | ||
383 | unsigned int pos, unsigned int count, | ||
384 | const void *kbuf, const void __user *ubuf) | ||
385 | { | ||
386 | int ret; | ||
387 | |||
388 | flush_vsx_to_thread(target); | ||
389 | |||
390 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
391 | target->thread.fpr, 0, | ||
392 | 32 * sizeof(vector128)); | ||
393 | |||
394 | return ret; | ||
395 | } | ||
396 | #endif /* CONFIG_VSX */ | ||
397 | |||
353 | #ifdef CONFIG_SPE | 398 | #ifdef CONFIG_SPE |
354 | 399 | ||
355 | /* | 400 | /* |
@@ -426,6 +471,9 @@ enum powerpc_regset { | |||
426 | #ifdef CONFIG_ALTIVEC | 471 | #ifdef CONFIG_ALTIVEC |
427 | REGSET_VMX, | 472 | REGSET_VMX, |
428 | #endif | 473 | #endif |
474 | #ifdef CONFIG_VSX | ||
475 | REGSET_VSX, | ||
476 | #endif | ||
429 | #ifdef CONFIG_SPE | 477 | #ifdef CONFIG_SPE |
430 | REGSET_SPE, | 478 | REGSET_SPE, |
431 | #endif | 479 | #endif |
@@ -449,6 +497,13 @@ static const struct user_regset native_regsets[] = { | |||
449 | .active = vr_active, .get = vr_get, .set = vr_set | 497 | .active = vr_active, .get = vr_get, .set = vr_set |
450 | }, | 498 | }, |
451 | #endif | 499 | #endif |
500 | #ifdef CONFIG_VSX | ||
501 | [REGSET_VSX] = { | ||
502 | .n = 32, | ||
503 | .size = sizeof(vector128), .align = sizeof(vector128), | ||
504 | .active = vsr_active, .get = vsr_get, .set = vsr_set | ||
505 | }, | ||
506 | #endif | ||
452 | #ifdef CONFIG_SPE | 507 | #ifdef CONFIG_SPE |
453 | [REGSET_SPE] = { | 508 | [REGSET_SPE] = { |
454 | .n = 35, | 509 | .n = 35, |
@@ -849,6 +904,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
849 | sizeof(u32)), | 904 | sizeof(u32)), |
850 | (const void __user *) data); | 905 | (const void __user *) data); |
851 | #endif | 906 | #endif |
907 | #ifdef CONFIG_VSX | ||
908 | case PTRACE_GETVSRREGS: | ||
909 | return copy_regset_to_user(child, &user_ppc_native_view, | ||
910 | REGSET_VSX, | ||
911 | 0, (32 * sizeof(vector128) + | ||
912 | sizeof(u32)), | ||
913 | (void __user *) data); | ||
914 | |||
915 | case PTRACE_SETVSRREGS: | ||
916 | return copy_regset_from_user(child, &user_ppc_native_view, | ||
917 | REGSET_VSX, | ||
918 | 0, (32 * sizeof(vector128) + | ||
919 | sizeof(u32)), | ||
920 | (const void __user *) data); | ||
921 | #endif | ||
852 | #ifdef CONFIG_SPE | 922 | #ifdef CONFIG_SPE |
853 | case PTRACE_GETEVRREGS: | 923 | case PTRACE_GETEVRREGS: |
854 | /* Get the child spe register state. */ | 924 | /* Get the child spe register state. */ |