Commit e1d74fbe authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://github.com/openrisc/linux

Pull OpenRISC updates from Stafford Horne:
 "A few patches all over the place during this cycle, mostly bug and
  sparse warning fixes for OpenRISC, but a few enhancements too. Note,
  there are 2 non OpenRISC specific fixups.

  Non OpenRISC fixes:

   - In init we need to align the init_task correctly to fix an issue
     with MUTEX_FLAGS, reviewed by Peter Z. No one picked this up so I
     kept it on my tree.

   - In asm-generic/io.h I fixed up some sparse warnings, OK'd by Arnd.
     Arnd asked to merge it via my tree.

  OpenRISC fixes:

   - Many fixes for OpenRISC sprase warnings.

   - Add support OpenRISC SMP tlb flushing rather than always flushing
     the entire TLB on every CPU.

   - Fix bug when dumping stack via /proc/xxx/stack of user threads"

* tag 'for-linus' of git://github.com/openrisc/linux:
  openrisc: uaccess: Add user address space check to access_ok
  openrisc: signal: Fix sparse address space warnings
  openrisc: uaccess: Remove unused macro __addr_ok
  openrisc: uaccess: Use static inline function in access_ok
  openrisc: uaccess: Fix sparse address space warnings
  openrisc: io: Fixup defines and move include to the end
  asm-generic/io.h: Fix sparse warnings on big-endian architectures
  openrisc: Implement proper SMP tlb flushing
  openrisc: Fix oops caused when dumping stack
  openrisc: Add support for external initrd images
  init: Align init_task to avoid conflict with MUTEX_FLAGS
  openrisc: fix __user in raw_copy_to_user()'s prototype
parents 7fca4dee 55b2662e
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#ifndef __ASM_OPENRISC_IO_H #ifndef __ASM_OPENRISC_IO_H
#define __ASM_OPENRISC_IO_H #define __ASM_OPENRISC_IO_H
#include <linux/types.h>
/* /*
* PCI: can we really do 0 here if we have no port IO? * PCI: can we really do 0 here if we have no port IO?
*/ */
...@@ -25,9 +27,12 @@ ...@@ -25,9 +27,12 @@
#define PIO_OFFSET 0 #define PIO_OFFSET 0
#define PIO_MASK 0 #define PIO_MASK 0
#include <asm-generic/io.h> #define ioremap ioremap
void __iomem *ioremap(phys_addr_t offset, unsigned long size); void __iomem *ioremap(phys_addr_t offset, unsigned long size);
#define iounmap iounmap
extern void iounmap(void *addr); extern void iounmap(void *addr);
#include <asm-generic/io.h>
#endif #endif
...@@ -48,16 +48,17 @@ ...@@ -48,16 +48,17 @@
/* Ensure that the range from addr to addr+size is all within the process' /* Ensure that the range from addr to addr+size is all within the process'
* address space * address space
*/ */
#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size)) static inline int __range_ok(unsigned long addr, unsigned long size)
{
const mm_segment_t fs = get_fs();
/* Ensure that addr is below task's addr_limit */ return size <= fs && addr <= (fs - size);
#define __addr_ok(addr) ((unsigned long) addr < get_fs()) }
#define access_ok(addr, size) \ #define access_ok(addr, size) \
({ \ ({ \
unsigned long __ao_addr = (unsigned long)(addr); \ __chk_user_ptr(addr); \
unsigned long __ao_size = (unsigned long)(size); \ __range_ok((unsigned long)(addr), (size)); \
__range_ok(__ao_addr, __ao_size); \
}) })
/* /*
...@@ -100,7 +101,7 @@ extern long __put_user_bad(void); ...@@ -100,7 +101,7 @@ extern long __put_user_bad(void);
#define __put_user_check(x, ptr, size) \ #define __put_user_check(x, ptr, size) \
({ \ ({ \
long __pu_err = -EFAULT; \ long __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
if (access_ok(__pu_addr, size)) \ if (access_ok(__pu_addr, size)) \
__put_user_size((x), __pu_addr, (size), __pu_err); \ __put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \ __pu_err; \
...@@ -173,7 +174,7 @@ struct __large_struct { ...@@ -173,7 +174,7 @@ struct __large_struct {
#define __get_user_check(x, ptr, size) \ #define __get_user_check(x, ptr, size) \
({ \ ({ \
long __gu_err = -EFAULT, __gu_val = 0; \ long __gu_err = -EFAULT, __gu_val = 0; \
const __typeof__(*(ptr)) * __gu_addr = (ptr); \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
if (access_ok(__gu_addr, size)) \ if (access_ok(__gu_addr, size)) \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \ (x) = (__force __typeof__(*(ptr)))__gu_val; \
...@@ -241,17 +242,17 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long size) ...@@ -241,17 +242,17 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long size)
return __copy_tofrom_user(to, (__force const void *)from, size); return __copy_tofrom_user(to, (__force const void *)from, size);
} }
static inline unsigned long static inline unsigned long
raw_copy_to_user(void *to, const void __user *from, unsigned long size) raw_copy_to_user(void __user *to, const void *from, unsigned long size)
{ {
return __copy_tofrom_user((__force void *)to, from, size); return __copy_tofrom_user((__force void *)to, from, size);
} }
#define INLINE_COPY_FROM_USER #define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER #define INLINE_COPY_TO_USER
extern unsigned long __clear_user(void *addr, unsigned long size); extern unsigned long __clear_user(void __user *addr, unsigned long size);
static inline __must_check unsigned long static inline __must_check unsigned long
clear_user(void *addr, unsigned long size) clear_user(void __user *addr, unsigned long size)
{ {
if (likely(access_ok(addr, size))) if (likely(access_ok(addr, size)))
size = __clear_user(addr, size); size = __clear_user(addr, size);
......
...@@ -292,13 +292,15 @@ void __init setup_arch(char **cmdline_p) ...@@ -292,13 +292,15 @@ void __init setup_arch(char **cmdline_p)
init_mm.brk = (unsigned long)_end; init_mm.brk = (unsigned long)_end;
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
initrd_start = (unsigned long)&__initrd_start;
initrd_end = (unsigned long)&__initrd_end;
if (initrd_start == initrd_end) { if (initrd_start == initrd_end) {
printk(KERN_INFO "Initial ramdisk not found\n");
initrd_start = 0; initrd_start = 0;
initrd_end = 0; initrd_end = 0;
} else {
printk(KERN_INFO "Initial ramdisk at: 0x%p (%lu bytes)\n",
(void *)(initrd_start), initrd_end - initrd_start);
initrd_below_start_ok = 1;
} }
initrd_below_start_ok = 1;
#endif #endif
/* setup memblock allocator */ /* setup memblock allocator */
......
...@@ -68,7 +68,7 @@ static int restore_sigcontext(struct pt_regs *regs, ...@@ -68,7 +68,7 @@ static int restore_sigcontext(struct pt_regs *regs,
asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
{ {
struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp; struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->sp;
sigset_t set; sigset_t set;
/* /*
...@@ -76,7 +76,7 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) ...@@ -76,7 +76,7 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
* then frame should be dword aligned here. If it's * then frame should be dword aligned here. If it's
* not, then the user is trying to mess with us. * not, then the user is trying to mess with us.
*/ */
if (((long)frame) & 3) if (((unsigned long)frame) & 3)
goto badframe; goto badframe;
if (!access_ok(frame, sizeof(*frame))) if (!access_ok(frame, sizeof(*frame)))
...@@ -151,7 +151,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig, ...@@ -151,7 +151,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe *frame; struct rt_sigframe __user *frame;
unsigned long return_ip; unsigned long return_ip;
int err = 0; int err = 0;
...@@ -181,10 +181,10 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, ...@@ -181,10 +181,10 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
l.ori r11,r0,__NR_sigreturn l.ori r11,r0,__NR_sigreturn
l.sys 1 l.sys 1
*/ */
err |= __put_user(0xa960, (short *)(frame->retcode + 0)); err |= __put_user(0xa960, (short __user *)(frame->retcode + 0));
err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2)); err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode + 2));
err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); err |= __put_user(0x20000001, (unsigned long __user *)(frame->retcode + 4));
err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); err |= __put_user(0x15000000, (unsigned long __user *)(frame->retcode + 8));
if (err) if (err)
return -EFAULT; return -EFAULT;
......
...@@ -219,30 +219,99 @@ static inline void ipi_flush_tlb_all(void *ignored) ...@@ -219,30 +219,99 @@ static inline void ipi_flush_tlb_all(void *ignored)
local_flush_tlb_all(); local_flush_tlb_all();
} }
static inline void ipi_flush_tlb_mm(void *info)
{
struct mm_struct *mm = (struct mm_struct *)info;
local_flush_tlb_mm(mm);
}
static void smp_flush_tlb_mm(struct cpumask *cmask, struct mm_struct *mm)
{
unsigned int cpuid;
if (cpumask_empty(cmask))
return;
cpuid = get_cpu();
if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
/* local cpu is the only cpu present in cpumask */
local_flush_tlb_mm(mm);
} else {
on_each_cpu_mask(cmask, ipi_flush_tlb_mm, mm, 1);
}
put_cpu();
}
struct flush_tlb_data {
unsigned long addr1;
unsigned long addr2;
};
static inline void ipi_flush_tlb_page(void *info)
{
struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
local_flush_tlb_page(NULL, fd->addr1);
}
static inline void ipi_flush_tlb_range(void *info)
{
struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
local_flush_tlb_range(NULL, fd->addr1, fd->addr2);
}
static void smp_flush_tlb_range(struct cpumask *cmask, unsigned long start,
unsigned long end)
{
unsigned int cpuid;
if (cpumask_empty(cmask))
return;
cpuid = get_cpu();
if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
/* local cpu is the only cpu present in cpumask */
if ((end - start) <= PAGE_SIZE)
local_flush_tlb_page(NULL, start);
else
local_flush_tlb_range(NULL, start, end);
} else {
struct flush_tlb_data fd;
fd.addr1 = start;
fd.addr2 = end;
if ((end - start) <= PAGE_SIZE)
on_each_cpu_mask(cmask, ipi_flush_tlb_page, &fd, 1);
else
on_each_cpu_mask(cmask, ipi_flush_tlb_range, &fd, 1);
}
put_cpu();
}
void flush_tlb_all(void) void flush_tlb_all(void)
{ {
on_each_cpu(ipi_flush_tlb_all, NULL, 1); on_each_cpu(ipi_flush_tlb_all, NULL, 1);
} }
/*
* FIXME: implement proper functionality instead of flush_tlb_all.
* *But*, as things currently stands, the local_tlb_flush_* functions will
* all boil down to local_tlb_flush_all anyway.
*/
void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_mm(struct mm_struct *mm)
{ {
on_each_cpu(ipi_flush_tlb_all, NULL, 1); smp_flush_tlb_mm(mm_cpumask(mm), mm);
} }
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
{ {
on_each_cpu(ipi_flush_tlb_all, NULL, 1); smp_flush_tlb_range(mm_cpumask(vma->vm_mm), uaddr, uaddr + PAGE_SIZE);
} }
void flush_tlb_range(struct vm_area_struct *vma, void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
{ {
on_each_cpu(ipi_flush_tlb_all, NULL, 1); smp_flush_tlb_range(mm_cpumask(vma->vm_mm), start, end);
} }
/* Instruction cache invalidate - performed on each cpu */ /* Instruction cache invalidate - performed on each cpu */
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/debug.h> #include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
#include <linux/stacktrace.h> #include <linux/stacktrace.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -68,12 +69,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) ...@@ -68,12 +69,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{ {
unsigned long *sp = NULL; unsigned long *sp = NULL;
if (!try_get_task_stack(tsk))
return;
if (tsk == current) if (tsk == current)
sp = (unsigned long *) &sp; sp = (unsigned long *) &sp;
else else {
sp = (unsigned long *) KSTK_ESP(tsk); unsigned long ksp;
/* Locate stack from kernel context */
ksp = task_thread_info(tsk)->ksp;
ksp += STACK_FRAME_OVERHEAD; /* redzone */
ksp += sizeof(struct pt_regs);
sp = (unsigned long *) ksp;
}
unwind_stack(trace, sp, save_stack_address_nosched); unwind_stack(trace, sp, save_stack_address_nosched);
put_task_stack(tsk);
} }
EXPORT_SYMBOL_GPL(save_stack_trace_tsk); EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
......
...@@ -96,18 +96,6 @@ SECTIONS ...@@ -96,18 +96,6 @@ SECTIONS
__init_end = .; __init_end = .;
. = ALIGN(PAGE_SIZE);
.initrd : AT(ADDR(.initrd) - LOAD_OFFSET)
{
__initrd_start = .;
*(.initrd)
__initrd_end = .;
FILL (0);
. = ALIGN (PAGE_SIZE);
}
__vmlinux_end = .; /* last address of the physical file */
BSS_SECTION(0, 0, 0x20) BSS_SECTION(0, 0, 0x20)
_end = .; _end = .;
......
...@@ -137,21 +137,28 @@ void local_flush_tlb_mm(struct mm_struct *mm) ...@@ -137,21 +137,28 @@ void local_flush_tlb_mm(struct mm_struct *mm)
void switch_mm(struct mm_struct *prev, struct mm_struct *next, void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *next_tsk) struct task_struct *next_tsk)
{ {
unsigned int cpu;
if (unlikely(prev == next))
return;
cpu = smp_processor_id();
cpumask_clear_cpu(cpu, mm_cpumask(prev));
cpumask_set_cpu(cpu, mm_cpumask(next));
/* remember the pgd for the fault handlers /* remember the pgd for the fault handlers
* this is similar to the pgd register in some other CPU's. * this is similar to the pgd register in some other CPU's.
* we need our own copy of it because current and active_mm * we need our own copy of it because current and active_mm
* might be invalid at points where we still need to derefer * might be invalid at points where we still need to derefer
* the pgd. * the pgd.
*/ */
current_pgd[smp_processor_id()] = next->pgd; current_pgd[cpu] = next->pgd;
/* We don't have context support implemented, so flush all /* We don't have context support implemented, so flush all
* entries belonging to previous map * entries belonging to previous map
*/ */
local_flush_tlb_mm(prev);
if (prev != next)
local_flush_tlb_mm(prev);
} }
/* /*
......
...@@ -163,7 +163,7 @@ static inline u16 readw(const volatile void __iomem *addr) ...@@ -163,7 +163,7 @@ static inline u16 readw(const volatile void __iomem *addr)
u16 val; u16 val;
__io_br(); __io_br();
val = __le16_to_cpu(__raw_readw(addr)); val = __le16_to_cpu((__le16 __force)__raw_readw(addr));
__io_ar(val); __io_ar(val);
return val; return val;
} }
...@@ -176,7 +176,7 @@ static inline u32 readl(const volatile void __iomem *addr) ...@@ -176,7 +176,7 @@ static inline u32 readl(const volatile void __iomem *addr)
u32 val; u32 val;
__io_br(); __io_br();
val = __le32_to_cpu(__raw_readl(addr)); val = __le32_to_cpu((__le32 __force)__raw_readl(addr));
__io_ar(val); __io_ar(val);
return val; return val;
} }
...@@ -212,7 +212,7 @@ static inline void writeb(u8 value, volatile void __iomem *addr) ...@@ -212,7 +212,7 @@ static inline void writeb(u8 value, volatile void __iomem *addr)
static inline void writew(u16 value, volatile void __iomem *addr) static inline void writew(u16 value, volatile void __iomem *addr)
{ {
__io_bw(); __io_bw();
__raw_writew(cpu_to_le16(value), addr); __raw_writew((u16 __force)cpu_to_le16(value), addr);
__io_aw(); __io_aw();
} }
#endif #endif
...@@ -222,7 +222,7 @@ static inline void writew(u16 value, volatile void __iomem *addr) ...@@ -222,7 +222,7 @@ static inline void writew(u16 value, volatile void __iomem *addr)
static inline void writel(u32 value, volatile void __iomem *addr) static inline void writel(u32 value, volatile void __iomem *addr)
{ {
__io_bw(); __io_bw();
__raw_writel(__cpu_to_le32(value), addr); __raw_writel((u32 __force)__cpu_to_le32(value), addr);
__io_aw(); __io_aw();
} }
#endif #endif
...@@ -474,7 +474,7 @@ static inline u16 _inw(unsigned long addr) ...@@ -474,7 +474,7 @@ static inline u16 _inw(unsigned long addr)
u16 val; u16 val;
__io_pbr(); __io_pbr();
val = __le16_to_cpu(__raw_readw(PCI_IOBASE + addr)); val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
__io_par(val); __io_par(val);
return val; return val;
} }
...@@ -487,7 +487,7 @@ static inline u32 _inl(unsigned long addr) ...@@ -487,7 +487,7 @@ static inline u32 _inl(unsigned long addr)
u32 val; u32 val;
__io_pbr(); __io_pbr();
val = __le32_to_cpu(__raw_readl(PCI_IOBASE + addr)); val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
__io_par(val); __io_par(val);
return val; return val;
} }
...@@ -508,7 +508,7 @@ static inline void _outb(u8 value, unsigned long addr) ...@@ -508,7 +508,7 @@ static inline void _outb(u8 value, unsigned long addr)
static inline void _outw(u16 value, unsigned long addr) static inline void _outw(u16 value, unsigned long addr)
{ {
__io_pbw(); __io_pbw();
__raw_writew(cpu_to_le16(value), PCI_IOBASE + addr); __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
__io_paw(); __io_paw();
} }
#endif #endif
...@@ -518,7 +518,7 @@ static inline void _outw(u16 value, unsigned long addr) ...@@ -518,7 +518,7 @@ static inline void _outw(u16 value, unsigned long addr)
static inline void _outl(u32 value, unsigned long addr) static inline void _outl(u32 value, unsigned long addr)
{ {
__io_pbw(); __io_pbw();
__raw_writel(cpu_to_le32(value), PCI_IOBASE + addr); __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
__io_paw(); __io_paw();
} }
#endif #endif
......
...@@ -65,6 +65,7 @@ struct task_struct init_task ...@@ -65,6 +65,7 @@ struct task_struct init_task
#ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK #ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK
__init_task_data __init_task_data
#endif #endif
__aligned(L1_CACHE_BYTES)
= { = {
#ifdef CONFIG_THREAD_INFO_IN_TASK #ifdef CONFIG_THREAD_INFO_IN_TASK
.thread_info = INIT_THREAD_INFO(init_task), .thread_info = INIT_THREAD_INFO(init_task),
......
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