Commit 8be7eb35 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile

* 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  arch/tile: fix formatting bug in register dumps
  arch/tile: fix memcpy_fromio()/memcpy_toio() signatures
  arch/tile: Save and restore extra user state for tilegx
  arch/tile: Change struct sigcontext to be more useful
  arch/tile: finish const-ifying sys_execve()
parents 3a919cf0 7040dea4
...@@ -150,6 +150,9 @@ ...@@ -150,6 +150,9 @@
/** Is the PROC_STATUS SPR supported? */ /** Is the PROC_STATUS SPR supported? */
#define CHIP_HAS_PROC_STATUS_SPR() 0 #define CHIP_HAS_PROC_STATUS_SPR() 0
/** Is the DSTREAM_PF SPR supported? */
#define CHIP_HAS_DSTREAM_PF() 0
/** Log of the number of mshims we have. */ /** Log of the number of mshims we have. */
#define CHIP_LOG_NUM_MSHIMS() 2 #define CHIP_LOG_NUM_MSHIMS() 2
......
...@@ -150,6 +150,9 @@ ...@@ -150,6 +150,9 @@
/** Is the PROC_STATUS SPR supported? */ /** Is the PROC_STATUS SPR supported? */
#define CHIP_HAS_PROC_STATUS_SPR() 1 #define CHIP_HAS_PROC_STATUS_SPR() 1
/** Is the DSTREAM_PF SPR supported? */
#define CHIP_HAS_DSTREAM_PF() 0
/** Log of the number of mshims we have. */ /** Log of the number of mshims we have. */
#define CHIP_LOG_NUM_MSHIMS() 2 #define CHIP_LOG_NUM_MSHIMS() 2
......
...@@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, ...@@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
struct compat_sigaction; struct compat_sigaction;
struct compat_siginfo; struct compat_siginfo;
struct compat_sigaltstack; struct compat_sigaltstack;
long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, long compat_sys_execve(const char __user *path,
compat_uptr_t __user *envp); const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp);
long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
struct compat_sigaction __user *oact, struct compat_sigaction __user *oact,
size_t sigsetsize); size_t sigsetsize);
......
...@@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr) ...@@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr)
#define iowrite32 writel #define iowrite32 writel
#define iowrite64 writeq #define iowrite64 writeq
static inline void *memcpy_fromio(void *dst, void *src, int len) static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
size_t len)
{ {
int x; int x;
BUG_ON((unsigned long)src & 0x3); BUG_ON((unsigned long)src & 0x3);
for (x = 0; x < len; x += 4) for (x = 0; x < len; x += 4)
*(u32 *)(dst + x) = readl(src + x); *(u32 *)(dst + x) = readl(src + x);
return dst;
} }
static inline void *memcpy_toio(void *dst, void *src, int len) static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
size_t len)
{ {
int x; int x;
BUG_ON((unsigned long)dst & 0x3); BUG_ON((unsigned long)dst & 0x3);
for (x = 0; x < len; x += 4) for (x = 0; x < len; x += 4)
writel(*(u32 *)(src + x), dst + x); writel(*(u32 *)(src + x), dst + x);
return dst;
} }
/* /*
......
...@@ -103,6 +103,18 @@ struct thread_struct { ...@@ -103,6 +103,18 @@ struct thread_struct {
/* Any other miscellaneous processor state bits */ /* Any other miscellaneous processor state bits */
unsigned long proc_status; unsigned long proc_status;
#endif #endif
#if !CHIP_HAS_FIXED_INTVEC_BASE()
/* Interrupt base for PL0 interrupts */
unsigned long interrupt_vector_base;
#endif
#if CHIP_HAS_TILE_RTF_HWM()
/* Tile cache retry fifo high-water mark */
unsigned long tile_rtf_hwm;
#endif
#if CHIP_HAS_DSTREAM_PF()
/* Data stream prefetch control */
unsigned long dstream_pf;
#endif
#ifdef CONFIG_HARDWALL #ifdef CONFIG_HARDWALL
/* Is this task tied to an activated hardwall? */ /* Is this task tied to an activated hardwall? */
struct hardwall_info *hardwall; struct hardwall_info *hardwall;
......
...@@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t; ...@@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t;
/* /*
* This struct defines the way the registers are stored on the stack during a * This struct defines the way the registers are stored on the stack during a
* system call/exception. It should be a multiple of 8 bytes to preserve * system call or exception. "struct sigcontext" has the same shape.
* normal stack alignment rules.
*
* Must track <sys/ucontext.h> and <sys/procfs.h>
*/ */
struct pt_regs { struct pt_regs {
/* Saved main processor registers; 56..63 are special. */ /* Saved main processor registers; 56..63 are special. */
...@@ -80,11 +77,6 @@ struct pt_regs { ...@@ -80,11 +77,6 @@ struct pt_regs {
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* Flag bits in pt_regs.flags */
#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */
#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */
#define PTRACE_GETREGS 12 #define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13 #define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 #define PTRACE_GETFPREGS 14
...@@ -101,6 +93,11 @@ struct pt_regs { ...@@ -101,6 +93,11 @@ struct pt_regs {
#ifdef __KERNEL__ #ifdef __KERNEL__
/* Flag bits in pt_regs.flags */
#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */
#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */
#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define instruction_pointer(regs) ((regs)->pc) #define instruction_pointer(regs) ((regs)->pc)
......
...@@ -15,13 +15,21 @@ ...@@ -15,13 +15,21 @@
#ifndef _ASM_TILE_SIGCONTEXT_H #ifndef _ASM_TILE_SIGCONTEXT_H
#define _ASM_TILE_SIGCONTEXT_H #define _ASM_TILE_SIGCONTEXT_H
/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */ #include <arch/abi.h>
#include <asm/ptrace.h>
/* Must track <sys/ucontext.h> */
/*
* struct sigcontext has the same shape as struct pt_regs,
* but is simplified since we know the fault is from userspace.
*/
struct sigcontext { struct sigcontext {
struct pt_regs regs; uint_reg_t gregs[53]; /* General-purpose registers. */
uint_reg_t tp; /* Aliases gregs[TREG_TP]. */
uint_reg_t sp; /* Aliases gregs[TREG_SP]. */
uint_reg_t lr; /* Aliases gregs[TREG_LR]. */
uint_reg_t pc; /* Program counter. */
uint_reg_t ics; /* In Interrupt Critical Section? */
uint_reg_t faultnum; /* Fault number. */
uint_reg_t pad[5];
}; };
#endif /* _ASM_TILE_SIGCONTEXT_H */ #endif /* _ASM_TILE_SIGCONTEXT_H */
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm-generic/signal.h> #include <asm-generic/signal.h>
#if defined(__KERNEL__) && !defined(__ASSEMBLY__) #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
struct pt_regs;
int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
void do_signal(struct pt_regs *regs); void do_signal(struct pt_regs *regs);
......
...@@ -62,10 +62,12 @@ long sys_fork(void); ...@@ -62,10 +62,12 @@ long sys_fork(void);
long _sys_fork(struct pt_regs *regs); long _sys_fork(struct pt_regs *regs);
long sys_vfork(void); long sys_vfork(void);
long _sys_vfork(struct pt_regs *regs); long _sys_vfork(struct pt_regs *regs);
long sys_execve(char __user *filename, char __user * __user *argv, long sys_execve(const char __user *filename,
char __user * __user *envp); const char __user *const __user *argv,
long _sys_execve(char __user *filename, char __user * __user *argv, const char __user *const __user *envp);
char __user * __user *envp, struct pt_regs *regs); long _sys_execve(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp, struct pt_regs *regs);
/* kernel/signal.c */ /* kernel/signal.c */
long sys_sigaltstack(const stack_t __user *, stack_t __user *); long sys_sigaltstack(const stack_t __user *, stack_t __user *);
...@@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); ...@@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
#endif #endif
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, long compat_sys_execve(const char __user *path,
compat_uptr_t __user *envp); const compat_uptr_t __user *argv,
long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, const compat_uptr_t __user *envp);
compat_uptr_t __user *envp, struct pt_regs *regs); long _compat_sys_execve(const char __user *path,
const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp,
struct pt_regs *regs);
long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
struct compat_sigaltstack __user *uoss_ptr); struct compat_sigaltstack __user *uoss_ptr);
long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
......
...@@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t) ...@@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t)
#if CHIP_HAS_PROC_STATUS_SPR() #if CHIP_HAS_PROC_STATUS_SPR()
t->proc_status = __insn_mfspr(SPR_PROC_STATUS); t->proc_status = __insn_mfspr(SPR_PROC_STATUS);
#endif #endif
#if !CHIP_HAS_FIXED_INTVEC_BASE()
t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0);
#endif
#if CHIP_HAS_TILE_RTF_HWM()
t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM);
#endif
#if CHIP_HAS_DSTREAM_PF()
t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF);
#endif
} }
static void restore_arch_state(const struct thread_struct *t) static void restore_arch_state(const struct thread_struct *t)
...@@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t) ...@@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t)
#if CHIP_HAS_PROC_STATUS_SPR() #if CHIP_HAS_PROC_STATUS_SPR()
__insn_mtspr(SPR_PROC_STATUS, t->proc_status); __insn_mtspr(SPR_PROC_STATUS, t->proc_status);
#endif #endif
#if !CHIP_HAS_FIXED_INTVEC_BASE()
__insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base);
#endif
#if CHIP_HAS_TILE_RTF_HWM() #if CHIP_HAS_TILE_RTF_HWM()
/* __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm);
* Clear this whenever we switch back to a process in case #endif
* the previous process was monkeying with it. Even if enabled #if CHIP_HAS_DSTREAM_PF()
* in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf);
* performance hint, so isn't worth a full save/restore.
*/
__insn_mtspr(SPR_TILE_RTF_HWM, 0);
#endif #endif
} }
...@@ -561,8 +570,9 @@ long _sys_execve(const char __user *path, ...@@ -561,8 +570,9 @@ long _sys_execve(const char __user *path,
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, long _compat_sys_execve(const char __user *path,
compat_uptr_t __user *envp, struct pt_regs *regs) const compat_uptr_t __user *argv,
const compat_uptr_t __user *envp, struct pt_regs *regs)
{ {
long error; long error;
char *filename; char *filename;
...@@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs) ...@@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs)
regs->regs[51], regs->regs[52], regs->tp); regs->regs[51], regs->regs[52], regs->tp);
pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
#else #else
for (i = 0; i < 52; i += 3) for (i = 0; i < 52; i += 4)
pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT
" r%-2d: "REGFMT" r%-2d: "REGFMT"\n", " r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
i, regs->regs[i], i+1, regs->regs[i+1], i, regs->regs[i], i+1, regs->regs[i+1],
......
...@@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs, ...@@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs,
/* Always make any pending restarted system calls return -EINTR */ /* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
/*
* Enforce that sigcontext is like pt_regs, and doesn't mess
* up our stack alignment rules.
*/
BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
err |= __get_user(((long *)regs)[i], err |= __get_user(regs->regs[i], &sc->gregs[i]);
&((long __user *)(&sc->regs))[i]);
regs->faultnum = INT_SWINT_1_SIGRETURN; regs->faultnum = INT_SWINT_1_SIGRETURN;
err |= __get_user(*pr0, &sc->regs.regs[0]); err |= __get_user(*pr0, &sc->gregs[0]);
return err; return err;
} }
...@@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) ...@@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
int i, err = 0; int i, err = 0;
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
err |= __put_user(((long *)regs)[i], err |= __put_user(regs->regs[i], &sc->gregs[i]);
&((long __user *)(&sc->regs))[i]);
return err; return err;
} }
...@@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Set up registers for signal handler. * Set up registers for signal handler.
* Registers that we don't modify keep the value they had from * Registers that we don't modify keep the value they had from
* user-space at the time we took the signal. * user-space at the time we took the signal.
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c).
*/ */
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ka->sa.sa_handler;
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = (unsigned long) frame; regs->sp = (unsigned long) frame;
regs->lr = restorer; regs->lr = restorer;
regs->regs[0] = (unsigned long) usig; regs->regs[0] = (unsigned long) usig;
if (ka->sa.sa_flags & SA_SIGINFO) {
/* Need extra arguments, so mark to restore caller-saves. */
regs->regs[1] = (unsigned long) &frame->info; regs->regs[1] = (unsigned long) &frame->info;
regs->regs[2] = (unsigned long) &frame->uc; regs->regs[2] = (unsigned long) &frame->uc;
regs->flags |= PT_FLAGS_CALLER_SAVES; regs->flags |= PT_FLAGS_CALLER_SAVES;
}
/* /*
* Notify any tracer that was single-stepping it. * Notify any tracer that was single-stepping it.
......
...@@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) ...@@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
pr_err(" <received signal %d>\n", pr_err(" <received signal %d>\n",
frame->info.si_signo); frame->info.si_signo);
} }
return &frame->uc.uc_mcontext.regs; return (struct pt_regs *)&frame->uc.uc_mcontext;
} }
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment