Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://github.com/openrisc/linux
Browse files Browse the repository at this point in the history
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
  • Loading branch information
torvalds committed Aug 14, 2020
2 parents 7fca4de + 55b2662 commit e1d74fb
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 58 deletions.
9 changes: 7 additions & 2 deletions arch/openrisc/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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?
*/
Expand All @@ -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
23 changes: 12 additions & 11 deletions arch/openrisc/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)); \
})

/*
Expand Down Expand Up @@ -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; \
Expand Down Expand Up @@ -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; \
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions arch/openrisc/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
initrd_below_start_ok = 1;
#endif

/* setup memblock allocator */
Expand Down
14 changes: 7 additions & 7 deletions arch/openrisc/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ 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;

/*
* Since we stacked the signal on a dword boundary,
* 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)))
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
85 changes: 77 additions & 8 deletions arch/openrisc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
18 changes: 16 additions & 2 deletions arch/openrisc/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);

Expand Down
12 changes: 0 additions & 12 deletions arch/openrisc/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -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 = .;
Expand Down
17 changes: 12 additions & 5 deletions arch/openrisc/mm/tlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

local_flush_tlb_mm(prev);
}

/*
Expand Down
Loading

0 comments on commit e1d74fb

Please sign in to comment.