X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=arch%2Fpowerpc%2Flib%2Fsstep.c;h=4aae0c3876452919d17b95322682ea7486d0beb6;hb=b643b0fdbc59cf6bbb086974b29d2571e9e9f646;hp=c251d9936612916eb9f0329ebd4998d2be4ef1db;hpb=af308377e204e25f1f58627d05fe0f483703b514;p=pandora-kernel.git diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index c251d9936612..4aae0c387645 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -9,8 +9,8 @@ * 2 of the License, or (at your option) any later version. */ #include +#include #include -#include #include #include @@ -26,7 +26,7 @@ extern char system_call_common[]; /* * Determine whether a conditional branch instruction would branch. */ -static int branch_taken(unsigned int instr, struct pt_regs *regs) +static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) { unsigned int bo = (instr >> 21) & 0x1f; unsigned int bi; @@ -52,9 +52,9 @@ static int branch_taken(unsigned int instr, struct pt_regs *regs) * or -1 if the instruction is one that should not be stepped, * such as an rfid, or a mtmsrd that would clear MSR_RI. */ -int emulate_step(struct pt_regs *regs, unsigned int instr) +int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) { - unsigned int opcode, rd; + unsigned int opcode, rs, rb, rd, spr; unsigned long int imm; opcode = instr >> 26; @@ -152,6 +152,49 @@ int emulate_step(struct pt_regs *regs, unsigned int instr) regs->nip &= 0xffffffffUL; return 1; #endif + case 0x26: /* mfcr */ + regs->gpr[rd] = regs->ccr; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x2a6: /* mfspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mfxer */ + regs->gpr[rd] = regs->xer; + regs->gpr[rd] &= 0xffffffffUL; + goto mtspr_out; + case 0x100: /* mflr */ + regs->gpr[rd] = regs->link; + goto mtspr_out; + case 0x120: /* mfctr */ + regs->gpr[rd] = regs->ctr; + goto mtspr_out; + } + break; + case 0x378: /* orx */ + rs = (instr >> 21) & 0x1f; + rb = (instr >> 11) & 0x1f; + if (rs == rb) { /* mr */ + rd = (instr >> 16) & 0x1f; + regs->gpr[rd] = regs->gpr[rs]; + goto mtspr_out; + } + break; + case 0x3a6: /* mtspr */ + spr = (instr >> 11) & 0x3ff; + switch (spr) { + case 0x20: /* mtxer */ + regs->xer = (regs->gpr[rd] & 0xffffffffUL); + goto mtspr_out; + case 0x100: /* mtlr */ + regs->link = regs->gpr[rd]; + goto mtspr_out; + case 0x120: /* mtctr */ + regs->ctr = regs->gpr[rd]; +mtspr_out: + regs->nip += 4; + return 1; + } } } return 0;