Skip to content

Commit

Permalink
Merge tag 'trace-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/rostedt/linux-trace

Pull syscall-get-arguments cleanup and fixes from Steven Rostedt:
 "Andy Lutomirski approached me to tell me that the
  syscall_get_arguments() implementation in x86 was horrible and gcc
  certainly gets it wrong.

  He said that since the tracepoints only pass in 0 and 6 for i and n
  repectively, it should be optimized for that case. Inspecting the
  kernel, I discovered that all users pass in 0 for i and only one file
  passing in something other than 6 for the number of arguments. That
  code happens to be my own code used for the special syscall tracing.

  That can easily be converted to just using 0 and 6 as well, and only
  copying what is needed. Which is probably the faster path anyway for
  that case.

  Along the way, a couple of real fixes came from this as the
  syscall_get_arguments() function was incorrect for csky and riscv.

  x86 has been optimized to for the new interface that removes the
  variable number of arguments, but the other architectures could still
  use some loving and take more advantage of the simpler interface"

* tag 'trace-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  syscalls: Remove start and number from syscall_set_arguments() args
  syscalls: Remove start and number from syscall_get_arguments() args
  csky: Fix syscall_get_arguments() and syscall_set_arguments()
  riscv: Fix syscall_get_arguments() and syscall_set_arguments()
  tracing/syscalls: Pass in hardcoded 6 into syscall_get_arguments()
  ptrace: Remove maxargs from task_current_syscall()
  • Loading branch information
Linus Torvalds committed Apr 5, 2019
2 parents 7f46774 + 32d9258 commit 970b766
Show file tree
Hide file tree
Showing 32 changed files with 247 additions and 722 deletions.
7 changes: 3 additions & 4 deletions arch/arc/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,11 @@ syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
*/
static inline void
syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, unsigned long *args)
unsigned long *args)
{
unsigned long *inside_ptregs = &(regs->r0);
inside_ptregs -= i;

BUG_ON((i + n) > 6);
unsigned int n = 6;
unsigned int i = 0;

while (n--) {
args[i++] = (*inside_ptregs);
Expand Down
47 changes: 8 additions & 39 deletions arch/arm/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,53 +55,22 @@ static inline void syscall_set_return_value(struct task_struct *task,

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
if (n == 0)
return;

if (i + n > SYSCALL_MAX_ARGS) {
unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
pr_warn("%s called with max args %d, handling only %d\n",
__func__, i + n, SYSCALL_MAX_ARGS);
memset(args_bad, 0, n_bad * sizeof(args[0]));
n = SYSCALL_MAX_ARGS - i;
}

if (i == 0) {
args[0] = regs->ARM_ORIG_r0;
args++;
i++;
n--;
}

memcpy(args, &regs->ARM_r0 + i, n * sizeof(args[0]));
args[0] = regs->ARM_ORIG_r0;
args++;

memcpy(args, &regs->ARM_r0 + 1, 5 * sizeof(args[0]));
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
if (n == 0)
return;

if (i + n > SYSCALL_MAX_ARGS) {
pr_warn("%s called with max args %d, handling only %d\n",
__func__, i + n, SYSCALL_MAX_ARGS);
n = SYSCALL_MAX_ARGS - i;
}

if (i == 0) {
regs->ARM_ORIG_r0 = args[0];
args++;
i++;
n--;
}

memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0]));
regs->ARM_ORIG_r0 = args[0];
args++;

memcpy(&regs->ARM_r0 + 1, args, 5 * sizeof(args[0]));
}

static inline int syscall_get_arch(void)
Expand Down
46 changes: 8 additions & 38 deletions arch/arm64/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,52 +65,22 @@ static inline void syscall_set_return_value(struct task_struct *task,

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
if (n == 0)
return;

if (i + n > SYSCALL_MAX_ARGS) {
unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
pr_warning("%s called with max args %d, handling only %d\n",
__func__, i + n, SYSCALL_MAX_ARGS);
memset(args_bad, 0, n_bad * sizeof(args[0]));
}

if (i == 0) {
args[0] = regs->orig_x0;
args++;
i++;
n--;
}

memcpy(args, &regs->regs[i], n * sizeof(args[0]));
args[0] = regs->orig_x0;
args++;

memcpy(args, &regs->regs[1], 5 * sizeof(args[0]));
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
if (n == 0)
return;

if (i + n > SYSCALL_MAX_ARGS) {
pr_warning("%s called with max args %d, handling only %d\n",
__func__, i + n, SYSCALL_MAX_ARGS);
n = SYSCALL_MAX_ARGS - i;
}

if (i == 0) {
regs->orig_x0 = args[0];
args++;
i++;
n--;
}

memcpy(&regs->regs[i], args, n * sizeof(args[0]));
regs->orig_x0 = args[0];
args++;

memcpy(&regs->regs[1], args, 5 * sizeof(args[0]));
}

/*
Expand Down
79 changes: 14 additions & 65 deletions arch/c6x/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,78 +46,27 @@ static inline void syscall_set_return_value(struct task_struct *task,
}

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs, unsigned int i,
unsigned int n, unsigned long *args)
struct pt_regs *regs,
unsigned long *args)
{
switch (i) {
case 0:
if (!n--)
break;
*args++ = regs->a4;
case 1:
if (!n--)
break;
*args++ = regs->b4;
case 2:
if (!n--)
break;
*args++ = regs->a6;
case 3:
if (!n--)
break;
*args++ = regs->b6;
case 4:
if (!n--)
break;
*args++ = regs->a8;
case 5:
if (!n--)
break;
*args++ = regs->b8;
case 6:
if (!n--)
break;
default:
BUG();
}
*args++ = regs->a4;
*args++ = regs->b4;
*args++ = regs->a6;
*args++ = regs->b6;
*args++ = regs->a8;
*args = regs->b8;
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
switch (i) {
case 0:
if (!n--)
break;
regs->a4 = *args++;
case 1:
if (!n--)
break;
regs->b4 = *args++;
case 2:
if (!n--)
break;
regs->a6 = *args++;
case 3:
if (!n--)
break;
regs->b6 = *args++;
case 4:
if (!n--)
break;
regs->a8 = *args++;
case 5:
if (!n--)
break;
regs->a9 = *args++;
case 6:
if (!n)
break;
default:
BUG();
}
regs->a4 = *args++;
regs->b4 = *args++;
regs->a6 = *args++;
regs->b6 = *args++;
regs->a8 = *args++;
regs->a9 = *args;
}

#endif /* __ASM_C6X_SYSCALLS_H */
26 changes: 8 additions & 18 deletions arch/csky/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,20 @@ syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,

static inline void
syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, unsigned long *args)
unsigned long *args)
{
BUG_ON(i + n > 6);
if (i == 0) {
args[0] = regs->orig_a0;
args++;
i++;
n--;
}
memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0]));
args[0] = regs->orig_a0;
args++;
memcpy(args, &regs->a1, 5 * sizeof(args[0]));
}

static inline void
syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, const unsigned long *args)
const unsigned long *args)
{
BUG_ON(i + n > 6);
if (i == 0) {
regs->orig_a0 = args[0];
args++;
i++;
n--;
}
memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
regs->orig_a0 = args[0];
args++;
memcpy(&regs->a1, args, 5 * sizeof(regs->a1));
}

static inline int
Expand Down
34 changes: 7 additions & 27 deletions arch/h8300/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,14 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)

static inline void
syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, unsigned long *args)
unsigned long *args)
{
BUG_ON(i + n > 6);

while (n > 0) {
switch (i) {
case 0:
*args++ = regs->er1;
break;
case 1:
*args++ = regs->er2;
break;
case 2:
*args++ = regs->er3;
break;
case 3:
*args++ = regs->er4;
break;
case 4:
*args++ = regs->er5;
break;
case 5:
*args++ = regs->er6;
break;
}
i++;
n--;
}
*args++ = regs->er1;
*args++ = regs->er2;
*args++ = regs->er3;
*args++ = regs->er4;
*args++ = regs->er5;
*args = regs->er6;
}


Expand Down
4 changes: 1 addition & 3 deletions arch/hexagon/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ static inline long syscall_get_nr(struct task_struct *task,

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
memcpy(args, &(&regs->r00)[0], 6 * sizeof(args[0]));
}
#endif
13 changes: 3 additions & 10 deletions arch/ia64/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,19 @@ static inline void syscall_set_return_value(struct task_struct *task,
}

extern void ia64_syscall_get_set_arguments(struct task_struct *task,
struct pt_regs *regs, unsigned int i, unsigned int n,
unsigned long *args, int rw);
struct pt_regs *regs, unsigned long *args, int rw);
static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
BUG_ON(i + n > 6);

ia64_syscall_get_set_arguments(task, regs, i, n, args, 0);
ia64_syscall_get_set_arguments(task, regs, args, 0);
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
BUG_ON(i + n > 6);

ia64_syscall_get_set_arguments(task, regs, i, n, args, 1);
ia64_syscall_get_set_arguments(task, regs, args, 1);
}

static inline int syscall_get_arch(void)
Expand Down
7 changes: 3 additions & 4 deletions arch/ia64/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2179,12 +2179,11 @@ static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data)
}

void ia64_syscall_get_set_arguments(struct task_struct *task,
struct pt_regs *regs, unsigned int i, unsigned int n,
unsigned long *args, int rw)
struct pt_regs *regs, unsigned long *args, int rw)
{
struct syscall_get_set_args data = {
.i = i,
.n = n,
.i = 0,
.n = 6,
.args = args,
.regs = regs,
.rw = rw,
Expand Down
8 changes: 6 additions & 2 deletions arch/microblaze/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,22 @@ static inline void microblaze_set_syscall_arg(struct pt_regs *regs,

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
unsigned int i = 0;
unsigned int n = 6;

while (n--)
*args++ = microblaze_get_syscall_arg(regs, i++);
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
unsigned int i = 0;
unsigned int n = 6;

while (n--)
microblaze_set_syscall_arg(regs, i++, *args++);
}
Expand Down
Loading

0 comments on commit 970b766

Please sign in to comment.