From: Greg Ungerer <gerg@uclinux.org>
To: Andreas Schwab <schwab@linux-m68k.org>
Cc: linux-m68k@vger.kernel.org
Subject: Re: [PATCH] m68k: use conventional function parameters for do_sigreturn
Date: Wed, 3 Feb 2016 14:14:33 +1000 [thread overview]
Message-ID: <56B17EA9.8020504@uclinux.org> (raw)
In-Reply-To: <871t8u7w43.fsf@linux-m68k.org>
[-- Attachment #1: Type: text/plain, Size: 710 bytes --]
On 03/02/16 05:25, Andreas Schwab wrote:
> Greg Ungerer <gerg@uclinux.org> 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
[-- Attachment #2: signal.i --]
[-- Type: text/plain, Size: 7447 bytes --]
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;
}
next prev parent reply other threads:[~2016-02-03 4:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-19 5:56 [PATCH] m68k: use conventional function parameters for do_sigreturn Greg Ungerer
2016-02-01 4:33 ` Greg Ungerer
2016-02-01 18:39 ` Andreas Schwab
2016-02-01 23:59 ` Greg Ungerer
2016-02-02 19:25 ` Andreas Schwab
2016-02-03 4:14 ` Greg Ungerer [this message]
2016-02-08 23:31 ` Andreas Schwab
2016-02-09 0:21 ` Greg Ungerer
2016-02-09 9:48 ` Andreas Schwab
2016-02-09 13:05 ` Greg Ungerer
2016-02-09 13:17 ` Andreas Schwab
2016-02-09 14:01 ` Philippe De Muyter
2016-02-09 14:36 ` Andreas Schwab
2016-02-09 15:26 ` Philippe De Muyter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56B17EA9.8020504@uclinux.org \
--to=gerg@uclinux.org \
--cc=linux-m68k@vger.kernel.org \
--cc=schwab@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.