summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/sstep.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-20 13:28:01 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-20 13:28:01 -0700
commit82aff107f8c9194586f68e86412246629d05670a (patch)
treec4336e8bbd453235dafecba6b8dca24c8cbcb2e5 /arch/powerpc/lib/sstep.c
parentd974d905cbfc1039a73ba0c7eea3f4d4e13c0624 (diff)
parent208b3a4c196e733b9cec006dc132cfc149b2810a (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (152 commits) powerpc: Fix hard CPU IDs detection powerpc/pmac: Update via-pmu to new syscore_ops powerpc/kvm: Fix the build for 32-bit Book 3S (classic) processors powerpc/kvm: Fix kvmppc_core_pending_dec powerpc: Remove last piece of GEMINI powerpc: Fix for Pegasos keyboard and mouse powerpc: Make early memory scan more resilient to out of order nodes powerpc/pseries/iommu: Cleanup ddw naming powerpc/pseries/iommu: Find windows after kexec during boot powerpc/pseries/iommu: Remove ddw property when destroying window powerpc/pseries/iommu: Add additional checks when changing iommu mask powerpc/pseries/iommu: Use correct return type in dupe_ddw_if_already_created powerpc: Remove unused/obsolete CONFIG_XICS misc: Add CARMA DATA-FPGA Programmer support misc: Add CARMA DATA-FPGA Access Driver powerpc: Make IRQ_NOREQUEST last to clear, first to set powerpc: Integrated Flash controller device tree bindings powerpc/85xx: Create dts of each core in CAMP mode for P1020RDB powerpc/85xx: Fix PCIe IDSEL for Px020RDB powerpc/85xx: P2020 DTS: re-organize dts files ...
Diffstat (limited to 'arch/powerpc/lib/sstep.c')
-rw-r--r--arch/powerpc/lib/sstep.c61
1 files changed, 27 insertions, 34 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index f73daa6f397..9a52349874e 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -46,6 +46,18 @@ extern int do_stxvd2x(int rn, unsigned long ea);
#endif
/*
+ * Emulate the truncation of 64 bit values in 32-bit mode.
+ */
+static unsigned long truncate_if_32bit(unsigned long msr, unsigned long val)
+{
+#ifdef __powerpc64__
+ if ((msr & MSR_64BIT) == 0)
+ val &= 0xffffffffUL;
+#endif
+ return val;
+}
+
+/*
* Determine whether a conditional branch instruction would branch.
*/
static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
@@ -91,11 +103,8 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs
if (instr & 0x04000000) /* update forms */
regs->gpr[ra] = ea;
}
-#ifdef __powerpc64__
- if (!(regs->msr & MSR_SF))
- ea &= 0xffffffffUL;
-#endif
- return ea;
+
+ return truncate_if_32bit(regs->msr, ea);
}
#ifdef __powerpc64__
@@ -114,9 +123,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg
if ((instr & 3) == 1) /* update forms */
regs->gpr[ra] = ea;
}
- if (!(regs->msr & MSR_SF))
- ea &= 0xffffffffUL;
- return ea;
+
+ return truncate_if_32bit(regs->msr, ea);
}
#endif /* __powerpc64 */
@@ -137,11 +145,8 @@ static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs
if (do_update) /* update forms */
regs->gpr[ra] = ea;
}
-#ifdef __powerpc64__
- if (!(regs->msr & MSR_SF))
- ea &= 0xffffffffUL;
-#endif
- return ea;
+
+ return truncate_if_32bit(regs->msr, ea);
}
/*
@@ -467,7 +472,7 @@ static void __kprobes set_cr0(struct pt_regs *regs, int rd)
regs->ccr = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
#ifdef __powerpc64__
- if (!(regs->msr & MSR_SF))
+ if (!(regs->msr & MSR_64BIT))
val = (int) val;
#endif
if (val < 0)
@@ -488,7 +493,7 @@ static void __kprobes add_with_carry(struct pt_regs *regs, int rd,
++val;
regs->gpr[rd] = val;
#ifdef __powerpc64__
- if (!(regs->msr & MSR_SF)) {
+ if (!(regs->msr & MSR_64BIT)) {
val = (unsigned int) val;
val1 = (unsigned int) val1;
}
@@ -571,8 +576,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
if ((instr & 2) == 0)
imm += regs->nip;
regs->nip += 4;
- if ((regs->msr & MSR_SF) == 0)
- regs->nip &= 0xffffffffUL;
+ regs->nip = truncate_if_32bit(regs->msr, regs->nip);
if (instr & 1)
regs->link = regs->nip;
if (branch_taken(instr, regs))
@@ -605,13 +609,9 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
imm -= 0x04000000;
if ((instr & 2) == 0)
imm += regs->nip;
- if (instr & 1) {
- regs->link = regs->nip + 4;
- if ((regs->msr & MSR_SF) == 0)
- regs->link &= 0xffffffffUL;
- }
- if ((regs->msr & MSR_SF) == 0)
- imm &= 0xffffffffUL;
+ if (instr & 1)
+ regs->link = truncate_if_32bit(regs->msr, regs->nip + 4);
+ imm = truncate_if_32bit(regs->msr, imm);
regs->nip = imm;
return 1;
case 19:
@@ -619,11 +619,8 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 16: /* bclr */
case 528: /* bcctr */
imm = (instr & 0x400)? regs->ctr: regs->link;
- regs->nip += 4;
- if ((regs->msr & MSR_SF) == 0) {
- regs->nip &= 0xffffffffUL;
- imm &= 0xffffffffUL;
- }
+ regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
+ imm = truncate_if_32bit(regs->msr, imm);
if (instr & 1)
regs->link = regs->nip;
if (branch_taken(instr, regs))
@@ -1617,11 +1614,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
return 0; /* invoke DSI if -EFAULT? */
}
instr_done:
- regs->nip += 4;
-#ifdef __powerpc64__
- if ((regs->msr & MSR_SF) == 0)
- regs->nip &= 0xffffffffUL;
-#endif
+ regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
return 1;
logical_done: