linux_dsm_epyc7002/arch/x86
Denys Vlasenko 1ea30fb645 uprobes/x86: Fix scratch register selection for rip-relative fixups
Before this patch, instructions such as div, mul, shifts with count
in CL, cmpxchg are mishandled.

This patch adds vex prefix handling. In particular, it avoids colliding
with register operand encoded in vex.vvvv field.

Since we need to avoid two possible register operands, the selection of
scratch register needs to be from at least three registers.

After looking through a lot of CPU docs, it looks like the safest choice
is SI,DI,BX. Selecting BX needs care to not collide with implicit use of
BX by cmpxchg8b.

Test-case:

	#include <stdio.h>

	static const char *const pass[] = { "FAIL", "pass" };

	long two = 2;
	void test1(void)
	{
		long ax = 0, dx = 0;
		asm volatile("\n"
	"			xor	%%edx,%%edx\n"
	"			lea	2(%%edx),%%eax\n"
	// We divide 2 by 2. Result (in eax) should be 1:
	"	probe1:		.globl	probe1\n"
	"			divl	two(%%rip)\n"
	// If we have a bug (eax mangled on entry) the result will be 2,
	// because eax gets restored by probe machinery.
		: "=a" (ax), "=d" (dx) /*out*/
		: "0" (ax), "1" (dx) /*in*/
		: "memory" /*clobber*/
		);
		dprintf(2, "%s: %s\n", __func__,
			pass[ax == 1]
		);
	}

	long val2 = 0;
	void test2(void)
	{
		long old_val = val2;
		long ax = 0, dx = 0;
		asm volatile("\n"
	"			mov	val2,%%eax\n"     // eax := val2
	"			lea	1(%%eax),%%edx\n" // edx := eax+1
	// eax is equal to val2. cmpxchg should store edx to val2:
	"	probe2:		.globl  probe2\n"
	"			cmpxchg %%edx,val2(%%rip)\n"
	// If we have a bug (eax mangled on entry), val2 will stay unchanged
		: "=a" (ax), "=d" (dx) /*out*/
		: "0" (ax), "1" (dx) /*in*/
		: "memory" /*clobber*/
		);
		dprintf(2, "%s: %s\n", __func__,
			pass[val2 == old_val + 1]
		);
	}

	long val3[2] = {0,0};
	void test3(void)
	{
		long old_val = val3[0];
		long ax = 0, dx = 0;
		asm volatile("\n"
	"			mov	val3,%%eax\n"  // edx:eax := val3
	"			mov	val3+4,%%edx\n"
	"			mov	%%eax,%%ebx\n" // ecx:ebx := edx:eax + 1
	"			mov	%%edx,%%ecx\n"
	"			add	$1,%%ebx\n"
	"			adc	$0,%%ecx\n"
	// edx:eax is equal to val3. cmpxchg8b should store ecx:ebx to val3:
	"	probe3:		.globl  probe3\n"
	"			cmpxchg8b val3(%%rip)\n"
	// If we have a bug (edx:eax mangled on entry), val3 will stay unchanged.
	// If ecx:edx in mangled, val3 will get wrong value.
		: "=a" (ax), "=d" (dx) /*out*/
		: "0" (ax), "1" (dx) /*in*/
		: "cx", "bx", "memory" /*clobber*/
		);
		dprintf(2, "%s: %s\n", __func__,
			pass[val3[0] == old_val + 1 && val3[1] == 0]
		);
	}

	int main(int argc, char **argv)
	{
		test1();
		test2();
		test3();
		return 0;
	}

Before this change all tests fail if probe{1,2,3} are probed.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
2014-05-14 13:57:25 +02:00
..
boot Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-11 11:58:33 -07:00
configs ACPI: Remove Kconfig symbol ACPI_PROCFS 2014-02-19 00:27:37 +01:00
crypto crypto: ghash-clmulni-intel - use C implementation for setkey() 2014-04-01 17:22:47 +08:00
ia32 constify copy_siginfo_to_user{,32}() 2013-11-09 00:16:29 -05:00
include uprobes/x86: Simplify rip-relative handling 2014-05-14 13:57:25 +02:00
kernel uprobes/x86: Fix scratch register selection for rip-relative fixups 2014-05-14 13:57:25 +02:00
kvm Merge git://git.kernel.org/pub/scm/virt/kvm/kvm 2014-04-14 16:21:28 -07:00
lguest x86, asmlinkage, lguest: Fix C functions used by inline assembler 2014-01-29 22:17:17 -08:00
lib Merge branch 'x86-asmlinkage-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-03-31 14:13:25 -07:00
math-emu x86: math-emu: Drop already-disabled print of build date 2014-01-27 23:14:12 +01:00
mm arch/x86/mm/kmemcheck/kmemcheck.c: use kstrtoint() instead of sscanf() 2014-04-08 16:48:52 -07:00
net net: filter: add jited flag to indicate jit compiled filters 2014-03-31 00:45:08 -04:00
oprofile x86, oprofile, nmi: Fix CPU hotplug callback registration 2014-03-20 13:43:43 +01:00
pci CPU hotplug notifiers registration fixes for 3.15-rc1 2014-04-07 14:55:46 -07:00
platform Merge branch 'x86-nuke-platforms-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-02 13:15:58 -07:00
power x86, asmlinkage, power: Make various symbols used by the suspend asm code visible 2013-08-06 14:21:03 -07:00
realmode Merge commit 'f4bcd8ccddb02833340652e9f46f5127828eb79d' into x86/build 2014-01-29 09:07:00 -08:00
syscalls x86/build: Supress "Nothing to be done for ..." messages 2014-04-14 11:44:36 +02:00
tools x86/build: Supress "Nothing to be done for ..." messages 2014-04-14 11:44:36 +02:00
um x86: Remove CONFIG_X86_OOSTORE 2014-03-11 10:16:18 -07:00
vdso Merge branch 'x86-vdso-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-22 09:09:06 -07:00
video
xen Xen regression and bug fixes for 3.15-rc1. 2014-04-17 10:54:07 -07:00
.gitignore
Kbuild
Kconfig Merge git://git.infradead.org/users/eparis/audit 2014-04-12 12:38:53 -07:00
Kconfig.cpu Merge branch 'x86-nuke-platforms-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-02 13:15:58 -07:00
Kconfig.debug x86/efi: Dump the EFI page table 2014-03-04 16:17:17 +00:00
Makefile Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-16 16:40:18 -07:00
Makefile_32.cpu
Makefile.um