Re: [PATCH] m68k: use conventional function parameters for do_sigreturn

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/02/16 05:25, Andreas Schwab wrote:
Greg Ungerer <gerg@xxxxxxxxxxx> writes:
Does it work to use this signature:

asmlinkage int do_sigreturn(struct switch_stack sw, struct pt_regs regs)

without changing the caller?

No, same problem.

So this is unrelated to aliasing.  Can you create a test case?

Attached is a test case - derived from the original signal.c code.
I removed a lot to get it to a manageable size. It still exhibits
the problem. I compile this test case with:

  m68k-uclinux-gcc -Wall -mcpu=5208 -fno-strict-aliasing -O2 -c -o signal.o signal.i

I get the same result if I use a m68k-linux-gcc as well (I am
using gcc-5.3 based toolchains).

Regards
Greg



typedef unsigned int __u32;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef unsigned int __kernel_size_t;
typedef int __kernel_clockid_t;
typedef __kernel_clockid_t clockid_t;
typedef __kernel_size_t size_t;

typedef struct {
 unsigned long fds_bits[1024 / (8 * sizeof(long))];
} __kernel_fd_set;

typedef struct {
 unsigned long sig[(64 / 32)];
} sigset_t;

typedef struct sigaltstack {
 void *ss_sp;
 int ss_flags;
 size_t ss_size;
} stack_t;

struct sigcontext {
 unsigned long sc_mask;
 unsigned long sc_usp;
 unsigned long sc_d0;
 unsigned long sc_d1;
 unsigned long sc_a0;
 unsigned long sc_a1;
 unsigned long sc_a5;
 unsigned short sc_sr;
 unsigned long sc_pc;
 unsigned short sc_formatvec;
};
struct pt_regs {
 long d1;
 long d2;
 long d3;
 long d4;
 long d5;
 long a0;
 long a1;
 long a2;
 long d0;
 long orig_d0;
 long stkadj;

 unsigned format : 4;
 unsigned vector : 12;
 unsigned short sr;
 unsigned long pc;
};

struct switch_stack {
 unsigned long d6;
 unsigned long d7;
 unsigned long a3;
 unsigned long a4;
 unsigned long a5;
 unsigned long a6;
 unsigned long retpc;
};

struct timespec;

struct restart_block {
 long (*fn)(struct restart_block *);
 union {
  struct {
   u32 *uaddr;
   u32 val;
   u32 flags;
   u32 bitset;
   u64 time;
   u32 *uaddr2;
  } futex;

  struct {
   clockid_t clockid;
   struct timespec *rmtp;
   u64 expires;
  } nanosleep;

  struct {
   struct pollfd *ufds;
   int nfds;
   int has_timeout;
   unsigned long tv_sec;
   unsigned long tv_nsec;
  } poll;
 };
};

struct thread_struct {
 unsigned long ksp;
 unsigned long usp;
 unsigned short sr;
 unsigned short fs;
 unsigned long crp[2];
 unsigned long esp0;
 unsigned long faddr;
 int signo, code;
 unsigned long fp[8*3];
 unsigned long fpcntl[3];
 unsigned char fpstate[(0)];
};

struct mm_struct {
 u32 vmacache_seqnum;
 unsigned long start_code, end_code, start_data, end_data;
 unsigned long start_brk, brk, start_stack;
 unsigned long arg_start, arg_end, env_start, env_end;
};
struct task_struct {
 volatile long state;
 void *stack;
 struct mm_struct *mm, *active_mm;
 struct restart_block restart_block;
 int exit_state;
 int exit_code, exit_signal;
};

typedef struct {
 unsigned long seg;
} mm_segment_t;

struct thread_info {
 struct task_struct *task;
 unsigned long flags;
 mm_segment_t addr_limit;
 int preempt_count;
 __u32 cpu;
 unsigned long tp_value;
};

typedef int greg_t;
typedef greg_t gregset_t[18];

typedef struct fpregset {
 int f_fpcntl[3];
 int f_fpregs[8*3];
} fpregset_t;

struct mcontext {
 int version;
 gregset_t gregs;
 fpregset_t fpregs;
};

struct ucontext {
 unsigned long uc_flags;
 struct ucontext *uc_link;
 stack_t uc_stack;
 struct mcontext uc_mcontext;
 unsigned long uc_filler[80];
 sigset_t uc_sigmask;
};

struct sigframe
{
 char *pretcode;
 int sig;
 int code;
 struct sigcontext *psc;
 char retcode[8];
 unsigned long extramask[(64 / 32)-1];
 struct sigcontext sc;
};

extern void force_sig(int, struct task_struct *);
extern void set_current_blocked(sigset_t *);
extern long do_no_restart_syscall(struct restart_block *parm);
extern int __builtin_memcmp(const void *, const void *, __kernel_size_t);
extern int __get_user_bad(void);

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) struct thread_info *current_thread_info(void)
{
 struct thread_info *ti;
 __asm__(
  "move.l %%sp, %0 \n\t"
  "and.l  %1, %0"
  : "=&d"(ti)
  : "di" (~(((1UL) << 13)-1))
  );
 return ti;
}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) struct task_struct *get_current(void)
{
 return(current_thread_info()->task);
}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) unsigned long rdusp(void)
{
 register unsigned long usp __asm__("a0");
 __asm__ __volatile__(".word 0x4e68" : "=a" (usp));
 return usp;

}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) void wrusp(unsigned long usp)
{
 register unsigned long a0 __asm__("a0") = usp;
 __asm__ __volatile__(".word 0x4e60" : : "a" (a0) );

}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) int _access_ok(unsigned long addr, unsigned long size)
{
 return 1;
}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) int frame_extra_sizes(int f)
{
 return 0;
}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) int restore_fpu_state(struct sigcontext *sc)
{
 return 0;
}

static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, void *fp)
{
 int fsize = frame_extra_sizes(formatvec >> 12);
 if (fsize < 0) {
  return 1;
 }
 if (!fsize) {
  regs->format = formatvec >> 12;
  regs->vector = formatvec & 0xfff;
 } else {
  struct switch_stack *sw = (struct switch_stack *)regs - 1;
  unsigned long buf[fsize / 2];

  if ((__builtin_memcpy(buf + fsize / 4, fp, fsize), 0))
   return 1;

  regs->format = formatvec >> 12;
  regs->vector = formatvec & 0xfff;

  __asm__ __volatile__ (

    "   movel %0,%/sp\n\t"
    "   bra ret_from_signal\n"
    :
    : "a" (sw), "d" (fsize), "d" ((sizeof(struct pt_regs)+sizeof(struct switch_stack))/4-1),
      "n" ((sizeof(struct pt_regs)+sizeof(struct switch_stack))), "a" (buf + fsize/4)
    : "a0");

 }
 return 0;
}

static inline __attribute__((always_inline)) __attribute__((no_instrument_function)) int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp)
{
 int formatvec;
 struct sigcontext context;
 int err = 0;

 get_current()->restart_block.fn = do_no_restart_syscall;

 if ((__builtin_memcpy(&context, usc, sizeof(context)), 0))
  goto badframe;

 regs->d0 = context.sc_d0;
 regs->d1 = context.sc_d1;
 regs->a0 = context.sc_a0;
 regs->a1 = context.sc_a1;
 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
 regs->pc = context.sc_pc;
 regs->orig_d0 = -1;
 wrusp(context.sc_usp);
 formatvec = context.sc_formatvec;

 err = restore_fpu_state(&context);

 if (err || mangle_kernel_stack(regs, formatvec, fp))
  goto badframe;

 return 0;

badframe:
 return 1;
}

 int do_sigreturn(unsigned long __unused)
{
 struct switch_stack *sw = (struct switch_stack *) &__unused;
 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 unsigned long usp = rdusp();
 struct sigframe *frame = (struct sigframe *)(usp - 4);
 sigset_t set;

 if (!_access_ok((unsigned long)(frame),(sizeof(*frame))))
  goto badframe;
 if (({ int __gu_err = 0; typeof(set.sig[0]) __gu_val = 0; switch (sizeof(*(&frame->sc.sc_mask))) { case 1: __asm__ ("move" "b" " %1,%0" : "=d" (__gu_val) : "m" (*((unsigned long *)(&frame->sc.sc_mask)))); break; case 2: __asm__ ("move" "w" " %1,%0" : "=d" (__gu_val) : "m" (*((unsigned long *)(&frame->sc.sc_mask)))); break; case 4: __asm__ ("move" "l" " %1,%0" : "=d" (__gu_val) : "m" (*((unsigned long *)(&frame->sc.sc_mask)))); break; case 8: __builtin_memcpy((void *) &__gu_val, &frame->sc.sc_mask, sizeof (*(&frame->sc.sc_mask))); break; default: __gu_val = 0; __gu_err = __get_user_bad(); break; } (set.sig[0]) = (typeof(*(&frame->sc.sc_mask))) __gu_val; __gu_err; }) ||
     ((64 / 32) > 1 &&
      (__builtin_memcpy(&set.sig[1], &frame->extramask, sizeof(frame->extramask)), 0)
                                  ))
  goto badframe;

 set_current_blocked(&set);

 if (restore_sigcontext(regs, &frame->sc, frame + 1))
  goto badframe;
 return regs->d0;

badframe:
 force_sig(11, get_current());
 return 0;
}

[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux