On Fri, 2014-05-02 at 17:04 +0200, Denys Vlasenko wrote: > Before this patch, instructions such as div, mul, > shifts with count in CL, cmpxchg are mishandled.
I just noticed that this sounds rather worse than it is. It would be more precise to say, "Before this patch, the rip-relative addressing mode in instructions such as ... is mishandled." ... > > Signed-off-by: Denys Vlasenko <dvlas...@redhat.com> > CC: Jim Keniston <jkeni...@us.ibm.com> > CC: Masami Hiramatsu <masami.hiramatsu...@hitachi.com> > CC: Srikar Dronamraju <sri...@linux.vnet.ibm.com> > CC: Ingo Molnar <mi...@kernel.org> > CC: Oleg Nesterov <o...@redhat.com> > --- > arch/x86/kernel/uprobes.c | 179 > +++++++++++++++++++++++++++++++++------------- > 1 file changed, 128 insertions(+), 51 deletions(-) > > diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c > index dbbf6cd..5b387b7 100644 > --- a/arch/x86/kernel/uprobes.c > +++ b/arch/x86/kernel/uprobes.c > @@ -41,8 +41,12 @@ > /* Instruction will modify TF, don't change it */ > #define UPROBE_FIX_SETF 0x04 > > -#define UPROBE_FIX_RIP_AX 0x08 > -#define UPROBE_FIX_RIP_CX 0x10 > +#define UPROBE_FIX_RIP_SI 0x08 > +#define UPROBE_FIX_RIP_DI 0x10 > +#define UPROBE_FIX_RIP_BX 0x20 > +#define UPROBE_FIX_RIP_MASK (UPROBE_FIX_RIP_SI \ > + | UPROBE_FIX_RIP_DI \ > + | UPROBE_FIX_RIP_BX) Yes. ... > + /* Fetch vex.vvvv */ > + reg2 = 0xff; > + if (insn->vex_prefix.nbytes == 2) { > + reg2 = insn->vex_prefix.bytes[1]; > + } > + if (insn->vex_prefix.nbytes == 3) { > + reg2 = insn->vex_prefix.bytes[2]; > + } > + /* TODO: add XOP, EXEV vvvv reading */ > + /* > + * vex.vvvv field is in bits 6-3, bits are inverted. > + * But in 32-bit mode, high-order bit may be ignored. > + * Therefore, let's consider only 3 low-order bits. > + */ > + reg2 = ((reg2 >> 3) & 0x7) ^ 0x7; > > + /* Register numbering is ax,cx,dx,bx, sp,bp,si,di, r8..r15 */ > + /* > + * Choose scratch reg. Order is important: > + * must not select bx if we can use si (cmpxchg8b case!) It'd be good to add here: * For instructions without a VEX prefix, reg2 is 0 here. Otherwise it kind of looks like you forgot to address that case, and the reader shouldn't have to do the bit fiddling to figure it out. > + */ > + if (reg != 6 && reg2 != 6) { > + reg2 = 6; > + auprobe->def.fixups |= UPROBE_FIX_RIP_SI; > + } else if (reg != 7 && reg2 != 7) { > + reg2 = 7; > + auprobe->def.fixups |= UPROBE_FIX_RIP_DI; > + /* TODO (paranoia): force maskmovq to not use di */ > + } else { > + reg2 = 3; /* BX */ > + auprobe->def.fixups |= UPROBE_FIX_RIP_BX; > + } Yes. Looks good from here down. Reviewed-by: Jim Keniston <jkeni...@us.ibm.com> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/