Commit be96f633 authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman

powerpc: Split out instruction analysis part of emulate_step()

This splits out the instruction analysis part of emulate_step() into
a separate analyse_instr() function, which decodes the instruction,
but doesn't execute any load or store instructions.  It does execute
integer instructions and branches which can be executed purely by
updating register values in the pt_regs struct.  For other instructions,
it returns the instruction type and other details in a new
instruction_op struct.  emulate_step() then uses that information
to execute loads, stores, cache operations, mfmsr, mtmsr[d], and
(on 64-bit) sc instructions.

The reason for doing this is so that the KVM code can use it instead
of having its own separate instruction emulation code.  Possibly the
alignment interrupt handler could also use this.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent ad72a279
...@@ -25,3 +25,64 @@ struct pt_regs; ...@@ -25,3 +25,64 @@ struct pt_regs;
/* Emulate instructions that cause a transfer of control. */ /* Emulate instructions that cause a transfer of control. */
extern int emulate_step(struct pt_regs *regs, unsigned int instr); extern int emulate_step(struct pt_regs *regs, unsigned int instr);
enum instruction_type {
COMPUTE, /* arith/logical/CR op, etc. */
LOAD,
LOAD_MULTI,
LOAD_FP,
LOAD_VMX,
LOAD_VSX,
STORE,
STORE_MULTI,
STORE_FP,
STORE_VMX,
STORE_VSX,
LARX,
STCX,
BRANCH,
MFSPR,
MTSPR,
CACHEOP,
BARRIER,
SYSCALL,
MFMSR,
MTMSR,
RFI,
INTERRUPT,
UNKNOWN
};
#define INSTR_TYPE_MASK 0x1f
/* Load/store flags, ORed in with type */
#define SIGNEXT 0x20
#define UPDATE 0x40 /* matches bit in opcode 31 instructions */
#define BYTEREV 0x80
/* Cacheop values, ORed in with type */
#define CACHEOP_MASK 0x700
#define DCBST 0
#define DCBF 0x100
#define DCBTST 0x200
#define DCBT 0x300
/* Size field in type word */
#define SIZE(n) ((n) << 8)
#define GETSIZE(w) ((w) >> 8)
#define MKOP(t, f, s) ((t) | (f) | SIZE(s))
struct instruction_op {
int type;
int reg;
unsigned long val;
/* For LOAD/STORE/LARX/STCX */
unsigned long ea;
int update_reg;
/* For MFSPR */
int spr;
};
extern int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
unsigned int instr);
...@@ -98,13 +98,8 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs ...@@ -98,13 +98,8 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs
ra = (instr >> 16) & 0x1f; ra = (instr >> 16) & 0x1f;
ea = (signed short) instr; /* sign-extend */ ea = (signed short) instr; /* sign-extend */
if (ra) { if (ra)
ea += regs->gpr[ra]; ea += regs->gpr[ra];
if (instr & 0x04000000) { /* update forms */
if ((instr>>26) != 47) /* stmw is not an update form */
regs->gpr[ra] = ea;
}
}
return truncate_if_32bit(regs->msr, ea); return truncate_if_32bit(regs->msr, ea);
} }
...@@ -120,11 +115,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg ...@@ -120,11 +115,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg
ra = (instr >> 16) & 0x1f; ra = (instr >> 16) & 0x1f;
ea = (signed short) (instr & ~3); /* sign-extend */ ea = (signed short) (instr & ~3); /* sign-extend */
if (ra) { if (ra)
ea += regs->gpr[ra]; ea += regs->gpr[ra];
if ((instr & 3) == 1) /* update forms */
regs->gpr[ra] = ea;
}
return truncate_if_32bit(regs->msr, ea); return truncate_if_32bit(regs->msr, ea);
} }
...@@ -133,8 +125,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg ...@@ -133,8 +125,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg
/* /*
* Calculate effective address for an X-form instruction * Calculate effective address for an X-form instruction
*/ */
static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs, static unsigned long __kprobes xform_ea(unsigned int instr,
int do_update) struct pt_regs *regs)
{ {
int ra, rb; int ra, rb;
unsigned long ea; unsigned long ea;
...@@ -142,11 +134,8 @@ static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs ...@@ -142,11 +134,8 @@ static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs
ra = (instr >> 16) & 0x1f; ra = (instr >> 16) & 0x1f;
rb = (instr >> 11) & 0x1f; rb = (instr >> 11) & 0x1f;
ea = regs->gpr[rb]; ea = regs->gpr[rb];
if (ra) { if (ra)
ea += regs->gpr[ra]; ea += regs->gpr[ra];
if (do_update) /* update forms */
regs->gpr[ra] = ea;
}
return truncate_if_32bit(regs->msr, ea); return truncate_if_32bit(regs->msr, ea);
} }
...@@ -627,26 +616,27 @@ static void __kprobes do_cmp_unsigned(struct pt_regs *regs, unsigned long v1, ...@@ -627,26 +616,27 @@ static void __kprobes do_cmp_unsigned(struct pt_regs *regs, unsigned long v1,
#define ROTATE(x, n) ((n) ? (((x) << (n)) | ((x) >> (8 * sizeof(long) - (n)))) : (x)) #define ROTATE(x, n) ((n) ? (((x) << (n)) | ((x) >> (8 * sizeof(long) - (n)))) : (x))
/* /*
* Emulate instructions that cause a transfer of control, * Decode an instruction, and execute it if that can be done just by
* loads and stores, and a few other instructions. * modifying *regs (i.e. integer arithmetic and logical instructions,
* Returns 1 if the step was emulated, 0 if not, * branches, and barrier instructions).
* or -1 if the instruction is one that should not be stepped, * Returns 1 if the instruction has been executed, or 0 if not.
* such as an rfid, or a mtmsrd that would clear MSR_RI. * Sets *op to indicate what the instruction does.
*/ */
int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs,
unsigned int instr)
{ {
unsigned int opcode, ra, rb, rd, spr, u; unsigned int opcode, ra, rb, rd, spr, u;
unsigned long int imm; unsigned long int imm;
unsigned long int val, val2; unsigned long int val, val2;
unsigned long int ea; unsigned int mb, me, sh;
unsigned int cr, mb, me, sh;
int err;
unsigned long old_ra, val3;
long ival; long ival;
op->type = COMPUTE;
opcode = instr >> 26; opcode = instr >> 26;
switch (opcode) { switch (opcode) {
case 16: /* bc */ case 16: /* bc */
op->type = BRANCH;
imm = (signed short)(instr & 0xfffc); imm = (signed short)(instr & 0xfffc);
if ((instr & 2) == 0) if ((instr & 2) == 0)
imm += regs->nip; imm += regs->nip;
...@@ -659,26 +649,14 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -659,26 +649,14 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
return 1; return 1;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
case 17: /* sc */ case 17: /* sc */
/* if ((instr & 0xfe2) == 2)
* N.B. this uses knowledge about how the syscall op->type = SYSCALL;
* entry code works. If that is changed, this will else
* need to be changed also. op->type = UNKNOWN;
*/ return 0;
if (regs->gpr[0] == 0x1ebe &&
cpu_has_feature(CPU_FTR_REAL_LE)) {
regs->msr ^= MSR_LE;
goto instr_done;
}
regs->gpr[9] = regs->gpr[13];
regs->gpr[10] = MSR_KERNEL;
regs->gpr[11] = regs->nip + 4;
regs->gpr[12] = regs->msr & MSR_MASK;
regs->gpr[13] = (unsigned long) get_paca();
regs->nip = (unsigned long) &system_call_common;
regs->msr = MSR_KERNEL;
return 1;
#endif #endif
case 18: /* b */ case 18: /* b */
op->type = BRANCH;
imm = instr & 0x03fffffc; imm = instr & 0x03fffffc;
if (imm & 0x02000000) if (imm & 0x02000000)
imm -= 0x04000000; imm -= 0x04000000;
...@@ -693,6 +671,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -693,6 +671,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
switch ((instr >> 1) & 0x3ff) { switch ((instr >> 1) & 0x3ff) {
case 16: /* bclr */ case 16: /* bclr */
case 528: /* bcctr */ case 528: /* bcctr */
op->type = BRANCH;
imm = (instr & 0x400)? regs->ctr: regs->link; imm = (instr & 0x400)? regs->ctr: regs->link;
regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4); regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
imm = truncate_if_32bit(regs->msr, imm); imm = truncate_if_32bit(regs->msr, imm);
...@@ -703,9 +682,13 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -703,9 +682,13 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
return 1; return 1;
case 18: /* rfid, scary */ case 18: /* rfid, scary */
return -1; if (regs->msr & MSR_PR)
goto priv;
op->type = RFI;
return 0;
case 150: /* isync */ case 150: /* isync */
op->type = BARRIER;
isync(); isync();
goto instr_done; goto instr_done;
...@@ -731,6 +714,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -731,6 +714,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 31: case 31:
switch ((instr >> 1) & 0x3ff) { switch ((instr >> 1) & 0x3ff) {
case 598: /* sync */ case 598: /* sync */
op->type = BARRIER;
#ifdef __powerpc64__ #ifdef __powerpc64__
switch ((instr >> 21) & 3) { switch ((instr >> 21) & 3) {
case 1: /* lwsync */ case 1: /* lwsync */
...@@ -745,6 +729,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -745,6 +729,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
goto instr_done; goto instr_done;
case 854: /* eieio */ case 854: /* eieio */
op->type = BARRIER;
eieio(); eieio();
goto instr_done; goto instr_done;
} }
...@@ -910,33 +895,30 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -910,33 +895,30 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
switch ((instr >> 1) & 0x3ff) { switch ((instr >> 1) & 0x3ff) {
case 83: /* mfmsr */ case 83: /* mfmsr */
if (regs->msr & MSR_PR) if (regs->msr & MSR_PR)
break; goto priv;
regs->gpr[rd] = regs->msr & MSR_MASK; op->type = MFMSR;
goto instr_done; op->reg = rd;
return 0;
case 146: /* mtmsr */ case 146: /* mtmsr */
if (regs->msr & MSR_PR) if (regs->msr & MSR_PR)
break; goto priv;
imm = regs->gpr[rd]; op->type = MTMSR;
if ((imm & MSR_RI) == 0) op->reg = rd;
/* can't step mtmsr that would clear MSR_RI */ op->val = 0xffffffff & ~(MSR_ME | MSR_LE);
return -1; return 0;
regs->msr = imm;
goto instr_done;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
case 178: /* mtmsrd */ case 178: /* mtmsrd */
/* only MSR_EE and MSR_RI get changed if bit 15 set */
/* mtmsrd doesn't change MSR_HV and MSR_ME */
if (regs->msr & MSR_PR) if (regs->msr & MSR_PR)
break; goto priv;
imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL; op->type = MTMSR;
imm = (regs->msr & MSR_MASK & ~imm) op->reg = rd;
| (regs->gpr[rd] & imm); /* only MSR_EE and MSR_RI get changed if bit 15 set */
if ((imm & MSR_RI) == 0) /* mtmsrd doesn't change MSR_HV, MSR_ME or MSR_LE */
/* can't step mtmsrd that would clear MSR_RI */ imm = (instr & 0x10000)? 0x8002: 0xefffffffffffeffeUL;
return -1; op->val = imm;
regs->msr = imm; return 0;
goto instr_done;
#endif #endif
case 19: /* mfcr */ case 19: /* mfcr */
regs->gpr[rd] = regs->ccr; regs->gpr[rd] = regs->ccr;
regs->gpr[rd] &= 0xffffffffUL; regs->gpr[rd] &= 0xffffffffUL;
...@@ -954,33 +936,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -954,33 +936,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
goto instr_done; goto instr_done;
case 339: /* mfspr */ case 339: /* mfspr */
spr = (instr >> 11) & 0x3ff; spr = ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0);
switch (spr) { switch (spr) {
case 0x20: /* mfxer */ case SPRN_XER: /* mfxer */
regs->gpr[rd] = regs->xer; regs->gpr[rd] = regs->xer;
regs->gpr[rd] &= 0xffffffffUL; regs->gpr[rd] &= 0xffffffffUL;
goto instr_done; goto instr_done;
case 0x100: /* mflr */ case SPRN_LR: /* mflr */
regs->gpr[rd] = regs->link; regs->gpr[rd] = regs->link;
goto instr_done; goto instr_done;
case 0x120: /* mfctr */ case SPRN_CTR: /* mfctr */
regs->gpr[rd] = regs->ctr; regs->gpr[rd] = regs->ctr;
goto instr_done; goto instr_done;
default:
op->type = MFSPR;
op->reg = rd;
op->spr = spr;
return 0;
} }
break; break;
case 467: /* mtspr */ case 467: /* mtspr */
spr = (instr >> 11) & 0x3ff; spr = ((instr >> 16) & 0x1f) | ((instr >> 6) & 0x3e0);
switch (spr) { switch (spr) {
case 0x20: /* mtxer */ case SPRN_XER: /* mtxer */
regs->xer = (regs->gpr[rd] & 0xffffffffUL); regs->xer = (regs->gpr[rd] & 0xffffffffUL);
goto instr_done; goto instr_done;
case 0x100: /* mtlr */ case SPRN_LR: /* mtlr */
regs->link = regs->gpr[rd]; regs->link = regs->gpr[rd];
goto instr_done; goto instr_done;
case 0x120: /* mtctr */ case SPRN_CTR: /* mtctr */
regs->ctr = regs->gpr[rd]; regs->ctr = regs->gpr[rd];
goto instr_done; goto instr_done;
default:
op->type = MTSPR;
op->val = regs->gpr[rd];
op->spr = spr;
return 0;
} }
break; break;
...@@ -1257,294 +1249,210 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -1257,294 +1249,210 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
* Cache instructions * Cache instructions
*/ */
case 54: /* dcbst */ case 54: /* dcbst */
ea = xform_ea(instr, regs, 0); op->type = MKOP(CACHEOP, DCBST, 0);
if (!address_ok(regs, ea, 8)) op->ea = xform_ea(instr, regs);
return 0; return 0;
err = 0;
__cacheop_user_asmx(ea, err, "dcbst");
if (err)
return 0;
goto instr_done;
case 86: /* dcbf */ case 86: /* dcbf */
ea = xform_ea(instr, regs, 0); op->type = MKOP(CACHEOP, DCBF, 0);
if (!address_ok(regs, ea, 8)) op->ea = xform_ea(instr, regs);
return 0; return 0;
err = 0;
__cacheop_user_asmx(ea, err, "dcbf");
if (err)
return 0;
goto instr_done;
case 246: /* dcbtst */ case 246: /* dcbtst */
if (rd == 0) { op->type = MKOP(CACHEOP, DCBTST, 0);
ea = xform_ea(instr, regs, 0); op->ea = xform_ea(instr, regs);
prefetchw((void *) ea); op->reg = rd;
} return 0;
goto instr_done;
case 278: /* dcbt */ case 278: /* dcbt */
if (rd == 0) { op->type = MKOP(CACHEOP, DCBTST, 0);
ea = xform_ea(instr, regs, 0); op->ea = xform_ea(instr, regs);
prefetch((void *) ea); op->reg = rd;
} return 0;
goto instr_done;
} }
break; break;
} }
/* /*
* Following cases are for loads and stores, so bail out * Loads and stores.
* if we're in little-endian mode.
*/ */
if (regs->msr & MSR_LE) op->type = UNKNOWN;
return 0; op->update_reg = ra;
op->reg = rd;
/* op->val = regs->gpr[rd];
* Save register RA in case it's an update form load or store u = (instr >> 20) & UPDATE;
* and the access faults.
*/
old_ra = regs->gpr[ra];
switch (opcode) { switch (opcode) {
case 31: case 31:
u = instr & 0x40; u = instr & UPDATE;
op->ea = xform_ea(instr, regs);
switch ((instr >> 1) & 0x3ff) { switch ((instr >> 1) & 0x3ff) {
case 20: /* lwarx */ case 20: /* lwarx */
ea = xform_ea(instr, regs, 0); op->type = MKOP(LARX, 0, 4);
if (ea & 3) break;
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, ea, 4))
goto ldst_done;
err = 0;
__get_user_asmx(val, ea, err, "lwarx");
if (!err)
regs->gpr[rd] = val;
goto ldst_done;
case 150: /* stwcx. */ case 150: /* stwcx. */
ea = xform_ea(instr, regs, 0); op->type = MKOP(STCX, 0, 4);
if (ea & 3) break;
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, ea, 4))
goto ldst_done;
err = 0;
__put_user_asmx(regs->gpr[rd], ea, err, "stwcx.", cr);
if (!err)
regs->ccr = (regs->ccr & 0x0fffffff) |
(cr & 0xe0000000) |
((regs->xer >> 3) & 0x10000000);
goto ldst_done;
#ifdef __powerpc64__ #ifdef __powerpc64__
case 84: /* ldarx */ case 84: /* ldarx */
ea = xform_ea(instr, regs, 0); op->type = MKOP(LARX, 0, 8);
if (ea & 7) break;
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, ea, 8))
goto ldst_done;
err = 0;
__get_user_asmx(val, ea, err, "ldarx");
if (!err)
regs->gpr[rd] = val;
goto ldst_done;
case 214: /* stdcx. */ case 214: /* stdcx. */
ea = xform_ea(instr, regs, 0); op->type = MKOP(STCX, 0, 8);
if (ea & 7) break;
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, ea, 8))
goto ldst_done;
err = 0;
__put_user_asmx(regs->gpr[rd], ea, err, "stdcx.", cr);
if (!err)
regs->ccr = (regs->ccr & 0x0fffffff) |
(cr & 0xe0000000) |
((regs->xer >> 3) & 0x10000000);
goto ldst_done;
case 21: /* ldx */ case 21: /* ldx */
case 53: /* ldux */ case 53: /* ldux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, u, 8);
8, regs); break;
goto ldst_done;
#endif #endif
case 23: /* lwzx */ case 23: /* lwzx */
case 55: /* lwzux */ case 55: /* lwzux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, u, 4);
4, regs); break;
goto ldst_done;
case 87: /* lbzx */ case 87: /* lbzx */
case 119: /* lbzux */ case 119: /* lbzux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, u, 1);
1, regs); break;
goto ldst_done;
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
case 103: /* lvx */ case 103: /* lvx */
case 359: /* lvxl */ case 359: /* lvxl */
if (!(regs->msr & MSR_VEC)) if (!(regs->msr & MSR_VEC))
break; goto vecunavail;
ea = xform_ea(instr, regs, 0); op->type = MKOP(LOAD_VMX, 0, 16);
err = do_vec_load(rd, do_lvx, ea, regs); break;
goto ldst_done;
case 231: /* stvx */ case 231: /* stvx */
case 487: /* stvxl */ case 487: /* stvxl */
if (!(regs->msr & MSR_VEC)) if (!(regs->msr & MSR_VEC))
break; goto vecunavail;
ea = xform_ea(instr, regs, 0); op->type = MKOP(STORE_VMX, 0, 16);
err = do_vec_store(rd, do_stvx, ea, regs); break;
goto ldst_done;
#endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_ALTIVEC */
#ifdef __powerpc64__ #ifdef __powerpc64__
case 149: /* stdx */ case 149: /* stdx */
case 181: /* stdux */ case 181: /* stdux */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 8);
err = write_mem(val, xform_ea(instr, regs, u), 8, regs); break;
goto ldst_done;
#endif #endif
case 151: /* stwx */ case 151: /* stwx */
case 183: /* stwux */ case 183: /* stwux */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 4);
err = write_mem(val, xform_ea(instr, regs, u), 4, regs); break;
goto ldst_done;
case 215: /* stbx */ case 215: /* stbx */
case 247: /* stbux */ case 247: /* stbux */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 1);
err = write_mem(val, xform_ea(instr, regs, u), 1, regs); break;
goto ldst_done;
case 279: /* lhzx */ case 279: /* lhzx */
case 311: /* lhzux */ case 311: /* lhzux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, u, 2);
2, regs); break;
goto ldst_done;
#ifdef __powerpc64__ #ifdef __powerpc64__
case 341: /* lwax */ case 341: /* lwax */
case 373: /* lwaux */ case 373: /* lwaux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, SIGNEXT | u, 4);
4, regs); break;
if (!err)
regs->gpr[rd] = (signed int) regs->gpr[rd];
goto ldst_done;
#endif #endif
case 343: /* lhax */ case 343: /* lhax */
case 375: /* lhaux */ case 375: /* lhaux */
err = read_mem(&regs->gpr[rd], xform_ea(instr, regs, u), op->type = MKOP(LOAD, SIGNEXT | u, 2);
2, regs); break;
if (!err)
regs->gpr[rd] = (signed short) regs->gpr[rd];
goto ldst_done;
case 407: /* sthx */ case 407: /* sthx */
case 439: /* sthux */ case 439: /* sthux */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 2);
err = write_mem(val, xform_ea(instr, regs, u), 2, regs); break;
goto ldst_done;
#ifdef __powerpc64__ #ifdef __powerpc64__
case 532: /* ldbrx */ case 532: /* ldbrx */
err = read_mem(&val, xform_ea(instr, regs, 0), 8, regs); op->type = MKOP(LOAD, BYTEREV, 8);
if (!err) break;
regs->gpr[rd] = byterev_8(val);
goto ldst_done;
#endif #endif
case 534: /* lwbrx */ case 534: /* lwbrx */
err = read_mem(&val, xform_ea(instr, regs, 0), 4, regs); op->type = MKOP(LOAD, BYTEREV, 4);
if (!err) break;
regs->gpr[rd] = byterev_4(val);
goto ldst_done;
#ifdef CONFIG_PPC_FPU #ifdef CONFIG_PPC_FPU
case 535: /* lfsx */ case 535: /* lfsx */
case 567: /* lfsux */ case 567: /* lfsux */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = xform_ea(instr, regs, u); op->type = MKOP(LOAD_FP, u, 4);
err = do_fp_load(rd, do_lfs, ea, 4, regs); break;
goto ldst_done;
case 599: /* lfdx */ case 599: /* lfdx */
case 631: /* lfdux */ case 631: /* lfdux */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = xform_ea(instr, regs, u); op->type = MKOP(LOAD_FP, u, 8);
err = do_fp_load(rd, do_lfd, ea, 8, regs); break;
goto ldst_done;
case 663: /* stfsx */ case 663: /* stfsx */
case 695: /* stfsux */ case 695: /* stfsux */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = xform_ea(instr, regs, u); op->type = MKOP(STORE_FP, u, 4);
err = do_fp_store(rd, do_stfs, ea, 4, regs); break;
goto ldst_done;
case 727: /* stfdx */ case 727: /* stfdx */
case 759: /* stfdux */ case 759: /* stfdux */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = xform_ea(instr, regs, u); op->type = MKOP(STORE_FP, u, 8);
err = do_fp_store(rd, do_stfd, ea, 8, regs); break;
goto ldst_done;
#endif #endif
#ifdef __powerpc64__ #ifdef __powerpc64__
case 660: /* stdbrx */ case 660: /* stdbrx */
val = byterev_8(regs->gpr[rd]); op->type = MKOP(STORE, BYTEREV, 8);
err = write_mem(val, xform_ea(instr, regs, 0), 8, regs); op->val = byterev_8(regs->gpr[rd]);
goto ldst_done; break;
#endif #endif
case 662: /* stwbrx */ case 662: /* stwbrx */
val = byterev_4(regs->gpr[rd]); op->type = MKOP(STORE, BYTEREV, 4);
err = write_mem(val, xform_ea(instr, regs, 0), 4, regs); op->val = byterev_4(regs->gpr[rd]);
goto ldst_done; break;
case 790: /* lhbrx */ case 790: /* lhbrx */
err = read_mem(&val, xform_ea(instr, regs, 0), 2, regs); op->type = MKOP(LOAD, BYTEREV, 2);
if (!err) break;
regs->gpr[rd] = byterev_2(val);
goto ldst_done;
case 918: /* sthbrx */ case 918: /* sthbrx */
val = byterev_2(regs->gpr[rd]); op->type = MKOP(STORE, BYTEREV, 2);
err = write_mem(val, xform_ea(instr, regs, 0), 2, regs); op->val = byterev_2(regs->gpr[rd]);
goto ldst_done; break;
#ifdef CONFIG_VSX #ifdef CONFIG_VSX
case 844: /* lxvd2x */ case 844: /* lxvd2x */
case 876: /* lxvd2ux */ case 876: /* lxvd2ux */
if (!(regs->msr & MSR_VSX)) if (!(regs->msr & MSR_VSX))
break; goto vsxunavail;
rd |= (instr & 1) << 5; op->reg = rd | ((instr & 1) << 5);
ea = xform_ea(instr, regs, u); op->type = MKOP(LOAD_VSX, u, 16);
err = do_vsx_load(rd, do_lxvd2x, ea, regs); break;
goto ldst_done;
case 972: /* stxvd2x */ case 972: /* stxvd2x */
case 1004: /* stxvd2ux */ case 1004: /* stxvd2ux */
if (!(regs->msr & MSR_VSX)) if (!(regs->msr & MSR_VSX))
break; goto vsxunavail;
rd |= (instr & 1) << 5; op->reg = rd | ((instr & 1) << 5);
ea = xform_ea(instr, regs, u); op->type = MKOP(STORE_VSX, u, 16);
err = do_vsx_store(rd, do_stxvd2x, ea, regs); break;
goto ldst_done;
#endif /* CONFIG_VSX */ #endif /* CONFIG_VSX */
} }
...@@ -1552,178 +1460,124 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -1552,178 +1460,124 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 32: /* lwz */ case 32: /* lwz */
case 33: /* lwzu */ case 33: /* lwzu */
err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 4, regs); op->type = MKOP(LOAD, u, 4);
goto ldst_done; op->ea = dform_ea(instr, regs);
break;
case 34: /* lbz */ case 34: /* lbz */
case 35: /* lbzu */ case 35: /* lbzu */
err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 1, regs); op->type = MKOP(LOAD, u, 1);
goto ldst_done; op->ea = dform_ea(instr, regs);
break;
case 36: /* stw */ case 36: /* stw */
val = regs->gpr[rd];
err = write_mem(val, dform_ea(instr, regs), 4, regs);
goto ldst_done;
case 37: /* stwu */ case 37: /* stwu */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 4);
val3 = dform_ea(instr, regs); op->ea = dform_ea(instr, regs);
/* break;
* For PPC32 we always use stwu to change stack point with r1. So
* this emulated store may corrupt the exception frame, now we
* have to provide the exception frame trampoline, which is pushed
* below the kprobed function stack. So we only update gpr[1] but
* don't emulate the real store operation. We will do real store
* operation safely in exception return code by checking this flag.
*/
if ((ra == 1) && !(regs->msr & MSR_PR) \
&& (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
#ifdef CONFIG_PPC32
/*
* Check if we will touch kernel sack overflow
*/
if (val3 - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) {
printk(KERN_CRIT "Can't kprobe this since Kernel stack overflow.\n");
err = -EINVAL;
break;
}
#endif /* CONFIG_PPC32 */
/*
* Check if we already set since that means we'll
* lose the previous value.
*/
WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
set_thread_flag(TIF_EMULATE_STACK_STORE);
err = 0;
} else
err = write_mem(val, val3, 4, regs);
goto ldst_done;
case 38: /* stb */ case 38: /* stb */
case 39: /* stbu */ case 39: /* stbu */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 1);
err = write_mem(val, dform_ea(instr, regs), 1, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
case 40: /* lhz */ case 40: /* lhz */
case 41: /* lhzu */ case 41: /* lhzu */
err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 2, regs); op->type = MKOP(LOAD, u, 2);
goto ldst_done; op->ea = dform_ea(instr, regs);
break;
case 42: /* lha */ case 42: /* lha */
case 43: /* lhau */ case 43: /* lhau */
err = read_mem(&regs->gpr[rd], dform_ea(instr, regs), 2, regs); op->type = MKOP(LOAD, SIGNEXT | u, 2);
if (!err) op->ea = dform_ea(instr, regs);
regs->gpr[rd] = (signed short) regs->gpr[rd]; break;
goto ldst_done;
case 44: /* sth */ case 44: /* sth */
case 45: /* sthu */ case 45: /* sthu */
val = regs->gpr[rd]; op->type = MKOP(STORE, u, 2);
err = write_mem(val, dform_ea(instr, regs), 2, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
case 46: /* lmw */ case 46: /* lmw */
ra = (instr >> 16) & 0x1f; ra = (instr >> 16) & 0x1f;
if (ra >= rd) if (ra >= rd)
break; /* invalid form, ra in range to load */ break; /* invalid form, ra in range to load */
ea = dform_ea(instr, regs); op->type = MKOP(LOAD_MULTI, 0, 4);
do { op->ea = dform_ea(instr, regs);
err = read_mem(&regs->gpr[rd], ea, 4, regs); break;
if (err)
return 0;
ea += 4;
} while (++rd < 32);
goto instr_done;
case 47: /* stmw */ case 47: /* stmw */
ea = dform_ea(instr, regs); op->type = MKOP(STORE_MULTI, 0, 4);
do { op->ea = dform_ea(instr, regs);
err = write_mem(regs->gpr[rd], ea, 4, regs); break;
if (err)
return 0;
ea += 4;
} while (++rd < 32);
goto instr_done;
#ifdef CONFIG_PPC_FPU #ifdef CONFIG_PPC_FPU
case 48: /* lfs */ case 48: /* lfs */
case 49: /* lfsu */ case 49: /* lfsu */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = dform_ea(instr, regs); op->type = MKOP(LOAD_FP, u, 4);
err = do_fp_load(rd, do_lfs, ea, 4, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
case 50: /* lfd */ case 50: /* lfd */
case 51: /* lfdu */ case 51: /* lfdu */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = dform_ea(instr, regs); op->type = MKOP(LOAD_FP, u, 8);
err = do_fp_load(rd, do_lfd, ea, 8, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
case 52: /* stfs */ case 52: /* stfs */
case 53: /* stfsu */ case 53: /* stfsu */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = dform_ea(instr, regs); op->type = MKOP(STORE_FP, u, 4);
err = do_fp_store(rd, do_stfs, ea, 4, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
case 54: /* stfd */ case 54: /* stfd */
case 55: /* stfdu */ case 55: /* stfdu */
if (!(regs->msr & MSR_FP)) if (!(regs->msr & MSR_FP))
break; goto fpunavail;
ea = dform_ea(instr, regs); op->type = MKOP(STORE_FP, u, 8);
err = do_fp_store(rd, do_stfd, ea, 8, regs); op->ea = dform_ea(instr, regs);
goto ldst_done; break;
#endif #endif
#ifdef __powerpc64__ #ifdef __powerpc64__
case 58: /* ld[u], lwa */ case 58: /* ld[u], lwa */
op->ea = dsform_ea(instr, regs);
switch (instr & 3) { switch (instr & 3) {
case 0: /* ld */ case 0: /* ld */
err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs), op->type = MKOP(LOAD, 0, 8);
8, regs); break;
goto ldst_done;
case 1: /* ldu */ case 1: /* ldu */
err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs), op->type = MKOP(LOAD, UPDATE, 8);
8, regs); break;
goto ldst_done;
case 2: /* lwa */ case 2: /* lwa */
err = read_mem(&regs->gpr[rd], dsform_ea(instr, regs), op->type = MKOP(LOAD, SIGNEXT, 4);
4, regs); break;
if (!err)
regs->gpr[rd] = (signed int) regs->gpr[rd];
goto ldst_done;
} }
break; break;
case 62: /* std[u] */ case 62: /* std[u] */
val = regs->gpr[rd]; op->ea = dsform_ea(instr, regs);
switch (instr & 3) { switch (instr & 3) {
case 0: /* std */ case 0: /* std */
err = write_mem(val, dsform_ea(instr, regs), 8, regs); op->type = MKOP(STORE, 0, 8);
goto ldst_done; break;
case 1: /* stdu */ case 1: /* stdu */
err = write_mem(val, dsform_ea(instr, regs), 8, regs); op->type = MKOP(STORE, UPDATE, 8);
goto ldst_done; break;
} }
break; break;
#endif /* __powerpc64__ */ #endif /* __powerpc64__ */
} }
err = -EINVAL; return 0;
ldst_done:
if (err) {
regs->gpr[ra] = old_ra;
return 0; /* invoke DSI if -EFAULT? */
}
instr_done:
regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
return 1;
logical_done: logical_done:
if (instr & 1) if (instr & 1)
...@@ -1733,5 +1587,328 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) ...@@ -1733,5 +1587,328 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
arith_done: arith_done:
if (instr & 1) if (instr & 1)
set_cr0(regs, rd); set_cr0(regs, rd);
goto instr_done;
instr_done:
regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
return 1;
priv:
op->type = INTERRUPT | 0x700;
op->val = SRR1_PROGPRIV;
return 0;
#ifdef CONFIG_PPC_FPU
fpunavail:
op->type = INTERRUPT | 0x800;
return 0;
#endif
#ifdef CONFIG_ALTIVEC
vecunavail:
op->type = INTERRUPT | 0xf20;
return 0;
#endif
#ifdef CONFIG_VSX
vsxunavail:
op->type = INTERRUPT | 0xf40;
return 0;
#endif
}
EXPORT_SYMBOL_GPL(analyse_instr);
/*
* For PPC32 we always use stwu with r1 to change the stack pointer.
* So this emulated store may corrupt the exception frame, now we
* have to provide the exception frame trampoline, which is pushed
* below the kprobed function stack. So we only update gpr[1] but
* don't emulate the real store operation. We will do real store
* operation safely in exception return code by checking this flag.
*/
static __kprobes int handle_stack_update(unsigned long ea, struct pt_regs *regs)
{
#ifdef CONFIG_PPC32
/*
* Check if we will touch kernel stack overflow
*/
if (ea - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) {
printk(KERN_CRIT "Can't kprobe this since kernel stack would overflow.\n");
return -EINVAL;
}
#endif /* CONFIG_PPC32 */
/*
* Check if we already set since that means we'll
* lose the previous value.
*/
WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
set_thread_flag(TIF_EMULATE_STACK_STORE);
return 0;
}
static __kprobes void do_signext(unsigned long *valp, int size)
{
switch (size) {
case 2:
*valp = (signed short) *valp;
break;
case 4:
*valp = (signed int) *valp;
break;
}
}
static __kprobes void do_byterev(unsigned long *valp, int size)
{
switch (size) {
case 2:
*valp = byterev_2(*valp);
break;
case 4:
*valp = byterev_4(*valp);
break;
#ifdef __powerpc64__
case 8:
*valp = byterev_8(*valp);
break;
#endif
}
}
/*
* Emulate instructions that cause a transfer of control,
* loads and stores, and a few other instructions.
* Returns 1 if the step was emulated, 0 if not,
* 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 __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
{
struct instruction_op op;
int r, err, size;
unsigned long val;
unsigned int cr;
int rd;
r = analyse_instr(&op, regs, instr);
if (r != 0)
return r;
err = 0;
size = GETSIZE(op.type);
switch (op.type & INSTR_TYPE_MASK) {
case CACHEOP:
if (!address_ok(regs, op.ea, 8))
return 0;
switch (op.type & CACHEOP_MASK) {
case DCBST:
__cacheop_user_asmx(op.ea, err, "dcbst");
break;
case DCBF:
__cacheop_user_asmx(op.ea, err, "dcbf");
break;
case DCBTST:
if (op.reg == 0)
prefetchw((void *) op.ea);
break;
case DCBT:
if (op.reg == 0)
prefetch((void *) op.ea);
break;
}
if (err)
return 0;
goto instr_done;
case LARX:
if (regs->msr & MSR_LE)
return 0;
if (op.ea & (size - 1))
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, op.ea, size))
goto ldst_done;
err = 0;
switch (size) {
case 4:
__get_user_asmx(val, op.ea, err, "lwarx");
break;
case 8:
__get_user_asmx(val, op.ea, err, "ldarx");
break;
default:
return 0;
}
if (!err)
regs->gpr[op.reg] = val;
goto ldst_done;
case STCX:
if (regs->msr & MSR_LE)
return 0;
if (op.ea & (size - 1))
break; /* can't handle misaligned */
err = -EFAULT;
if (!address_ok(regs, op.ea, size))
goto ldst_done;
err = 0;
switch (size) {
case 4:
__put_user_asmx(op.val, op.ea, err, "stwcx.", cr);
break;
case 8:
__put_user_asmx(op.val, op.ea, err, "stdcx.", cr);
break;
default:
return 0;
}
if (!err)
regs->ccr = (regs->ccr & 0x0fffffff) |
(cr & 0xe0000000) |
((regs->xer >> 3) & 0x10000000);
goto ldst_done;
case LOAD:
if (regs->msr & MSR_LE)
return 0;
err = read_mem(&regs->gpr[op.reg], op.ea, size, regs);
if (!err) {
if (op.type & SIGNEXT)
do_signext(&regs->gpr[op.reg], size);
if (op.type & BYTEREV)
do_byterev(&regs->gpr[op.reg], size);
}
goto ldst_done;
case LOAD_FP:
if (regs->msr & MSR_LE)
return 0;
if (size == 4)
err = do_fp_load(op.reg, do_lfs, op.ea, size, regs);
else
err = do_fp_load(op.reg, do_lfd, op.ea, size, regs);
goto ldst_done;
#ifdef CONFIG_ALTIVEC
case LOAD_VMX:
if (regs->msr & MSR_LE)
return 0;
err = do_vec_load(op.reg, do_lvx, op.ea & ~0xfUL, regs);
goto ldst_done;
#endif
#ifdef CONFIG_VSX
case LOAD_VSX:
if (regs->msr & MSR_LE)
return 0;
err = do_vsx_load(op.reg, do_lxvd2x, op.ea, regs);
goto ldst_done;
#endif
case LOAD_MULTI:
if (regs->msr & MSR_LE)
return 0;
rd = op.reg;
do {
err = read_mem(&regs->gpr[rd], op.ea, 4, regs);
if (err)
return 0;
op.ea += 4;
} while (++rd < 32);
goto instr_done;
case STORE:
if (regs->msr & MSR_LE)
return 0;
if ((op.type & UPDATE) && size == sizeof(long) &&
op.reg == 1 && op.update_reg == 1 &&
!(regs->msr & MSR_PR) &&
op.ea >= regs->gpr[1] - STACK_INT_FRAME_SIZE) {
err = handle_stack_update(op.ea, regs);
goto ldst_done;
}
err = write_mem(op.val, op.ea, size, regs);
goto ldst_done;
case STORE_FP:
if (regs->msr & MSR_LE)
return 0;
if (size == 4)
err = do_fp_store(op.reg, do_stfs, op.ea, size, regs);
else
err = do_fp_store(op.reg, do_stfd, op.ea, size, regs);
goto ldst_done;
#ifdef CONFIG_ALTIVEC
case STORE_VMX:
if (regs->msr & MSR_LE)
return 0;
err = do_vec_store(op.reg, do_stvx, op.ea & ~0xfUL, regs);
goto ldst_done;
#endif
#ifdef CONFIG_VSX
case STORE_VSX:
if (regs->msr & MSR_LE)
return 0;
err = do_vsx_store(op.reg, do_stxvd2x, op.ea, regs);
goto ldst_done;
#endif
case STORE_MULTI:
if (regs->msr & MSR_LE)
return 0;
rd = op.reg;
do {
err = write_mem(regs->gpr[rd], op.ea, 4, regs);
if (err)
return 0;
op.ea += 4;
} while (++rd < 32);
goto instr_done;
case MFMSR:
regs->gpr[op.reg] = regs->msr & MSR_MASK;
goto instr_done;
case MTMSR:
val = regs->gpr[op.reg];
if ((val & MSR_RI) == 0)
/* can't step mtmsr[d] that would clear MSR_RI */
return -1;
/* here op.val is the mask of bits to change */
regs->msr = (regs->msr & ~op.val) | (val & op.val);
goto instr_done;
#ifdef CONFIG_PPC64
case SYSCALL: /* sc */
/*
* N.B. this uses knowledge about how the syscall
* entry code works. If that is changed, this will
* need to be changed also.
*/
if (regs->gpr[0] == 0x1ebe &&
cpu_has_feature(CPU_FTR_REAL_LE)) {
regs->msr ^= MSR_LE;
goto instr_done;
}
regs->gpr[9] = regs->gpr[13];
regs->gpr[10] = MSR_KERNEL;
regs->gpr[11] = regs->nip + 4;
regs->gpr[12] = regs->msr & MSR_MASK;
regs->gpr[13] = (unsigned long) get_paca();
regs->nip = (unsigned long) &system_call_common;
regs->msr = MSR_KERNEL;
return 1;
case RFI:
return -1;
#endif
}
return 0;
ldst_done:
if (err)
return 0;
if (op.type & UPDATE)
regs->gpr[op.update_reg] = op.ea;
instr_done:
regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
return 1;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment