Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa21df04 authored by Denys Vlasenko's avatar Denys Vlasenko Committed by Ingo Molnar
Browse files

perf/x86/64: Do not guess user_regs->cs, ss, sp in get_regs_user()



After recent changes to syscall entry points,
user_regs->{cs,ss,sp} are always correct. (They used to be
undefined while in syscalls).

We can report them reliably, without guessing.

Signed-off-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1428671219-29341-1-git-send-email-dvlasenk@redhat.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 54cfa458
Loading
Loading
Loading
Loading
+9 −14
Original line number Original line Diff line number Diff line
@@ -131,8 +131,8 @@ void perf_get_regs_user(struct perf_regs *regs_user,
	}
	}


	/*
	/*
	 * RIP, flags, and the argument registers are usually saved.
	 * These registers are always saved on 64-bit syscall entry.
	 * orig_ax is probably okay, too.
	 * On 32-bit entry points, they are saved too except r8..r11.
	 */
	 */
	regs_user_copy->ip = user_regs->ip;
	regs_user_copy->ip = user_regs->ip;
	regs_user_copy->cx = user_regs->cx;
	regs_user_copy->cx = user_regs->cx;
@@ -145,9 +145,12 @@ void perf_get_regs_user(struct perf_regs *regs_user,
	regs_user_copy->r11 = user_regs->r11;
	regs_user_copy->r11 = user_regs->r11;
	regs_user_copy->orig_ax = user_regs->orig_ax;
	regs_user_copy->orig_ax = user_regs->orig_ax;
	regs_user_copy->flags = user_regs->flags;
	regs_user_copy->flags = user_regs->flags;
	regs_user_copy->sp = user_regs->sp;
	regs_user_copy->cs = user_regs->cs;
	regs_user_copy->ss = user_regs->ss;


	/*
	/*
	 * Don't even try to report the "rest" regs.
	 * Most system calls don't save these registers, don't report them.
	 */
	 */
	regs_user_copy->bx = -1;
	regs_user_copy->bx = -1;
	regs_user_copy->bp = -1;
	regs_user_copy->bp = -1;
@@ -158,7 +161,7 @@ void perf_get_regs_user(struct perf_regs *regs_user,


	/*
	/*
	 * For this to be at all useful, we need a reasonable guess for
	 * For this to be at all useful, we need a reasonable guess for
	 * sp and the ABI.  Be careful: we're in NMI context, and we're
	 * the ABI.  Be careful: we're in NMI context, and we're
	 * considering current to be the current task, so we should
	 * considering current to be the current task, so we should
	 * be careful not to look at any other percpu variables that might
	 * be careful not to look at any other percpu variables that might
	 * change during context switches.
	 * change during context switches.
@@ -167,9 +170,6 @@ void perf_get_regs_user(struct perf_regs *regs_user,
	    task_thread_info(current)->status & TS_COMPAT) {
	    task_thread_info(current)->status & TS_COMPAT) {
		/* Easy case: we're in a compat syscall. */
		/* Easy case: we're in a compat syscall. */
		regs_user->abi = PERF_SAMPLE_REGS_ABI_32;
		regs_user->abi = PERF_SAMPLE_REGS_ABI_32;
		regs_user_copy->sp = user_regs->sp;
		regs_user_copy->cs = user_regs->cs;
		regs_user_copy->ss = user_regs->ss;
	} else if (user_regs->orig_ax != -1) {
	} else if (user_regs->orig_ax != -1) {
		/*
		/*
		 * We're probably in a 64-bit syscall.
		 * We're probably in a 64-bit syscall.
@@ -177,17 +177,12 @@ void perf_get_regs_user(struct perf_regs *regs_user,
		 * than just blindly copying user_regs.
		 * than just blindly copying user_regs.
		 */
		 */
		regs_user->abi = PERF_SAMPLE_REGS_ABI_64;
		regs_user->abi = PERF_SAMPLE_REGS_ABI_64;
		regs_user_copy->sp = user_regs->sp;
		/* usually contains return address (same as ->ip) */
		regs_user_copy->cs = __USER_CS;
		regs_user_copy->cx = -1;
		regs_user_copy->ss = __USER_DS;
		regs_user_copy->cx = -1;  /* usually contains garbage */
	} else {
	} else {
		/* We're probably in an interrupt or exception. */
		/* We're probably in an interrupt or exception. */
		regs_user->abi = user_64bit_mode(user_regs) ?
		regs_user->abi = user_64bit_mode(user_regs) ?
			PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32;
			PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32;
		regs_user_copy->sp = user_regs->sp;
		regs_user_copy->cs = user_regs->cs;
		regs_user_copy->ss = user_regs->ss;
	}
	}


	regs_user->regs = regs_user_copy;
	regs_user->regs = regs_user_copy;