Skip to content

Commit e1d74fb

Browse files
committed
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
2 parents 7fca4de + 55b2662 commit e1d74fb

File tree

10 files changed

+145
-58
lines changed

10 files changed

+145
-58
lines changed

arch/openrisc/include/asm/io.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#ifndef __ASM_OPENRISC_IO_H
1515
#define __ASM_OPENRISC_IO_H
1616

17+
#include <linux/types.h>
18+
1719
/*
1820
* PCI: can we really do 0 here if we have no port IO?
1921
*/
@@ -25,9 +27,12 @@
2527
#define PIO_OFFSET 0
2628
#define PIO_MASK 0
2729

28-
#include <asm-generic/io.h>
29-
30+
#define ioremap ioremap
3031
void __iomem *ioremap(phys_addr_t offset, unsigned long size);
32+
33+
#define iounmap iounmap
3134
extern void iounmap(void *addr);
3235

36+
#include <asm-generic/io.h>
37+
3338
#endif

arch/openrisc/include/asm/uaccess.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,17 @@
4848
/* Ensure that the range from addr to addr+size is all within the process'
4949
* address space
5050
*/
51-
#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
51+
static inline int __range_ok(unsigned long addr, unsigned long size)
52+
{
53+
const mm_segment_t fs = get_fs();
5254

53-
/* Ensure that addr is below task's addr_limit */
54-
#define __addr_ok(addr) ((unsigned long) addr < get_fs())
55+
return size <= fs && addr <= (fs - size);
56+
}
5557

5658
#define access_ok(addr, size) \
5759
({ \
58-
unsigned long __ao_addr = (unsigned long)(addr); \
59-
unsigned long __ao_size = (unsigned long)(size); \
60-
__range_ok(__ao_addr, __ao_size); \
60+
__chk_user_ptr(addr); \
61+
__range_ok((unsigned long)(addr), (size)); \
6162
})
6263

6364
/*
@@ -100,7 +101,7 @@ extern long __put_user_bad(void);
100101
#define __put_user_check(x, ptr, size) \
101102
({ \
102103
long __pu_err = -EFAULT; \
103-
__typeof__(*(ptr)) *__pu_addr = (ptr); \
104+
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
104105
if (access_ok(__pu_addr, size)) \
105106
__put_user_size((x), __pu_addr, (size), __pu_err); \
106107
__pu_err; \
@@ -173,7 +174,7 @@ struct __large_struct {
173174
#define __get_user_check(x, ptr, size) \
174175
({ \
175176
long __gu_err = -EFAULT, __gu_val = 0; \
176-
const __typeof__(*(ptr)) * __gu_addr = (ptr); \
177+
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
177178
if (access_ok(__gu_addr, size)) \
178179
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
179180
(x) = (__force __typeof__(*(ptr)))__gu_val; \
@@ -241,17 +242,17 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long size)
241242
return __copy_tofrom_user(to, (__force const void *)from, size);
242243
}
243244
static inline unsigned long
244-
raw_copy_to_user(void *to, const void __user *from, unsigned long size)
245+
raw_copy_to_user(void __user *to, const void *from, unsigned long size)
245246
{
246247
return __copy_tofrom_user((__force void *)to, from, size);
247248
}
248249
#define INLINE_COPY_FROM_USER
249250
#define INLINE_COPY_TO_USER
250251

251-
extern unsigned long __clear_user(void *addr, unsigned long size);
252+
extern unsigned long __clear_user(void __user *addr, unsigned long size);
252253

253254
static inline __must_check unsigned long
254-
clear_user(void *addr, unsigned long size)
255+
clear_user(void __user *addr, unsigned long size)
255256
{
256257
if (likely(access_ok(addr, size)))
257258
size = __clear_user(addr, size);

arch/openrisc/kernel/setup.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,15 @@ void __init setup_arch(char **cmdline_p)
292292
init_mm.brk = (unsigned long)_end;
293293

294294
#ifdef CONFIG_BLK_DEV_INITRD
295-
initrd_start = (unsigned long)&__initrd_start;
296-
initrd_end = (unsigned long)&__initrd_end;
297295
if (initrd_start == initrd_end) {
296+
printk(KERN_INFO "Initial ramdisk not found\n");
298297
initrd_start = 0;
299298
initrd_end = 0;
299+
} else {
300+
printk(KERN_INFO "Initial ramdisk at: 0x%p (%lu bytes)\n",
301+
(void *)(initrd_start), initrd_end - initrd_start);
302+
initrd_below_start_ok = 1;
300303
}
301-
initrd_below_start_ok = 1;
302304
#endif
303305

304306
/* setup memblock allocator */

arch/openrisc/kernel/signal.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ static int restore_sigcontext(struct pt_regs *regs,
6868

6969
asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
7070
{
71-
struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
71+
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->sp;
7272
sigset_t set;
7373

7474
/*
7575
* Since we stacked the signal on a dword boundary,
7676
* then frame should be dword aligned here. If it's
7777
* not, then the user is trying to mess with us.
7878
*/
79-
if (((long)frame) & 3)
79+
if (((unsigned long)frame) & 3)
8080
goto badframe;
8181

8282
if (!access_ok(frame, sizeof(*frame)))
@@ -151,7 +151,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
151151
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
152152
struct pt_regs *regs)
153153
{
154-
struct rt_sigframe *frame;
154+
struct rt_sigframe __user *frame;
155155
unsigned long return_ip;
156156
int err = 0;
157157

@@ -181,10 +181,10 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
181181
l.ori r11,r0,__NR_sigreturn
182182
l.sys 1
183183
*/
184-
err |= __put_user(0xa960, (short *)(frame->retcode + 0));
185-
err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
186-
err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
187-
err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
184+
err |= __put_user(0xa960, (short __user *)(frame->retcode + 0));
185+
err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode + 2));
186+
err |= __put_user(0x20000001, (unsigned long __user *)(frame->retcode + 4));
187+
err |= __put_user(0x15000000, (unsigned long __user *)(frame->retcode + 8));
188188

189189
if (err)
190190
return -EFAULT;

arch/openrisc/kernel/smp.c

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,30 +219,99 @@ static inline void ipi_flush_tlb_all(void *ignored)
219219
local_flush_tlb_all();
220220
}
221221

222+
static inline void ipi_flush_tlb_mm(void *info)
223+
{
224+
struct mm_struct *mm = (struct mm_struct *)info;
225+
226+
local_flush_tlb_mm(mm);
227+
}
228+
229+
static void smp_flush_tlb_mm(struct cpumask *cmask, struct mm_struct *mm)
230+
{
231+
unsigned int cpuid;
232+
233+
if (cpumask_empty(cmask))
234+
return;
235+
236+
cpuid = get_cpu();
237+
238+
if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
239+
/* local cpu is the only cpu present in cpumask */
240+
local_flush_tlb_mm(mm);
241+
} else {
242+
on_each_cpu_mask(cmask, ipi_flush_tlb_mm, mm, 1);
243+
}
244+
put_cpu();
245+
}
246+
247+
struct flush_tlb_data {
248+
unsigned long addr1;
249+
unsigned long addr2;
250+
};
251+
252+
static inline void ipi_flush_tlb_page(void *info)
253+
{
254+
struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
255+
256+
local_flush_tlb_page(NULL, fd->addr1);
257+
}
258+
259+
static inline void ipi_flush_tlb_range(void *info)
260+
{
261+
struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
262+
263+
local_flush_tlb_range(NULL, fd->addr1, fd->addr2);
264+
}
265+
266+
static void smp_flush_tlb_range(struct cpumask *cmask, unsigned long start,
267+
unsigned long end)
268+
{
269+
unsigned int cpuid;
270+
271+
if (cpumask_empty(cmask))
272+
return;
273+
274+
cpuid = get_cpu();
275+
276+
if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
277+
/* local cpu is the only cpu present in cpumask */
278+
if ((end - start) <= PAGE_SIZE)
279+
local_flush_tlb_page(NULL, start);
280+
else
281+
local_flush_tlb_range(NULL, start, end);
282+
} else {
283+
struct flush_tlb_data fd;
284+
285+
fd.addr1 = start;
286+
fd.addr2 = end;
287+
288+
if ((end - start) <= PAGE_SIZE)
289+
on_each_cpu_mask(cmask, ipi_flush_tlb_page, &fd, 1);
290+
else
291+
on_each_cpu_mask(cmask, ipi_flush_tlb_range, &fd, 1);
292+
}
293+
put_cpu();
294+
}
295+
222296
void flush_tlb_all(void)
223297
{
224298
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
225299
}
226300

227-
/*
228-
* FIXME: implement proper functionality instead of flush_tlb_all.
229-
* *But*, as things currently stands, the local_tlb_flush_* functions will
230-
* all boil down to local_tlb_flush_all anyway.
231-
*/
232301
void flush_tlb_mm(struct mm_struct *mm)
233302
{
234-
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
303+
smp_flush_tlb_mm(mm_cpumask(mm), mm);
235304
}
236305

237306
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
238307
{
239-
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
308+
smp_flush_tlb_range(mm_cpumask(vma->vm_mm), uaddr, uaddr + PAGE_SIZE);
240309
}
241310

242311
void flush_tlb_range(struct vm_area_struct *vma,
243312
unsigned long start, unsigned long end)
244313
{
245-
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
314+
smp_flush_tlb_range(mm_cpumask(vma->vm_mm), start, end);
246315
}
247316

248317
/* Instruction cache invalidate - performed on each cpu */

arch/openrisc/kernel/stacktrace.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/export.h>
1414
#include <linux/sched.h>
1515
#include <linux/sched/debug.h>
16+
#include <linux/sched/task_stack.h>
1617
#include <linux/stacktrace.h>
1718

1819
#include <asm/processor.h>
@@ -68,12 +69,25 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
6869
{
6970
unsigned long *sp = NULL;
7071

72+
if (!try_get_task_stack(tsk))
73+
return;
74+
7175
if (tsk == current)
7276
sp = (unsigned long *) &sp;
73-
else
74-
sp = (unsigned long *) KSTK_ESP(tsk);
77+
else {
78+
unsigned long ksp;
79+
80+
/* Locate stack from kernel context */
81+
ksp = task_thread_info(tsk)->ksp;
82+
ksp += STACK_FRAME_OVERHEAD; /* redzone */
83+
ksp += sizeof(struct pt_regs);
84+
85+
sp = (unsigned long *) ksp;
86+
}
7587

7688
unwind_stack(trace, sp, save_stack_address_nosched);
89+
90+
put_task_stack(tsk);
7791
}
7892
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
7993

arch/openrisc/kernel/vmlinux.lds.S

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,6 @@ SECTIONS
9696

9797
__init_end = .;
9898

99-
. = ALIGN(PAGE_SIZE);
100-
.initrd : AT(ADDR(.initrd) - LOAD_OFFSET)
101-
{
102-
__initrd_start = .;
103-
*(.initrd)
104-
__initrd_end = .;
105-
FILL (0);
106-
. = ALIGN (PAGE_SIZE);
107-
}
108-
109-
__vmlinux_end = .; /* last address of the physical file */
110-
11199
BSS_SECTION(0, 0, 0x20)
112100

113101
_end = .;

arch/openrisc/mm/tlb.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,21 +137,28 @@ void local_flush_tlb_mm(struct mm_struct *mm)
137137
void switch_mm(struct mm_struct *prev, struct mm_struct *next,
138138
struct task_struct *next_tsk)
139139
{
140+
unsigned int cpu;
141+
142+
if (unlikely(prev == next))
143+
return;
144+
145+
cpu = smp_processor_id();
146+
147+
cpumask_clear_cpu(cpu, mm_cpumask(prev));
148+
cpumask_set_cpu(cpu, mm_cpumask(next));
149+
140150
/* remember the pgd for the fault handlers
141151
* this is similar to the pgd register in some other CPU's.
142152
* we need our own copy of it because current and active_mm
143153
* might be invalid at points where we still need to derefer
144154
* the pgd.
145155
*/
146-
current_pgd[smp_processor_id()] = next->pgd;
156+
current_pgd[cpu] = next->pgd;
147157

148158
/* We don't have context support implemented, so flush all
149159
* entries belonging to previous map
150160
*/
151-
152-
if (prev != next)
153-
local_flush_tlb_mm(prev);
154-
161+
local_flush_tlb_mm(prev);
155162
}
156163

157164
/*

0 commit comments

Comments
 (0)