aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/sstep.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/lib/sstep.c')
-rw-r--r--arch/powerpc/lib/sstep.c62
1 files changed, 28 insertions, 34 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index ae5189ab0049..9a52349874ee 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -11,6 +11,7 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/kprobes.h> 12#include <linux/kprobes.h>
13#include <linux/ptrace.h> 13#include <linux/ptrace.h>
14#include <linux/prefetch.h>
14#include <asm/sstep.h> 15#include <asm/sstep.h>
15#include <asm/processor.h> 16#include <asm/processor.h>
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
@@ -45,6 +46,18 @@ extern int do_stxvd2x(int rn, unsigned long ea);
45#endif 46#endif
46 47
47/* 48/*
49 * Emulate the truncation of 64 bit values in 32-bit mode.
50 */
51static unsigned long truncate_if_32bit(unsigned long msr, unsigned long val)
52{
53#ifdef __powerpc64__
54 if ((msr & MSR_64BIT) == 0)
55 val &= 0xffffffffUL;
56#endif
57 return val;
58}
59
60/*
48 * Determine whether a conditional branch instruction would branch. 61 * Determine whether a conditional branch instruction would branch.
49 */ 62 */
50static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) 63static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
@@ -90,11 +103,8 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs
90 if (instr & 0x04000000) /* update forms */ 103 if (instr & 0x04000000) /* update forms */
91 regs->gpr[ra] = ea; 104 regs->gpr[ra] = ea;
92 } 105 }
93#ifdef __powerpc64__ 106
94 if (!(regs->msr & MSR_SF)) 107 return truncate_if_32bit(regs->msr, ea);
95 ea &= 0xffffffffUL;
96#endif
97 return ea;
98} 108}
99 109
100#ifdef __powerpc64__ 110#ifdef __powerpc64__
@@ -113,9 +123,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg
113 if ((instr & 3) == 1) /* update forms */ 123 if ((instr & 3) == 1) /* update forms */
114 regs->gpr[ra] = ea; 124 regs->gpr[ra] = ea;
115 } 125 }
116 if (!(regs->msr & MSR_SF)) 126
117 ea &= 0xffffffffUL; 127 return truncate_if_32bit(regs->msr, ea);
118 return ea;
119} 128}
120#endif /* __powerpc64 */ 129#endif /* __powerpc64 */
121 130
@@ -136,11 +145,8 @@ static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs
136 if (do_update) /* update forms */ 145 if (do_update) /* update forms */
137 regs->gpr[ra] = ea; 146 regs->gpr[ra] = ea;
138 } 147 }
139#ifdef __powerpc64__ 148
140 if (!(regs->msr & MSR_SF)) 149 return truncate_if_32bit(regs->msr, ea);
141 ea &= 0xffffffffUL;
142#endif
143 return ea;
144} 150}
145 151
146/* 152/*
@@ -466,7 +472,7 @@ static void __kprobes set_cr0(struct pt_regs *regs, int rd)
466 472
467 regs->ccr = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000); 473 regs->ccr = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
468#ifdef __powerpc64__ 474#ifdef __powerpc64__
469 if (!(regs->msr & MSR_SF)) 475 if (!(regs->msr & MSR_64BIT))
470 val = (int) val; 476 val = (int) val;
471#endif 477#endif
472 if (val < 0) 478 if (val < 0)
@@ -487,7 +493,7 @@ static void __kprobes add_with_carry(struct pt_regs *regs, int rd,
487 ++val; 493 ++val;
488 regs->gpr[rd] = val; 494 regs->gpr[rd] = val;
489#ifdef __powerpc64__ 495#ifdef __powerpc64__
490 if (!(regs->msr & MSR_SF)) { 496 if (!(regs->msr & MSR_64BIT)) {
491 val = (unsigned int) val; 497 val = (unsigned int) val;
492 val1 = (unsigned int) val1; 498 val1 = (unsigned int) val1;
493 } 499 }
@@ -570,8 +576,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
570 if ((instr & 2) == 0) 576 if ((instr & 2) == 0)
571 imm += regs->nip; 577 imm += regs->nip;
572 regs->nip += 4; 578 regs->nip += 4;
573 if ((regs->msr & MSR_SF) == 0) 579 regs->nip = truncate_if_32bit(regs->msr, regs->nip);
574 regs->nip &= 0xffffffffUL;
575 if (instr & 1) 580 if (instr & 1)
576 regs->link = regs->nip; 581 regs->link = regs->nip;
577 if (branch_taken(instr, regs)) 582 if (branch_taken(instr, regs))
@@ -604,13 +609,9 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
604 imm -= 0x04000000; 609 imm -= 0x04000000;
605 if ((instr & 2) == 0) 610 if ((instr & 2) == 0)
606 imm += regs->nip; 611 imm += regs->nip;
607 if (instr & 1) { 612 if (instr & 1)
608 regs->link = regs->nip + 4; 613 regs->link = truncate_if_32bit(regs->msr, regs->nip + 4);
609 if ((regs->msr & MSR_SF) == 0) 614 imm = truncate_if_32bit(regs->msr, imm);
610 regs->link &= 0xffffffffUL;
611 }
612 if ((regs->msr & MSR_SF) == 0)
613 imm &= 0xffffffffUL;
614 regs->nip = imm; 615 regs->nip = imm;
615 return 1; 616 return 1;
616 case 19: 617 case 19:
@@ -618,11 +619,8 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
618 case 16: /* bclr */ 619 case 16: /* bclr */
619 case 528: /* bcctr */ 620 case 528: /* bcctr */
620 imm = (instr & 0x400)? regs->ctr: regs->link; 621 imm = (instr & 0x400)? regs->ctr: regs->link;
621 regs->nip += 4; 622 regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
622 if ((regs->msr & MSR_SF) == 0) { 623 imm = truncate_if_32bit(regs->msr, imm);
623 regs->nip &= 0xffffffffUL;
624 imm &= 0xffffffffUL;
625 }
626 if (instr & 1) 624 if (instr & 1)
627 regs->link = regs->nip; 625 regs->link = regs->nip;
628 if (branch_taken(instr, regs)) 626 if (branch_taken(instr, regs))
@@ -1616,11 +1614,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
1616 return 0; /* invoke DSI if -EFAULT? */ 1614 return 0; /* invoke DSI if -EFAULT? */
1617 } 1615 }
1618 instr_done: 1616 instr_done:
1619 regs->nip += 4; 1617 regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
1620#ifdef __powerpc64__
1621 if ((regs->msr & MSR_SF) == 0)
1622 regs->nip &= 0xffffffffUL;
1623#endif
1624 return 1; 1618 return 1;
1625 1619
1626 logical_done: 1620 logical_done: