diff options
Diffstat (limited to 'arch/mips/kernel/ptrace.c')
-rw-r--r-- | arch/mips/kernel/ptrace.c | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index b52e1d2b33e0..7da9b76db4d9 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -137,13 +137,13 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data) | |||
137 | if (cpu_has_mipsmt) { | 137 | if (cpu_has_mipsmt) { |
138 | unsigned int vpflags = dvpe(); | 138 | unsigned int vpflags = dvpe(); |
139 | flags = read_c0_status(); | 139 | flags = read_c0_status(); |
140 | __enable_fpu(); | 140 | __enable_fpu(FPU_AS_IS); |
141 | __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); | 141 | __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); |
142 | write_c0_status(flags); | 142 | write_c0_status(flags); |
143 | evpe(vpflags); | 143 | evpe(vpflags); |
144 | } else { | 144 | } else { |
145 | flags = read_c0_status(); | 145 | flags = read_c0_status(); |
146 | __enable_fpu(); | 146 | __enable_fpu(FPU_AS_IS); |
147 | __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); | 147 | __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); |
148 | write_c0_status(flags); | 148 | write_c0_status(flags); |
149 | } | 149 | } |
@@ -408,6 +408,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
408 | /* Read the word at location addr in the USER area. */ | 408 | /* Read the word at location addr in the USER area. */ |
409 | case PTRACE_PEEKUSR: { | 409 | case PTRACE_PEEKUSR: { |
410 | struct pt_regs *regs; | 410 | struct pt_regs *regs; |
411 | fpureg_t *fregs; | ||
411 | unsigned long tmp = 0; | 412 | unsigned long tmp = 0; |
412 | 413 | ||
413 | regs = task_pt_regs(child); | 414 | regs = task_pt_regs(child); |
@@ -418,26 +419,28 @@ long arch_ptrace(struct task_struct *child, long request, | |||
418 | tmp = regs->regs[addr]; | 419 | tmp = regs->regs[addr]; |
419 | break; | 420 | break; |
420 | case FPR_BASE ... FPR_BASE + 31: | 421 | case FPR_BASE ... FPR_BASE + 31: |
421 | if (tsk_used_math(child)) { | 422 | if (!tsk_used_math(child)) { |
422 | fpureg_t *fregs = get_fpu_regs(child); | 423 | /* FP not yet used */ |
424 | tmp = -1; | ||
425 | break; | ||
426 | } | ||
427 | fregs = get_fpu_regs(child); | ||
423 | 428 | ||
424 | #ifdef CONFIG_32BIT | 429 | #ifdef CONFIG_32BIT |
430 | if (test_thread_flag(TIF_32BIT_FPREGS)) { | ||
425 | /* | 431 | /* |
426 | * The odd registers are actually the high | 432 | * The odd registers are actually the high |
427 | * order bits of the values stored in the even | 433 | * order bits of the values stored in the even |
428 | * registers - unless we're using r2k_switch.S. | 434 | * registers - unless we're using r2k_switch.S. |
429 | */ | 435 | */ |
430 | if (addr & 1) | 436 | if (addr & 1) |
431 | tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); | 437 | tmp = fregs[(addr & ~1) - 32] >> 32; |
432 | else | 438 | else |
433 | tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); | 439 | tmp = fregs[addr - 32]; |
434 | #endif | 440 | break; |
435 | #ifdef CONFIG_64BIT | ||
436 | tmp = fregs[addr - FPR_BASE]; | ||
437 | #endif | ||
438 | } else { | ||
439 | tmp = -1; /* FP not yet used */ | ||
440 | } | 441 | } |
442 | #endif | ||
443 | tmp = fregs[addr - FPR_BASE]; | ||
441 | break; | 444 | break; |
442 | case PC: | 445 | case PC: |
443 | tmp = regs->cp0_epc; | 446 | tmp = regs->cp0_epc; |
@@ -483,13 +486,13 @@ long arch_ptrace(struct task_struct *child, long request, | |||
483 | if (cpu_has_mipsmt) { | 486 | if (cpu_has_mipsmt) { |
484 | unsigned int vpflags = dvpe(); | 487 | unsigned int vpflags = dvpe(); |
485 | flags = read_c0_status(); | 488 | flags = read_c0_status(); |
486 | __enable_fpu(); | 489 | __enable_fpu(FPU_AS_IS); |
487 | __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); | 490 | __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); |
488 | write_c0_status(flags); | 491 | write_c0_status(flags); |
489 | evpe(vpflags); | 492 | evpe(vpflags); |
490 | } else { | 493 | } else { |
491 | flags = read_c0_status(); | 494 | flags = read_c0_status(); |
492 | __enable_fpu(); | 495 | __enable_fpu(FPU_AS_IS); |
493 | __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); | 496 | __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); |
494 | write_c0_status(flags); | 497 | write_c0_status(flags); |
495 | } | 498 | } |
@@ -554,22 +557,25 @@ long arch_ptrace(struct task_struct *child, long request, | |||
554 | child->thread.fpu.fcr31 = 0; | 557 | child->thread.fpu.fcr31 = 0; |
555 | } | 558 | } |
556 | #ifdef CONFIG_32BIT | 559 | #ifdef CONFIG_32BIT |
557 | /* | 560 | if (test_thread_flag(TIF_32BIT_FPREGS)) { |
558 | * The odd registers are actually the high order bits | 561 | /* |
559 | * of the values stored in the even registers - unless | 562 | * The odd registers are actually the high |
560 | * we're using r2k_switch.S. | 563 | * order bits of the values stored in the even |
561 | */ | 564 | * registers - unless we're using r2k_switch.S. |
562 | if (addr & 1) { | 565 | */ |
563 | fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; | 566 | if (addr & 1) { |
564 | fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; | 567 | fregs[(addr & ~1) - FPR_BASE] &= |
565 | } else { | 568 | 0xffffffff; |
566 | fregs[addr - FPR_BASE] &= ~0xffffffffLL; | 569 | fregs[(addr & ~1) - FPR_BASE] |= |
567 | fregs[addr - FPR_BASE] |= data; | 570 | ((u64)data) << 32; |
571 | } else { | ||
572 | fregs[addr - FPR_BASE] &= ~0xffffffffLL; | ||
573 | fregs[addr - FPR_BASE] |= data; | ||
574 | } | ||
575 | break; | ||
568 | } | 576 | } |
569 | #endif | 577 | #endif |
570 | #ifdef CONFIG_64BIT | ||
571 | fregs[addr - FPR_BASE] = data; | 578 | fregs[addr - FPR_BASE] = data; |
572 | #endif | ||
573 | break; | 579 | break; |
574 | } | 580 | } |
575 | case PC: | 581 | case PC: |