aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 05:34:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 05:34:24 -0400
commit6325e940e7e0c690c6bdfaf5d54309e71845d3d9 (patch)
treebd1d2c33ae9420e98d3feee1f924fdad3f22552f /arch/arm64/kernel
parent536fd93d432858eb6b7c1ad1dcfe051840ebef47 (diff)
parent0a6479b0ffad8dd236915e271faaf2cbb4cac287 (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Catalin Marinas: - eBPF JIT compiler for arm64 - CPU suspend backend for PSCI (firmware interface) with standard idle states defined in DT (generic idle driver to be merged via a different tree) - Support for CONFIG_DEBUG_SET_MODULE_RONX - Support for unmapped cpu-release-addr (outside kernel linear mapping) - set_arch_dma_coherent_ops() implemented and bus notifiers removed - EFI_STUB improvements when base of DRAM is occupied - Typos in KGDB macros - Clean-up to (partially) allow kernel building with LLVM - Other clean-ups (extern keyword, phys_addr_t usage) * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (51 commits) arm64: Remove unneeded extern keyword ARM64: make of_device_ids const arm64: Use phys_addr_t type for physical address aarch64: filter $x from kallsyms arm64: Use DMA_ERROR_CODE to denote failed allocation arm64: Fix typos in KGDB macros arm64: insn: Add return statements after BUG_ON() arm64: debug: don't re-enable debug exceptions on return from el1_dbg Revert "arm64: dmi: Add SMBIOS/DMI support" arm64: Implement set_arch_dma_coherent_ops() to replace bus notifiers of: amba: use of_dma_configure for AMBA devices arm64: dmi: Add SMBIOS/DMI support arm64: Correct ftrace calls to aarch64_insn_gen_branch_imm() arm64:mm: initialize max_mapnr using function set_max_mapnr setup: Move unmask of async interrupts after possible earlycon setup arm64: LLVMLinux: Fix inline arm64 assembly for use with clang arm64: pageattr: Correctly adjust unaligned start addresses net: bpf: arm64: fix module memory leak when JIT image build fails arm64: add PSCI CPU_SUSPEND based cpu_suspend support arm64: kernel: introduce cpu_init_idle CPU operation ...
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/Makefile1
-rw-r--r--arch/arm64/kernel/cpuidle.c31
-rw-r--r--arch/arm64/kernel/cpuinfo.c28
-rw-r--r--arch/arm64/kernel/efi-stub.c16
-rw-r--r--arch/arm64/kernel/entry.S1
-rw-r--r--arch/arm64/kernel/ftrace.c10
-rw-r--r--arch/arm64/kernel/head.S6
-rw-r--r--arch/arm64/kernel/insn.c671
-rw-r--r--arch/arm64/kernel/kgdb.c4
-rw-r--r--arch/arm64/kernel/perf_event.c2
-rw-r--r--arch/arm64/kernel/process.c30
-rw-r--r--arch/arm64/kernel/psci.c104
-rw-r--r--arch/arm64/kernel/return_address.c3
-rw-r--r--arch/arm64/kernel/setup.c11
-rw-r--r--arch/arm64/kernel/sleep.S47
-rw-r--r--arch/arm64/kernel/smp_spin_table.c22
-rw-r--r--arch/arm64/kernel/stacktrace.c3
-rw-r--r--arch/arm64/kernel/suspend.c48
-rw-r--r--arch/arm64/kernel/traps.c3
19 files changed, 935 insertions, 106 deletions
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index df7ef8768fc2..6e9538c2d28a 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -26,6 +26,7 @@ arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
26arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 26arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
27arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o 27arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
28arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o 28arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
29arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
29arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o 30arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
30arm64-obj-$(CONFIG_KGDB) += kgdb.o 31arm64-obj-$(CONFIG_KGDB) += kgdb.o
31arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o 32arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o
diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
new file mode 100644
index 000000000000..19d17f51db37
--- /dev/null
+++ b/arch/arm64/kernel/cpuidle.c
@@ -0,0 +1,31 @@
1/*
2 * ARM64 CPU idle arch support
3 *
4 * Copyright (C) 2014 ARM Ltd.
5 * Author: Lorenzo Pieralisi <lorenzo.pieralisi@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
12#include <linux/of.h>
13#include <linux/of_device.h>
14
15#include <asm/cpuidle.h>
16#include <asm/cpu_ops.h>
17
18int cpu_init_idle(unsigned int cpu)
19{
20 int ret = -EOPNOTSUPP;
21 struct device_node *cpu_node = of_cpu_device_node_get(cpu);
22
23 if (!cpu_node)
24 return -ENODEV;
25
26 if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_init_idle)
27 ret = cpu_ops[cpu]->cpu_init_idle(cpu_node, cpu);
28
29 of_node_put(cpu_node);
30 return ret;
31}
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 177169623026..504fdaa8367e 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -20,8 +20,10 @@
20#include <asm/cputype.h> 20#include <asm/cputype.h>
21 21
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <linux/bug.h>
23#include <linux/init.h> 24#include <linux/init.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/preempt.h>
25#include <linux/printk.h> 27#include <linux/printk.h>
26#include <linux/smp.h> 28#include <linux/smp.h>
27 29
@@ -47,8 +49,18 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
47 unsigned int cpu = smp_processor_id(); 49 unsigned int cpu = smp_processor_id();
48 u32 l1ip = CTR_L1IP(info->reg_ctr); 50 u32 l1ip = CTR_L1IP(info->reg_ctr);
49 51
50 if (l1ip != ICACHE_POLICY_PIPT) 52 if (l1ip != ICACHE_POLICY_PIPT) {
51 set_bit(ICACHEF_ALIASING, &__icache_flags); 53 /*
54 * VIPT caches are non-aliasing if the VA always equals the PA
55 * in all bit positions that are covered by the index. This is
56 * the case if the size of a way (# of sets * line size) does
57 * not exceed PAGE_SIZE.
58 */
59 u32 waysize = icache_get_numsets() * icache_get_linesize();
60
61 if (l1ip != ICACHE_POLICY_VIPT || waysize > PAGE_SIZE)
62 set_bit(ICACHEF_ALIASING, &__icache_flags);
63 }
52 if (l1ip == ICACHE_POLICY_AIVIVT) 64 if (l1ip == ICACHE_POLICY_AIVIVT)
53 set_bit(ICACHEF_AIVIVT, &__icache_flags); 65 set_bit(ICACHEF_AIVIVT, &__icache_flags);
54 66
@@ -190,3 +202,15 @@ void __init cpuinfo_store_boot_cpu(void)
190 202
191 boot_cpu_data = *info; 203 boot_cpu_data = *info;
192} 204}
205
206u64 __attribute_const__ icache_get_ccsidr(void)
207{
208 u64 ccsidr;
209
210 WARN_ON(preemptible());
211
212 /* Select L1 I-cache and read its size ID register */
213 asm("msr csselr_el1, %1; isb; mrs %0, ccsidr_el1"
214 : "=r"(ccsidr) : "r"(1L));
215 return ccsidr;
216}
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
index 1317fef8dde9..d27dd982ff26 100644
--- a/arch/arm64/kernel/efi-stub.c
+++ b/arch/arm64/kernel/efi-stub.c
@@ -28,20 +28,16 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
28 kernel_size = _edata - _text; 28 kernel_size = _edata - _text;
29 if (*image_addr != (dram_base + TEXT_OFFSET)) { 29 if (*image_addr != (dram_base + TEXT_OFFSET)) {
30 kernel_memsize = kernel_size + (_end - _edata); 30 kernel_memsize = kernel_size + (_end - _edata);
31 status = efi_relocate_kernel(sys_table, image_addr, 31 status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET,
32 kernel_size, kernel_memsize, 32 SZ_2M, reserve_addr);
33 dram_base + TEXT_OFFSET,
34 PAGE_SIZE);
35 if (status != EFI_SUCCESS) { 33 if (status != EFI_SUCCESS) {
36 pr_efi_err(sys_table, "Failed to relocate kernel\n"); 34 pr_efi_err(sys_table, "Failed to relocate kernel\n");
37 return status; 35 return status;
38 } 36 }
39 if (*image_addr != (dram_base + TEXT_OFFSET)) { 37 memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr,
40 pr_efi_err(sys_table, "Failed to alloc kernel memory\n"); 38 kernel_size);
41 efi_free(sys_table, kernel_memsize, *image_addr); 39 *image_addr = *reserve_addr + TEXT_OFFSET;
42 return EFI_LOAD_ERROR; 40 *reserve_size = kernel_memsize + TEXT_OFFSET;
43 }
44 *image_size = kernel_memsize;
45 } 41 }
46 42
47 43
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f0b5e5120a87..726b910fe6ec 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -324,7 +324,6 @@ el1_dbg:
324 mrs x0, far_el1 324 mrs x0, far_el1
325 mov x2, sp // struct pt_regs 325 mov x2, sp // struct pt_regs
326 bl do_debug_exception 326 bl do_debug_exception
327 enable_dbg
328 kernel_exit 1 327 kernel_exit 1
329el1_inv: 328el1_inv:
330 // TODO: add support for undefined instructions in kernel mode 329 // TODO: add support for undefined instructions in kernel mode
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index 7924d73b6476..cf8556ae09d0 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -58,7 +58,8 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
58 u32 new; 58 u32 new;
59 59
60 pc = (unsigned long)&ftrace_call; 60 pc = (unsigned long)&ftrace_call;
61 new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true); 61 new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func,
62 AARCH64_INSN_BRANCH_LINK);
62 63
63 return ftrace_modify_code(pc, 0, new, false); 64 return ftrace_modify_code(pc, 0, new, false);
64} 65}
@@ -72,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
72 u32 old, new; 73 u32 old, new;
73 74
74 old = aarch64_insn_gen_nop(); 75 old = aarch64_insn_gen_nop();
75 new = aarch64_insn_gen_branch_imm(pc, addr, true); 76 new = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
76 77
77 return ftrace_modify_code(pc, old, new, true); 78 return ftrace_modify_code(pc, old, new, true);
78} 79}
@@ -86,7 +87,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
86 unsigned long pc = rec->ip; 87 unsigned long pc = rec->ip;
87 u32 old, new; 88 u32 old, new;
88 89
89 old = aarch64_insn_gen_branch_imm(pc, addr, true); 90 old = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
90 new = aarch64_insn_gen_nop(); 91 new = aarch64_insn_gen_nop();
91 92
92 return ftrace_modify_code(pc, old, new, true); 93 return ftrace_modify_code(pc, old, new, true);
@@ -154,7 +155,8 @@ static int ftrace_modify_graph_caller(bool enable)
154 u32 branch, nop; 155 u32 branch, nop;
155 156
156 branch = aarch64_insn_gen_branch_imm(pc, 157 branch = aarch64_insn_gen_branch_imm(pc,
157 (unsigned long)ftrace_graph_caller, false); 158 (unsigned long)ftrace_graph_caller,
159 AARCH64_INSN_BRANCH_LINK);
158 nop = aarch64_insn_gen_nop(); 160 nop = aarch64_insn_gen_nop();
159 161
160 if (enable) 162 if (enable)
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 873069056229..0a6e4f924df8 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -151,7 +151,7 @@ optional_header:
151 .short 0x20b // PE32+ format 151 .short 0x20b // PE32+ format
152 .byte 0x02 // MajorLinkerVersion 152 .byte 0x02 // MajorLinkerVersion
153 .byte 0x14 // MinorLinkerVersion 153 .byte 0x14 // MinorLinkerVersion
154 .long _edata - stext // SizeOfCode 154 .long _end - stext // SizeOfCode
155 .long 0 // SizeOfInitializedData 155 .long 0 // SizeOfInitializedData
156 .long 0 // SizeOfUninitializedData 156 .long 0 // SizeOfUninitializedData
157 .long efi_stub_entry - efi_head // AddressOfEntryPoint 157 .long efi_stub_entry - efi_head // AddressOfEntryPoint
@@ -169,7 +169,7 @@ extra_header_fields:
169 .short 0 // MinorSubsystemVersion 169 .short 0 // MinorSubsystemVersion
170 .long 0 // Win32VersionValue 170 .long 0 // Win32VersionValue
171 171
172 .long _edata - efi_head // SizeOfImage 172 .long _end - efi_head // SizeOfImage
173 173
174 // Everything before the kernel image is considered part of the header 174 // Everything before the kernel image is considered part of the header
175 .long stext - efi_head // SizeOfHeaders 175 .long stext - efi_head // SizeOfHeaders
@@ -216,7 +216,7 @@ section_table:
216 .byte 0 216 .byte 0
217 .byte 0 217 .byte 0
218 .byte 0 // end of 0 padding of section name 218 .byte 0 // end of 0 padding of section name
219 .long _edata - stext // VirtualSize 219 .long _end - stext // VirtualSize
220 .long stext - efi_head // VirtualAddress 220 .long stext - efi_head // VirtualAddress
221 .long _edata - stext // SizeOfRawData 221 .long _edata - stext // SizeOfRawData
222 .long stext - efi_head // PointerToRawData 222 .long stext - efi_head // PointerToRawData
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 92f36835486b..e007714ded04 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -2,6 +2,8 @@
2 * Copyright (C) 2013 Huawei Ltd. 2 * Copyright (C) 2013 Huawei Ltd.
3 * Author: Jiang Liu <liuj97@gmail.com> 3 * Author: Jiang Liu <liuj97@gmail.com>
4 * 4 *
5 * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com>
6 *
5 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
@@ -20,9 +22,14 @@
20#include <linux/smp.h> 22#include <linux/smp.h>
21#include <linux/stop_machine.h> 23#include <linux/stop_machine.h>
22#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25
23#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
27#include <asm/debug-monitors.h>
24#include <asm/insn.h> 28#include <asm/insn.h>
25 29
30#define AARCH64_INSN_SF_BIT BIT(31)
31#define AARCH64_INSN_N_BIT BIT(22)
32
26static int aarch64_insn_encoding_class[] = { 33static int aarch64_insn_encoding_class[] = {
27 AARCH64_INSN_CLS_UNKNOWN, 34 AARCH64_INSN_CLS_UNKNOWN,
28 AARCH64_INSN_CLS_UNKNOWN, 35 AARCH64_INSN_CLS_UNKNOWN,
@@ -251,6 +258,19 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
251 mask = BIT(9) - 1; 258 mask = BIT(9) - 1;
252 shift = 12; 259 shift = 12;
253 break; 260 break;
261 case AARCH64_INSN_IMM_7:
262 mask = BIT(7) - 1;
263 shift = 15;
264 break;
265 case AARCH64_INSN_IMM_6:
266 case AARCH64_INSN_IMM_S:
267 mask = BIT(6) - 1;
268 shift = 10;
269 break;
270 case AARCH64_INSN_IMM_R:
271 mask = BIT(6) - 1;
272 shift = 16;
273 break;
254 default: 274 default:
255 pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n", 275 pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n",
256 type); 276 type);
@@ -264,10 +284,76 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
264 return insn; 284 return insn;
265} 285}
266 286
267u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, 287static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
268 enum aarch64_insn_branch_type type) 288 u32 insn,
289 enum aarch64_insn_register reg)
290{
291 int shift;
292
293 if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) {
294 pr_err("%s: unknown register encoding %d\n", __func__, reg);
295 return 0;
296 }
297
298 switch (type) {
299 case AARCH64_INSN_REGTYPE_RT:
300 case AARCH64_INSN_REGTYPE_RD:
301 shift = 0;
302 break;
303 case AARCH64_INSN_REGTYPE_RN:
304 shift = 5;
305 break;
306 case AARCH64_INSN_REGTYPE_RT2:
307 case AARCH64_INSN_REGTYPE_RA:
308 shift = 10;
309 break;
310 case AARCH64_INSN_REGTYPE_RM:
311 shift = 16;
312 break;
313 default:
314 pr_err("%s: unknown register type encoding %d\n", __func__,
315 type);
316 return 0;
317 }
318
319 insn &= ~(GENMASK(4, 0) << shift);
320 insn |= reg << shift;
321
322 return insn;
323}
324
325static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
326 u32 insn)
327{
328 u32 size;
329
330 switch (type) {
331 case AARCH64_INSN_SIZE_8:
332 size = 0;
333 break;
334 case AARCH64_INSN_SIZE_16:
335 size = 1;
336 break;
337 case AARCH64_INSN_SIZE_32:
338 size = 2;
339 break;
340 case AARCH64_INSN_SIZE_64:
341 size = 3;
342 break;
343 default:
344 pr_err("%s: unknown size encoding %d\n", __func__, type);
345 return 0;
346 }
347
348 insn &= ~GENMASK(31, 30);
349 insn |= size << 30;
350
351 return insn;
352}
353
354static inline long branch_imm_common(unsigned long pc, unsigned long addr,
355 long range)
269{ 356{
270 u32 insn;
271 long offset; 357 long offset;
272 358
273 /* 359 /*
@@ -276,23 +362,97 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
276 */ 362 */
277 BUG_ON((pc & 0x3) || (addr & 0x3)); 363 BUG_ON((pc & 0x3) || (addr & 0x3));
278 364
365 offset = ((long)addr - (long)pc);
366 BUG_ON(offset < -range || offset >= range);
367
368 return offset;
369}
370
371u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
372 enum aarch64_insn_branch_type type)
373{
374 u32 insn;
375 long offset;
376
279 /* 377 /*
280 * B/BL support [-128M, 128M) offset 378 * B/BL support [-128M, 128M) offset
281 * ARM64 virtual address arrangement guarantees all kernel and module 379 * ARM64 virtual address arrangement guarantees all kernel and module
282 * texts are within +/-128M. 380 * texts are within +/-128M.
283 */ 381 */
284 offset = ((long)addr - (long)pc); 382 offset = branch_imm_common(pc, addr, SZ_128M);
285 BUG_ON(offset < -SZ_128M || offset >= SZ_128M);
286 383
287 if (type == AARCH64_INSN_BRANCH_LINK) 384 switch (type) {
385 case AARCH64_INSN_BRANCH_LINK:
288 insn = aarch64_insn_get_bl_value(); 386 insn = aarch64_insn_get_bl_value();
289 else 387 break;
388 case AARCH64_INSN_BRANCH_NOLINK:
290 insn = aarch64_insn_get_b_value(); 389 insn = aarch64_insn_get_b_value();
390 break;
391 default:
392 BUG_ON(1);
393 return AARCH64_BREAK_FAULT;
394 }
291 395
292 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn, 396 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
293 offset >> 2); 397 offset >> 2);
294} 398}
295 399
400u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
401 enum aarch64_insn_register reg,
402 enum aarch64_insn_variant variant,
403 enum aarch64_insn_branch_type type)
404{
405 u32 insn;
406 long offset;
407
408 offset = branch_imm_common(pc, addr, SZ_1M);
409
410 switch (type) {
411 case AARCH64_INSN_BRANCH_COMP_ZERO:
412 insn = aarch64_insn_get_cbz_value();
413 break;
414 case AARCH64_INSN_BRANCH_COMP_NONZERO:
415 insn = aarch64_insn_get_cbnz_value();
416 break;
417 default:
418 BUG_ON(1);
419 return AARCH64_BREAK_FAULT;
420 }
421
422 switch (variant) {
423 case AARCH64_INSN_VARIANT_32BIT:
424 break;
425 case AARCH64_INSN_VARIANT_64BIT:
426 insn |= AARCH64_INSN_SF_BIT;
427 break;
428 default:
429 BUG_ON(1);
430 return AARCH64_BREAK_FAULT;
431 }
432
433 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
434
435 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
436 offset >> 2);
437}
438
439u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
440 enum aarch64_insn_condition cond)
441{
442 u32 insn;
443 long offset;
444
445 offset = branch_imm_common(pc, addr, SZ_1M);
446
447 insn = aarch64_insn_get_bcond_value();
448
449 BUG_ON(cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL);
450 insn |= cond;
451
452 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
453 offset >> 2);
454}
455
296u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_op op) 456u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_op op)
297{ 457{
298 return aarch64_insn_get_hint_value() | op; 458 return aarch64_insn_get_hint_value() | op;
@@ -302,3 +462,500 @@ u32 __kprobes aarch64_insn_gen_nop(void)
302{ 462{
303 return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP); 463 return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
304} 464}
465
466u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
467 enum aarch64_insn_branch_type type)
468{
469 u32 insn;
470
471 switch (type) {
472 case AARCH64_INSN_BRANCH_NOLINK:
473 insn = aarch64_insn_get_br_value();
474 break;
475 case AARCH64_INSN_BRANCH_LINK:
476 insn = aarch64_insn_get_blr_value();
477 break;
478 case AARCH64_INSN_BRANCH_RETURN:
479 insn = aarch64_insn_get_ret_value();
480 break;
481 default:
482 BUG_ON(1);
483 return AARCH64_BREAK_FAULT;
484 }
485
486 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg);
487}
488
489u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
490 enum aarch64_insn_register base,
491 enum aarch64_insn_register offset,
492 enum aarch64_insn_size_type size,
493 enum aarch64_insn_ldst_type type)
494{
495 u32 insn;
496
497 switch (type) {
498 case AARCH64_INSN_LDST_LOAD_REG_OFFSET:
499 insn = aarch64_insn_get_ldr_reg_value();
500 break;
501 case AARCH64_INSN_LDST_STORE_REG_OFFSET:
502 insn = aarch64_insn_get_str_reg_value();
503 break;
504 default:
505 BUG_ON(1);
506 return AARCH64_BREAK_FAULT;
507 }
508
509 insn = aarch64_insn_encode_ldst_size(size, insn);
510
511 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
512
513 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
514 base);
515
516 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
517 offset);
518}
519
520u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
521 enum aarch64_insn_register reg2,
522 enum aarch64_insn_register base,
523 int offset,
524 enum aarch64_insn_variant variant,
525 enum aarch64_insn_ldst_type type)
526{
527 u32 insn;
528 int shift;
529
530 switch (type) {
531 case AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX:
532 insn = aarch64_insn_get_ldp_pre_value();
533 break;
534 case AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX:
535 insn = aarch64_insn_get_stp_pre_value();
536 break;
537 case AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX:
538 insn = aarch64_insn_get_ldp_post_value();
539 break;
540 case AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX:
541 insn = aarch64_insn_get_stp_post_value();
542 break;
543 default:
544 BUG_ON(1);
545 return AARCH64_BREAK_FAULT;
546 }
547
548 switch (variant) {
549 case AARCH64_INSN_VARIANT_32BIT:
550 /* offset must be multiples of 4 in the range [-256, 252] */
551 BUG_ON(offset & 0x3);
552 BUG_ON(offset < -256 || offset > 252);
553 shift = 2;
554 break;
555 case AARCH64_INSN_VARIANT_64BIT:
556 /* offset must be multiples of 8 in the range [-512, 504] */
557 BUG_ON(offset & 0x7);
558 BUG_ON(offset < -512 || offset > 504);
559 shift = 3;
560 insn |= AARCH64_INSN_SF_BIT;
561 break;
562 default:
563 BUG_ON(1);
564 return AARCH64_BREAK_FAULT;
565 }
566
567 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
568 reg1);
569
570 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
571 reg2);
572
573 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
574 base);
575
576 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_7, insn,
577 offset >> shift);
578}
579
580u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
581 enum aarch64_insn_register src,
582 int imm, enum aarch64_insn_variant variant,
583 enum aarch64_insn_adsb_type type)
584{
585 u32 insn;
586
587 switch (type) {
588 case AARCH64_INSN_ADSB_ADD:
589 insn = aarch64_insn_get_add_imm_value();
590 break;
591 case AARCH64_INSN_ADSB_SUB:
592 insn = aarch64_insn_get_sub_imm_value();
593 break;
594 case AARCH64_INSN_ADSB_ADD_SETFLAGS:
595 insn = aarch64_insn_get_adds_imm_value();
596 break;
597 case AARCH64_INSN_ADSB_SUB_SETFLAGS:
598 insn = aarch64_insn_get_subs_imm_value();
599 break;
600 default:
601 BUG_ON(1);
602 return AARCH64_BREAK_FAULT;
603 }
604
605 switch (variant) {
606 case AARCH64_INSN_VARIANT_32BIT:
607 break;
608 case AARCH64_INSN_VARIANT_64BIT:
609 insn |= AARCH64_INSN_SF_BIT;
610 break;
611 default:
612 BUG_ON(1);
613 return AARCH64_BREAK_FAULT;
614 }
615
616 BUG_ON(imm & ~(SZ_4K - 1));
617
618 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
619
620 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
621
622 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
623}
624
625u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
626 enum aarch64_insn_register src,
627 int immr, int imms,
628 enum aarch64_insn_variant variant,
629 enum aarch64_insn_bitfield_type type)
630{
631 u32 insn;
632 u32 mask;
633
634 switch (type) {
635 case AARCH64_INSN_BITFIELD_MOVE:
636 insn = aarch64_insn_get_bfm_value();
637 break;
638 case AARCH64_INSN_BITFIELD_MOVE_UNSIGNED:
639 insn = aarch64_insn_get_ubfm_value();
640 break;
641 case AARCH64_INSN_BITFIELD_MOVE_SIGNED:
642 insn = aarch64_insn_get_sbfm_value();
643 break;
644 default:
645 BUG_ON(1);
646 return AARCH64_BREAK_FAULT;
647 }
648
649 switch (variant) {
650 case AARCH64_INSN_VARIANT_32BIT:
651 mask = GENMASK(4, 0);
652 break;
653 case AARCH64_INSN_VARIANT_64BIT:
654 insn |= AARCH64_INSN_SF_BIT | AARCH64_INSN_N_BIT;
655 mask = GENMASK(5, 0);
656 break;
657 default:
658 BUG_ON(1);
659 return AARCH64_BREAK_FAULT;
660 }
661
662 BUG_ON(immr & ~mask);
663 BUG_ON(imms & ~mask);
664
665 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
666
667 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
668
669 insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
670
671 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
672}
673
674u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst,
675 int imm, int shift,
676 enum aarch64_insn_variant variant,
677 enum aarch64_insn_movewide_type type)
678{
679 u32 insn;
680
681 switch (type) {
682 case AARCH64_INSN_MOVEWIDE_ZERO:
683 insn = aarch64_insn_get_movz_value();
684 break;
685 case AARCH64_INSN_MOVEWIDE_KEEP:
686 insn = aarch64_insn_get_movk_value();
687 break;
688 case AARCH64_INSN_MOVEWIDE_INVERSE:
689 insn = aarch64_insn_get_movn_value();
690 break;
691 default:
692 BUG_ON(1);
693 return AARCH64_BREAK_FAULT;
694 }
695
696 BUG_ON(imm & ~(SZ_64K - 1));
697
698 switch (variant) {
699 case AARCH64_INSN_VARIANT_32BIT:
700 BUG_ON(shift != 0 && shift != 16);
701 break;
702 case AARCH64_INSN_VARIANT_64BIT:
703 insn |= AARCH64_INSN_SF_BIT;
704 BUG_ON(shift != 0 && shift != 16 && shift != 32 &&
705 shift != 48);
706 break;
707 default:
708 BUG_ON(1);
709 return AARCH64_BREAK_FAULT;
710 }
711
712 insn |= (shift >> 4) << 21;
713
714 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
715
716 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_16, insn, imm);
717}
718
719u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst,
720 enum aarch64_insn_register src,
721 enum aarch64_insn_register reg,
722 int shift,
723 enum aarch64_insn_variant variant,
724 enum aarch64_insn_adsb_type type)
725{
726 u32 insn;
727
728 switch (type) {
729 case AARCH64_INSN_ADSB_ADD:
730 insn = aarch64_insn_get_add_value();
731 break;
732 case AARCH64_INSN_ADSB_SUB:
733 insn = aarch64_insn_get_sub_value();
734 break;
735 case AARCH64_INSN_ADSB_ADD_SETFLAGS:
736 insn = aarch64_insn_get_adds_value();
737 break;
738 case AARCH64_INSN_ADSB_SUB_SETFLAGS:
739 insn = aarch64_insn_get_subs_value();
740 break;
741 default:
742 BUG_ON(1);
743 return AARCH64_BREAK_FAULT;
744 }
745
746 switch (variant) {
747 case AARCH64_INSN_VARIANT_32BIT:
748 BUG_ON(shift & ~(SZ_32 - 1));
749 break;
750 case AARCH64_INSN_VARIANT_64BIT:
751 insn |= AARCH64_INSN_SF_BIT;
752 BUG_ON(shift & ~(SZ_64 - 1));
753 break;
754 default:
755 BUG_ON(1);
756 return AARCH64_BREAK_FAULT;
757 }
758
759
760 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
761
762 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
763
764 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
765
766 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
767}
768
769u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst,
770 enum aarch64_insn_register src,
771 enum aarch64_insn_variant variant,
772 enum aarch64_insn_data1_type type)
773{
774 u32 insn;
775
776 switch (type) {
777 case AARCH64_INSN_DATA1_REVERSE_16:
778 insn = aarch64_insn_get_rev16_value();
779 break;
780 case AARCH64_INSN_DATA1_REVERSE_32:
781 insn = aarch64_insn_get_rev32_value();
782 break;
783 case AARCH64_INSN_DATA1_REVERSE_64:
784 BUG_ON(variant != AARCH64_INSN_VARIANT_64BIT);
785 insn = aarch64_insn_get_rev64_value();
786 break;
787 default:
788 BUG_ON(1);
789 return AARCH64_BREAK_FAULT;
790 }
791
792 switch (variant) {
793 case AARCH64_INSN_VARIANT_32BIT:
794 break;
795 case AARCH64_INSN_VARIANT_64BIT:
796 insn |= AARCH64_INSN_SF_BIT;
797 break;
798 default:
799 BUG_ON(1);
800 return AARCH64_BREAK_FAULT;
801 }
802
803 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
804
805 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
806}
807
808u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
809 enum aarch64_insn_register src,
810 enum aarch64_insn_register reg,
811 enum aarch64_insn_variant variant,
812 enum aarch64_insn_data2_type type)
813{
814 u32 insn;
815
816 switch (type) {
817 case AARCH64_INSN_DATA2_UDIV:
818 insn = aarch64_insn_get_udiv_value();
819 break;
820 case AARCH64_INSN_DATA2_SDIV:
821 insn = aarch64_insn_get_sdiv_value();
822 break;
823 case AARCH64_INSN_DATA2_LSLV:
824 insn = aarch64_insn_get_lslv_value();
825 break;
826 case AARCH64_INSN_DATA2_LSRV:
827 insn = aarch64_insn_get_lsrv_value();
828 break;
829 case AARCH64_INSN_DATA2_ASRV:
830 insn = aarch64_insn_get_asrv_value();
831 break;
832 case AARCH64_INSN_DATA2_RORV:
833 insn = aarch64_insn_get_rorv_value();
834 break;
835 default:
836 BUG_ON(1);
837 return AARCH64_BREAK_FAULT;
838 }
839
840 switch (variant) {
841 case AARCH64_INSN_VARIANT_32BIT:
842 break;
843 case AARCH64_INSN_VARIANT_64BIT:
844 insn |= AARCH64_INSN_SF_BIT;
845 break;
846 default:
847 BUG_ON(1);
848 return AARCH64_BREAK_FAULT;
849 }
850
851 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
852
853 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
854
855 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
856}
857
858u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
859 enum aarch64_insn_register src,
860 enum aarch64_insn_register reg1,
861 enum aarch64_insn_register reg2,
862 enum aarch64_insn_variant variant,
863 enum aarch64_insn_data3_type type)
864{
865 u32 insn;
866
867 switch (type) {
868 case AARCH64_INSN_DATA3_MADD:
869 insn = aarch64_insn_get_madd_value();
870 break;
871 case AARCH64_INSN_DATA3_MSUB:
872 insn = aarch64_insn_get_msub_value();
873 break;
874 default:
875 BUG_ON(1);
876 return AARCH64_BREAK_FAULT;
877 }
878
879 switch (variant) {
880 case AARCH64_INSN_VARIANT_32BIT:
881 break;
882 case AARCH64_INSN_VARIANT_64BIT:
883 insn |= AARCH64_INSN_SF_BIT;
884 break;
885 default:
886 BUG_ON(1);
887 return AARCH64_BREAK_FAULT;
888 }
889
890 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
891
892 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RA, insn, src);
893
894 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
895 reg1);
896
897 return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
898 reg2);
899}
900
901u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
902 enum aarch64_insn_register src,
903 enum aarch64_insn_register reg,
904 int shift,
905 enum aarch64_insn_variant variant,
906 enum aarch64_insn_logic_type type)
907{
908 u32 insn;
909
910 switch (type) {
911 case AARCH64_INSN_LOGIC_AND:
912 insn = aarch64_insn_get_and_value();
913 break;
914 case AARCH64_INSN_LOGIC_BIC:
915 insn = aarch64_insn_get_bic_value();
916 break;
917 case AARCH64_INSN_LOGIC_ORR:
918 insn = aarch64_insn_get_orr_value();
919 break;
920 case AARCH64_INSN_LOGIC_ORN:
921 insn = aarch64_insn_get_orn_value();
922 break;
923 case AARCH64_INSN_LOGIC_EOR:
924 insn = aarch64_insn_get_eor_value();
925 break;
926 case AARCH64_INSN_LOGIC_EON:
927 insn = aarch64_insn_get_eon_value();
928 break;
929 case AARCH64_INSN_LOGIC_AND_SETFLAGS:
930 insn = aarch64_insn_get_ands_value();
931 break;
932 case AARCH64_INSN_LOGIC_BIC_SETFLAGS:
933 insn = aarch64_insn_get_bics_value();
934 break;
935 default:
936 BUG_ON(1);
937 return AARCH64_BREAK_FAULT;
938 }
939
940 switch (variant) {
941 case AARCH64_INSN_VARIANT_32BIT:
942 BUG_ON(shift & ~(SZ_32 - 1));
943 break;
944 case AARCH64_INSN_VARIANT_64BIT:
945 insn |= AARCH64_INSN_SF_BIT;
946 BUG_ON(shift & ~(SZ_64 - 1));
947 break;
948 default:
949 BUG_ON(1);
950 return AARCH64_BREAK_FAULT;
951 }
952
953
954 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
955
956 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
957
958 insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
959
960 return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
961}
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 75c9cf1aafee..a0d10c55f307 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -235,13 +235,13 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
235 235
236static struct break_hook kgdb_brkpt_hook = { 236static struct break_hook kgdb_brkpt_hook = {
237 .esr_mask = 0xffffffff, 237 .esr_mask = 0xffffffff,
238 .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM), 238 .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DBG_BRK_IMM),
239 .fn = kgdb_brk_fn 239 .fn = kgdb_brk_fn
240}; 240};
241 241
242static struct break_hook kgdb_compiled_brkpt_hook = { 242static struct break_hook kgdb_compiled_brkpt_hook = {
243 .esr_mask = 0xffffffff, 243 .esr_mask = 0xffffffff,
244 .esr_val = DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM), 244 .esr_val = DBG_ESR_VAL_BRK(KGDB_COMPILED_DBG_BRK_IMM),
245 .fn = kgdb_compiled_brk_fn 245 .fn = kgdb_compiled_brk_fn
246}; 246};
247 247
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index baf5afb7e6a0..aa29ecb4f800 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1276,7 +1276,7 @@ arch_initcall(cpu_pmu_reset);
1276/* 1276/*
1277 * PMU platform driver and devicetree bindings. 1277 * PMU platform driver and devicetree bindings.
1278 */ 1278 */
1279static struct of_device_id armpmu_of_device_ids[] = { 1279static const struct of_device_id armpmu_of_device_ids[] = {
1280 {.compatible = "arm,armv8-pmuv3"}, 1280 {.compatible = "arm,armv8-pmuv3"},
1281 {}, 1281 {},
1282}; 1282};
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 29d48690f2ac..89f41f7d27dd 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -57,36 +57,10 @@ unsigned long __stack_chk_guard __read_mostly;
57EXPORT_SYMBOL(__stack_chk_guard); 57EXPORT_SYMBOL(__stack_chk_guard);
58#endif 58#endif
59 59
60static void setup_restart(void)
61{
62 /*
63 * Tell the mm system that we are going to reboot -
64 * we may need it to insert some 1:1 mappings so that
65 * soft boot works.
66 */
67 setup_mm_for_reboot();
68
69 /* Clean and invalidate caches */
70 flush_cache_all();
71
72 /* Turn D-cache off */
73 cpu_cache_off();
74
75 /* Push out any further dirty data, and ensure cache is empty */
76 flush_cache_all();
77}
78
79void soft_restart(unsigned long addr) 60void soft_restart(unsigned long addr)
80{ 61{
81 typedef void (*phys_reset_t)(unsigned long); 62 setup_mm_for_reboot();
82 phys_reset_t phys_reset; 63 cpu_soft_restart(virt_to_phys(cpu_reset), addr);
83
84 setup_restart();
85
86 /* Switch to the identity mapping */
87 phys_reset = (phys_reset_t)virt_to_phys(cpu_reset);
88 phys_reset(addr);
89
90 /* Should never get here */ 64 /* Should never get here */
91 BUG(); 65 BUG();
92} 66}
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 553954771a67..866c1c821860 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -21,6 +21,7 @@
21#include <linux/reboot.h> 21#include <linux/reboot.h>
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/slab.h>
24#include <uapi/linux/psci.h> 25#include <uapi/linux/psci.h>
25 26
26#include <asm/compiler.h> 27#include <asm/compiler.h>
@@ -28,6 +29,7 @@
28#include <asm/errno.h> 29#include <asm/errno.h>
29#include <asm/psci.h> 30#include <asm/psci.h>
30#include <asm/smp_plat.h> 31#include <asm/smp_plat.h>
32#include <asm/suspend.h>
31#include <asm/system_misc.h> 33#include <asm/system_misc.h>
32 34
33#define PSCI_POWER_STATE_TYPE_STANDBY 0 35#define PSCI_POWER_STATE_TYPE_STANDBY 0
@@ -65,6 +67,8 @@ enum psci_function {
65 PSCI_FN_MAX, 67 PSCI_FN_MAX,
66}; 68};
67 69
70static DEFINE_PER_CPU_READ_MOSTLY(struct psci_power_state *, psci_power_state);
71
68static u32 psci_function_id[PSCI_FN_MAX]; 72static u32 psci_function_id[PSCI_FN_MAX];
69 73
70static int psci_to_linux_errno(int errno) 74static int psci_to_linux_errno(int errno)
@@ -93,6 +97,18 @@ static u32 psci_power_state_pack(struct psci_power_state state)
93 & PSCI_0_2_POWER_STATE_AFFL_MASK); 97 & PSCI_0_2_POWER_STATE_AFFL_MASK);
94} 98}
95 99
100static void psci_power_state_unpack(u32 power_state,
101 struct psci_power_state *state)
102{
103 state->id = (power_state & PSCI_0_2_POWER_STATE_ID_MASK) >>
104 PSCI_0_2_POWER_STATE_ID_SHIFT;
105 state->type = (power_state & PSCI_0_2_POWER_STATE_TYPE_MASK) >>
106 PSCI_0_2_POWER_STATE_TYPE_SHIFT;
107 state->affinity_level =
108 (power_state & PSCI_0_2_POWER_STATE_AFFL_MASK) >>
109 PSCI_0_2_POWER_STATE_AFFL_SHIFT;
110}
111
96/* 112/*
97 * The following two functions are invoked via the invoke_psci_fn pointer 113 * The following two functions are invoked via the invoke_psci_fn pointer
98 * and will not be inlined, allowing us to piggyback on the AAPCS. 114 * and will not be inlined, allowing us to piggyback on the AAPCS.
@@ -199,6 +215,63 @@ static int psci_migrate_info_type(void)
199 return err; 215 return err;
200} 216}
201 217
218static int __maybe_unused cpu_psci_cpu_init_idle(struct device_node *cpu_node,
219 unsigned int cpu)
220{
221 int i, ret, count = 0;
222 struct psci_power_state *psci_states;
223 struct device_node *state_node;
224
225 /*
226 * If the PSCI cpu_suspend function hook has not been initialized
227 * idle states must not be enabled, so bail out
228 */
229 if (!psci_ops.cpu_suspend)
230 return -EOPNOTSUPP;
231
232 /* Count idle states */
233 while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
234 count))) {
235 count++;
236 of_node_put(state_node);
237 }
238
239 if (!count)
240 return -ENODEV;
241
242 psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
243 if (!psci_states)
244 return -ENOMEM;
245
246 for (i = 0; i < count; i++) {
247 u32 psci_power_state;
248
249 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
250
251 ret = of_property_read_u32(state_node,
252 "arm,psci-suspend-param",
253 &psci_power_state);
254 if (ret) {
255 pr_warn(" * %s missing arm,psci-suspend-param property\n",
256 state_node->full_name);
257 of_node_put(state_node);
258 goto free_mem;
259 }
260
261 of_node_put(state_node);
262 pr_debug("psci-power-state %#x index %d\n", psci_power_state,
263 i);
264 psci_power_state_unpack(psci_power_state, &psci_states[i]);
265 }
266 /* Idle states parsed correctly, initialize per-cpu pointer */
267 per_cpu(psci_power_state, cpu) = psci_states;
268 return 0;
269
270free_mem:
271 kfree(psci_states);
272 return ret;
273}
274
202static int get_set_conduit_method(struct device_node *np) 275static int get_set_conduit_method(struct device_node *np)
203{ 276{
204 const char *method; 277 const char *method;
@@ -436,8 +509,39 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
436#endif 509#endif
437#endif 510#endif
438 511
512static int psci_suspend_finisher(unsigned long index)
513{
514 struct psci_power_state *state = __get_cpu_var(psci_power_state);
515
516 return psci_ops.cpu_suspend(state[index - 1],
517 virt_to_phys(cpu_resume));
518}
519
520static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
521{
522 int ret;
523 struct psci_power_state *state = __get_cpu_var(psci_power_state);
524 /*
525 * idle state index 0 corresponds to wfi, should never be called
526 * from the cpu_suspend operations
527 */
528 if (WARN_ON_ONCE(!index))
529 return -EINVAL;
530
531 if (state->type == PSCI_POWER_STATE_TYPE_STANDBY)
532 ret = psci_ops.cpu_suspend(state[index - 1], 0);
533 else
534 ret = __cpu_suspend(index, psci_suspend_finisher);
535
536 return ret;
537}
538
439const struct cpu_operations cpu_psci_ops = { 539const struct cpu_operations cpu_psci_ops = {
440 .name = "psci", 540 .name = "psci",
541#ifdef CONFIG_CPU_IDLE
542 .cpu_init_idle = cpu_psci_cpu_init_idle,
543 .cpu_suspend = cpu_psci_cpu_suspend,
544#endif
441#ifdef CONFIG_SMP 545#ifdef CONFIG_SMP
442 .cpu_init = cpu_psci_cpu_init, 546 .cpu_init = cpu_psci_cpu_init,
443 .cpu_prepare = cpu_psci_cpu_prepare, 547 .cpu_prepare = cpu_psci_cpu_prepare,
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index 89102a6ffad5..6c4fd2810ecb 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -36,13 +36,12 @@ void *return_address(unsigned int level)
36{ 36{
37 struct return_address_data data; 37 struct return_address_data data;
38 struct stackframe frame; 38 struct stackframe frame;
39 register unsigned long current_sp asm ("sp");
40 39
41 data.level = level + 2; 40 data.level = level + 2;
42 data.addr = NULL; 41 data.addr = NULL;
43 42
44 frame.fp = (unsigned long)__builtin_frame_address(0); 43 frame.fp = (unsigned long)__builtin_frame_address(0);
45 frame.sp = current_sp; 44 frame.sp = current_stack_pointer;
46 frame.pc = (unsigned long)return_address; /* dummy */ 45 frame.pc = (unsigned long)return_address; /* dummy */
47 46
48 walk_stackframe(&frame, save_return_addr, &data); 47 walk_stackframe(&frame, save_return_addr, &data);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index edb146d01857..2437196cc5d4 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -365,11 +365,6 @@ u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
365 365
366void __init setup_arch(char **cmdline_p) 366void __init setup_arch(char **cmdline_p)
367{ 367{
368 /*
369 * Unmask asynchronous aborts early to catch possible system errors.
370 */
371 local_async_enable();
372
373 setup_processor(); 368 setup_processor();
374 369
375 setup_machine_fdt(__fdt_pointer); 370 setup_machine_fdt(__fdt_pointer);
@@ -385,6 +380,12 @@ void __init setup_arch(char **cmdline_p)
385 380
386 parse_early_param(); 381 parse_early_param();
387 382
383 /*
384 * Unmask asynchronous aborts after bringing up possible earlycon.
385 * (Report possible System Errors once we can report this occurred)
386 */
387 local_async_enable();
388
388 efi_init(); 389 efi_init();
389 arm64_memblock_init(); 390 arm64_memblock_init();
390 391
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index b1925729c692..a564b440416a 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -49,28 +49,39 @@
49 orr \dst, \dst, \mask // dst|=(aff3>>rs3) 49 orr \dst, \dst, \mask // dst|=(aff3>>rs3)
50 .endm 50 .endm
51/* 51/*
52 * Save CPU state for a suspend. This saves callee registers, and allocates 52 * Save CPU state for a suspend and execute the suspend finisher.
53 * space on the kernel stack to save the CPU specific registers + some 53 * On success it will return 0 through cpu_resume - ie through a CPU
54 * other data for resume. 54 * soft/hard reboot from the reset vector.
55 * On failure it returns the suspend finisher return value or force
56 * -EOPNOTSUPP if the finisher erroneously returns 0 (the suspend finisher
57 * is not allowed to return, if it does this must be considered failure).
58 * It saves callee registers, and allocates space on the kernel stack
59 * to save the CPU specific registers + some other data for resume.
55 * 60 *
56 * x0 = suspend finisher argument 61 * x0 = suspend finisher argument
62 * x1 = suspend finisher function pointer
57 */ 63 */
58ENTRY(__cpu_suspend) 64ENTRY(__cpu_suspend_enter)
59 stp x29, lr, [sp, #-96]! 65 stp x29, lr, [sp, #-96]!
60 stp x19, x20, [sp,#16] 66 stp x19, x20, [sp,#16]
61 stp x21, x22, [sp,#32] 67 stp x21, x22, [sp,#32]
62 stp x23, x24, [sp,#48] 68 stp x23, x24, [sp,#48]
63 stp x25, x26, [sp,#64] 69 stp x25, x26, [sp,#64]
64 stp x27, x28, [sp,#80] 70 stp x27, x28, [sp,#80]
71 /*
72 * Stash suspend finisher and its argument in x20 and x19
73 */
74 mov x19, x0
75 mov x20, x1
65 mov x2, sp 76 mov x2, sp
66 sub sp, sp, #CPU_SUSPEND_SZ // allocate cpu_suspend_ctx 77 sub sp, sp, #CPU_SUSPEND_SZ // allocate cpu_suspend_ctx
67 mov x1, sp 78 mov x0, sp
68 /* 79 /*
69 * x1 now points to struct cpu_suspend_ctx allocated on the stack 80 * x0 now points to struct cpu_suspend_ctx allocated on the stack
70 */ 81 */
71 str x2, [x1, #CPU_CTX_SP] 82 str x2, [x0, #CPU_CTX_SP]
72 ldr x2, =sleep_save_sp 83 ldr x1, =sleep_save_sp
73 ldr x2, [x2, #SLEEP_SAVE_SP_VIRT] 84 ldr x1, [x1, #SLEEP_SAVE_SP_VIRT]
74#ifdef CONFIG_SMP 85#ifdef CONFIG_SMP
75 mrs x7, mpidr_el1 86 mrs x7, mpidr_el1
76 ldr x9, =mpidr_hash 87 ldr x9, =mpidr_hash
@@ -82,11 +93,21 @@ ENTRY(__cpu_suspend)
82 ldp w3, w4, [x9, #MPIDR_HASH_SHIFTS] 93 ldp w3, w4, [x9, #MPIDR_HASH_SHIFTS]
83 ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)] 94 ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)]
84 compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10 95 compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10
85 add x2, x2, x8, lsl #3 96 add x1, x1, x8, lsl #3
86#endif 97#endif
87 bl __cpu_suspend_finisher 98 bl __cpu_suspend_save
99 /*
100 * Grab suspend finisher in x20 and its argument in x19
101 */
102 mov x0, x19
103 mov x1, x20
104 /*
105 * We are ready for power down, fire off the suspend finisher
106 * in x1, with argument in x0
107 */
108 blr x1
88 /* 109 /*
89 * Never gets here, unless suspend fails. 110 * Never gets here, unless suspend finisher fails.
90 * Successful cpu_suspend should return from cpu_resume, returning 111 * Successful cpu_suspend should return from cpu_resume, returning
91 * through this code path is considered an error 112 * through this code path is considered an error
92 * If the return value is set to 0 force x0 = -EOPNOTSUPP 113 * If the return value is set to 0 force x0 = -EOPNOTSUPP
@@ -103,7 +124,7 @@ ENTRY(__cpu_suspend)
103 ldp x27, x28, [sp, #80] 124 ldp x27, x28, [sp, #80]
104 ldp x29, lr, [sp], #96 125 ldp x29, lr, [sp], #96
105 ret 126 ret
106ENDPROC(__cpu_suspend) 127ENDPROC(__cpu_suspend_enter)
107 .ltorg 128 .ltorg
108 129
109/* 130/*
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 0347d38eea29..4f93c67e63de 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -20,6 +20,7 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/smp.h> 22#include <linux/smp.h>
23#include <linux/types.h>
23 24
24#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
25#include <asm/cpu_ops.h> 26#include <asm/cpu_ops.h>
@@ -65,12 +66,21 @@ static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
65 66
66static int smp_spin_table_cpu_prepare(unsigned int cpu) 67static int smp_spin_table_cpu_prepare(unsigned int cpu)
67{ 68{
68 void **release_addr; 69 __le64 __iomem *release_addr;
69 70
70 if (!cpu_release_addr[cpu]) 71 if (!cpu_release_addr[cpu])
71 return -ENODEV; 72 return -ENODEV;
72 73
73 release_addr = __va(cpu_release_addr[cpu]); 74 /*
75 * The cpu-release-addr may or may not be inside the linear mapping.
76 * As ioremap_cache will either give us a new mapping or reuse the
77 * existing linear mapping, we can use it to cover both cases. In
78 * either case the memory will be MT_NORMAL.
79 */
80 release_addr = ioremap_cache(cpu_release_addr[cpu],
81 sizeof(*release_addr));
82 if (!release_addr)
83 return -ENOMEM;
74 84
75 /* 85 /*
76 * We write the release address as LE regardless of the native 86 * We write the release address as LE regardless of the native
@@ -79,15 +89,17 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu)
79 * boot-loader's endianess before jumping. This is mandated by 89 * boot-loader's endianess before jumping. This is mandated by
80 * the boot protocol. 90 * the boot protocol.
81 */ 91 */
82 release_addr[0] = (void *) cpu_to_le64(__pa(secondary_holding_pen)); 92 writeq_relaxed(__pa(secondary_holding_pen), release_addr);
83 93 __flush_dcache_area((__force void *)release_addr,
84 __flush_dcache_area(release_addr, sizeof(release_addr[0])); 94 sizeof(*release_addr));
85 95
86 /* 96 /*
87 * Send an event to wake up the secondary CPU. 97 * Send an event to wake up the secondary CPU.
88 */ 98 */
89 sev(); 99 sev();
90 100
101 iounmap(release_addr);
102
91 return 0; 103 return 0;
92} 104}
93 105
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 55437ba1f5a4..407991bf79f5 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -111,10 +111,9 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
111 frame.sp = thread_saved_sp(tsk); 111 frame.sp = thread_saved_sp(tsk);
112 frame.pc = thread_saved_pc(tsk); 112 frame.pc = thread_saved_pc(tsk);
113 } else { 113 } else {
114 register unsigned long current_sp asm("sp");
115 data.no_sched_functions = 0; 114 data.no_sched_functions = 0;
116 frame.fp = (unsigned long)__builtin_frame_address(0); 115 frame.fp = (unsigned long)__builtin_frame_address(0);
117 frame.sp = current_sp; 116 frame.sp = current_stack_pointer;
118 frame.pc = (unsigned long)save_stack_trace_tsk; 117 frame.pc = (unsigned long)save_stack_trace_tsk;
119 } 118 }
120 119
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 55a99b9a97e0..13ad4dbb1615 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -9,22 +9,19 @@
9#include <asm/suspend.h> 9#include <asm/suspend.h>
10#include <asm/tlbflush.h> 10#include <asm/tlbflush.h>
11 11
12extern int __cpu_suspend(unsigned long); 12extern int __cpu_suspend_enter(unsigned long arg, int (*fn)(unsigned long));
13/* 13/*
14 * This is called by __cpu_suspend() to save the state, and do whatever 14 * This is called by __cpu_suspend_enter() to save the state, and do whatever
15 * flushing is required to ensure that when the CPU goes to sleep we have 15 * flushing is required to ensure that when the CPU goes to sleep we have
16 * the necessary data available when the caches are not searched. 16 * the necessary data available when the caches are not searched.
17 * 17 *
18 * @arg: Argument to pass to suspend operations 18 * ptr: CPU context virtual address
19 * @ptr: CPU context virtual address 19 * save_ptr: address of the location where the context physical address
20 * @save_ptr: address of the location where the context physical address 20 * must be saved
21 * must be saved
22 */ 21 */
23int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, 22void notrace __cpu_suspend_save(struct cpu_suspend_ctx *ptr,
24 phys_addr_t *save_ptr) 23 phys_addr_t *save_ptr)
25{ 24{
26 int cpu = smp_processor_id();
27
28 *save_ptr = virt_to_phys(ptr); 25 *save_ptr = virt_to_phys(ptr);
29 26
30 cpu_do_suspend(ptr); 27 cpu_do_suspend(ptr);
@@ -35,8 +32,6 @@ int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr,
35 */ 32 */
36 __flush_dcache_area(ptr, sizeof(*ptr)); 33 __flush_dcache_area(ptr, sizeof(*ptr));
37 __flush_dcache_area(save_ptr, sizeof(*save_ptr)); 34 __flush_dcache_area(save_ptr, sizeof(*save_ptr));
38
39 return cpu_ops[cpu]->cpu_suspend(arg);
40} 35}
41 36
42/* 37/*
@@ -56,15 +51,15 @@ void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *))
56} 51}
57 52
58/** 53/**
59 * cpu_suspend 54 * cpu_suspend() - function to enter a low-power state
55 * @arg: argument to pass to CPU suspend operations
60 * 56 *
61 * @arg: argument to pass to the finisher function 57 * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU
58 * operations back-end error code otherwise.
62 */ 59 */
63int cpu_suspend(unsigned long arg) 60int cpu_suspend(unsigned long arg)
64{ 61{
65 struct mm_struct *mm = current->active_mm; 62 int cpu = smp_processor_id();
66 int ret, cpu = smp_processor_id();
67 unsigned long flags;
68 63
69 /* 64 /*
70 * If cpu_ops have not been registered or suspend 65 * If cpu_ops have not been registered or suspend
@@ -72,6 +67,21 @@ int cpu_suspend(unsigned long arg)
72 */ 67 */
73 if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) 68 if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend)
74 return -EOPNOTSUPP; 69 return -EOPNOTSUPP;
70 return cpu_ops[cpu]->cpu_suspend(arg);
71}
72
73/*
74 * __cpu_suspend
75 *
76 * arg: argument to pass to the finisher function
77 * fn: finisher function pointer
78 *
79 */
80int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
81{
82 struct mm_struct *mm = current->active_mm;
83 int ret;
84 unsigned long flags;
75 85
76 /* 86 /*
77 * From this point debug exceptions are disabled to prevent 87 * From this point debug exceptions are disabled to prevent
@@ -86,7 +96,7 @@ int cpu_suspend(unsigned long arg)
86 * page tables, so that the thread address space is properly 96 * page tables, so that the thread address space is properly
87 * set-up on function return. 97 * set-up on function return.
88 */ 98 */
89 ret = __cpu_suspend(arg); 99 ret = __cpu_suspend_enter(arg, fn);
90 if (ret == 0) { 100 if (ret == 0) {
91 cpu_switch_mm(mm->pgd, mm); 101 cpu_switch_mm(mm->pgd, mm);
92 flush_tlb_all(); 102 flush_tlb_all();
@@ -95,7 +105,7 @@ int cpu_suspend(unsigned long arg)
95 * Restore per-cpu offset before any kernel 105 * Restore per-cpu offset before any kernel
96 * subsystem relying on it has a chance to run. 106 * subsystem relying on it has a chance to run.
97 */ 107 */
98 set_my_cpu_offset(per_cpu_offset(cpu)); 108 set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
99 109
100 /* 110 /*
101 * Restore HW breakpoint registers to sane values 111 * Restore HW breakpoint registers to sane values
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 02cd3f023e9a..de1b085e7963 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -132,7 +132,6 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
132static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) 132static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
133{ 133{
134 struct stackframe frame; 134 struct stackframe frame;
135 const register unsigned long current_sp asm ("sp");
136 135
137 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 136 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
138 137
@@ -145,7 +144,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
145 frame.pc = regs->pc; 144 frame.pc = regs->pc;
146 } else if (tsk == current) { 145 } else if (tsk == current) {
147 frame.fp = (unsigned long)__builtin_frame_address(0); 146 frame.fp = (unsigned long)__builtin_frame_address(0);
148 frame.sp = current_sp; 147 frame.sp = current_stack_pointer;
149 frame.pc = (unsigned long)dump_backtrace; 148 frame.pc = (unsigned long)dump_backtrace;
150 } else { 149 } else {
151 /* 150 /*