OpenRISC updates for 5.9

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE2cRzVK74bBA6Je/xw7McLV5mJ+QFAl829wgACgkQw7McLV5m
 J+RvMg/+Ik9jmHiCoDilVzB5yqJ0Ea8oLjg75V9eBE3YtnYJMAbDHb8ye2OsYrlp
 QhrAHFi8PB7nJQphod3XXt8Y5JWMYjKIgdazybVQtUlD5IAXgYAR6/IxJ1DVzxa0
 AzJ7TGmYSxnhW7GzbRU5xjgdIi5cKQjBUcVM/blDQB6/GZ4wY3OBxK1pn0kNXMPU
 gnS+0yPDlwXaZw67YmbF5kF34lvEe0knkOaxxP/S0t2ROb6Xu0PJCEDTbdcGApsB
 2xdm0dJwK50ulS0/HWxC18vC/R7d1b0qjR+xvisjydHbZawEN2Kcf3mOCSAETSTk
 ST1WFxuTAObqdyc4F15tdsqFvbchPtCH9UAjkkSbmRxGVOKQa88NmW1A+s0hj4BX
 enf6I9SYzqiU/WkuFDwSnJ4NETOpPaUVqZbi3WTUfljyXmOdqXbT+416YxViOXpx
 OtSyGVN18qs8wjsWlWiGyhM/eAnHwr9q0q1kJ8VZTh+nQSnQFmuWjHSfRan2PkmQ
 nnbvXHXJcgWYVlk+JZLOnhOB3zrkH5xmlM2UakVUvP92ESnnSmBCC0RLA0k6kGZ3
 PkFBbY4etbA7Ug8r1KueOaqHKwJpTpIb4tU75y3KXyi05FeLEln1doC5M4EQUPDy
 eXzdWj6afuEKmAPILiEYlSVXO3t8iIncVBkK7isaR37dURNnJWE=
 =0MlF
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2020-08-14 14:04:53 -07:00
commit e1d74fbe50
10 changed files with 145 additions and 58 deletions

View File

@ -14,6 +14,8 @@
#ifndef __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?
*/
@ -25,9 +27,12 @@
#define PIO_OFFSET 0
#define PIO_MASK 0
#include <asm-generic/io.h>
#define ioremap ioremap
void __iomem *ioremap(phys_addr_t offset, unsigned long size);
#define iounmap iounmap
extern void iounmap(void *addr);
#include <asm-generic/io.h>
#endif

View File

@ -48,16 +48,17 @@
/* Ensure that the range from addr to addr+size is all within the process'
* 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 */
#define __addr_ok(addr) ((unsigned long) addr < get_fs())
return size <= fs && addr <= (fs - size);
}
#define access_ok(addr, size) \
({ \
unsigned long __ao_addr = (unsigned long)(addr); \
unsigned long __ao_size = (unsigned long)(size); \
__range_ok(__ao_addr, __ao_size); \
__chk_user_ptr(addr); \
__range_ok((unsigned long)(addr), (size)); \
})
/*
@ -100,7 +101,7 @@ extern long __put_user_bad(void);
#define __put_user_check(x, ptr, size) \
({ \
long __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
if (access_ok(__pu_addr, size)) \
__put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \
@ -173,7 +174,7 @@ struct __large_struct {
#define __get_user_check(x, ptr, size) \
({ \
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)) \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \
@ -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);
}
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);
}
#define INLINE_COPY_FROM_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
clear_user(void *addr, unsigned long size)
clear_user(void __user *addr, unsigned long size)
{
if (likely(access_ok(addr, size)))
size = __clear_user(addr, size);

View File

@ -292,13 +292,15 @@ void __init setup_arch(char **cmdline_p)
init_mm.brk = (unsigned long)_end;
#ifdef CONFIG_BLK_DEV_INITRD
initrd_start = (unsigned long)&__initrd_start;
initrd_end = (unsigned long)&__initrd_end;
if (initrd_start == initrd_end) {
printk(KERN_INFO "Initial ramdisk not found\n");
initrd_start = 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;
}
#endif
/* setup memblock allocator */

View File

@ -68,7 +68,7 @@ static int restore_sigcontext(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;
/*
@ -76,7 +76,7 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
* then frame should be dword aligned here. If it's
* not, then the user is trying to mess with us.
*/
if (((long)frame) & 3)
if (((unsigned long)frame) & 3)
goto badframe;
if (!access_ok(frame, sizeof(*frame)))
@ -151,7 +151,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
struct rt_sigframe *frame;
struct rt_sigframe __user *frame;
unsigned long return_ip;
int err = 0;
@ -181,10 +181,10 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
l.ori r11,r0,__NR_sigreturn
l.sys 1
*/
err |= __put_user(0xa960, (short *)(frame->retcode + 0));
err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
err |= __put_user(0xa960, (short __user *)(frame->retcode + 0));
err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode + 2));
err |= __put_user(0x20000001, (unsigned long __user *)(frame->retcode + 4));
err |= __put_user(0x15000000, (unsigned long __user *)(frame->retcode + 8));
if (err)
return -EFAULT;

View File

@ -219,30 +219,99 @@ static inline void ipi_flush_tlb_all(void *ignored)
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)
{
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)
{
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)
{
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,
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 */

View File

@ -13,6 +13,7 @@
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
#include <linux/stacktrace.h>
#include <asm/processor.h>
@ -68,12 +69,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
unsigned long *sp = NULL;
if (!try_get_task_stack(tsk))
return;
if (tsk == current)
sp = (unsigned long *) &sp;
else
sp = (unsigned long *) KSTK_ESP(tsk);
else {
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);
put_task_stack(tsk);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);

View File

@ -96,18 +96,6 @@ SECTIONS
__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)
_end = .;

View File

@ -137,21 +137,28 @@ void local_flush_tlb_mm(struct mm_struct *mm)
void switch_mm(struct mm_struct *prev, struct mm_struct *next,
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
* this is similar to the pgd register in some other CPU's.
* we need our own copy of it because current and active_mm
* might be invalid at points where we still need to derefer
* the pgd.
*/
current_pgd[smp_processor_id()] = next->pgd;
current_pgd[cpu] = next->pgd;
/* We don't have context support implemented, so flush all
* entries belonging to previous map
*/
if (prev != next)
local_flush_tlb_mm(prev);
}
/*

View File

@ -163,7 +163,7 @@ static inline u16 readw(const volatile void __iomem *addr)
u16 val;
__io_br();
val = __le16_to_cpu(__raw_readw(addr));
val = __le16_to_cpu((__le16 __force)__raw_readw(addr));
__io_ar(val);
return val;
}
@ -176,7 +176,7 @@ static inline u32 readl(const volatile void __iomem *addr)
u32 val;
__io_br();
val = __le32_to_cpu(__raw_readl(addr));
val = __le32_to_cpu((__le32 __force)__raw_readl(addr));
__io_ar(val);
return val;
}
@ -212,7 +212,7 @@ static inline void writeb(u8 value, volatile void __iomem *addr)
static inline void writew(u16 value, volatile void __iomem *addr)
{
__io_bw();
__raw_writew(cpu_to_le16(value), addr);
__raw_writew((u16 __force)cpu_to_le16(value), addr);
__io_aw();
}
#endif
@ -222,7 +222,7 @@ static inline void writew(u16 value, volatile void __iomem *addr)
static inline void writel(u32 value, volatile void __iomem *addr)
{
__io_bw();
__raw_writel(__cpu_to_le32(value), addr);
__raw_writel((u32 __force)__cpu_to_le32(value), addr);
__io_aw();
}
#endif
@ -474,7 +474,7 @@ static inline u16 _inw(unsigned long addr)
u16 val;
__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);
return val;
}
@ -487,7 +487,7 @@ static inline u32 _inl(unsigned long addr)
u32 val;
__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);
return val;
}
@ -508,7 +508,7 @@ static inline void _outb(u8 value, unsigned long addr)
static inline void _outw(u16 value, unsigned long addr)
{
__io_pbw();
__raw_writew(cpu_to_le16(value), PCI_IOBASE + addr);
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
__io_paw();
}
#endif
@ -518,7 +518,7 @@ static inline void _outw(u16 value, unsigned long addr)
static inline void _outl(u32 value, unsigned long addr)
{
__io_pbw();
__raw_writel(cpu_to_le32(value), PCI_IOBASE + addr);
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
__io_paw();
}
#endif

View File

@ -65,6 +65,7 @@ struct task_struct init_task
#ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK
__init_task_data
#endif
__aligned(L1_CACHE_BYTES)
= {
#ifdef CONFIG_THREAD_INFO_IN_TASK
.thread_info = INIT_THREAD_INFO(init_task),