aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-24 21:37:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-24 21:37:03 -0500
commit9e314890292c0dd357eadef6a043704fa0b4c157 (patch)
treed70b074818b4dc45b180ea860ba66ce573129688
parentf8e6859ea9d06ae1565b21278c4e10fbce5f1eab (diff)
parenta4d4426635804379d618dd28e29f574a2bc11184 (diff)
Merge tag 'openrisc-for-linus' of git://github.com/openrisc/linux
Pull OpenRISC updates from Stafford Horne: "Highlights include: - optimized memset and memcpy routines, ~20% boot time saving - support for cpu idling - adding support for l.swa and l.lwa atomic operations (in spec from 2014) - use atomics to implement: bitops, cmpxchg, futex - the atomics are in preparation for SMP support" * tag 'openrisc-for-linus' of git://github.com/openrisc/linux: (25 commits) openrisc: head: Init r0 to 0 on start openrisc: Export ioremap symbols used by modules arch/openrisc/lib/memcpy.c: use correct OR1200 option openrisc: head: Remove unused strings openrisc: head: Move init strings to rodata section openrisc: entry: Fix delay slot detection openrisc: entry: Whitespace and comment cleanups scripts/checkstack.pl: Add openrisc support MAINTAINERS: Add the openrisc official repository openrisc: Add .gitignore openrisc: Add optimized memcpy routine openrisc: Add optimized memset openrisc: Initial support for the idle state openrisc: Fix the bitmask for the unit present register openrisc: remove unnecessary stddef.h include openrisc: add futex_atomic_* implementations openrisc: add optimized atomic operations openrisc: add cmpxchg and xchg implementations openrisc: add atomic bitops openrisc: add l.lwa/l.swa emulation ...
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/openrisc/Kconfig1
-rw-r--r--arch/openrisc/TODO.openrisc1
-rw-r--r--arch/openrisc/include/asm/Kbuild5
-rw-r--r--arch/openrisc/include/asm/atomic.h126
-rw-r--r--arch/openrisc/include/asm/bitops.h2
-rw-r--r--arch/openrisc/include/asm/bitops/atomic.h123
-rw-r--r--arch/openrisc/include/asm/cmpxchg.h83
-rw-r--r--arch/openrisc/include/asm/cpuinfo.h2
-rw-r--r--arch/openrisc/include/asm/futex.h135
-rw-r--r--arch/openrisc/include/asm/spr_defs.h4
-rw-r--r--arch/openrisc/include/asm/string.h10
-rw-r--r--arch/openrisc/kernel/.gitignore1
-rw-r--r--arch/openrisc/kernel/entry.S60
-rw-r--r--arch/openrisc/kernel/head.S200
-rw-r--r--arch/openrisc/kernel/or32_ksyms.c1
-rw-r--r--arch/openrisc/kernel/process.c14
-rw-r--r--arch/openrisc/kernel/ptrace.c1
-rw-r--r--arch/openrisc/kernel/setup.c67
-rw-r--r--arch/openrisc/kernel/traps.c183
-rw-r--r--arch/openrisc/lib/Makefile2
-rw-r--r--arch/openrisc/lib/memcpy.c124
-rw-r--r--arch/openrisc/lib/memset.S98
-rw-r--r--arch/openrisc/mm/ioremap.c2
-rw-r--r--include/asm-generic/atomic.h2
-rwxr-xr-xscripts/checkstack.pl3
26 files changed, 1064 insertions, 187 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4b03c4701030..8f05facab3b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9315,6 +9315,7 @@ OPENRISC ARCHITECTURE
9315M: Jonas Bonn <jonas@southpole.se> 9315M: Jonas Bonn <jonas@southpole.se>
9316M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 9316M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
9317M: Stafford Horne <shorne@gmail.com> 9317M: Stafford Horne <shorne@gmail.com>
9318T: git git://github.com/openrisc/linux.git
9318L: openrisc@lists.librecores.org 9319L: openrisc@lists.librecores.org
9319W: http://openrisc.io 9320W: http://openrisc.io
9320S: Maintained 9321S: Maintained
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 8d22015fde3e..1e95920b0737 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -12,6 +12,7 @@ config OPENRISC
12 select HAVE_MEMBLOCK 12 select HAVE_MEMBLOCK
13 select GPIOLIB 13 select GPIOLIB
14 select HAVE_ARCH_TRACEHOOK 14 select HAVE_ARCH_TRACEHOOK
15 select SPARSE_IRQ
15 select GENERIC_IRQ_CHIP 16 select GENERIC_IRQ_CHIP
16 select GENERIC_IRQ_PROBE 17 select GENERIC_IRQ_PROBE
17 select GENERIC_IRQ_SHOW 18 select GENERIC_IRQ_SHOW
diff --git a/arch/openrisc/TODO.openrisc b/arch/openrisc/TODO.openrisc
index 0eb04c8240f9..c43d4e1d14eb 100644
--- a/arch/openrisc/TODO.openrisc
+++ b/arch/openrisc/TODO.openrisc
@@ -10,4 +10,3 @@ that are due for investigation shortly, i.e. our TODO list:
10 or1k and this change is slowly trickling through the stack. For the time 10 or1k and this change is slowly trickling through the stack. For the time
11 being, or32 is equivalent to or1k. 11 being, or32 is equivalent to or1k.
12 12
13-- Implement optimized version of memcpy and memset
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ef8d1ccc3e45..fb241757f7f0 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -1,7 +1,6 @@
1 1
2header-y += ucontext.h 2header-y += ucontext.h
3 3
4generic-y += atomic.h
5generic-y += auxvec.h 4generic-y += auxvec.h
6generic-y += barrier.h 5generic-y += barrier.h
7generic-y += bitsperlong.h 6generic-y += bitsperlong.h
@@ -10,8 +9,6 @@ generic-y += bugs.h
10generic-y += cacheflush.h 9generic-y += cacheflush.h
11generic-y += checksum.h 10generic-y += checksum.h
12generic-y += clkdev.h 11generic-y += clkdev.h
13generic-y += cmpxchg-local.h
14generic-y += cmpxchg.h
15generic-y += current.h 12generic-y += current.h
16generic-y += device.h 13generic-y += device.h
17generic-y += div64.h 14generic-y += div64.h
@@ -22,12 +19,12 @@ generic-y += exec.h
22generic-y += fb.h 19generic-y += fb.h
23generic-y += fcntl.h 20generic-y += fcntl.h
24generic-y += ftrace.h 21generic-y += ftrace.h
25generic-y += futex.h
26generic-y += hardirq.h 22generic-y += hardirq.h
27generic-y += hw_irq.h 23generic-y += hw_irq.h
28generic-y += ioctl.h 24generic-y += ioctl.h
29generic-y += ioctls.h 25generic-y += ioctls.h
30generic-y += ipcbuf.h 26generic-y += ipcbuf.h
27generic-y += irq.h
31generic-y += irq_regs.h 28generic-y += irq_regs.h
32generic-y += irq_work.h 29generic-y += irq_work.h
33generic-y += kdebug.h 30generic-y += kdebug.h
diff --git a/arch/openrisc/include/asm/atomic.h b/arch/openrisc/include/asm/atomic.h
new file mode 100644
index 000000000000..146e1660f00e
--- /dev/null
+++ b/arch/openrisc/include/asm/atomic.h
@@ -0,0 +1,126 @@
1/*
2 * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
3 *
4 * This file is licensed under the terms of the GNU General Public License
5 * version 2. This program is licensed "as is" without any warranty of any
6 * kind, whether express or implied.
7 */
8
9#ifndef __ASM_OPENRISC_ATOMIC_H
10#define __ASM_OPENRISC_ATOMIC_H
11
12#include <linux/types.h>
13
14/* Atomically perform op with v->counter and i */
15#define ATOMIC_OP(op) \
16static inline void atomic_##op(int i, atomic_t *v) \
17{ \
18 int tmp; \
19 \
20 __asm__ __volatile__( \
21 "1: l.lwa %0,0(%1) \n" \
22 " l." #op " %0,%0,%2 \n" \
23 " l.swa 0(%1),%0 \n" \
24 " l.bnf 1b \n" \
25 " l.nop \n" \
26 : "=&r"(tmp) \
27 : "r"(&v->counter), "r"(i) \
28 : "cc", "memory"); \
29}
30
31/* Atomically perform op with v->counter and i, return the result */
32#define ATOMIC_OP_RETURN(op) \
33static inline int atomic_##op##_return(int i, atomic_t *v) \
34{ \
35 int tmp; \
36 \
37 __asm__ __volatile__( \
38 "1: l.lwa %0,0(%1) \n" \
39 " l." #op " %0,%0,%2 \n" \
40 " l.swa 0(%1),%0 \n" \
41 " l.bnf 1b \n" \
42 " l.nop \n" \
43 : "=&r"(tmp) \
44 : "r"(&v->counter), "r"(i) \
45 : "cc", "memory"); \
46 \
47 return tmp; \
48}
49
50/* Atomically perform op with v->counter and i, return orig v->counter */
51#define ATOMIC_FETCH_OP(op) \
52static inline int atomic_fetch_##op(int i, atomic_t *v) \
53{ \
54 int tmp, old; \
55 \
56 __asm__ __volatile__( \
57 "1: l.lwa %0,0(%2) \n" \
58 " l." #op " %1,%0,%3 \n" \
59 " l.swa 0(%2),%1 \n" \
60 " l.bnf 1b \n" \
61 " l.nop \n" \
62 : "=&r"(old), "=&r"(tmp) \
63 : "r"(&v->counter), "r"(i) \
64 : "cc", "memory"); \
65 \
66 return old; \
67}
68
69ATOMIC_OP_RETURN(add)
70ATOMIC_OP_RETURN(sub)
71
72ATOMIC_FETCH_OP(add)
73ATOMIC_FETCH_OP(sub)
74ATOMIC_FETCH_OP(and)
75ATOMIC_FETCH_OP(or)
76ATOMIC_FETCH_OP(xor)
77
78ATOMIC_OP(and)
79ATOMIC_OP(or)
80ATOMIC_OP(xor)
81
82#undef ATOMIC_FETCH_OP
83#undef ATOMIC_OP_RETURN
84#undef ATOMIC_OP
85
86#define atomic_add_return atomic_add_return
87#define atomic_sub_return atomic_sub_return
88#define atomic_fetch_add atomic_fetch_add
89#define atomic_fetch_sub atomic_fetch_sub
90#define atomic_fetch_and atomic_fetch_and
91#define atomic_fetch_or atomic_fetch_or
92#define atomic_fetch_xor atomic_fetch_xor
93#define atomic_and atomic_and
94#define atomic_or atomic_or
95#define atomic_xor atomic_xor
96
97/*
98 * Atomically add a to v->counter as long as v is not already u.
99 * Returns the original value at v->counter.
100 *
101 * This is often used through atomic_inc_not_zero()
102 */
103static inline int __atomic_add_unless(atomic_t *v, int a, int u)
104{
105 int old, tmp;
106
107 __asm__ __volatile__(
108 "1: l.lwa %0, 0(%2) \n"
109 " l.sfeq %0, %4 \n"
110 " l.bf 2f \n"
111 " l.add %1, %0, %3 \n"
112 " l.swa 0(%2), %1 \n"
113 " l.bnf 1b \n"
114 " l.nop \n"
115 "2: \n"
116 : "=&r"(old), "=&r" (tmp)
117 : "r"(&v->counter), "r"(a), "r"(u)
118 : "cc", "memory");
119
120 return old;
121}
122#define __atomic_add_unless __atomic_add_unless
123
124#include <asm-generic/atomic.h>
125
126#endif /* __ASM_OPENRISC_ATOMIC_H */
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
index 3003cdad561b..689f56819d53 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -45,7 +45,7 @@
45#include <asm-generic/bitops/hweight.h> 45#include <asm-generic/bitops/hweight.h>
46#include <asm-generic/bitops/lock.h> 46#include <asm-generic/bitops/lock.h>
47 47
48#include <asm-generic/bitops/atomic.h> 48#include <asm/bitops/atomic.h>
49#include <asm-generic/bitops/non-atomic.h> 49#include <asm-generic/bitops/non-atomic.h>
50#include <asm-generic/bitops/le.h> 50#include <asm-generic/bitops/le.h>
51#include <asm-generic/bitops/ext2-atomic.h> 51#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/openrisc/include/asm/bitops/atomic.h b/arch/openrisc/include/asm/bitops/atomic.h
new file mode 100644
index 000000000000..35fb85f61b4a
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/atomic.h
@@ -0,0 +1,123 @@
1/*
2 * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
3 *
4 * This file is licensed under the terms of the GNU General Public License
5 * version 2. This program is licensed "as is" without any warranty of any
6 * kind, whether express or implied.
7 */
8
9#ifndef __ASM_OPENRISC_BITOPS_ATOMIC_H
10#define __ASM_OPENRISC_BITOPS_ATOMIC_H
11
12static inline void set_bit(int nr, volatile unsigned long *addr)
13{
14 unsigned long mask = BIT_MASK(nr);
15 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
16 unsigned long tmp;
17
18 __asm__ __volatile__(
19 "1: l.lwa %0,0(%1) \n"
20 " l.or %0,%0,%2 \n"
21 " l.swa 0(%1),%0 \n"
22 " l.bnf 1b \n"
23 " l.nop \n"
24 : "=&r"(tmp)
25 : "r"(p), "r"(mask)
26 : "cc", "memory");
27}
28
29static inline void clear_bit(int nr, volatile unsigned long *addr)
30{
31 unsigned long mask = BIT_MASK(nr);
32 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
33 unsigned long tmp;
34
35 __asm__ __volatile__(
36 "1: l.lwa %0,0(%1) \n"
37 " l.and %0,%0,%2 \n"
38 " l.swa 0(%1),%0 \n"
39 " l.bnf 1b \n"
40 " l.nop \n"
41 : "=&r"(tmp)
42 : "r"(p), "r"(~mask)
43 : "cc", "memory");
44}
45
46static inline void change_bit(int nr, volatile unsigned long *addr)
47{
48 unsigned long mask = BIT_MASK(nr);
49 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
50 unsigned long tmp;
51
52 __asm__ __volatile__(
53 "1: l.lwa %0,0(%1) \n"
54 " l.xor %0,%0,%2 \n"
55 " l.swa 0(%1),%0 \n"
56 " l.bnf 1b \n"
57 " l.nop \n"
58 : "=&r"(tmp)
59 : "r"(p), "r"(mask)
60 : "cc", "memory");
61}
62
63static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
64{
65 unsigned long mask = BIT_MASK(nr);
66 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
67 unsigned long old;
68 unsigned long tmp;
69
70 __asm__ __volatile__(
71 "1: l.lwa %0,0(%2) \n"
72 " l.or %1,%0,%3 \n"
73 " l.swa 0(%2),%1 \n"
74 " l.bnf 1b \n"
75 " l.nop \n"
76 : "=&r"(old), "=&r"(tmp)
77 : "r"(p), "r"(mask)
78 : "cc", "memory");
79
80 return (old & mask) != 0;
81}
82
83static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
84{
85 unsigned long mask = BIT_MASK(nr);
86 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
87 unsigned long old;
88 unsigned long tmp;
89
90 __asm__ __volatile__(
91 "1: l.lwa %0,0(%2) \n"
92 " l.and %1,%0,%3 \n"
93 " l.swa 0(%2),%1 \n"
94 " l.bnf 1b \n"
95 " l.nop \n"
96 : "=&r"(old), "=&r"(tmp)
97 : "r"(p), "r"(~mask)
98 : "cc", "memory");
99
100 return (old & mask) != 0;
101}
102
103static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
104{
105 unsigned long mask = BIT_MASK(nr);
106 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
107 unsigned long old;
108 unsigned long tmp;
109
110 __asm__ __volatile__(
111 "1: l.lwa %0,0(%2) \n"
112 " l.xor %1,%0,%3 \n"
113 " l.swa 0(%2),%1 \n"
114 " l.bnf 1b \n"
115 " l.nop \n"
116 : "=&r"(old), "=&r"(tmp)
117 : "r"(p), "r"(mask)
118 : "cc", "memory");
119
120 return (old & mask) != 0;
121}
122
123#endif /* __ASM_OPENRISC_BITOPS_ATOMIC_H */
diff --git a/arch/openrisc/include/asm/cmpxchg.h b/arch/openrisc/include/asm/cmpxchg.h
new file mode 100644
index 000000000000..5fcb9ac72693
--- /dev/null
+++ b/arch/openrisc/include/asm/cmpxchg.h
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
3 *
4 * This file is licensed under the terms of the GNU General Public License
5 * version 2. This program is licensed "as is" without any warranty of any
6 * kind, whether express or implied.
7 */
8
9#ifndef __ASM_OPENRISC_CMPXCHG_H
10#define __ASM_OPENRISC_CMPXCHG_H
11
12#include <linux/types.h>
13
14/*
15 * This function doesn't exist, so you'll get a linker error
16 * if something tries to do an invalid cmpxchg().
17 */
18extern void __cmpxchg_called_with_bad_pointer(void);
19
20#define __HAVE_ARCH_CMPXCHG 1
21
22static inline unsigned long
23__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
24{
25 if (size != 4) {
26 __cmpxchg_called_with_bad_pointer();
27 return old;
28 }
29
30 __asm__ __volatile__(
31 "1: l.lwa %0, 0(%1) \n"
32 " l.sfeq %0, %2 \n"
33 " l.bnf 2f \n"
34 " l.nop \n"
35 " l.swa 0(%1), %3 \n"
36 " l.bnf 1b \n"
37 " l.nop \n"
38 "2: \n"
39 : "=&r"(old)
40 : "r"(ptr), "r"(old), "r"(new)
41 : "cc", "memory");
42
43 return old;
44}
45
46#define cmpxchg(ptr, o, n) \
47 ({ \
48 (__typeof__(*(ptr))) __cmpxchg((ptr), \
49 (unsigned long)(o), \
50 (unsigned long)(n), \
51 sizeof(*(ptr))); \
52 })
53
54/*
55 * This function doesn't exist, so you'll get a linker error if
56 * something tries to do an invalidly-sized xchg().
57 */
58extern void __xchg_called_with_bad_pointer(void);
59
60static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
61 int size)
62{
63 if (size != 4) {
64 __xchg_called_with_bad_pointer();
65 return val;
66 }
67
68 __asm__ __volatile__(
69 "1: l.lwa %0, 0(%1) \n"
70 " l.swa 0(%1), %2 \n"
71 " l.bnf 1b \n"
72 " l.nop \n"
73 : "=&r"(val)
74 : "r"(ptr), "r"(val)
75 : "cc", "memory");
76
77 return val;
78}
79
80#define xchg(ptr, with) \
81 ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), sizeof(*(ptr))))
82
83#endif /* __ASM_OPENRISC_CMPXCHG_H */
diff --git a/arch/openrisc/include/asm/cpuinfo.h b/arch/openrisc/include/asm/cpuinfo.h
index 917318b6a970..ec10679d6429 100644
--- a/arch/openrisc/include/asm/cpuinfo.h
+++ b/arch/openrisc/include/asm/cpuinfo.h
@@ -24,9 +24,11 @@ struct cpuinfo {
24 24
25 u32 icache_size; 25 u32 icache_size;
26 u32 icache_block_size; 26 u32 icache_block_size;
27 u32 icache_ways;
27 28
28 u32 dcache_size; 29 u32 dcache_size;
29 u32 dcache_block_size; 30 u32 dcache_block_size;
31 u32 dcache_ways;
30}; 32};
31 33
32extern struct cpuinfo cpuinfo; 34extern struct cpuinfo cpuinfo;
diff --git a/arch/openrisc/include/asm/futex.h b/arch/openrisc/include/asm/futex.h
new file mode 100644
index 000000000000..778087341977
--- /dev/null
+++ b/arch/openrisc/include/asm/futex.h
@@ -0,0 +1,135 @@
1#ifndef __ASM_OPENRISC_FUTEX_H
2#define __ASM_OPENRISC_FUTEX_H
3
4#ifdef __KERNEL__
5
6#include <linux/futex.h>
7#include <linux/uaccess.h>
8#include <asm/errno.h>
9
10#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
11({ \
12 __asm__ __volatile__ ( \
13 "1: l.lwa %0, %2 \n" \
14 insn "\n" \
15 "2: l.swa %2, %1 \n" \
16 " l.bnf 1b \n" \
17 " l.ori %1, r0, 0 \n" \
18 "3: \n" \
19 ".section .fixup,\"ax\" \n" \
20 "4: l.j 3b \n" \
21 " l.addi %1, r0, %3 \n" \
22 ".previous \n" \
23 ".section __ex_table,\"a\" \n" \
24 ".word 1b,4b,2b,4b \n" \
25 ".previous \n" \
26 : "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
27 : "i" (-EFAULT), "r" (oparg) \
28 : "cc", "memory" \
29 ); \
30})
31
32static inline int
33futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
34{
35 int op = (encoded_op >> 28) & 7;
36 int cmp = (encoded_op >> 24) & 15;
37 int oparg = (encoded_op << 8) >> 20;
38 int cmparg = (encoded_op << 20) >> 20;
39 int oldval = 0, ret;
40
41 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
42 oparg = 1 << oparg;
43
44 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
45 return -EFAULT;
46
47 pagefault_disable();
48
49 switch (op) {
50 case FUTEX_OP_SET:
51 __futex_atomic_op("l.or %1,%4,%4", ret, oldval, uaddr, oparg);
52 break;
53 case FUTEX_OP_ADD:
54 __futex_atomic_op("l.add %1,%0,%4", ret, oldval, uaddr, oparg);
55 break;
56 case FUTEX_OP_OR:
57 __futex_atomic_op("l.or %1,%0,%4", ret, oldval, uaddr, oparg);
58 break;
59 case FUTEX_OP_ANDN:
60 __futex_atomic_op("l.and %1,%0,%4", ret, oldval, uaddr, ~oparg);
61 break;
62 case FUTEX_OP_XOR:
63 __futex_atomic_op("l.xor %1,%0,%4", ret, oldval, uaddr, oparg);
64 break;
65 default:
66 ret = -ENOSYS;
67 }
68
69 pagefault_enable();
70
71 if (!ret) {
72 switch (cmp) {
73 case FUTEX_OP_CMP_EQ:
74 ret = (oldval == cmparg);
75 break;
76 case FUTEX_OP_CMP_NE:
77 ret = (oldval != cmparg);
78 break;
79 case FUTEX_OP_CMP_LT:
80 ret = (oldval < cmparg);
81 break;
82 case FUTEX_OP_CMP_GE:
83 ret = (oldval >= cmparg);
84 break;
85 case FUTEX_OP_CMP_LE:
86 ret = (oldval <= cmparg);
87 break;
88 case FUTEX_OP_CMP_GT:
89 ret = (oldval > cmparg);
90 break;
91 default:
92 ret = -ENOSYS;
93 }
94 }
95 return ret;
96}
97
98static inline int
99futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
100 u32 oldval, u32 newval)
101{
102 int ret = 0;
103 u32 prev;
104
105 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
106 return -EFAULT;
107
108 __asm__ __volatile__ ( \
109 "1: l.lwa %1, %2 \n" \
110 " l.sfeq %1, %3 \n" \
111 " l.bnf 3f \n" \
112 " l.nop \n" \
113 "2: l.swa %2, %4 \n" \
114 " l.bnf 1b \n" \
115 " l.nop \n" \
116 "3: \n" \
117 ".section .fixup,\"ax\" \n" \
118 "4: l.j 3b \n" \
119 " l.addi %0, r0, %5 \n" \
120 ".previous \n" \
121 ".section __ex_table,\"a\" \n" \
122 ".word 1b,4b,2b,4b \n" \
123 ".previous \n" \
124 : "+r" (ret), "=&r" (prev), "+m" (*uaddr) \
125 : "r" (oldval), "r" (newval), "i" (-EFAULT) \
126 : "cc", "memory" \
127 );
128
129 *uval = prev;
130 return ret;
131}
132
133#endif /* __KERNEL__ */
134
135#endif /* __ASM_OPENRISC_FUTEX_H */
diff --git a/arch/openrisc/include/asm/spr_defs.h b/arch/openrisc/include/asm/spr_defs.h
index 5dbc668865c4..367dac70326a 100644
--- a/arch/openrisc/include/asm/spr_defs.h
+++ b/arch/openrisc/include/asm/spr_defs.h
@@ -152,8 +152,8 @@
152#define SPR_UPR_MP 0x00000020 /* MAC present */ 152#define SPR_UPR_MP 0x00000020 /* MAC present */
153#define SPR_UPR_DUP 0x00000040 /* Debug unit present */ 153#define SPR_UPR_DUP 0x00000040 /* Debug unit present */
154#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */ 154#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */
155#define SPR_UPR_PMP 0x00000100 /* Power management present */ 155#define SPR_UPR_PICP 0x00000100 /* PIC present */
156#define SPR_UPR_PICP 0x00000200 /* PIC present */ 156#define SPR_UPR_PMP 0x00000200 /* Power management present */
157#define SPR_UPR_TTP 0x00000400 /* Tick timer present */ 157#define SPR_UPR_TTP 0x00000400 /* Tick timer present */
158#define SPR_UPR_RES 0x00fe0000 /* Reserved */ 158#define SPR_UPR_RES 0x00fe0000 /* Reserved */
159#define SPR_UPR_CUP 0xff000000 /* Context units present */ 159#define SPR_UPR_CUP 0xff000000 /* Context units present */
diff --git a/arch/openrisc/include/asm/string.h b/arch/openrisc/include/asm/string.h
new file mode 100644
index 000000000000..64939ccd7531
--- /dev/null
+++ b/arch/openrisc/include/asm/string.h
@@ -0,0 +1,10 @@
1#ifndef __ASM_OPENRISC_STRING_H
2#define __ASM_OPENRISC_STRING_H
3
4#define __HAVE_ARCH_MEMSET
5extern void *memset(void *s, int c, __kernel_size_t n);
6
7#define __HAVE_ARCH_MEMCPY
8extern void *memcpy(void *dest, __const void *src, __kernel_size_t n);
9
10#endif /* __ASM_OPENRISC_STRING_H */
diff --git a/arch/openrisc/kernel/.gitignore b/arch/openrisc/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/openrisc/kernel/.gitignore
@@ -0,0 +1 @@
vmlinux.lds
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index aac0bde3330c..bc6500860f4d 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -173,6 +173,11 @@ handler: ;\
173 l.j _ret_from_exception ;\ 173 l.j _ret_from_exception ;\
174 l.nop 174 l.nop
175 175
176/* clobbers 'reg' */
177#define CLEAR_LWA_FLAG(reg) \
178 l.movhi reg,hi(lwa_flag) ;\
179 l.ori reg,reg,lo(lwa_flag) ;\
180 l.sw 0(reg),r0
176/* 181/*
177 * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR 182 * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR
178 * contain the same values as when exception we're handling 183 * contain the same values as when exception we're handling
@@ -193,6 +198,7 @@ EXCEPTION_ENTRY(_tng_kernel_start)
193/* ---[ 0x200: BUS exception ]------------------------------------------- */ 198/* ---[ 0x200: BUS exception ]------------------------------------------- */
194 199
195EXCEPTION_ENTRY(_bus_fault_handler) 200EXCEPTION_ENTRY(_bus_fault_handler)
201 CLEAR_LWA_FLAG(r3)
196 /* r4: EA of fault (set by EXCEPTION_HANDLE) */ 202 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
197 l.jal do_bus_fault 203 l.jal do_bus_fault
198 l.addi r3,r1,0 /* pt_regs */ 204 l.addi r3,r1,0 /* pt_regs */
@@ -202,11 +208,13 @@ EXCEPTION_ENTRY(_bus_fault_handler)
202 208
203/* ---[ 0x300: Data Page Fault exception ]------------------------------- */ 209/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
204EXCEPTION_ENTRY(_dtlb_miss_page_fault_handler) 210EXCEPTION_ENTRY(_dtlb_miss_page_fault_handler)
211 CLEAR_LWA_FLAG(r3)
205 l.and r5,r5,r0 212 l.and r5,r5,r0
206 l.j 1f 213 l.j 1f
207 l.nop 214 l.nop
208 215
209EXCEPTION_ENTRY(_data_page_fault_handler) 216EXCEPTION_ENTRY(_data_page_fault_handler)
217 CLEAR_LWA_FLAG(r3)
210 /* set up parameters for do_page_fault */ 218 /* set up parameters for do_page_fault */
211 l.ori r5,r0,0x300 // exception vector 219 l.ori r5,r0,0x300 // exception vector
2121: 2201:
@@ -220,7 +228,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
220 * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part 228 * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
221 */ 229 */
222#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX 230#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
223 l.lwz r6,PT_PC(r3) // address of an offending insn 231 l.lwz r6,PT_PC(r3) // address of an offending insn
224 l.lwz r6,0(r6) // instruction that caused pf 232 l.lwz r6,0(r6) // instruction that caused pf
225 233
226 l.srli r6,r6,26 // check opcode for jump insn 234 l.srli r6,r6,26 // check opcode for jump insn
@@ -236,57 +244,57 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
236 l.bf 8f 244 l.bf 8f
237 l.sfeqi r6,0x12 // l.jalr 245 l.sfeqi r6,0x12 // l.jalr
238 l.bf 8f 246 l.bf 8f
239 247 l.nop
240 l.nop
241 248
242 l.j 9f 249 l.j 9f
243 l.nop 250 l.nop
2448:
245 251
246 l.lwz r6,PT_PC(r3) // address of an offending insn 2528: // offending insn is in delay slot
253 l.lwz r6,PT_PC(r3) // address of an offending insn
247 l.addi r6,r6,4 254 l.addi r6,r6,4
248 l.lwz r6,0(r6) // instruction that caused pf 255 l.lwz r6,0(r6) // instruction that caused pf
249 l.srli r6,r6,26 // get opcode 256 l.srli r6,r6,26 // get opcode
2509: 2579: // offending instruction opcode loaded in r6
251 258
252#else 259#else
253 260
254 l.mfspr r6,r0,SPR_SR // SR 261 l.lwz r6,PT_SR(r3) // SR
255// l.lwz r6,PT_SR(r3) // ESR 262 l.andi r6,r6,SPR_SR_DSX // check for delay slot exception
256 l.andi r6,r6,SPR_SR_DSX // check for delay slot exception 263 l.sfne r6,r0 // exception happened in delay slot
257 l.sfeqi r6,0x1 // exception happened in delay slot 264 l.bnf 7f
258 l.bnf 7f 265 l.lwz r6,PT_PC(r3) // address of an offending insn
259 l.lwz r6,PT_PC(r3) // address of an offending insn
260 266
261 l.addi r6,r6,4 // offending insn is in delay slot 267 l.addi r6,r6,4 // offending insn is in delay slot
2627: 2687:
263 l.lwz r6,0(r6) // instruction that caused pf 269 l.lwz r6,0(r6) // instruction that caused pf
264 l.srli r6,r6,26 // check opcode for write access 270 l.srli r6,r6,26 // check opcode for write access
265#endif 271#endif
266 272
267 l.sfgeui r6,0x33 // check opcode for write access 273 l.sfgeui r6,0x33 // check opcode for write access
268 l.bnf 1f 274 l.bnf 1f
269 l.sfleui r6,0x37 275 l.sfleui r6,0x37
270 l.bnf 1f 276 l.bnf 1f
271 l.ori r6,r0,0x1 // write access 277 l.ori r6,r0,0x1 // write access
272 l.j 2f 278 l.j 2f
273 l.nop 279 l.nop
2741: l.ori r6,r0,0x0 // !write access 2801: l.ori r6,r0,0x0 // !write access
2752: 2812:
276 282
277 /* call fault.c handler in or32/mm/fault.c */ 283 /* call fault.c handler in or32/mm/fault.c */
278 l.jal do_page_fault 284 l.jal do_page_fault
279 l.nop 285 l.nop
280 l.j _ret_from_exception 286 l.j _ret_from_exception
281 l.nop 287 l.nop
282 288
283/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */ 289/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
284EXCEPTION_ENTRY(_itlb_miss_page_fault_handler) 290EXCEPTION_ENTRY(_itlb_miss_page_fault_handler)
291 CLEAR_LWA_FLAG(r3)
285 l.and r5,r5,r0 292 l.and r5,r5,r0
286 l.j 1f 293 l.j 1f
287 l.nop 294 l.nop
288 295
289EXCEPTION_ENTRY(_insn_page_fault_handler) 296EXCEPTION_ENTRY(_insn_page_fault_handler)
297 CLEAR_LWA_FLAG(r3)
290 /* set up parameters for do_page_fault */ 298 /* set up parameters for do_page_fault */
291 l.ori r5,r0,0x400 // exception vector 299 l.ori r5,r0,0x400 // exception vector
2921: 3001:
@@ -296,14 +304,15 @@ EXCEPTION_ENTRY(_insn_page_fault_handler)
296 304
297 /* call fault.c handler in or32/mm/fault.c */ 305 /* call fault.c handler in or32/mm/fault.c */
298 l.jal do_page_fault 306 l.jal do_page_fault
299 l.nop 307 l.nop
300 l.j _ret_from_exception 308 l.j _ret_from_exception
301 l.nop 309 l.nop
302 310
303 311
304/* ---[ 0x500: Timer exception ]----------------------------------------- */ 312/* ---[ 0x500: Timer exception ]----------------------------------------- */
305 313
306EXCEPTION_ENTRY(_timer_handler) 314EXCEPTION_ENTRY(_timer_handler)
315 CLEAR_LWA_FLAG(r3)
307 l.jal timer_interrupt 316 l.jal timer_interrupt
308 l.addi r3,r1,0 /* pt_regs */ 317 l.addi r3,r1,0 /* pt_regs */
309 318
@@ -313,6 +322,7 @@ EXCEPTION_ENTRY(_timer_handler)
313/* ---[ 0x600: Aligment exception ]-------------------------------------- */ 322/* ---[ 0x600: Aligment exception ]-------------------------------------- */
314 323
315EXCEPTION_ENTRY(_alignment_handler) 324EXCEPTION_ENTRY(_alignment_handler)
325 CLEAR_LWA_FLAG(r3)
316 /* r4: EA of fault (set by EXCEPTION_HANDLE) */ 326 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
317 l.jal do_unaligned_access 327 l.jal do_unaligned_access
318 l.addi r3,r1,0 /* pt_regs */ 328 l.addi r3,r1,0 /* pt_regs */
@@ -509,6 +519,7 @@ EXCEPTION_ENTRY(_external_irq_handler)
509// l.sw PT_SR(r1),r4 519// l.sw PT_SR(r1),r4
5101: 5201:
511#endif 521#endif
522 CLEAR_LWA_FLAG(r3)
512 l.addi r3,r1,0 523 l.addi r3,r1,0
513 l.movhi r8,hi(do_IRQ) 524 l.movhi r8,hi(do_IRQ)
514 l.ori r8,r8,lo(do_IRQ) 525 l.ori r8,r8,lo(do_IRQ)
@@ -556,8 +567,12 @@ ENTRY(_sys_call_handler)
556 * they should be clobbered, otherwise 567 * they should be clobbered, otherwise
557 */ 568 */
558 l.sw PT_GPR3(r1),r3 569 l.sw PT_GPR3(r1),r3
559 /* r4 already saved */ 570 /*
560 /* r4 holds the EEAR address of the fault, load the original r4 */ 571 * r4 already saved
572 * r4 holds the EEAR address of the fault, use it as screatch reg and
573 * then load the original r4
574 */
575 CLEAR_LWA_FLAG(r4)
561 l.lwz r4,PT_GPR4(r1) 576 l.lwz r4,PT_GPR4(r1)
562 l.sw PT_GPR5(r1),r5 577 l.sw PT_GPR5(r1),r5
563 l.sw PT_GPR6(r1),r6 578 l.sw PT_GPR6(r1),r6
@@ -776,6 +791,7 @@ UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)
776/* ---[ 0xe00: Trap exception ]------------------------------------------ */ 791/* ---[ 0xe00: Trap exception ]------------------------------------------ */
777 792
778EXCEPTION_ENTRY(_trap_handler) 793EXCEPTION_ENTRY(_trap_handler)
794 CLEAR_LWA_FLAG(r3)
779 /* r4: EA of fault (set by EXCEPTION_HANDLE) */ 795 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
780 l.jal do_trap 796 l.jal do_trap
781 l.addi r3,r1,0 /* pt_regs */ 797 l.addi r3,r1,0 /* pt_regs */
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
index f14793306b03..d01b82eace3e 100644
--- a/arch/openrisc/kernel/head.S
+++ b/arch/openrisc/kernel/head.S
@@ -24,6 +24,7 @@
24#include <asm/page.h> 24#include <asm/page.h>
25#include <asm/mmu.h> 25#include <asm/mmu.h>
26#include <asm/pgtable.h> 26#include <asm/pgtable.h>
27#include <asm/thread_info.h>
27#include <asm/cache.h> 28#include <asm/cache.h>
28#include <asm/spr_defs.h> 29#include <asm/spr_defs.h>
29#include <asm/asm-offsets.h> 30#include <asm/asm-offsets.h>
@@ -34,7 +35,7 @@
34 l.add rd,rd,rs 35 l.add rd,rd,rs
35 36
36#define CLEAR_GPR(gpr) \ 37#define CLEAR_GPR(gpr) \
37 l.or gpr,r0,r0 38 l.movhi gpr,0x0
38 39
39#define LOAD_SYMBOL_2_GPR(gpr,symbol) \ 40#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
40 l.movhi gpr,hi(symbol) ;\ 41 l.movhi gpr,hi(symbol) ;\
@@ -442,6 +443,9 @@ _dispatch_do_ipage_fault:
442 __HEAD 443 __HEAD
443 .global _start 444 .global _start
444_start: 445_start:
446 /* Init r0 to zero as per spec */
447 CLEAR_GPR(r0)
448
445 /* save kernel parameters */ 449 /* save kernel parameters */
446 l.or r25,r0,r3 /* pointer to fdt */ 450 l.or r25,r0,r3 /* pointer to fdt */
447 451
@@ -486,7 +490,8 @@ _start:
486 /* 490 /*
487 * set up initial ksp and current 491 * set up initial ksp and current
488 */ 492 */
489 LOAD_SYMBOL_2_GPR(r1,init_thread_union+0x2000) // setup kernel stack 493 /* setup kernel stack */
494 LOAD_SYMBOL_2_GPR(r1,init_thread_union + THREAD_SIZE)
490 LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current 495 LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current
491 tophys (r31,r10) 496 tophys (r31,r10)
492 l.sw TI_KSP(r31), r1 497 l.sw TI_KSP(r31), r1
@@ -520,22 +525,8 @@ enable_dc:
520 l.nop 525 l.nop
521 526
522flush_tlb: 527flush_tlb:
523 /* 528 l.jal _flush_tlb
524 * I N V A L I D A T E T L B e n t r i e s 529 l.nop
525 */
526 LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
527 LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
528 l.addi r7,r0,128 /* Maximum number of sets */
5291:
530 l.mtspr r5,r0,0x0
531 l.mtspr r6,r0,0x0
532
533 l.addi r5,r5,1
534 l.addi r6,r6,1
535 l.sfeq r7,r0
536 l.bnf 1b
537 l.addi r7,r7,-1
538
539 530
540/* The MMU needs to be enabled before or32_early_setup is called */ 531/* The MMU needs to be enabled before or32_early_setup is called */
541 532
@@ -627,6 +618,26 @@ jump_start_kernel:
627 l.jr r30 618 l.jr r30
628 l.nop 619 l.nop
629 620
621_flush_tlb:
622 /*
623 * I N V A L I D A T E T L B e n t r i e s
624 */
625 LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
626 LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
627 l.addi r7,r0,128 /* Maximum number of sets */
6281:
629 l.mtspr r5,r0,0x0
630 l.mtspr r6,r0,0x0
631
632 l.addi r5,r5,1
633 l.addi r6,r6,1
634 l.sfeq r7,r0
635 l.bnf 1b
636 l.addi r7,r7,-1
637
638 l.jr r9
639 l.nop
640
630/* ========================================[ cache ]=== */ 641/* ========================================[ cache ]=== */
631 642
632 /* aligment here so we don't change memory offsets with 643 /* aligment here so we don't change memory offsets with
@@ -971,8 +982,6 @@ ENTRY(dtlb_miss_handler)
971 EXCEPTION_STORE_GPR2 982 EXCEPTION_STORE_GPR2
972 EXCEPTION_STORE_GPR3 983 EXCEPTION_STORE_GPR3
973 EXCEPTION_STORE_GPR4 984 EXCEPTION_STORE_GPR4
974 EXCEPTION_STORE_GPR5
975 EXCEPTION_STORE_GPR6
976 /* 985 /*
977 * get EA of the miss 986 * get EA of the miss
978 */ 987 */
@@ -980,91 +989,70 @@ ENTRY(dtlb_miss_handler)
980 /* 989 /*
981 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr)); 990 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
982 */ 991 */
983 GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp 992 GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r4 is temp
984 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2) 993 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
985 l.slli r4,r4,0x2 // to get address << 2 994 l.slli r4,r4,0x2 // to get address << 2
986 l.add r5,r4,r3 // r4 is pgd_index(daddr) 995 l.add r3,r4,r3 // r4 is pgd_index(daddr)
987 /* 996 /*
988 * if (pmd_none(*pmd)) 997 * if (pmd_none(*pmd))
989 * goto pmd_none: 998 * goto pmd_none:
990 */ 999 */
991 tophys (r4,r5) 1000 tophys (r4,r3)
992 l.lwz r3,0x0(r4) // get *pmd value 1001 l.lwz r3,0x0(r4) // get *pmd value
993 l.sfne r3,r0 1002 l.sfne r3,r0
994 l.bnf d_pmd_none 1003 l.bnf d_pmd_none
995 l.andi r3,r3,~PAGE_MASK //0x1fff // ~PAGE_MASK 1004 l.addi r3,r0,0xffffe000 // PAGE_MASK
996 /* 1005
997 * if (pmd_bad(*pmd))
998 * pmd_clear(pmd)
999 * goto pmd_bad:
1000 */
1001// l.sfeq r3,r0 // check *pmd value
1002// l.bf d_pmd_good
1003 l.addi r3,r0,0xffffe000 // PAGE_MASK
1004// l.j d_pmd_bad
1005// l.sw 0x0(r4),r0 // clear pmd
1006d_pmd_good: 1006d_pmd_good:
1007 /* 1007 /*
1008 * pte = *pte_offset(pmd, daddr); 1008 * pte = *pte_offset(pmd, daddr);
1009 */ 1009 */
1010 l.lwz r4,0x0(r4) // get **pmd value 1010 l.lwz r4,0x0(r4) // get **pmd value
1011 l.and r4,r4,r3 // & PAGE_MASK 1011 l.and r4,r4,r3 // & PAGE_MASK
1012 l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR 1012 l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1013 l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1 1013 l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
1014 l.slli r3,r3,0x2 // to get address << 2 1014 l.slli r3,r3,0x2 // to get address << 2
1015 l.add r3,r3,r4 1015 l.add r3,r3,r4
1016 l.lwz r2,0x0(r3) // this is pte at last 1016 l.lwz r3,0x0(r3) // this is pte at last
1017 /* 1017 /*
1018 * if (!pte_present(pte)) 1018 * if (!pte_present(pte))
1019 */ 1019 */
1020 l.andi r4,r2,0x1 1020 l.andi r4,r3,0x1
1021 l.sfne r4,r0 // is pte present 1021 l.sfne r4,r0 // is pte present
1022 l.bnf d_pte_not_present 1022 l.bnf d_pte_not_present
1023 l.addi r3,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK 1023 l.addi r4,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK
1024 /* 1024 /*
1025 * fill DTLB TR register 1025 * fill DTLB TR register
1026 */ 1026 */
1027 l.and r4,r2,r3 // apply the mask 1027 l.and r4,r3,r4 // apply the mask
1028 // Determine number of DMMU sets 1028 // Determine number of DMMU sets
1029 l.mfspr r6, r0, SPR_DMMUCFGR 1029 l.mfspr r2, r0, SPR_DMMUCFGR
1030 l.andi r6, r6, SPR_DMMUCFGR_NTS 1030 l.andi r2, r2, SPR_DMMUCFGR_NTS
1031 l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF 1031 l.srli r2, r2, SPR_DMMUCFGR_NTS_OFF
1032 l.ori r3, r0, 0x1 1032 l.ori r3, r0, 0x1
1033 l.sll r3, r3, r6 // r3 = number DMMU sets DMMUCFGR 1033 l.sll r3, r3, r2 // r3 = number DMMU sets DMMUCFGR
1034 l.addi r6, r3, -1 // r6 = nsets mask 1034 l.addi r2, r3, -1 // r2 = nsets mask
1035 l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1) 1035 l.mfspr r3, r0, SPR_EEAR_BASE
1036 l.srli r3, r3, 0xd // >> PAGE_SHIFT
1037 l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
1036 //NUM_TLB_ENTRIES 1038 //NUM_TLB_ENTRIES
1037 l.mtspr r5,r4,SPR_DTLBTR_BASE(0) 1039 l.mtspr r2,r4,SPR_DTLBTR_BASE(0)
1038 /* 1040 /*
1039 * fill DTLB MR register 1041 * fill DTLB MR register
1040 */ 1042 */
1041 l.mfspr r2,r0,SPR_EEAR_BASE 1043 l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
1042 l.addi r3,r0,0xffffe000 // PAGE_MASK 1044 l.ori r4,r3,0x1 // set hardware valid bit: DTBL_MR entry
1043 l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?) 1045 l.mtspr r2,r4,SPR_DTLBMR_BASE(0)
1044 l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
1045 l.mtspr r5,r4,SPR_DTLBMR_BASE(0)
1046 1046
1047 EXCEPTION_LOAD_GPR2 1047 EXCEPTION_LOAD_GPR2
1048 EXCEPTION_LOAD_GPR3 1048 EXCEPTION_LOAD_GPR3
1049 EXCEPTION_LOAD_GPR4 1049 EXCEPTION_LOAD_GPR4
1050 EXCEPTION_LOAD_GPR5
1051 EXCEPTION_LOAD_GPR6
1052 l.rfe
1053d_pmd_bad:
1054 l.nop 1
1055 EXCEPTION_LOAD_GPR2
1056 EXCEPTION_LOAD_GPR3
1057 EXCEPTION_LOAD_GPR4
1058 EXCEPTION_LOAD_GPR5
1059 EXCEPTION_LOAD_GPR6
1060 l.rfe 1050 l.rfe
1061d_pmd_none: 1051d_pmd_none:
1062d_pte_not_present: 1052d_pte_not_present:
1063 EXCEPTION_LOAD_GPR2 1053 EXCEPTION_LOAD_GPR2
1064 EXCEPTION_LOAD_GPR3 1054 EXCEPTION_LOAD_GPR3
1065 EXCEPTION_LOAD_GPR4 1055 EXCEPTION_LOAD_GPR4
1066 EXCEPTION_LOAD_GPR5
1067 EXCEPTION_LOAD_GPR6
1068 EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler) 1056 EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler)
1069 1057
1070/* ==============================================[ ITLB miss handler ]=== */ 1058/* ==============================================[ ITLB miss handler ]=== */
@@ -1072,8 +1060,6 @@ ENTRY(itlb_miss_handler)
1072 EXCEPTION_STORE_GPR2 1060 EXCEPTION_STORE_GPR2
1073 EXCEPTION_STORE_GPR3 1061 EXCEPTION_STORE_GPR3
1074 EXCEPTION_STORE_GPR4 1062 EXCEPTION_STORE_GPR4
1075 EXCEPTION_STORE_GPR5
1076 EXCEPTION_STORE_GPR6
1077 /* 1063 /*
1078 * get EA of the miss 1064 * get EA of the miss
1079 */ 1065 */
@@ -1083,30 +1069,19 @@ ENTRY(itlb_miss_handler)
1083 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr)); 1069 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
1084 * 1070 *
1085 */ 1071 */
1086 GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp 1072 GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r5 is temp
1087 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2) 1073 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
1088 l.slli r4,r4,0x2 // to get address << 2 1074 l.slli r4,r4,0x2 // to get address << 2
1089 l.add r5,r4,r3 // r4 is pgd_index(daddr) 1075 l.add r3,r4,r3 // r4 is pgd_index(daddr)
1090 /* 1076 /*
1091 * if (pmd_none(*pmd)) 1077 * if (pmd_none(*pmd))
1092 * goto pmd_none: 1078 * goto pmd_none:
1093 */ 1079 */
1094 tophys (r4,r5) 1080 tophys (r4,r3)
1095 l.lwz r3,0x0(r4) // get *pmd value 1081 l.lwz r3,0x0(r4) // get *pmd value
1096 l.sfne r3,r0 1082 l.sfne r3,r0
1097 l.bnf i_pmd_none 1083 l.bnf i_pmd_none
1098 l.andi r3,r3,0x1fff // ~PAGE_MASK 1084 l.addi r3,r0,0xffffe000 // PAGE_MASK
1099 /*
1100 * if (pmd_bad(*pmd))
1101 * pmd_clear(pmd)
1102 * goto pmd_bad:
1103 */
1104
1105// l.sfeq r3,r0 // check *pmd value
1106// l.bf i_pmd_good
1107 l.addi r3,r0,0xffffe000 // PAGE_MASK
1108// l.j i_pmd_bad
1109// l.sw 0x0(r4),r0 // clear pmd
1110 1085
1111i_pmd_good: 1086i_pmd_good:
1112 /* 1087 /*
@@ -1115,35 +1090,36 @@ i_pmd_good:
1115 */ 1090 */
1116 l.lwz r4,0x0(r4) // get **pmd value 1091 l.lwz r4,0x0(r4) // get **pmd value
1117 l.and r4,r4,r3 // & PAGE_MASK 1092 l.and r4,r4,r3 // & PAGE_MASK
1118 l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR 1093 l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1119 l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1 1094 l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
1120 l.slli r3,r3,0x2 // to get address << 2 1095 l.slli r3,r3,0x2 // to get address << 2
1121 l.add r3,r3,r4 1096 l.add r3,r3,r4
1122 l.lwz r2,0x0(r3) // this is pte at last 1097 l.lwz r3,0x0(r3) // this is pte at last
1123 /* 1098 /*
1124 * if (!pte_present(pte)) 1099 * if (!pte_present(pte))
1125 * 1100 *
1126 */ 1101 */
1127 l.andi r4,r2,0x1 1102 l.andi r4,r3,0x1
1128 l.sfne r4,r0 // is pte present 1103 l.sfne r4,r0 // is pte present
1129 l.bnf i_pte_not_present 1104 l.bnf i_pte_not_present
1130 l.addi r3,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK 1105 l.addi r4,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK
1131 /* 1106 /*
1132 * fill ITLB TR register 1107 * fill ITLB TR register
1133 */ 1108 */
1134 l.and r4,r2,r3 // apply the mask 1109 l.and r4,r3,r4 // apply the mask
1135 l.andi r3,r2,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE 1110 l.andi r3,r3,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE
1136// l.andi r3,r2,0x400 // _PAGE_EXEC
1137 l.sfeq r3,r0 1111 l.sfeq r3,r0
1138 l.bf itlb_tr_fill //_workaround 1112 l.bf itlb_tr_fill //_workaround
1139 // Determine number of IMMU sets 1113 // Determine number of IMMU sets
1140 l.mfspr r6, r0, SPR_IMMUCFGR 1114 l.mfspr r2, r0, SPR_IMMUCFGR
1141 l.andi r6, r6, SPR_IMMUCFGR_NTS 1115 l.andi r2, r2, SPR_IMMUCFGR_NTS
1142 l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF 1116 l.srli r2, r2, SPR_IMMUCFGR_NTS_OFF
1143 l.ori r3, r0, 0x1 1117 l.ori r3, r0, 0x1
1144 l.sll r3, r3, r6 // r3 = number IMMU sets IMMUCFGR 1118 l.sll r3, r3, r2 // r3 = number IMMU sets IMMUCFGR
1145 l.addi r6, r3, -1 // r6 = nsets mask 1119 l.addi r2, r3, -1 // r2 = nsets mask
1146 l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1) 1120 l.mfspr r3, r0, SPR_EEAR_BASE
1121 l.srli r3, r3, 0xd // >> PAGE_SHIFT
1122 l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
1147 1123
1148/* 1124/*
1149 * __PHX__ :: fixme 1125 * __PHX__ :: fixme
@@ -1155,38 +1131,24 @@ i_pmd_good:
1155itlb_tr_fill_workaround: 1131itlb_tr_fill_workaround:
1156 l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE) 1132 l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE)
1157itlb_tr_fill: 1133itlb_tr_fill:
1158 l.mtspr r5,r4,SPR_ITLBTR_BASE(0) 1134 l.mtspr r2,r4,SPR_ITLBTR_BASE(0)
1159 /* 1135 /*
1160 * fill DTLB MR register 1136 * fill DTLB MR register
1161 */ 1137 */
1162 l.mfspr r2,r0,SPR_EEAR_BASE 1138 l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
1163 l.addi r3,r0,0xffffe000 // PAGE_MASK 1139 l.ori r4,r3,0x1 // set hardware valid bit: ITBL_MR entry
1164 l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?) 1140 l.mtspr r2,r4,SPR_ITLBMR_BASE(0)
1165 l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
1166 l.mtspr r5,r4,SPR_ITLBMR_BASE(0)
1167 1141
1168 EXCEPTION_LOAD_GPR2 1142 EXCEPTION_LOAD_GPR2
1169 EXCEPTION_LOAD_GPR3 1143 EXCEPTION_LOAD_GPR3
1170 EXCEPTION_LOAD_GPR4 1144 EXCEPTION_LOAD_GPR4
1171 EXCEPTION_LOAD_GPR5
1172 EXCEPTION_LOAD_GPR6
1173 l.rfe 1145 l.rfe
1174 1146
1175i_pmd_bad:
1176 l.nop 1
1177 EXCEPTION_LOAD_GPR2
1178 EXCEPTION_LOAD_GPR3
1179 EXCEPTION_LOAD_GPR4
1180 EXCEPTION_LOAD_GPR5
1181 EXCEPTION_LOAD_GPR6
1182 l.rfe
1183i_pmd_none: 1147i_pmd_none:
1184i_pte_not_present: 1148i_pte_not_present:
1185 EXCEPTION_LOAD_GPR2 1149 EXCEPTION_LOAD_GPR2
1186 EXCEPTION_LOAD_GPR3 1150 EXCEPTION_LOAD_GPR3
1187 EXCEPTION_LOAD_GPR4 1151 EXCEPTION_LOAD_GPR4
1188 EXCEPTION_LOAD_GPR5
1189 EXCEPTION_LOAD_GPR6
1190 EXCEPTION_HANDLE(_itlb_miss_page_fault_handler) 1152 EXCEPTION_HANDLE(_itlb_miss_page_fault_handler)
1191 1153
1192/* ==============================================[ boot tlb handlers ]=== */ 1154/* ==============================================[ boot tlb handlers ]=== */
@@ -1571,12 +1533,7 @@ ENTRY(_early_uart_init)
1571 l.jr r9 1533 l.jr r9
1572 l.nop 1534 l.nop
1573 1535
1574_string_copying_linux: 1536 .section .rodata
1575 .string "\n\n\n\n\n\rCopying Linux... \0"
1576
1577_string_ok_booting:
1578 .string "Ok, booting the kernel.\n\r\0"
1579
1580_string_unhandled_exception: 1537_string_unhandled_exception:
1581 .string "\n\rRunarunaround: Unhandled exception 0x\0" 1538 .string "\n\rRunarunaround: Unhandled exception 0x\0"
1582 1539
@@ -1586,11 +1543,6 @@ _string_epc_prefix:
1586_string_nl: 1543_string_nl:
1587 .string "\n\r\0" 1544 .string "\n\r\0"
1588 1545
1589 .global _string_esr_irq_bug
1590_string_esr_irq_bug:
1591 .string "\n\rESR external interrupt bug, for details look into entry.S\n\r\0"
1592
1593
1594 1546
1595/* ========================================[ page aligned structures ]=== */ 1547/* ========================================[ page aligned structures ]=== */
1596 1548
diff --git a/arch/openrisc/kernel/or32_ksyms.c b/arch/openrisc/kernel/or32_ksyms.c
index 86e31cf1de1d..5c4695d13542 100644
--- a/arch/openrisc/kernel/or32_ksyms.c
+++ b/arch/openrisc/kernel/or32_ksyms.c
@@ -44,3 +44,4 @@ DECLARE_EXPORT(__ashldi3);
44DECLARE_EXPORT(__lshrdi3); 44DECLARE_EXPORT(__lshrdi3);
45 45
46EXPORT_SYMBOL(__copy_tofrom_user); 46EXPORT_SYMBOL(__copy_tofrom_user);
47EXPORT_SYMBOL(memset);
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index d7990df9025a..6e9d1cb519f2 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -75,6 +75,17 @@ void machine_power_off(void)
75 __asm__("l.nop 1"); 75 __asm__("l.nop 1");
76} 76}
77 77
78/*
79 * Send the doze signal to the cpu if available.
80 * Make sure, that all interrupts are enabled
81 */
82void arch_cpu_idle(void)
83{
84 local_irq_enable();
85 if (mfspr(SPR_UPR) & SPR_UPR_PMP)
86 mtspr(SPR_PMR, mfspr(SPR_PMR) | SPR_PMR_DME);
87}
88
78void (*pm_power_off) (void) = machine_power_off; 89void (*pm_power_off) (void) = machine_power_off;
79 90
80/* 91/*
@@ -226,6 +237,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
226 237
227extern struct thread_info *_switch(struct thread_info *old_ti, 238extern struct thread_info *_switch(struct thread_info *old_ti,
228 struct thread_info *new_ti); 239 struct thread_info *new_ti);
240extern int lwa_flag;
229 241
230struct task_struct *__switch_to(struct task_struct *old, 242struct task_struct *__switch_to(struct task_struct *old,
231 struct task_struct *new) 243 struct task_struct *new)
@@ -243,6 +255,8 @@ struct task_struct *__switch_to(struct task_struct *old,
243 new_ti = new->stack; 255 new_ti = new->stack;
244 old_ti = old->stack; 256 old_ti = old->stack;
245 257
258 lwa_flag = 0;
259
246 current_thread_info_set[smp_processor_id()] = new_ti; 260 current_thread_info_set[smp_processor_id()] = new_ti;
247 last = (_switch(old_ti, new_ti))->task; 261 last = (_switch(old_ti, new_ti))->task;
248 262
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
index 4f59fa4e34e5..228288887d74 100644
--- a/arch/openrisc/kernel/ptrace.c
+++ b/arch/openrisc/kernel/ptrace.c
@@ -16,7 +16,6 @@
16 * 2 of the License, or (at your option) any later version. 16 * 2 of the License, or (at your option) any later version.
17 */ 17 */
18 18
19#include <stddef.h>
20#include <linux/kernel.h> 19#include <linux/kernel.h>
21#include <linux/sched.h> 20#include <linux/sched.h>
22#include <linux/string.h> 21#include <linux/string.h>
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
index cb797a3beb47..dbf5ee95a0d5 100644
--- a/arch/openrisc/kernel/setup.c
+++ b/arch/openrisc/kernel/setup.c
@@ -117,13 +117,15 @@ static void print_cpuinfo(void)
117 if (upr & SPR_UPR_DCP) 117 if (upr & SPR_UPR_DCP)
118 printk(KERN_INFO 118 printk(KERN_INFO
119 "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n", 119 "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n",
120 cpuinfo.dcache_size, cpuinfo.dcache_block_size, 1); 120 cpuinfo.dcache_size, cpuinfo.dcache_block_size,
121 cpuinfo.dcache_ways);
121 else 122 else
122 printk(KERN_INFO "-- dcache disabled\n"); 123 printk(KERN_INFO "-- dcache disabled\n");
123 if (upr & SPR_UPR_ICP) 124 if (upr & SPR_UPR_ICP)
124 printk(KERN_INFO 125 printk(KERN_INFO
125 "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n", 126 "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n",
126 cpuinfo.icache_size, cpuinfo.icache_block_size, 1); 127 cpuinfo.icache_size, cpuinfo.icache_block_size,
128 cpuinfo.icache_ways);
127 else 129 else
128 printk(KERN_INFO "-- icache disabled\n"); 130 printk(KERN_INFO "-- icache disabled\n");
129 131
@@ -155,25 +157,25 @@ void __init setup_cpuinfo(void)
155{ 157{
156 struct device_node *cpu; 158 struct device_node *cpu;
157 unsigned long iccfgr, dccfgr; 159 unsigned long iccfgr, dccfgr;
158 unsigned long cache_set_size, cache_ways; 160 unsigned long cache_set_size;
159 161
160 cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481"); 162 cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
161 if (!cpu) 163 if (!cpu)
162 panic("No compatible CPU found in device tree...\n"); 164 panic("No compatible CPU found in device tree...\n");
163 165
164 iccfgr = mfspr(SPR_ICCFGR); 166 iccfgr = mfspr(SPR_ICCFGR);
165 cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW); 167 cpuinfo.icache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
166 cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); 168 cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
167 cpuinfo.icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7); 169 cpuinfo.icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7);
168 cpuinfo.icache_size = 170 cpuinfo.icache_size =
169 cache_set_size * cache_ways * cpuinfo.icache_block_size; 171 cache_set_size * cpuinfo.icache_ways * cpuinfo.icache_block_size;
170 172
171 dccfgr = mfspr(SPR_DCCFGR); 173 dccfgr = mfspr(SPR_DCCFGR);
172 cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW); 174 cpuinfo.dcache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
173 cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); 175 cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
174 cpuinfo.dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7); 176 cpuinfo.dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7);
175 cpuinfo.dcache_size = 177 cpuinfo.dcache_size =
176 cache_set_size * cache_ways * cpuinfo.dcache_block_size; 178 cache_set_size * cpuinfo.dcache_ways * cpuinfo.dcache_block_size;
177 179
178 if (of_property_read_u32(cpu, "clock-frequency", 180 if (of_property_read_u32(cpu, "clock-frequency",
179 &cpuinfo.clock_frequency)) { 181 &cpuinfo.clock_frequency)) {
@@ -308,30 +310,33 @@ static int show_cpuinfo(struct seq_file *m, void *v)
308 revision = vr & SPR_VR_REV; 310 revision = vr & SPR_VR_REV;
309 311
310 seq_printf(m, 312 seq_printf(m,
311 "cpu\t\t: OpenRISC-%x\n" 313 "cpu\t\t: OpenRISC-%x\n"
312 "revision\t: %d\n" 314 "revision\t: %d\n"
313 "frequency\t: %ld\n" 315 "frequency\t: %ld\n"
314 "dcache size\t: %d bytes\n" 316 "dcache size\t: %d bytes\n"
315 "dcache block size\t: %d bytes\n" 317 "dcache block size\t: %d bytes\n"
316 "icache size\t: %d bytes\n" 318 "dcache ways\t: %d\n"
317 "icache block size\t: %d bytes\n" 319 "icache size\t: %d bytes\n"
318 "immu\t\t: %d entries, %lu ways\n" 320 "icache block size\t: %d bytes\n"
319 "dmmu\t\t: %d entries, %lu ways\n" 321 "icache ways\t: %d\n"
320 "bogomips\t: %lu.%02lu\n", 322 "immu\t\t: %d entries, %lu ways\n"
321 version, 323 "dmmu\t\t: %d entries, %lu ways\n"
322 revision, 324 "bogomips\t: %lu.%02lu\n",
323 loops_per_jiffy * HZ, 325 version,
324 cpuinfo.dcache_size, 326 revision,
325 cpuinfo.dcache_block_size, 327 loops_per_jiffy * HZ,
326 cpuinfo.icache_size, 328 cpuinfo.dcache_size,
327 cpuinfo.icache_block_size, 329 cpuinfo.dcache_block_size,
328 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2), 330 cpuinfo.dcache_ways,
329 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW), 331 cpuinfo.icache_size,
330 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2), 332 cpuinfo.icache_block_size,
331 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW), 333 cpuinfo.icache_ways,
332 (loops_per_jiffy * HZ) / 500000, 334 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
333 ((loops_per_jiffy * HZ) / 5000) % 100); 335 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW),
334 336 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
337 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW),
338 (loops_per_jiffy * HZ) / 500000,
339 ((loops_per_jiffy * HZ) / 5000) % 100);
335 return 0; 340 return 0;
336} 341}
337 342
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
index d29c41bfbffa..7e81ad258bca 100644
--- a/arch/openrisc/kernel/traps.c
+++ b/arch/openrisc/kernel/traps.c
@@ -40,6 +40,8 @@
40extern char _etext, _stext; 40extern char _etext, _stext;
41 41
42int kstack_depth_to_print = 0x180; 42int kstack_depth_to_print = 0x180;
43int lwa_flag;
44unsigned long __user *lwa_addr;
43 45
44static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) 46static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
45{ 47{
@@ -334,10 +336,191 @@ asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
334 } 336 }
335} 337}
336 338
339static inline int in_delay_slot(struct pt_regs *regs)
340{
341#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
342 /* No delay slot flag, do the old way */
343 unsigned int op, insn;
344
345 insn = *((unsigned int *)regs->pc);
346 op = insn >> 26;
347 switch (op) {
348 case 0x00: /* l.j */
349 case 0x01: /* l.jal */
350 case 0x03: /* l.bnf */
351 case 0x04: /* l.bf */
352 case 0x11: /* l.jr */
353 case 0x12: /* l.jalr */
354 return 1;
355 default:
356 return 0;
357 }
358#else
359 return regs->sr & SPR_SR_DSX;
360#endif
361}
362
363static inline void adjust_pc(struct pt_regs *regs, unsigned long address)
364{
365 int displacement;
366 unsigned int rb, op, jmp;
367
368 if (unlikely(in_delay_slot(regs))) {
369 /* In delay slot, instruction at pc is a branch, simulate it */
370 jmp = *((unsigned int *)regs->pc);
371
372 displacement = sign_extend32(((jmp) & 0x3ffffff) << 2, 27);
373 rb = (jmp & 0x0000ffff) >> 11;
374 op = jmp >> 26;
375
376 switch (op) {
377 case 0x00: /* l.j */
378 regs->pc += displacement;
379 return;
380 case 0x01: /* l.jal */
381 regs->pc += displacement;
382 regs->gpr[9] = regs->pc + 8;
383 return;
384 case 0x03: /* l.bnf */
385 if (regs->sr & SPR_SR_F)
386 regs->pc += 8;
387 else
388 regs->pc += displacement;
389 return;
390 case 0x04: /* l.bf */
391 if (regs->sr & SPR_SR_F)
392 regs->pc += displacement;
393 else
394 regs->pc += 8;
395 return;
396 case 0x11: /* l.jr */
397 regs->pc = regs->gpr[rb];
398 return;
399 case 0x12: /* l.jalr */
400 regs->pc = regs->gpr[rb];
401 regs->gpr[9] = regs->pc + 8;
402 return;
403 default:
404 break;
405 }
406 } else {
407 regs->pc += 4;
408 }
409}
410
411static inline void simulate_lwa(struct pt_regs *regs, unsigned long address,
412 unsigned int insn)
413{
414 unsigned int ra, rd;
415 unsigned long value;
416 unsigned long orig_pc;
417 long imm;
418
419 const struct exception_table_entry *entry;
420
421 orig_pc = regs->pc;
422 adjust_pc(regs, address);
423
424 ra = (insn >> 16) & 0x1f;
425 rd = (insn >> 21) & 0x1f;
426 imm = (short)insn;
427 lwa_addr = (unsigned long __user *)(regs->gpr[ra] + imm);
428
429 if ((unsigned long)lwa_addr & 0x3) {
430 do_unaligned_access(regs, address);
431 return;
432 }
433
434 if (get_user(value, lwa_addr)) {
435 if (user_mode(regs)) {
436 force_sig(SIGSEGV, current);
437 return;
438 }
439
440 if ((entry = search_exception_tables(orig_pc))) {
441 regs->pc = entry->fixup;
442 return;
443 }
444
445 /* kernel access in kernel space, load it directly */
446 value = *((unsigned long *)lwa_addr);
447 }
448
449 lwa_flag = 1;
450 regs->gpr[rd] = value;
451}
452
453static inline void simulate_swa(struct pt_regs *regs, unsigned long address,
454 unsigned int insn)
455{
456 unsigned long __user *vaddr;
457 unsigned long orig_pc;
458 unsigned int ra, rb;
459 long imm;
460
461 const struct exception_table_entry *entry;
462
463 orig_pc = regs->pc;
464 adjust_pc(regs, address);
465
466 ra = (insn >> 16) & 0x1f;
467 rb = (insn >> 11) & 0x1f;
468 imm = (short)(((insn & 0x2200000) >> 10) | (insn & 0x7ff));
469 vaddr = (unsigned long __user *)(regs->gpr[ra] + imm);
470
471 if (!lwa_flag || vaddr != lwa_addr) {
472 regs->sr &= ~SPR_SR_F;
473 return;
474 }
475
476 if ((unsigned long)vaddr & 0x3) {
477 do_unaligned_access(regs, address);
478 return;
479 }
480
481 if (put_user(regs->gpr[rb], vaddr)) {
482 if (user_mode(regs)) {
483 force_sig(SIGSEGV, current);
484 return;
485 }
486
487 if ((entry = search_exception_tables(orig_pc))) {
488 regs->pc = entry->fixup;
489 return;
490 }
491
492 /* kernel access in kernel space, store it directly */
493 *((unsigned long *)vaddr) = regs->gpr[rb];
494 }
495
496 lwa_flag = 0;
497 regs->sr |= SPR_SR_F;
498}
499
500#define INSN_LWA 0x1b
501#define INSN_SWA 0x33
502
337asmlinkage void do_illegal_instruction(struct pt_regs *regs, 503asmlinkage void do_illegal_instruction(struct pt_regs *regs,
338 unsigned long address) 504 unsigned long address)
339{ 505{
340 siginfo_t info; 506 siginfo_t info;
507 unsigned int op;
508 unsigned int insn = *((unsigned int *)address);
509
510 op = insn >> 26;
511
512 switch (op) {
513 case INSN_LWA:
514 simulate_lwa(regs, address, insn);
515 return;
516
517 case INSN_SWA:
518 simulate_swa(regs, address, insn);
519 return;
520
521 default:
522 break;
523 }
341 524
342 if (user_mode(regs)) { 525 if (user_mode(regs)) {
343 /* Send a SIGILL */ 526 /* Send a SIGILL */
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
index 966f65dbc6f0..17d9d37f32d2 100644
--- a/arch/openrisc/lib/Makefile
+++ b/arch/openrisc/lib/Makefile
@@ -2,4 +2,4 @@
2# Makefile for or32 specific library files.. 2# Makefile for or32 specific library files..
3# 3#
4 4
5obj-y = string.o delay.o 5obj-y := delay.o string.o memset.o memcpy.o
diff --git a/arch/openrisc/lib/memcpy.c b/arch/openrisc/lib/memcpy.c
new file mode 100644
index 000000000000..669887a60e27
--- /dev/null
+++ b/arch/openrisc/lib/memcpy.c
@@ -0,0 +1,124 @@
1/*
2 * arch/openrisc/lib/memcpy.c
3 *
4 * Optimized memory copy routines for openrisc. These are mostly copied
5 * from ohter sources but slightly entended based on ideas discuassed in
6 * #openrisc.
7 *
8 * The word unroll implementation is an extension to the arm byte
9 * unrolled implementation, but using word copies (if things are
10 * properly aligned)
11 *
12 * The great arm loop unroll algorithm can be found at:
13 * arch/arm/boot/compressed/string.c
14 */
15
16#include <linux/export.h>
17
18#include <linux/string.h>
19
20#ifdef CONFIG_OR1K_1200
21/*
22 * Do memcpy with word copies and loop unrolling. This gives the
23 * best performance on the OR1200 and MOR1KX archirectures
24 */
25void *memcpy(void *dest, __const void *src, __kernel_size_t n)
26{
27 int i = 0;
28 unsigned char *d, *s;
29 uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src;
30
31 /* If both source and dest are word aligned copy words */
32 if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) {
33 /* Copy 32 bytes per loop */
34 for (i = n >> 5; i > 0; i--) {
35 *dest_w++ = *src_w++;
36 *dest_w++ = *src_w++;
37 *dest_w++ = *src_w++;
38 *dest_w++ = *src_w++;
39 *dest_w++ = *src_w++;
40 *dest_w++ = *src_w++;
41 *dest_w++ = *src_w++;
42 *dest_w++ = *src_w++;
43 }
44
45 if (n & 1 << 4) {
46 *dest_w++ = *src_w++;
47 *dest_w++ = *src_w++;
48 *dest_w++ = *src_w++;
49 *dest_w++ = *src_w++;
50 }
51
52 if (n & 1 << 3) {
53 *dest_w++ = *src_w++;
54 *dest_w++ = *src_w++;
55 }
56
57 if (n & 1 << 2)
58 *dest_w++ = *src_w++;
59
60 d = (unsigned char *)dest_w;
61 s = (unsigned char *)src_w;
62
63 } else {
64 d = (unsigned char *)dest_w;
65 s = (unsigned char *)src_w;
66
67 for (i = n >> 3; i > 0; i--) {
68 *d++ = *s++;
69 *d++ = *s++;
70 *d++ = *s++;
71 *d++ = *s++;
72 *d++ = *s++;
73 *d++ = *s++;
74 *d++ = *s++;
75 *d++ = *s++;
76 }
77
78 if (n & 1 << 2) {
79 *d++ = *s++;
80 *d++ = *s++;
81 *d++ = *s++;
82 *d++ = *s++;
83 }
84 }
85
86 if (n & 1 << 1) {
87 *d++ = *s++;
88 *d++ = *s++;
89 }
90
91 if (n & 1)
92 *d++ = *s++;
93
94 return dest;
95}
96#else
97/*
98 * Use word copies but no loop unrolling as we cannot assume there
99 * will be benefits on the archirecture
100 */
101void *memcpy(void *dest, __const void *src, __kernel_size_t n)
102{
103 unsigned char *d = (unsigned char *)dest, *s = (unsigned char *)src;
104 uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src;
105
106 /* If both source and dest are word aligned copy words */
107 if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) {
108 for (; n >= 4; n -= 4)
109 *dest_w++ = *src_w++;
110 }
111
112 d = (unsigned char *)dest_w;
113 s = (unsigned char *)src_w;
114
115 /* For remaining or if not aligned, copy bytes */
116 for (; n >= 1; n -= 1)
117 *d++ = *s++;
118
119 return dest;
120
121}
122#endif
123
124EXPORT_SYMBOL(memcpy);
diff --git a/arch/openrisc/lib/memset.S b/arch/openrisc/lib/memset.S
new file mode 100644
index 000000000000..92cc2eac26fa
--- /dev/null
+++ b/arch/openrisc/lib/memset.S
@@ -0,0 +1,98 @@
1/*
2 * OpenRISC memset.S
3 *
4 * Hand-optimized assembler version of memset for OpenRISC.
5 * Algorithm inspired by several other arch-specific memset routines
6 * in the kernel tree
7 *
8 * Copyright (C) 2015 Olof Kindgren <olof.kindgren@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16 .global memset
17 .type memset, @function
18memset:
19 /* arguments:
20 * r3 = *s
21 * r4 = c
22 * r5 = n
23 * r13, r15, r17, r19 used as temp regs
24 */
25
26 /* Exit if n == 0 */
27 l.sfeqi r5, 0
28 l.bf 4f
29
30 /* Truncate c to char */
31 l.andi r13, r4, 0xff
32
33 /* Skip word extension if c is 0 */
34 l.sfeqi r13, 0
35 l.bf 1f
36 /* Check for at least two whole words (8 bytes) */
37 l.sfleui r5, 7
38
39 /* Extend char c to 32-bit word cccc in r13 */
40 l.slli r15, r13, 16 // r13 = 000c, r15 = 0c00
41 l.or r13, r13, r15 // r13 = 0c0c, r15 = 0c00
42 l.slli r15, r13, 8 // r13 = 0c0c, r15 = c0c0
43 l.or r13, r13, r15 // r13 = cccc, r15 = c0c0
44
451: l.addi r19, r3, 0 // Set r19 = src
46 /* Jump to byte copy loop if less than two words */
47 l.bf 3f
48 l.or r17, r5, r0 // Set r17 = n
49
50 /* Mask out two LSBs to check alignment */
51 l.andi r15, r3, 0x3
52
53 /* lsb == 00, jump to word copy loop */
54 l.sfeqi r15, 0
55 l.bf 2f
56 l.addi r19, r3, 0 // Set r19 = src
57
58 /* lsb == 01,10 or 11 */
59 l.sb 0(r3), r13 // *src = c
60 l.addi r17, r17, -1 // Decrease n
61
62 l.sfeqi r15, 3
63 l.bf 2f
64 l.addi r19, r3, 1 // src += 1
65
66 /* lsb == 01 or 10 */
67 l.sb 1(r3), r13 // *(src+1) = c
68 l.addi r17, r17, -1 // Decrease n
69
70 l.sfeqi r15, 2
71 l.bf 2f
72 l.addi r19, r3, 2 // src += 2
73
74 /* lsb == 01 */
75 l.sb 2(r3), r13 // *(src+2) = c
76 l.addi r17, r17, -1 // Decrease n
77 l.addi r19, r3, 3 // src += 3
78
79 /* Word copy loop */
802: l.sw 0(r19), r13 // *src = cccc
81 l.addi r17, r17, -4 // Decrease n
82 l.sfgeui r17, 4
83 l.bf 2b
84 l.addi r19, r19, 4 // Increase src
85
86 /* When n > 0, copy the remaining bytes, otherwise jump to exit */
87 l.sfeqi r17, 0
88 l.bf 4f
89
90 /* Byte copy loop */
913: l.addi r17, r17, -1 // Decrease n
92 l.sb 0(r19), r13 // *src = cccc
93 l.sfnei r17, 0
94 l.bf 3b
95 l.addi r19, r19, 1 // Increase src
96
974: l.jr r9
98 l.ori r11, r3, 0
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
index 8705a46218f9..2175e4bfd9fc 100644
--- a/arch/openrisc/mm/ioremap.c
+++ b/arch/openrisc/mm/ioremap.c
@@ -80,6 +80,7 @@ __ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
80 80
81 return (void __iomem *)(offset + (char *)v); 81 return (void __iomem *)(offset + (char *)v);
82} 82}
83EXPORT_SYMBOL(__ioremap);
83 84
84void iounmap(void *addr) 85void iounmap(void *addr)
85{ 86{
@@ -106,6 +107,7 @@ void iounmap(void *addr)
106 107
107 return vfree((void *)(PAGE_MASK & (unsigned long)addr)); 108 return vfree((void *)(PAGE_MASK & (unsigned long)addr));
108} 109}
110EXPORT_SYMBOL(iounmap);
109 111
110/** 112/**
111 * OK, this one's a bit tricky... ioremap can get called before memory is 113 * OK, this one's a bit tricky... ioremap can get called before memory is
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 9ed8b987185b..3f38eb03649c 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -223,6 +223,7 @@ static inline void atomic_dec(atomic_t *v)
223#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v))) 223#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
224#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) 224#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
225 225
226#ifndef __atomic_add_unless
226static inline int __atomic_add_unless(atomic_t *v, int a, int u) 227static inline int __atomic_add_unless(atomic_t *v, int a, int u)
227{ 228{
228 int c, old; 229 int c, old;
@@ -231,5 +232,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
231 c = old; 232 c = old;
232 return c; 233 return c;
233} 234}
235#endif
234 236
235#endif /* __ASM_GENERIC_ATOMIC_H */ 237#endif /* __ASM_GENERIC_ATOMIC_H */
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 694a075381b0..3033be701e9a 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -81,6 +81,9 @@ my (@stack, $re, $dre, $x, $xs, $funcre);
81 } elsif ($arch eq 'nios2') { 81 } elsif ($arch eq 'nios2') {
82 #25a8: defffb04 addi sp,sp,-20 82 #25a8: defffb04 addi sp,sp,-20
83 $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; 83 $re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;
84 } elsif ($arch eq 'openrisc') {
85 # c000043c: 9c 21 fe f0 l.addi r1,r1,-272
86 $re = qr/.*l\.addi.*r1,r1,-(([0-9]{2}|[3-9])[0-9]{2})/o;
84 } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { 87 } elsif ($arch eq 'parisc' || $arch eq 'parisc64') {
85 $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; 88 $re = qr/.*ldo ($x{1,8})\(sp\),sp/o;
86 } elsif ($arch eq 'ppc') { 89 } elsif ($arch eq 'ppc') {