aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm64/memory.txt2
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/Kconfig.debug17
-rw-r--r--arch/arm64/include/asm/Kbuild2
-rw-r--r--arch/arm64/include/asm/atomic.h132
-rw-r--r--arch/arm64/include/asm/cmpxchg.h74
-rw-r--r--arch/arm64/include/asm/futex.h2
-rw-r--r--arch/arm64/include/asm/io.h3
-rw-r--r--arch/arm64/include/asm/memory.h1
-rw-r--r--arch/arm64/include/asm/mmu.h1
-rw-r--r--arch/arm64/include/asm/mmu_context.h15
-rw-r--r--arch/arm64/include/asm/perf_event.h7
-rw-r--r--arch/arm64/include/asm/psci.h38
-rw-r--r--arch/arm64/include/asm/ptrace.h10
-rw-r--r--arch/arm64/include/asm/smp.h11
-rw-r--r--arch/arm64/include/asm/spinlock.h78
-rw-r--r--arch/arm64/include/uapi/asm/Kbuild3
-rw-r--r--arch/arm64/kernel/Makefile5
-rw-r--r--arch/arm64/kernel/early_printk.c118
-rw-r--r--arch/arm64/kernel/head.S12
-rw-r--r--arch/arm64/kernel/perf_event.c37
-rw-r--r--arch/arm64/kernel/process.c4
-rw-r--r--arch/arm64/kernel/psci.c211
-rw-r--r--arch/arm64/kernel/setup.c11
-rw-r--r--arch/arm64/kernel/signal32.c4
-rw-r--r--arch/arm64/kernel/smp.c69
-rw-r--r--arch/arm64/kernel/smp_psci.c52
-rw-r--r--arch/arm64/kernel/smp_spin_table.c66
-rw-r--r--arch/arm64/mm/mmu.c42
29 files changed, 855 insertions, 173 deletions
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index d758702fc03c..5f583af0a6e1 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -35,6 +35,8 @@ ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
35 35
36ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] 36ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
37 37
38ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device
39
38ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space 40ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space
39 41
40ffffffbbffff0000 ffffffbcffffffff ~2MB [guard] 42ffffffbbffff0000 ffffffbcffffffff ~2MB [guard]
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 75e915b72471..7c43569e3141 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
2 def_bool y 2 def_bool y
3 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE 3 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
4 select ARCH_WANT_COMPAT_IPC_PARSE_VERSION 4 select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
5 select ARCH_WANT_FRAME_POINTERS
5 select ARM_AMBA 6 select ARM_AMBA
6 select CLONE_BACKWARDS 7 select CLONE_BACKWARDS
7 select COMMON_CLK 8 select COMMON_CLK
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index d7553f2bda66..51493430f142 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -24,4 +24,21 @@ config DEBUG_STACK_USAGE
24 Enables the display of the minimum amount of free stack which each 24 Enables the display of the minimum amount of free stack which each
25 task has ever had available in the sysrq-T output. 25 task has ever had available in the sysrq-T output.
26 26
27config EARLY_PRINTK
28 bool "Early printk support"
29 default y
30 help
31 Say Y here if you want to have an early console using the
32 earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
33 is assumed that the early console device has been initialised
34 by the boot loader prior to starting the Linux kernel.
35
36config PID_IN_CONTEXTIDR
37 bool "Write the current PID to the CONTEXTIDR register"
38 help
39 Enabling this option causes the kernel to write the current PID to
40 the CONTEXTIDR register, at the expense of some additional
41 instructions during context switch. Say Y here only if you are
42 planning to use hardware trace tools with this kernel.
43
27endmenu 44endmenu
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 14a9d5a2b85b..e5fe4f99fe10 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -19,6 +19,7 @@ generic-y += ipcbuf.h
19generic-y += irq_regs.h 19generic-y += irq_regs.h
20generic-y += kdebug.h 20generic-y += kdebug.h
21generic-y += kmap_types.h 21generic-y += kmap_types.h
22generic-y += kvm_para.h
22generic-y += local.h 23generic-y += local.h
23generic-y += local64.h 24generic-y += local64.h
24generic-y += mman.h 25generic-y += mman.h
@@ -48,3 +49,4 @@ generic-y += trace_clock.h
48generic-y += types.h 49generic-y += types.h
49generic-y += unaligned.h 50generic-y += unaligned.h
50generic-y += user.h 51generic-y += user.h
52generic-y += xor.h
diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h
index 407717ba060e..836364468571 100644
--- a/arch/arm64/include/asm/atomic.h
+++ b/arch/arm64/include/asm/atomic.h
@@ -49,12 +49,12 @@ static inline void atomic_add(int i, atomic_t *v)
49 int result; 49 int result;
50 50
51 asm volatile("// atomic_add\n" 51 asm volatile("// atomic_add\n"
52"1: ldxr %w0, [%3]\n" 52"1: ldxr %w0, %2\n"
53" add %w0, %w0, %w4\n" 53" add %w0, %w0, %w3\n"
54" stxr %w1, %w0, [%3]\n" 54" stxr %w1, %w0, %2\n"
55" cbnz %w1, 1b" 55" cbnz %w1, 1b"
56 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 56 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
57 : "r" (&v->counter), "Ir" (i) 57 : "Ir" (i)
58 : "cc"); 58 : "cc");
59} 59}
60 60
@@ -64,13 +64,13 @@ static inline int atomic_add_return(int i, atomic_t *v)
64 int result; 64 int result;
65 65
66 asm volatile("// atomic_add_return\n" 66 asm volatile("// atomic_add_return\n"
67"1: ldaxr %w0, [%3]\n" 67"1: ldaxr %w0, %2\n"
68" add %w0, %w0, %w4\n" 68" add %w0, %w0, %w3\n"
69" stlxr %w1, %w0, [%3]\n" 69" stlxr %w1, %w0, %2\n"
70" cbnz %w1, 1b" 70" cbnz %w1, 1b"
71 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 71 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
72 : "r" (&v->counter), "Ir" (i) 72 : "Ir" (i)
73 : "cc"); 73 : "cc", "memory");
74 74
75 return result; 75 return result;
76} 76}
@@ -81,12 +81,12 @@ static inline void atomic_sub(int i, atomic_t *v)
81 int result; 81 int result;
82 82
83 asm volatile("// atomic_sub\n" 83 asm volatile("// atomic_sub\n"
84"1: ldxr %w0, [%3]\n" 84"1: ldxr %w0, %2\n"
85" sub %w0, %w0, %w4\n" 85" sub %w0, %w0, %w3\n"
86" stxr %w1, %w0, [%3]\n" 86" stxr %w1, %w0, %2\n"
87" cbnz %w1, 1b" 87" cbnz %w1, 1b"
88 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 88 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
89 : "r" (&v->counter), "Ir" (i) 89 : "Ir" (i)
90 : "cc"); 90 : "cc");
91} 91}
92 92
@@ -96,13 +96,13 @@ static inline int atomic_sub_return(int i, atomic_t *v)
96 int result; 96 int result;
97 97
98 asm volatile("// atomic_sub_return\n" 98 asm volatile("// atomic_sub_return\n"
99"1: ldaxr %w0, [%3]\n" 99"1: ldaxr %w0, %2\n"
100" sub %w0, %w0, %w4\n" 100" sub %w0, %w0, %w3\n"
101" stlxr %w1, %w0, [%3]\n" 101" stlxr %w1, %w0, %2\n"
102" cbnz %w1, 1b" 102" cbnz %w1, 1b"
103 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 103 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
104 : "r" (&v->counter), "Ir" (i) 104 : "Ir" (i)
105 : "cc"); 105 : "cc", "memory");
106 106
107 return result; 107 return result;
108} 108}
@@ -113,15 +113,15 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
113 int oldval; 113 int oldval;
114 114
115 asm volatile("// atomic_cmpxchg\n" 115 asm volatile("// atomic_cmpxchg\n"
116"1: ldaxr %w1, [%3]\n" 116"1: ldaxr %w1, %2\n"
117" cmp %w1, %w4\n" 117" cmp %w1, %w3\n"
118" b.ne 2f\n" 118" b.ne 2f\n"
119" stlxr %w0, %w5, [%3]\n" 119" stlxr %w0, %w4, %2\n"
120" cbnz %w0, 1b\n" 120" cbnz %w0, 1b\n"
121"2:" 121"2:"
122 : "=&r" (tmp), "=&r" (oldval), "+o" (ptr->counter) 122 : "=&r" (tmp), "=&r" (oldval), "+Q" (ptr->counter)
123 : "r" (&ptr->counter), "Ir" (old), "r" (new) 123 : "Ir" (old), "r" (new)
124 : "cc"); 124 : "cc", "memory");
125 125
126 return oldval; 126 return oldval;
127} 127}
@@ -131,12 +131,12 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
131 unsigned long tmp, tmp2; 131 unsigned long tmp, tmp2;
132 132
133 asm volatile("// atomic_clear_mask\n" 133 asm volatile("// atomic_clear_mask\n"
134"1: ldxr %0, [%3]\n" 134"1: ldxr %0, %2\n"
135" bic %0, %0, %4\n" 135" bic %0, %0, %3\n"
136" stxr %w1, %0, [%3]\n" 136" stxr %w1, %0, %2\n"
137" cbnz %w1, 1b" 137" cbnz %w1, 1b"
138 : "=&r" (tmp), "=&r" (tmp2), "+o" (*addr) 138 : "=&r" (tmp), "=&r" (tmp2), "+Q" (*addr)
139 : "r" (addr), "Ir" (mask) 139 : "Ir" (mask)
140 : "cc"); 140 : "cc");
141} 141}
142 142
@@ -182,12 +182,12 @@ static inline void atomic64_add(u64 i, atomic64_t *v)
182 unsigned long tmp; 182 unsigned long tmp;
183 183
184 asm volatile("// atomic64_add\n" 184 asm volatile("// atomic64_add\n"
185"1: ldxr %0, [%3]\n" 185"1: ldxr %0, %2\n"
186" add %0, %0, %4\n" 186" add %0, %0, %3\n"
187" stxr %w1, %0, [%3]\n" 187" stxr %w1, %0, %2\n"
188" cbnz %w1, 1b" 188" cbnz %w1, 1b"
189 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 189 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
190 : "r" (&v->counter), "Ir" (i) 190 : "Ir" (i)
191 : "cc"); 191 : "cc");
192} 192}
193 193
@@ -197,13 +197,13 @@ static inline long atomic64_add_return(long i, atomic64_t *v)
197 unsigned long tmp; 197 unsigned long tmp;
198 198
199 asm volatile("// atomic64_add_return\n" 199 asm volatile("// atomic64_add_return\n"
200"1: ldaxr %0, [%3]\n" 200"1: ldaxr %0, %2\n"
201" add %0, %0, %4\n" 201" add %0, %0, %3\n"
202" stlxr %w1, %0, [%3]\n" 202" stlxr %w1, %0, %2\n"
203" cbnz %w1, 1b" 203" cbnz %w1, 1b"
204 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 204 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
205 : "r" (&v->counter), "Ir" (i) 205 : "Ir" (i)
206 : "cc"); 206 : "cc", "memory");
207 207
208 return result; 208 return result;
209} 209}
@@ -214,12 +214,12 @@ static inline void atomic64_sub(u64 i, atomic64_t *v)
214 unsigned long tmp; 214 unsigned long tmp;
215 215
216 asm volatile("// atomic64_sub\n" 216 asm volatile("// atomic64_sub\n"
217"1: ldxr %0, [%3]\n" 217"1: ldxr %0, %2\n"
218" sub %0, %0, %4\n" 218" sub %0, %0, %3\n"
219" stxr %w1, %0, [%3]\n" 219" stxr %w1, %0, %2\n"
220" cbnz %w1, 1b" 220" cbnz %w1, 1b"
221 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 221 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
222 : "r" (&v->counter), "Ir" (i) 222 : "Ir" (i)
223 : "cc"); 223 : "cc");
224} 224}
225 225
@@ -229,13 +229,13 @@ static inline long atomic64_sub_return(long i, atomic64_t *v)
229 unsigned long tmp; 229 unsigned long tmp;
230 230
231 asm volatile("// atomic64_sub_return\n" 231 asm volatile("// atomic64_sub_return\n"
232"1: ldaxr %0, [%3]\n" 232"1: ldaxr %0, %2\n"
233" sub %0, %0, %4\n" 233" sub %0, %0, %3\n"
234" stlxr %w1, %0, [%3]\n" 234" stlxr %w1, %0, %2\n"
235" cbnz %w1, 1b" 235" cbnz %w1, 1b"
236 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 236 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
237 : "r" (&v->counter), "Ir" (i) 237 : "Ir" (i)
238 : "cc"); 238 : "cc", "memory");
239 239
240 return result; 240 return result;
241} 241}
@@ -246,15 +246,15 @@ static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new)
246 unsigned long res; 246 unsigned long res;
247 247
248 asm volatile("// atomic64_cmpxchg\n" 248 asm volatile("// atomic64_cmpxchg\n"
249"1: ldaxr %1, [%3]\n" 249"1: ldaxr %1, %2\n"
250" cmp %1, %4\n" 250" cmp %1, %3\n"
251" b.ne 2f\n" 251" b.ne 2f\n"
252" stlxr %w0, %5, [%3]\n" 252" stlxr %w0, %4, %2\n"
253" cbnz %w0, 1b\n" 253" cbnz %w0, 1b\n"
254"2:" 254"2:"
255 : "=&r" (res), "=&r" (oldval), "+o" (ptr->counter) 255 : "=&r" (res), "=&r" (oldval), "+Q" (ptr->counter)
256 : "r" (&ptr->counter), "Ir" (old), "r" (new) 256 : "Ir" (old), "r" (new)
257 : "cc"); 257 : "cc", "memory");
258 258
259 return oldval; 259 return oldval;
260} 260}
@@ -267,15 +267,15 @@ static inline long atomic64_dec_if_positive(atomic64_t *v)
267 unsigned long tmp; 267 unsigned long tmp;
268 268
269 asm volatile("// atomic64_dec_if_positive\n" 269 asm volatile("// atomic64_dec_if_positive\n"
270"1: ldaxr %0, [%3]\n" 270"1: ldaxr %0, %2\n"
271" subs %0, %0, #1\n" 271" subs %0, %0, #1\n"
272" b.mi 2f\n" 272" b.mi 2f\n"
273" stlxr %w1, %0, [%3]\n" 273" stlxr %w1, %0, %2\n"
274" cbnz %w1, 1b\n" 274" cbnz %w1, 1b\n"
275"2:" 275"2:"
276 : "=&r" (result), "=&r" (tmp), "+o" (v->counter) 276 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
277 : "r" (&v->counter) 277 :
278 : "cc"); 278 : "cc", "memory");
279 279
280 return result; 280 return result;
281} 281}
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
index e0e65b069d9e..968b5cbfc260 100644
--- a/arch/arm64/include/asm/cmpxchg.h
+++ b/arch/arm64/include/asm/cmpxchg.h
@@ -29,39 +29,39 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
29 switch (size) { 29 switch (size) {
30 case 1: 30 case 1:
31 asm volatile("// __xchg1\n" 31 asm volatile("// __xchg1\n"
32 "1: ldaxrb %w0, [%3]\n" 32 "1: ldaxrb %w0, %2\n"
33 " stlxrb %w1, %w2, [%3]\n" 33 " stlxrb %w1, %w3, %2\n"
34 " cbnz %w1, 1b\n" 34 " cbnz %w1, 1b\n"
35 : "=&r" (ret), "=&r" (tmp) 35 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
36 : "r" (x), "r" (ptr) 36 : "r" (x)
37 : "memory", "cc"); 37 : "cc", "memory");
38 break; 38 break;
39 case 2: 39 case 2:
40 asm volatile("// __xchg2\n" 40 asm volatile("// __xchg2\n"
41 "1: ldaxrh %w0, [%3]\n" 41 "1: ldaxrh %w0, %2\n"
42 " stlxrh %w1, %w2, [%3]\n" 42 " stlxrh %w1, %w3, %2\n"
43 " cbnz %w1, 1b\n" 43 " cbnz %w1, 1b\n"
44 : "=&r" (ret), "=&r" (tmp) 44 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
45 : "r" (x), "r" (ptr) 45 : "r" (x)
46 : "memory", "cc"); 46 : "cc", "memory");
47 break; 47 break;
48 case 4: 48 case 4:
49 asm volatile("// __xchg4\n" 49 asm volatile("// __xchg4\n"
50 "1: ldaxr %w0, [%3]\n" 50 "1: ldaxr %w0, %2\n"
51 " stlxr %w1, %w2, [%3]\n" 51 " stlxr %w1, %w3, %2\n"
52 " cbnz %w1, 1b\n" 52 " cbnz %w1, 1b\n"
53 : "=&r" (ret), "=&r" (tmp) 53 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
54 : "r" (x), "r" (ptr) 54 : "r" (x)
55 : "memory", "cc"); 55 : "cc", "memory");
56 break; 56 break;
57 case 8: 57 case 8:
58 asm volatile("// __xchg8\n" 58 asm volatile("// __xchg8\n"
59 "1: ldaxr %0, [%3]\n" 59 "1: ldaxr %0, %2\n"
60 " stlxr %w1, %2, [%3]\n" 60 " stlxr %w1, %3, %2\n"
61 " cbnz %w1, 1b\n" 61 " cbnz %w1, 1b\n"
62 : "=&r" (ret), "=&r" (tmp) 62 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
63 : "r" (x), "r" (ptr) 63 : "r" (x)
64 : "memory", "cc"); 64 : "cc", "memory");
65 break; 65 break;
66 default: 66 default:
67 BUILD_BUG(); 67 BUILD_BUG();
@@ -82,14 +82,14 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
82 case 1: 82 case 1:
83 do { 83 do {
84 asm volatile("// __cmpxchg1\n" 84 asm volatile("// __cmpxchg1\n"
85 " ldxrb %w1, [%2]\n" 85 " ldxrb %w1, %2\n"
86 " mov %w0, #0\n" 86 " mov %w0, #0\n"
87 " cmp %w1, %w3\n" 87 " cmp %w1, %w3\n"
88 " b.ne 1f\n" 88 " b.ne 1f\n"
89 " stxrb %w0, %w4, [%2]\n" 89 " stxrb %w0, %w4, %2\n"
90 "1:\n" 90 "1:\n"
91 : "=&r" (res), "=&r" (oldval) 91 : "=&r" (res), "=&r" (oldval), "+Q" (*(u8 *)ptr)
92 : "r" (ptr), "Ir" (old), "r" (new) 92 : "Ir" (old), "r" (new)
93 : "cc"); 93 : "cc");
94 } while (res); 94 } while (res);
95 break; 95 break;
@@ -97,29 +97,29 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
97 case 2: 97 case 2:
98 do { 98 do {
99 asm volatile("// __cmpxchg2\n" 99 asm volatile("// __cmpxchg2\n"
100 " ldxrh %w1, [%2]\n" 100 " ldxrh %w1, %2\n"
101 " mov %w0, #0\n" 101 " mov %w0, #0\n"
102 " cmp %w1, %w3\n" 102 " cmp %w1, %w3\n"
103 " b.ne 1f\n" 103 " b.ne 1f\n"
104 " stxrh %w0, %w4, [%2]\n" 104 " stxrh %w0, %w4, %2\n"
105 "1:\n" 105 "1:\n"
106 : "=&r" (res), "=&r" (oldval) 106 : "=&r" (res), "=&r" (oldval), "+Q" (*(u16 *)ptr)
107 : "r" (ptr), "Ir" (old), "r" (new) 107 : "Ir" (old), "r" (new)
108 : "memory", "cc"); 108 : "cc");
109 } while (res); 109 } while (res);
110 break; 110 break;
111 111
112 case 4: 112 case 4:
113 do { 113 do {
114 asm volatile("// __cmpxchg4\n" 114 asm volatile("// __cmpxchg4\n"
115 " ldxr %w1, [%2]\n" 115 " ldxr %w1, %2\n"
116 " mov %w0, #0\n" 116 " mov %w0, #0\n"
117 " cmp %w1, %w3\n" 117 " cmp %w1, %w3\n"
118 " b.ne 1f\n" 118 " b.ne 1f\n"
119 " stxr %w0, %w4, [%2]\n" 119 " stxr %w0, %w4, %2\n"
120 "1:\n" 120 "1:\n"
121 : "=&r" (res), "=&r" (oldval) 121 : "=&r" (res), "=&r" (oldval), "+Q" (*(u32 *)ptr)
122 : "r" (ptr), "Ir" (old), "r" (new) 122 : "Ir" (old), "r" (new)
123 : "cc"); 123 : "cc");
124 } while (res); 124 } while (res);
125 break; 125 break;
@@ -127,14 +127,14 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
127 case 8: 127 case 8:
128 do { 128 do {
129 asm volatile("// __cmpxchg8\n" 129 asm volatile("// __cmpxchg8\n"
130 " ldxr %1, [%2]\n" 130 " ldxr %1, %2\n"
131 " mov %w0, #0\n" 131 " mov %w0, #0\n"
132 " cmp %1, %3\n" 132 " cmp %1, %3\n"
133 " b.ne 1f\n" 133 " b.ne 1f\n"
134 " stxr %w0, %4, [%2]\n" 134 " stxr %w0, %4, %2\n"
135 "1:\n" 135 "1:\n"
136 : "=&r" (res), "=&r" (oldval) 136 : "=&r" (res), "=&r" (oldval), "+Q" (*(u64 *)ptr)
137 : "r" (ptr), "Ir" (old), "r" (new) 137 : "Ir" (old), "r" (new)
138 : "cc"); 138 : "cc");
139 } while (res); 139 } while (res);
140 break; 140 break;
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index 3468ae8439fa..c582fa316366 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -39,7 +39,7 @@
39" .popsection\n" \ 39" .popsection\n" \
40 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ 40 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \
41 : "r" (oparg), "Ir" (-EFAULT) \ 41 : "r" (oparg), "Ir" (-EFAULT) \
42 : "cc") 42 : "cc", "memory")
43 43
44static inline int 44static inline int
45futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 45futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index d2f05a608274..57f12c991de2 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -230,6 +230,9 @@ extern void __iounmap(volatile void __iomem *addr);
230#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) 230#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
231#define iounmap __iounmap 231#define iounmap __iounmap
232 232
233#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF)
234#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PTE_PXN | PTE_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
235
233#define ARCH_HAS_IOREMAP_WC 236#define ARCH_HAS_IOREMAP_WC
234#include <asm-generic/iomap.h> 237#include <asm-generic/iomap.h>
235 238
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 1cac16a001cb..381f556b664e 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -43,6 +43,7 @@
43#define PAGE_OFFSET UL(0xffffffc000000000) 43#define PAGE_OFFSET UL(0xffffffc000000000)
44#define MODULES_END (PAGE_OFFSET) 44#define MODULES_END (PAGE_OFFSET)
45#define MODULES_VADDR (MODULES_END - SZ_64M) 45#define MODULES_VADDR (MODULES_END - SZ_64M)
46#define EARLYCON_IOBASE (MODULES_VADDR - SZ_4M)
46#define VA_BITS (39) 47#define VA_BITS (39)
47#define TASK_SIZE_64 (UL(1) << VA_BITS) 48#define TASK_SIZE_64 (UL(1) << VA_BITS)
48 49
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index d4f7fd5b9e33..2494fc01896a 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -26,5 +26,6 @@ typedef struct {
26 26
27extern void paging_init(void); 27extern void paging_init(void);
28extern void setup_mm_for_reboot(void); 28extern void setup_mm_for_reboot(void);
29extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
29 30
30#endif 31#endif
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index f68465dee026..e2bc385adb6b 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -35,6 +35,21 @@ extern unsigned int cpu_last_asid;
35void __init_new_context(struct task_struct *tsk, struct mm_struct *mm); 35void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
36void __new_context(struct mm_struct *mm); 36void __new_context(struct mm_struct *mm);
37 37
38#ifdef CONFIG_PID_IN_CONTEXTIDR
39static inline void contextidr_thread_switch(struct task_struct *next)
40{
41 asm(
42 " msr contextidr_el1, %0\n"
43 " isb"
44 :
45 : "r" (task_pid_nr(next)));
46}
47#else
48static inline void contextidr_thread_switch(struct task_struct *next)
49{
50}
51#endif
52
38/* 53/*
39 * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0. 54 * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0.
40 */ 55 */
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index a6fffd511c5e..d26d1d53c0d7 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -17,6 +17,11 @@
17#ifndef __ASM_PERF_EVENT_H 17#ifndef __ASM_PERF_EVENT_H
18#define __ASM_PERF_EVENT_H 18#define __ASM_PERF_EVENT_H
19 19
20/* It's quiet around here... */ 20#ifdef CONFIG_HW_PERF_EVENTS
21struct pt_regs;
22extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
23extern unsigned long perf_misc_flags(struct pt_regs *regs);
24#define perf_misc_flags(regs) perf_misc_flags(regs)
25#endif
21 26
22#endif 27#endif
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
new file mode 100644
index 000000000000..0604237ecd99
--- /dev/null
+++ b/arch/arm64/include/asm/psci.h
@@ -0,0 +1,38 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2013 ARM Limited
12 */
13
14#ifndef __ASM_PSCI_H
15#define __ASM_PSCI_H
16
17#define PSCI_POWER_STATE_TYPE_STANDBY 0
18#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
19
20struct psci_power_state {
21 u16 id;
22 u8 type;
23 u8 affinity_level;
24};
25
26struct psci_operations {
27 int (*cpu_suspend)(struct psci_power_state state,
28 unsigned long entry_point);
29 int (*cpu_off)(struct psci_power_state state);
30 int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
31 int (*migrate)(unsigned long cpuid);
32};
33
34extern struct psci_operations psci_ops;
35
36int psci_init(void);
37
38#endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 4ce845f8ee1c..41a71ee4c3df 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -42,6 +42,16 @@
42#define COMPAT_PSR_MODE_UND 0x0000001b 42#define COMPAT_PSR_MODE_UND 0x0000001b
43#define COMPAT_PSR_MODE_SYS 0x0000001f 43#define COMPAT_PSR_MODE_SYS 0x0000001f
44#define COMPAT_PSR_T_BIT 0x00000020 44#define COMPAT_PSR_T_BIT 0x00000020
45#define COMPAT_PSR_F_BIT 0x00000040
46#define COMPAT_PSR_I_BIT 0x00000080
47#define COMPAT_PSR_A_BIT 0x00000100
48#define COMPAT_PSR_E_BIT 0x00000200
49#define COMPAT_PSR_J_BIT 0x01000000
50#define COMPAT_PSR_Q_BIT 0x08000000
51#define COMPAT_PSR_V_BIT 0x10000000
52#define COMPAT_PSR_C_BIT 0x20000000
53#define COMPAT_PSR_Z_BIT 0x40000000
54#define COMPAT_PSR_N_BIT 0x80000000
45#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ 55#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
46/* 56/*
47 * These are 'magic' values for PTRACE_PEEKUSR that return info about where a 57 * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 7e34295f78e3..4b8023c5d146 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -66,4 +66,15 @@ extern volatile unsigned long secondary_holding_pen_release;
66extern void arch_send_call_function_single_ipi(int cpu); 66extern void arch_send_call_function_single_ipi(int cpu);
67extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); 67extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
68 68
69struct device_node;
70
71struct smp_enable_ops {
72 const char *name;
73 int (*init_cpu)(struct device_node *, int);
74 int (*prepare_cpu)(int);
75};
76
77extern const struct smp_enable_ops smp_spin_table_ops;
78extern const struct smp_enable_ops smp_psci_ops;
79
69#endif /* ifndef __ASM_SMP_H */ 80#endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index 41112fe2f8b1..7065e920149d 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -45,13 +45,13 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
45 asm volatile( 45 asm volatile(
46 " sevl\n" 46 " sevl\n"
47 "1: wfe\n" 47 "1: wfe\n"
48 "2: ldaxr %w0, [%1]\n" 48 "2: ldaxr %w0, %1\n"
49 " cbnz %w0, 1b\n" 49 " cbnz %w0, 1b\n"
50 " stxr %w0, %w2, [%1]\n" 50 " stxr %w0, %w2, %1\n"
51 " cbnz %w0, 2b\n" 51 " cbnz %w0, 2b\n"
52 : "=&r" (tmp) 52 : "=&r" (tmp), "+Q" (lock->lock)
53 : "r" (&lock->lock), "r" (1) 53 : "r" (1)
54 : "memory"); 54 : "cc", "memory");
55} 55}
56 56
57static inline int arch_spin_trylock(arch_spinlock_t *lock) 57static inline int arch_spin_trylock(arch_spinlock_t *lock)
@@ -59,13 +59,13 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
59 unsigned int tmp; 59 unsigned int tmp;
60 60
61 asm volatile( 61 asm volatile(
62 " ldaxr %w0, [%1]\n" 62 " ldaxr %w0, %1\n"
63 " cbnz %w0, 1f\n" 63 " cbnz %w0, 1f\n"
64 " stxr %w0, %w2, [%1]\n" 64 " stxr %w0, %w2, %1\n"
65 "1:\n" 65 "1:\n"
66 : "=&r" (tmp) 66 : "=&r" (tmp), "+Q" (lock->lock)
67 : "r" (&lock->lock), "r" (1) 67 : "r" (1)
68 : "memory"); 68 : "cc", "memory");
69 69
70 return !tmp; 70 return !tmp;
71} 71}
@@ -73,8 +73,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
73static inline void arch_spin_unlock(arch_spinlock_t *lock) 73static inline void arch_spin_unlock(arch_spinlock_t *lock)
74{ 74{
75 asm volatile( 75 asm volatile(
76 " stlr %w1, [%0]\n" 76 " stlr %w1, %0\n"
77 : : "r" (&lock->lock), "r" (0) : "memory"); 77 : "=Q" (lock->lock) : "r" (0) : "memory");
78} 78}
79 79
80/* 80/*
@@ -94,13 +94,13 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
94 asm volatile( 94 asm volatile(
95 " sevl\n" 95 " sevl\n"
96 "1: wfe\n" 96 "1: wfe\n"
97 "2: ldaxr %w0, [%1]\n" 97 "2: ldaxr %w0, %1\n"
98 " cbnz %w0, 1b\n" 98 " cbnz %w0, 1b\n"
99 " stxr %w0, %w2, [%1]\n" 99 " stxr %w0, %w2, %1\n"
100 " cbnz %w0, 2b\n" 100 " cbnz %w0, 2b\n"
101 : "=&r" (tmp) 101 : "=&r" (tmp), "+Q" (rw->lock)
102 : "r" (&rw->lock), "r" (0x80000000) 102 : "r" (0x80000000)
103 : "memory"); 103 : "cc", "memory");
104} 104}
105 105
106static inline int arch_write_trylock(arch_rwlock_t *rw) 106static inline int arch_write_trylock(arch_rwlock_t *rw)
@@ -108,13 +108,13 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
108 unsigned int tmp; 108 unsigned int tmp;
109 109
110 asm volatile( 110 asm volatile(
111 " ldaxr %w0, [%1]\n" 111 " ldaxr %w0, %1\n"
112 " cbnz %w0, 1f\n" 112 " cbnz %w0, 1f\n"
113 " stxr %w0, %w2, [%1]\n" 113 " stxr %w0, %w2, %1\n"
114 "1:\n" 114 "1:\n"
115 : "=&r" (tmp) 115 : "=&r" (tmp), "+Q" (rw->lock)
116 : "r" (&rw->lock), "r" (0x80000000) 116 : "r" (0x80000000)
117 : "memory"); 117 : "cc", "memory");
118 118
119 return !tmp; 119 return !tmp;
120} 120}
@@ -122,8 +122,8 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
122static inline void arch_write_unlock(arch_rwlock_t *rw) 122static inline void arch_write_unlock(arch_rwlock_t *rw)
123{ 123{
124 asm volatile( 124 asm volatile(
125 " stlr %w1, [%0]\n" 125 " stlr %w1, %0\n"
126 : : "r" (&rw->lock), "r" (0) : "memory"); 126 : "=Q" (rw->lock) : "r" (0) : "memory");
127} 127}
128 128
129/* write_can_lock - would write_trylock() succeed? */ 129/* write_can_lock - would write_trylock() succeed? */
@@ -148,14 +148,14 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
148 asm volatile( 148 asm volatile(
149 " sevl\n" 149 " sevl\n"
150 "1: wfe\n" 150 "1: wfe\n"
151 "2: ldaxr %w0, [%2]\n" 151 "2: ldaxr %w0, %2\n"
152 " add %w0, %w0, #1\n" 152 " add %w0, %w0, #1\n"
153 " tbnz %w0, #31, 1b\n" 153 " tbnz %w0, #31, 1b\n"
154 " stxr %w1, %w0, [%2]\n" 154 " stxr %w1, %w0, %2\n"
155 " cbnz %w1, 2b\n" 155 " cbnz %w1, 2b\n"
156 : "=&r" (tmp), "=&r" (tmp2) 156 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
157 : "r" (&rw->lock) 157 :
158 : "memory"); 158 : "cc", "memory");
159} 159}
160 160
161static inline void arch_read_unlock(arch_rwlock_t *rw) 161static inline void arch_read_unlock(arch_rwlock_t *rw)
@@ -163,13 +163,13 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
163 unsigned int tmp, tmp2; 163 unsigned int tmp, tmp2;
164 164
165 asm volatile( 165 asm volatile(
166 "1: ldxr %w0, [%2]\n" 166 "1: ldxr %w0, %2\n"
167 " sub %w0, %w0, #1\n" 167 " sub %w0, %w0, #1\n"
168 " stlxr %w1, %w0, [%2]\n" 168 " stlxr %w1, %w0, %2\n"
169 " cbnz %w1, 1b\n" 169 " cbnz %w1, 1b\n"
170 : "=&r" (tmp), "=&r" (tmp2) 170 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
171 : "r" (&rw->lock) 171 :
172 : "memory"); 172 : "cc", "memory");
173} 173}
174 174
175static inline int arch_read_trylock(arch_rwlock_t *rw) 175static inline int arch_read_trylock(arch_rwlock_t *rw)
@@ -177,14 +177,14 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
177 unsigned int tmp, tmp2 = 1; 177 unsigned int tmp, tmp2 = 1;
178 178
179 asm volatile( 179 asm volatile(
180 " ldaxr %w0, [%2]\n" 180 " ldaxr %w0, %2\n"
181 " add %w0, %w0, #1\n" 181 " add %w0, %w0, #1\n"
182 " tbnz %w0, #31, 1f\n" 182 " tbnz %w0, #31, 1f\n"
183 " stxr %w1, %w0, [%2]\n" 183 " stxr %w1, %w0, %2\n"
184 "1:\n" 184 "1:\n"
185 : "=&r" (tmp), "+r" (tmp2) 185 : "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock)
186 : "r" (&rw->lock) 186 :
187 : "memory"); 187 : "cc", "memory");
188 188
189 return !tmp2; 189 return !tmp2;
190} 190}
diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild
index ca5b65f75c7b..e4b78bdca19e 100644
--- a/arch/arm64/include/uapi/asm/Kbuild
+++ b/arch/arm64/include/uapi/asm/Kbuild
@@ -1,11 +1,14 @@
1# UAPI Header export list 1# UAPI Header export list
2include include/uapi/asm-generic/Kbuild.asm 2include include/uapi/asm-generic/Kbuild.asm
3 3
4generic-y += kvm_para.h
5
4header-y += auxvec.h 6header-y += auxvec.h
5header-y += bitsperlong.h 7header-y += bitsperlong.h
6header-y += byteorder.h 8header-y += byteorder.h
7header-y += fcntl.h 9header-y += fcntl.h
8header-y += hwcap.h 10header-y += hwcap.h
11header-y += kvm_para.h
9header-y += param.h 12header-y += param.h
10header-y += ptrace.h 13header-y += ptrace.h
11header-y += setup.h 14header-y += setup.h
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 74239c31e25a..7b4b564961d4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,14 +9,15 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
9arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ 9arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
10 entry-fpsimd.o process.o ptrace.o setup.o signal.o \ 10 entry-fpsimd.o process.o ptrace.o setup.o signal.o \
11 sys.o stacktrace.o time.o traps.o io.o vdso.o \ 11 sys.o stacktrace.o time.o traps.o io.o vdso.o \
12 hyp-stub.o 12 hyp-stub.o psci.o
13 13
14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ 14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
15 sys_compat.o 15 sys_compat.o
16arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o 16arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
17arm64-obj-$(CONFIG_SMP) += smp.o 17arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o smp_psci.o
18arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 18arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
19arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o 19arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
20arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
20 21
21obj-y += $(arm64-obj-y) vdso/ 22obj-y += $(arm64-obj-y) vdso/
22obj-m += $(arm64-obj-m) 23obj-m += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
new file mode 100644
index 000000000000..7e320a2edb9b
--- /dev/null
+++ b/arch/arm64/kernel/early_printk.c
@@ -0,0 +1,118 @@
1/*
2 * Earlyprintk support.
3 *
4 * Copyright (C) 2012 ARM Ltd.
5 * Author: Catalin Marinas <catalin.marinas@arm.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <linux/kernel.h>
20#include <linux/console.h>
21#include <linux/init.h>
22#include <linux/string.h>
23#include <linux/mm.h>
24#include <linux/io.h>
25
26#include <linux/amba/serial.h>
27
28static void __iomem *early_base;
29static void (*printch)(char ch);
30
31/*
32 * PL011 single character TX.
33 */
34static void pl011_printch(char ch)
35{
36 while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_TXFF)
37 ;
38 writeb_relaxed(ch, early_base + UART01x_DR);
39 while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_BUSY)
40 ;
41}
42
43struct earlycon_match {
44 const char *name;
45 void (*printch)(char ch);
46};
47
48static const struct earlycon_match earlycon_match[] __initconst = {
49 { .name = "pl011", .printch = pl011_printch, },
50 {}
51};
52
53static void early_write(struct console *con, const char *s, unsigned n)
54{
55 while (n-- > 0) {
56 if (*s == '\n')
57 printch('\r');
58 printch(*s);
59 s++;
60 }
61}
62
63static struct console early_console = {
64 .name = "earlycon",
65 .write = early_write,
66 .flags = CON_PRINTBUFFER | CON_BOOT,
67 .index = -1,
68};
69
70/*
71 * Parse earlyprintk=... parameter in the format:
72 *
73 * <name>[,<addr>][,<options>]
74 *
75 * and register the early console. It is assumed that the UART has been
76 * initialised by the bootloader already.
77 */
78static int __init setup_early_printk(char *buf)
79{
80 const struct earlycon_match *match = earlycon_match;
81 phys_addr_t paddr = 0;
82
83 if (!buf) {
84 pr_warning("No earlyprintk arguments passed.\n");
85 return 0;
86 }
87
88 while (match->name) {
89 size_t len = strlen(match->name);
90 if (!strncmp(buf, match->name, len)) {
91 buf += len;
92 break;
93 }
94 match++;
95 }
96 if (!match->name) {
97 pr_warning("Unknown earlyprintk arguments: %s\n", buf);
98 return 0;
99 }
100
101 /* I/O address */
102 if (!strncmp(buf, ",0x", 3)) {
103 char *e;
104 paddr = simple_strtoul(buf + 1, &e, 16);
105 buf = e;
106 }
107 /* no options parsing yet */
108
109 if (paddr)
110 early_base = early_io_map(paddr, EARLYCON_IOBASE);
111
112 printch = match->printch;
113 register_console(&early_console);
114
115 return 0;
116}
117
118early_param("earlyprintk", setup_early_printk);
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 368ad1f7c36c..0a0a49756826 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -82,10 +82,8 @@
82 82
83#ifdef CONFIG_ARM64_64K_PAGES 83#ifdef CONFIG_ARM64_64K_PAGES
84#define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS 84#define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS
85#define IO_MMUFLAGS PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_XN | PTE_FLAGS
86#else 85#else
87#define MM_MMUFLAGS PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS 86#define MM_MMUFLAGS PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS
88#define IO_MMUFLAGS PMD_ATTRINDX(MT_DEVICE_nGnRE) | PMD_SECT_XN | PMD_FLAGS
89#endif 87#endif
90 88
91/* 89/*
@@ -368,6 +366,7 @@ ENDPROC(__calc_phys_offset)
368 * - identity mapping to enable the MMU (low address, TTBR0) 366 * - identity mapping to enable the MMU (low address, TTBR0)
369 * - first few MB of the kernel linear mapping to jump to once the MMU has 367 * - first few MB of the kernel linear mapping to jump to once the MMU has
370 * been enabled, including the FDT blob (TTBR1) 368 * been enabled, including the FDT blob (TTBR1)
369 * - UART mapping if CONFIG_EARLY_PRINTK is enabled (TTBR1)
371 */ 370 */
372__create_page_tables: 371__create_page_tables:
373 pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses 372 pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses
@@ -420,6 +419,15 @@ __create_page_tables:
420 sub x6, x6, #1 // inclusive range 419 sub x6, x6, #1 // inclusive range
421 create_block_map x0, x7, x3, x5, x6 420 create_block_map x0, x7, x3, x5, x6
4221: 4211:
422#ifdef CONFIG_EARLY_PRINTK
423 /*
424 * Create the pgd entry for the UART mapping. The full mapping is done
425 * later based earlyprintk kernel parameter.
426 */
427 ldr x5, =EARLYCON_IOBASE // UART virtual address
428 add x0, x26, #2 * PAGE_SIZE // section table address
429 create_pgd_entry x26, x0, x5, x6, x7
430#endif
423 ret 431 ret
424ENDPROC(__create_page_tables) 432ENDPROC(__create_page_tables)
425 .ltorg 433 .ltorg
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index f7073c7b1ca9..1e49e5eb81e9 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1331,6 +1331,11 @@ void perf_callchain_user(struct perf_callchain_entry *entry,
1331{ 1331{
1332 struct frame_tail __user *tail; 1332 struct frame_tail __user *tail;
1333 1333
1334 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1335 /* We don't support guest os callchain now */
1336 return;
1337 }
1338
1334 tail = (struct frame_tail __user *)regs->regs[29]; 1339 tail = (struct frame_tail __user *)regs->regs[29];
1335 1340
1336 while (entry->nr < PERF_MAX_STACK_DEPTH && 1341 while (entry->nr < PERF_MAX_STACK_DEPTH &&
@@ -1355,8 +1360,40 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
1355{ 1360{
1356 struct stackframe frame; 1361 struct stackframe frame;
1357 1362
1363 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1364 /* We don't support guest os callchain now */
1365 return;
1366 }
1367
1358 frame.fp = regs->regs[29]; 1368 frame.fp = regs->regs[29];
1359 frame.sp = regs->sp; 1369 frame.sp = regs->sp;
1360 frame.pc = regs->pc; 1370 frame.pc = regs->pc;
1361 walk_stackframe(&frame, callchain_trace, entry); 1371 walk_stackframe(&frame, callchain_trace, entry);
1362} 1372}
1373
1374unsigned long perf_instruction_pointer(struct pt_regs *regs)
1375{
1376 if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
1377 return perf_guest_cbs->get_guest_ip();
1378
1379 return instruction_pointer(regs);
1380}
1381
1382unsigned long perf_misc_flags(struct pt_regs *regs)
1383{
1384 int misc = 0;
1385
1386 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1387 if (perf_guest_cbs->is_user_mode())
1388 misc |= PERF_RECORD_MISC_GUEST_USER;
1389 else
1390 misc |= PERF_RECORD_MISC_GUEST_KERNEL;
1391 } else {
1392 if (user_mode(regs))
1393 misc |= PERF_RECORD_MISC_USER;
1394 else
1395 misc |= PERF_RECORD_MISC_KERNEL;
1396 }
1397
1398 return misc;
1399}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index c7002d40a9b0..0337cdb0667b 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -45,9 +45,10 @@
45 45
46#include <asm/compat.h> 46#include <asm/compat.h>
47#include <asm/cacheflush.h> 47#include <asm/cacheflush.h>
48#include <asm/fpsimd.h>
49#include <asm/mmu_context.h>
48#include <asm/processor.h> 50#include <asm/processor.h>
49#include <asm/stacktrace.h> 51#include <asm/stacktrace.h>
50#include <asm/fpsimd.h>
51 52
52static void setup_restart(void) 53static void setup_restart(void)
53{ 54{
@@ -314,6 +315,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
314 /* the actual thread switch */ 315 /* the actual thread switch */
315 last = cpu_switch_to(prev, next); 316 last = cpu_switch_to(prev, next);
316 317
318 contextidr_thread_switch(next);
317 return last; 319 return last;
318} 320}
319 321
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
new file mode 100644
index 000000000000..14f73c445ff5
--- /dev/null
+++ b/arch/arm64/kernel/psci.c
@@ -0,0 +1,211 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2013 ARM Limited
12 *
13 * Author: Will Deacon <will.deacon@arm.com>
14 */
15
16#define pr_fmt(fmt) "psci: " fmt
17
18#include <linux/init.h>
19#include <linux/of.h>
20
21#include <asm/compiler.h>
22#include <asm/errno.h>
23#include <asm/psci.h>
24
25struct psci_operations psci_ops;
26
27static int (*invoke_psci_fn)(u64, u64, u64, u64);
28
29enum psci_function {
30 PSCI_FN_CPU_SUSPEND,
31 PSCI_FN_CPU_ON,
32 PSCI_FN_CPU_OFF,
33 PSCI_FN_MIGRATE,
34 PSCI_FN_MAX,
35};
36
37static u32 psci_function_id[PSCI_FN_MAX];
38
39#define PSCI_RET_SUCCESS 0
40#define PSCI_RET_EOPNOTSUPP -1
41#define PSCI_RET_EINVAL -2
42#define PSCI_RET_EPERM -3
43
44static int psci_to_linux_errno(int errno)
45{
46 switch (errno) {
47 case PSCI_RET_SUCCESS:
48 return 0;
49 case PSCI_RET_EOPNOTSUPP:
50 return -EOPNOTSUPP;
51 case PSCI_RET_EINVAL:
52 return -EINVAL;
53 case PSCI_RET_EPERM:
54 return -EPERM;
55 };
56
57 return -EINVAL;
58}
59
60#define PSCI_POWER_STATE_ID_MASK 0xffff
61#define PSCI_POWER_STATE_ID_SHIFT 0
62#define PSCI_POWER_STATE_TYPE_MASK 0x1
63#define PSCI_POWER_STATE_TYPE_SHIFT 16
64#define PSCI_POWER_STATE_AFFL_MASK 0x3
65#define PSCI_POWER_STATE_AFFL_SHIFT 24
66
67static u32 psci_power_state_pack(struct psci_power_state state)
68{
69 return ((state.id & PSCI_POWER_STATE_ID_MASK)
70 << PSCI_POWER_STATE_ID_SHIFT) |
71 ((state.type & PSCI_POWER_STATE_TYPE_MASK)
72 << PSCI_POWER_STATE_TYPE_SHIFT) |
73 ((state.affinity_level & PSCI_POWER_STATE_AFFL_MASK)
74 << PSCI_POWER_STATE_AFFL_SHIFT);
75}
76
77/*
78 * The following two functions are invoked via the invoke_psci_fn pointer
79 * and will not be inlined, allowing us to piggyback on the AAPCS.
80 */
81static noinline int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1,
82 u64 arg2)
83{
84 asm volatile(
85 __asmeq("%0", "x0")
86 __asmeq("%1", "x1")
87 __asmeq("%2", "x2")
88 __asmeq("%3", "x3")
89 "hvc #0\n"
90 : "+r" (function_id)
91 : "r" (arg0), "r" (arg1), "r" (arg2));
92
93 return function_id;
94}
95
96static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
97 u64 arg2)
98{
99 asm volatile(
100 __asmeq("%0", "x0")
101 __asmeq("%1", "x1")
102 __asmeq("%2", "x2")
103 __asmeq("%3", "x3")
104 "smc #0\n"
105 : "+r" (function_id)
106 : "r" (arg0), "r" (arg1), "r" (arg2));
107
108 return function_id;
109}
110
111static int psci_cpu_suspend(struct psci_power_state state,
112 unsigned long entry_point)
113{
114 int err;
115 u32 fn, power_state;
116
117 fn = psci_function_id[PSCI_FN_CPU_SUSPEND];
118 power_state = psci_power_state_pack(state);
119 err = invoke_psci_fn(fn, power_state, entry_point, 0);
120 return psci_to_linux_errno(err);
121}
122
123static int psci_cpu_off(struct psci_power_state state)
124{
125 int err;
126 u32 fn, power_state;
127
128 fn = psci_function_id[PSCI_FN_CPU_OFF];
129 power_state = psci_power_state_pack(state);
130 err = invoke_psci_fn(fn, power_state, 0, 0);
131 return psci_to_linux_errno(err);
132}
133
134static int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
135{
136 int err;
137 u32 fn;
138
139 fn = psci_function_id[PSCI_FN_CPU_ON];
140 err = invoke_psci_fn(fn, cpuid, entry_point, 0);
141 return psci_to_linux_errno(err);
142}
143
144static int psci_migrate(unsigned long cpuid)
145{
146 int err;
147 u32 fn;
148
149 fn = psci_function_id[PSCI_FN_MIGRATE];
150 err = invoke_psci_fn(fn, cpuid, 0, 0);
151 return psci_to_linux_errno(err);
152}
153
154static const struct of_device_id psci_of_match[] __initconst = {
155 { .compatible = "arm,psci", },
156 {},
157};
158
159int __init psci_init(void)
160{
161 struct device_node *np;
162 const char *method;
163 u32 id;
164 int err = 0;
165
166 np = of_find_matching_node(NULL, psci_of_match);
167 if (!np)
168 return -ENODEV;
169
170 pr_info("probing function IDs from device-tree\n");
171
172 if (of_property_read_string(np, "method", &method)) {
173 pr_warning("missing \"method\" property\n");
174 err = -ENXIO;
175 goto out_put_node;
176 }
177
178 if (!strcmp("hvc", method)) {
179 invoke_psci_fn = __invoke_psci_fn_hvc;
180 } else if (!strcmp("smc", method)) {
181 invoke_psci_fn = __invoke_psci_fn_smc;
182 } else {
183 pr_warning("invalid \"method\" property: %s\n", method);
184 err = -EINVAL;
185 goto out_put_node;
186 }
187
188 if (!of_property_read_u32(np, "cpu_suspend", &id)) {
189 psci_function_id[PSCI_FN_CPU_SUSPEND] = id;
190 psci_ops.cpu_suspend = psci_cpu_suspend;
191 }
192
193 if (!of_property_read_u32(np, "cpu_off", &id)) {
194 psci_function_id[PSCI_FN_CPU_OFF] = id;
195 psci_ops.cpu_off = psci_cpu_off;
196 }
197
198 if (!of_property_read_u32(np, "cpu_on", &id)) {
199 psci_function_id[PSCI_FN_CPU_ON] = id;
200 psci_ops.cpu_on = psci_cpu_on;
201 }
202
203 if (!of_property_read_u32(np, "migrate", &id)) {
204 psci_function_id[PSCI_FN_MIGRATE] = id;
205 psci_ops.migrate = psci_migrate;
206 }
207
208out_put_node:
209 of_node_put(np);
210 return err;
211}
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 7665a9bfdb1e..113db863f832 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -39,6 +39,7 @@
39#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
40#include <linux/memblock.h> 40#include <linux/memblock.h>
41#include <linux/of_fdt.h> 41#include <linux/of_fdt.h>
42#include <linux/of_platform.h>
42 43
43#include <asm/cputype.h> 44#include <asm/cputype.h>
44#include <asm/elf.h> 45#include <asm/elf.h>
@@ -49,6 +50,7 @@
49#include <asm/tlbflush.h> 50#include <asm/tlbflush.h>
50#include <asm/traps.h> 51#include <asm/traps.h>
51#include <asm/memblock.h> 52#include <asm/memblock.h>
53#include <asm/psci.h>
52 54
53unsigned int processor_id; 55unsigned int processor_id;
54EXPORT_SYMBOL(processor_id); 56EXPORT_SYMBOL(processor_id);
@@ -260,6 +262,8 @@ void __init setup_arch(char **cmdline_p)
260 262
261 unflatten_device_tree(); 263 unflatten_device_tree();
262 264
265 psci_init();
266
263#ifdef CONFIG_SMP 267#ifdef CONFIG_SMP
264 smp_init_cpus(); 268 smp_init_cpus();
265#endif 269#endif
@@ -289,6 +293,13 @@ static int __init topology_init(void)
289} 293}
290subsys_initcall(topology_init); 294subsys_initcall(topology_init);
291 295
296static int __init arm64_device_probe(void)
297{
298 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
299 return 0;
300}
301device_initcall(arm64_device_probe);
302
292static const char *hwcap_str[] = { 303static const char *hwcap_str[] = {
293 "fp", 304 "fp",
294 "asimd", 305 "asimd",
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index a4db3d22aac4..41db148a7eb9 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -76,7 +76,7 @@ struct compat_sigcontext {
76 76
77struct compat_ucontext { 77struct compat_ucontext {
78 compat_ulong_t uc_flags; 78 compat_ulong_t uc_flags;
79 struct compat_ucontext *uc_link; 79 compat_uptr_t uc_link;
80 compat_stack_t uc_stack; 80 compat_stack_t uc_stack;
81 struct compat_sigcontext uc_mcontext; 81 struct compat_sigcontext uc_mcontext;
82 compat_sigset_t uc_sigmask; 82 compat_sigset_t uc_sigmask;
@@ -703,7 +703,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
703 err |= copy_siginfo_to_user32(&frame->info, info); 703 err |= copy_siginfo_to_user32(&frame->info, info);
704 704
705 __put_user_error(0, &frame->sig.uc.uc_flags, err); 705 __put_user_error(0, &frame->sig.uc.uc_flags, err);
706 __put_user_error(NULL, &frame->sig.uc.uc_link, err); 706 __put_user_error(0, &frame->sig.uc.uc_link, err);
707 707
708 memset(&stack, 0, sizeof(stack)); 708 memset(&stack, 0, sizeof(stack));
709 stack.ss_sp = (compat_uptr_t)current->sas_ss_sp; 709 stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 538300f2273d..bdd34597254b 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -233,7 +233,28 @@ void __init smp_prepare_boot_cpu(void)
233} 233}
234 234
235static void (*smp_cross_call)(const struct cpumask *, unsigned int); 235static void (*smp_cross_call)(const struct cpumask *, unsigned int);
236static phys_addr_t cpu_release_addr[NR_CPUS]; 236
237static const struct smp_enable_ops *enable_ops[] __initconst = {
238 &smp_spin_table_ops,
239 &smp_psci_ops,
240 NULL,
241};
242
243static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];
244
245static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
246{
247 const struct smp_enable_ops *ops = enable_ops[0];
248
249 while (ops) {
250 if (!strcmp(name, ops->name))
251 return ops;
252
253 ops++;
254 }
255
256 return NULL;
257}
237 258
238/* 259/*
239 * Enumerate the possible CPU set from the device tree. 260 * Enumerate the possible CPU set from the device tree.
@@ -252,22 +273,22 @@ void __init smp_init_cpus(void)
252 * We currently support only the "spin-table" enable-method. 273 * We currently support only the "spin-table" enable-method.
253 */ 274 */
254 enable_method = of_get_property(dn, "enable-method", NULL); 275 enable_method = of_get_property(dn, "enable-method", NULL);
255 if (!enable_method || strcmp(enable_method, "spin-table")) { 276 if (!enable_method) {
256 pr_err("CPU %d: missing or invalid enable-method property: %s\n", 277 pr_err("CPU %d: missing enable-method property\n", cpu);
257 cpu, enable_method);
258 goto next; 278 goto next;
259 } 279 }
260 280
261 /* 281 smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);
262 * Determine the address from which the CPU is polling. 282
263 */ 283 if (!smp_enable_ops[cpu]) {
264 if (of_property_read_u64(dn, "cpu-release-addr", 284 pr_err("CPU %d: invalid enable-method property: %s\n",
265 &cpu_release_addr[cpu])) { 285 cpu, enable_method);
266 pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
267 cpu);
268 goto next; 286 goto next;
269 } 287 }
270 288
289 if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
290 goto next;
291
271 set_cpu_possible(cpu, true); 292 set_cpu_possible(cpu, true);
272next: 293next:
273 cpu++; 294 cpu++;
@@ -281,8 +302,7 @@ next:
281 302
282void __init smp_prepare_cpus(unsigned int max_cpus) 303void __init smp_prepare_cpus(unsigned int max_cpus)
283{ 304{
284 int cpu; 305 int cpu, err;
285 void **release_addr;
286 unsigned int ncores = num_possible_cpus(); 306 unsigned int ncores = num_possible_cpus();
287 307
288 /* 308 /*
@@ -291,30 +311,35 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
291 if (max_cpus > ncores) 311 if (max_cpus > ncores)
292 max_cpus = ncores; 312 max_cpus = ncores;
293 313
314 /* Don't bother if we're effectively UP */
315 if (max_cpus <= 1)
316 return;
317
294 /* 318 /*
295 * Initialise the present map (which describes the set of CPUs 319 * Initialise the present map (which describes the set of CPUs
296 * actually populated at the present time) and release the 320 * actually populated at the present time) and release the
297 * secondaries from the bootloader. 321 * secondaries from the bootloader.
322 *
323 * Make sure we online at most (max_cpus - 1) additional CPUs.
298 */ 324 */
325 max_cpus--;
299 for_each_possible_cpu(cpu) { 326 for_each_possible_cpu(cpu) {
300 if (max_cpus == 0) 327 if (max_cpus == 0)
301 break; 328 break;
302 329
303 if (!cpu_release_addr[cpu]) 330 if (cpu == smp_processor_id())
331 continue;
332
333 if (!smp_enable_ops[cpu])
304 continue; 334 continue;
305 335
306 release_addr = __va(cpu_release_addr[cpu]); 336 err = smp_enable_ops[cpu]->prepare_cpu(cpu);
307 release_addr[0] = (void *)__pa(secondary_holding_pen); 337 if (err)
308 __flush_dcache_area(release_addr, sizeof(release_addr[0])); 338 continue;
309 339
310 set_cpu_present(cpu, true); 340 set_cpu_present(cpu, true);
311 max_cpus--; 341 max_cpus--;
312 } 342 }
313
314 /*
315 * Send an event to wake up the secondaries.
316 */
317 sev();
318} 343}
319 344
320 345
diff --git a/arch/arm64/kernel/smp_psci.c b/arch/arm64/kernel/smp_psci.c
new file mode 100644
index 000000000000..112091684c22
--- /dev/null
+++ b/arch/arm64/kernel/smp_psci.c
@@ -0,0 +1,52 @@
1/*
2 * PSCI SMP initialisation
3 *
4 * Copyright (C) 2013 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/init.h>
20#include <linux/of.h>
21#include <linux/smp.h>
22
23#include <asm/psci.h>
24
25static int __init smp_psci_init_cpu(struct device_node *dn, int cpu)
26{
27 return 0;
28}
29
30static int __init smp_psci_prepare_cpu(int cpu)
31{
32 int err;
33
34 if (!psci_ops.cpu_on) {
35 pr_err("psci: no cpu_on method, not booting CPU%d\n", cpu);
36 return -ENODEV;
37 }
38
39 err = psci_ops.cpu_on(cpu, __pa(secondary_holding_pen));
40 if (err) {
41 pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
42 return err;
43 }
44
45 return 0;
46}
47
48const struct smp_enable_ops smp_psci_ops __initconst = {
49 .name = "psci",
50 .init_cpu = smp_psci_init_cpu,
51 .prepare_cpu = smp_psci_prepare_cpu,
52};
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
new file mode 100644
index 000000000000..7c35fa682f76
--- /dev/null
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -0,0 +1,66 @@
1/*
2 * Spin Table SMP initialisation
3 *
4 * Copyright (C) 2013 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/init.h>
20#include <linux/of.h>
21#include <linux/smp.h>
22
23#include <asm/cacheflush.h>
24
25static phys_addr_t cpu_release_addr[NR_CPUS];
26
27static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu)
28{
29 /*
30 * Determine the address from which the CPU is polling.
31 */
32 if (of_property_read_u64(dn, "cpu-release-addr",
33 &cpu_release_addr[cpu])) {
34 pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
35 cpu);
36
37 return -1;
38 }
39
40 return 0;
41}
42
43static int __init smp_spin_table_prepare_cpu(int cpu)
44{
45 void **release_addr;
46
47 if (!cpu_release_addr[cpu])
48 return -ENODEV;
49
50 release_addr = __va(cpu_release_addr[cpu]);
51 release_addr[0] = (void *)__pa(secondary_holding_pen);
52 __flush_dcache_area(release_addr, sizeof(release_addr[0]));
53
54 /*
55 * Send an event to wake up the secondary CPU.
56 */
57 sev();
58
59 return 0;
60}
61
62const struct smp_enable_ops smp_spin_table_ops __initconst = {
63 .name = "spin-table",
64 .init_cpu = smp_spin_table_init_cpu,
65 .prepare_cpu = smp_spin_table_prepare_cpu,
66};
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a6885d896ab6..f4dd585898c5 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -25,6 +25,7 @@
25#include <linux/nodemask.h> 25#include <linux/nodemask.h>
26#include <linux/memblock.h> 26#include <linux/memblock.h>
27#include <linux/fs.h> 27#include <linux/fs.h>
28#include <linux/io.h>
28 29
29#include <asm/cputype.h> 30#include <asm/cputype.h>
30#include <asm/sections.h> 31#include <asm/sections.h>
@@ -251,6 +252,47 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt,
251 } while (pgd++, addr = next, addr != end); 252 } while (pgd++, addr = next, addr != end);
252} 253}
253 254
255#ifdef CONFIG_EARLY_PRINTK
256/*
257 * Create an early I/O mapping using the pgd/pmd entries already populated
258 * in head.S as this function is called too early to allocated any memory. The
259 * mapping size is 2MB with 4KB pages or 64KB or 64KB pages.
260 */
261void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt)
262{
263 unsigned long size, mask;
264 bool page64k = IS_ENABLED(ARM64_64K_PAGES);
265 pgd_t *pgd;
266 pud_t *pud;
267 pmd_t *pmd;
268 pte_t *pte;
269
270 /*
271 * No early pte entries with !ARM64_64K_PAGES configuration, so using
272 * sections (pmd).
273 */
274 size = page64k ? PAGE_SIZE : SECTION_SIZE;
275 mask = ~(size - 1);
276
277 pgd = pgd_offset_k(virt);
278 pud = pud_offset(pgd, virt);
279 if (pud_none(*pud))
280 return NULL;
281 pmd = pmd_offset(pud, virt);
282
283 if (page64k) {
284 if (pmd_none(*pmd))
285 return NULL;
286 pte = pte_offset_kernel(pmd, virt);
287 set_pte(pte, __pte((phys & mask) | PROT_DEVICE_nGnRE));
288 } else {
289 set_pmd(pmd, __pmd((phys & mask) | PROT_SECT_DEVICE_nGnRE));
290 }
291
292 return (void __iomem *)((virt & mask) + (phys & ~mask));
293}
294#endif
295
254static void __init map_mem(void) 296static void __init map_mem(void)
255{ 297{
256 struct memblock_region *reg; 298 struct memblock_region *reg;