diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 18:01:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 18:01:45 -0400 |
commit | 1ce235faa8fefa4eb7199cad890944c1d2ba1b3e (patch) | |
tree | 1ed51ca928c6760d524dc853cd879ab958e66bd9 | |
parent | e38be1b1066687204b05b6a46a2018806c7281de (diff) | |
parent | 196adf2f3015eacac0567278ba538e3ffdd16d0e (diff) |
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull ARM64 updates from Catalin Marinas:
- KGDB support for arm64
- PCI I/O space extended to 16M (in preparation of PCIe support
patches)
- Dropping ZONE_DMA32 in favour of ZONE_DMA (we only need one for the
time being), together with swiotlb late initialisation to correctly
setup the bounce buffer
- DMA API cache maintenance support (not all ARMv8 platforms have
hardware cache coherency)
- Crypto extensions advertising via ELF_HWCAP2 for compat user space
- Perf support for dwarf unwinding in compat mode
- asm/tlb.h converted to the generic mmu_gather code
- asm-generic rwsem implementation
- Code clean-up
* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (42 commits)
arm64: Remove pgprot_dmacoherent()
arm64: Support DMA_ATTR_WRITE_COMBINE
arm64: Implement custom mmap functions for dma mapping
arm64: Fix __range_ok macro
arm64: Fix duplicated Kconfig entries
arm64: mm: Route pmd thp functions through pte equivalents
arm64: rwsem: use asm-generic rwsem implementation
asm-generic: rwsem: de-PPCify rwsem.h
arm64: enable generic CPU feature modalias matching for this architecture
arm64: smp: make local symbol static
arm64: debug: make local symbols static
ARM64: perf: support dwarf unwinding in compat mode
ARM64: perf: add support for frame pointer unwinding in compat mode
ARM64: perf: add support for perf registers API
arm64: Add boot time configuration of Intermediate Physical Address size
arm64: Do not synchronise I and D caches for special ptes
arm64: Make DMA coherent and strongly ordered mappings not executable
arm64: barriers: add dmb barrier
arm64: topology: Implement basic CPU topology support
arm64: advertise ARMv8 extensions to 32-bit compat ELF binaries
...
45 files changed, 1368 insertions, 307 deletions
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt index 5e054bfe4dde..85e24c4f215c 100644 --- a/Documentation/arm64/memory.txt +++ b/Documentation/arm64/memory.txt | |||
@@ -35,11 +35,13 @@ ffffffbc00000000 ffffffbdffffffff 8GB vmemmap | |||
35 | 35 | ||
36 | ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] | 36 | ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] |
37 | 37 | ||
38 | ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device | 38 | ffffffbffa000000 ffffffbffaffffff 16MB PCI I/O space |
39 | |||
40 | ffffffbffb000000 ffffffbffbbfffff 12MB [guard] | ||
39 | 41 | ||
40 | ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space | 42 | ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device |
41 | 43 | ||
42 | ffffffbffbe10000 ffffffbcffffffff ~2MB [guard] | 44 | ffffffbffbe00000 ffffffbffbffffff 2MB [guard] |
43 | 45 | ||
44 | ffffffbffc000000 ffffffbfffffffff 64MB modules | 46 | ffffffbffc000000 ffffffbfffffffff 64MB modules |
45 | 47 | ||
@@ -60,11 +62,13 @@ fffffdfc00000000 fffffdfdffffffff 8GB vmemmap | |||
60 | 62 | ||
61 | fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap] | 63 | fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap] |
62 | 64 | ||
63 | fffffdfffbc00000 fffffdfffbdfffff 2MB earlyprintk device | 65 | fffffdfffa000000 fffffdfffaffffff 16MB PCI I/O space |
66 | |||
67 | fffffdfffb000000 fffffdfffbbfffff 12MB [guard] | ||
64 | 68 | ||
65 | fffffdfffbe00000 fffffdfffbe0ffff 64KB PCI I/O space | 69 | fffffdfffbc00000 fffffdfffbdfffff 2MB earlyprintk device |
66 | 70 | ||
67 | fffffdfffbe10000 fffffdfffbffffff ~2MB [guard] | 71 | fffffdfffbe00000 fffffdfffbffffff 2MB [guard] |
68 | 72 | ||
69 | fffffdfffc000000 fffffdffffffffff 64MB modules | 73 | fffffdfffc000000 fffffdffffffffff 64MB modules |
70 | 74 | ||
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 27bbcfc7202a..516d8a7ca697 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -16,6 +16,7 @@ config ARM64 | |||
16 | select DCACHE_WORD_ACCESS | 16 | select DCACHE_WORD_ACCESS |
17 | select GENERIC_CLOCKEVENTS | 17 | select GENERIC_CLOCKEVENTS |
18 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP | 18 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP |
19 | select GENERIC_CPU_AUTOPROBE | ||
19 | select GENERIC_IOMAP | 20 | select GENERIC_IOMAP |
20 | select GENERIC_IRQ_PROBE | 21 | select GENERIC_IRQ_PROBE |
21 | select GENERIC_IRQ_SHOW | 22 | select GENERIC_IRQ_SHOW |
@@ -26,6 +27,7 @@ config ARM64 | |||
26 | select GENERIC_TIME_VSYSCALL | 27 | select GENERIC_TIME_VSYSCALL |
27 | select HARDIRQS_SW_RESEND | 28 | select HARDIRQS_SW_RESEND |
28 | select HAVE_ARCH_JUMP_LABEL | 29 | select HAVE_ARCH_JUMP_LABEL |
30 | select HAVE_ARCH_KGDB | ||
29 | select HAVE_ARCH_TRACEHOOK | 31 | select HAVE_ARCH_TRACEHOOK |
30 | select HAVE_DEBUG_BUGVERBOSE | 32 | select HAVE_DEBUG_BUGVERBOSE |
31 | select HAVE_DEBUG_KMEMLEAK | 33 | select HAVE_DEBUG_KMEMLEAK |
@@ -38,6 +40,8 @@ config ARM64 | |||
38 | select HAVE_MEMBLOCK | 40 | select HAVE_MEMBLOCK |
39 | select HAVE_PATA_PLATFORM | 41 | select HAVE_PATA_PLATFORM |
40 | select HAVE_PERF_EVENTS | 42 | select HAVE_PERF_EVENTS |
43 | select HAVE_PERF_REGS | ||
44 | select HAVE_PERF_USER_STACK_DUMP | ||
41 | select IRQ_DOMAIN | 45 | select IRQ_DOMAIN |
42 | select MODULES_USE_ELF_RELA | 46 | select MODULES_USE_ELF_RELA |
43 | select NO_BOOTMEM | 47 | select NO_BOOTMEM |
@@ -73,7 +77,7 @@ config LOCKDEP_SUPPORT | |||
73 | config TRACE_IRQFLAGS_SUPPORT | 77 | config TRACE_IRQFLAGS_SUPPORT |
74 | def_bool y | 78 | def_bool y |
75 | 79 | ||
76 | config RWSEM_GENERIC_SPINLOCK | 80 | config RWSEM_XCHGADD_ALGORITHM |
77 | def_bool y | 81 | def_bool y |
78 | 82 | ||
79 | config GENERIC_HWEIGHT | 83 | config GENERIC_HWEIGHT |
@@ -85,7 +89,7 @@ config GENERIC_CSUM | |||
85 | config GENERIC_CALIBRATE_DELAY | 89 | config GENERIC_CALIBRATE_DELAY |
86 | def_bool y | 90 | def_bool y |
87 | 91 | ||
88 | config ZONE_DMA32 | 92 | config ZONE_DMA |
89 | def_bool y | 93 | def_bool y |
90 | 94 | ||
91 | config ARCH_DMA_ADDR_T_64BIT | 95 | config ARCH_DMA_ADDR_T_64BIT |
@@ -164,6 +168,22 @@ config SMP | |||
164 | 168 | ||
165 | If you don't know what to do here, say N. | 169 | If you don't know what to do here, say N. |
166 | 170 | ||
171 | config SCHED_MC | ||
172 | bool "Multi-core scheduler support" | ||
173 | depends on SMP | ||
174 | help | ||
175 | Multi-core scheduler support improves the CPU scheduler's decision | ||
176 | making when dealing with multi-core CPU chips at a cost of slightly | ||
177 | increased overhead in some places. If unsure say N here. | ||
178 | |||
179 | config SCHED_SMT | ||
180 | bool "SMT scheduler support" | ||
181 | depends on SMP | ||
182 | help | ||
183 | Improves the CPU scheduler's decision making when dealing with | ||
184 | MultiThreading at a cost of slightly increased overhead in some | ||
185 | places. If unsure say N here. | ||
186 | |||
167 | config NR_CPUS | 187 | config NR_CPUS |
168 | int "Maximum number of CPUs (2-32)" | 188 | int "Maximum number of CPUs (2-32)" |
169 | range 2 32 | 189 | range 2 32 |
@@ -301,6 +321,8 @@ menu "CPU Power Management" | |||
301 | 321 | ||
302 | source "drivers/cpuidle/Kconfig" | 322 | source "drivers/cpuidle/Kconfig" |
303 | 323 | ||
324 | source "drivers/cpufreq/Kconfig" | ||
325 | |||
304 | endmenu | 326 | endmenu |
305 | 327 | ||
306 | source "net/Kconfig" | 328 | source "net/Kconfig" |
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 3bdfdda70567..4bca4923fc0b 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild | |||
@@ -32,6 +32,7 @@ generic-y += poll.h | |||
32 | generic-y += posix_types.h | 32 | generic-y += posix_types.h |
33 | generic-y += preempt.h | 33 | generic-y += preempt.h |
34 | generic-y += resource.h | 34 | generic-y += resource.h |
35 | generic-y += rwsem.h | ||
35 | generic-y += scatterlist.h | 36 | generic-y += scatterlist.h |
36 | generic-y += sections.h | 37 | generic-y += sections.h |
37 | generic-y += segment.h | 38 | generic-y += segment.h |
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 409ca370cfe2..66eb7648043b 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define wfi() asm volatile("wfi" : : : "memory") | 25 | #define wfi() asm volatile("wfi" : : : "memory") |
26 | 26 | ||
27 | #define isb() asm volatile("isb" : : : "memory") | 27 | #define isb() asm volatile("isb" : : : "memory") |
28 | #define dmb(opt) asm volatile("dmb sy" : : : "memory") | ||
28 | #define dsb(opt) asm volatile("dsb sy" : : : "memory") | 29 | #define dsb(opt) asm volatile("dsb sy" : : : "memory") |
29 | 30 | ||
30 | #define mb() dsb() | 31 | #define mb() dsb() |
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h index 889324981aa4..4c60e64a801c 100644 --- a/arch/arm64/include/asm/cacheflush.h +++ b/arch/arm64/include/asm/cacheflush.h | |||
@@ -85,6 +85,13 @@ static inline void flush_cache_page(struct vm_area_struct *vma, | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /* | 87 | /* |
88 | * Cache maintenance functions used by the DMA API. No to be used directly. | ||
89 | */ | ||
90 | extern void __dma_map_area(const void *, size_t, int); | ||
91 | extern void __dma_unmap_area(const void *, size_t, int); | ||
92 | extern void __dma_flush_range(const void *, const void *); | ||
93 | |||
94 | /* | ||
88 | * Copy user data from/to a page which is mapped into a different | 95 | * Copy user data from/to a page which is mapped into a different |
89 | * processes address space. Really, we want to allow our "user | 96 | * processes address space. Really, we want to allow our "user |
90 | * space" model to handle this. | 97 | * space" model to handle this. |
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index fda2704b3f9f..e71f81fe127a 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h | |||
@@ -228,7 +228,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
228 | return (u32)(unsigned long)uptr; | 228 | return (u32)(unsigned long)uptr; |
229 | } | 229 | } |
230 | 230 | ||
231 | #define compat_user_stack_pointer() (current_pt_regs()->compat_sp) | 231 | #define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs())) |
232 | 232 | ||
233 | static inline void __user *arch_compat_alloc_user_space(long len) | 233 | static inline void __user *arch_compat_alloc_user_space(long len) |
234 | { | 234 | { |
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h new file mode 100644 index 000000000000..cd4ac0516488 --- /dev/null +++ b/arch/arm64/include/asm/cpufeature.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __ASM_CPUFEATURE_H | ||
10 | #define __ASM_CPUFEATURE_H | ||
11 | |||
12 | #include <asm/hwcap.h> | ||
13 | |||
14 | /* | ||
15 | * In the arm64 world (as in the ARM world), elf_hwcap is used both internally | ||
16 | * in the kernel and for user space to keep track of which optional features | ||
17 | * are supported by the current system. So let's map feature 'x' to HWCAP_x. | ||
18 | * Note that HWCAP_x constants are bit fields so we need to take the log. | ||
19 | */ | ||
20 | |||
21 | #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) | ||
22 | #define cpu_feature(x) ilog2(HWCAP_ ## x) | ||
23 | |||
24 | static inline bool cpu_have_feature(unsigned int num) | ||
25 | { | ||
26 | return elf_hwcap & (1UL << num); | ||
27 | } | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index 62314791570c..6e9b5b36921c 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h | |||
@@ -26,6 +26,53 @@ | |||
26 | #define DBG_ESR_EVT_HWWP 0x2 | 26 | #define DBG_ESR_EVT_HWWP 0x2 |
27 | #define DBG_ESR_EVT_BRK 0x6 | 27 | #define DBG_ESR_EVT_BRK 0x6 |
28 | 28 | ||
29 | /* | ||
30 | * Break point instruction encoding | ||
31 | */ | ||
32 | #define BREAK_INSTR_SIZE 4 | ||
33 | |||
34 | /* | ||
35 | * ESR values expected for dynamic and compile time BRK instruction | ||
36 | */ | ||
37 | #define DBG_ESR_VAL_BRK(x) (0xf2000000 | ((x) & 0xfffff)) | ||
38 | |||
39 | /* | ||
40 | * #imm16 values used for BRK instruction generation | ||
41 | * Allowed values for kgbd are 0x400 - 0x7ff | ||
42 | * 0x400: for dynamic BRK instruction | ||
43 | * 0x401: for compile time BRK instruction | ||
44 | */ | ||
45 | #define KGDB_DYN_DGB_BRK_IMM 0x400 | ||
46 | #define KDBG_COMPILED_DBG_BRK_IMM 0x401 | ||
47 | |||
48 | /* | ||
49 | * BRK instruction encoding | ||
50 | * The #imm16 value should be placed at bits[20:5] within BRK ins | ||
51 | */ | ||
52 | #define AARCH64_BREAK_MON 0xd4200000 | ||
53 | |||
54 | /* | ||
55 | * Extract byte from BRK instruction | ||
56 | */ | ||
57 | #define KGDB_DYN_DGB_BRK_INS_BYTE(x) \ | ||
58 | ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff) | ||
59 | |||
60 | /* | ||
61 | * Extract byte from BRK #imm16 | ||
62 | */ | ||
63 | #define KGBD_DYN_DGB_BRK_IMM_BYTE(x) \ | ||
64 | (((((KGDB_DYN_DGB_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff) | ||
65 | |||
66 | #define KGDB_DYN_DGB_BRK_BYTE(x) \ | ||
67 | (KGDB_DYN_DGB_BRK_INS_BYTE(x) | KGBD_DYN_DGB_BRK_IMM_BYTE(x)) | ||
68 | |||
69 | #define KGDB_DYN_BRK_INS_BYTE0 KGDB_DYN_DGB_BRK_BYTE(0) | ||
70 | #define KGDB_DYN_BRK_INS_BYTE1 KGDB_DYN_DGB_BRK_BYTE(1) | ||
71 | #define KGDB_DYN_BRK_INS_BYTE2 KGDB_DYN_DGB_BRK_BYTE(2) | ||
72 | #define KGDB_DYN_BRK_INS_BYTE3 KGDB_DYN_DGB_BRK_BYTE(3) | ||
73 | |||
74 | #define CACHE_FLUSH_IS_SAFE 1 | ||
75 | |||
29 | enum debug_el { | 76 | enum debug_el { |
30 | DBG_ACTIVE_EL0 = 0, | 77 | DBG_ACTIVE_EL0 = 0, |
31 | DBG_ACTIVE_EL1, | 78 | DBG_ACTIVE_EL1, |
@@ -43,23 +90,6 @@ enum debug_el { | |||
43 | #ifndef __ASSEMBLY__ | 90 | #ifndef __ASSEMBLY__ |
44 | struct task_struct; | 91 | struct task_struct; |
45 | 92 | ||
46 | #define local_dbg_save(flags) \ | ||
47 | do { \ | ||
48 | typecheck(unsigned long, flags); \ | ||
49 | asm volatile( \ | ||
50 | "mrs %0, daif // local_dbg_save\n" \ | ||
51 | "msr daifset, #8" \ | ||
52 | : "=r" (flags) : : "memory"); \ | ||
53 | } while (0) | ||
54 | |||
55 | #define local_dbg_restore(flags) \ | ||
56 | do { \ | ||
57 | typecheck(unsigned long, flags); \ | ||
58 | asm volatile( \ | ||
59 | "msr daif, %0 // local_dbg_restore\n" \ | ||
60 | : : "r" (flags) : "memory"); \ | ||
61 | } while (0) | ||
62 | |||
63 | #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ | 93 | #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ |
64 | 94 | ||
65 | #define DBG_HOOK_HANDLED 0 | 95 | #define DBG_HOOK_HANDLED 0 |
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index fd0c0c0e447a..3a4572ec3273 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #define DMA_ERROR_CODE (~(dma_addr_t)0) | 31 | #define DMA_ERROR_CODE (~(dma_addr_t)0) |
32 | extern struct dma_map_ops *dma_ops; | 32 | extern struct dma_map_ops *dma_ops; |
33 | extern struct dma_map_ops coherent_swiotlb_dma_ops; | ||
34 | extern struct dma_map_ops noncoherent_swiotlb_dma_ops; | ||
33 | 35 | ||
34 | static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) | 36 | static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) |
35 | { | 37 | { |
@@ -47,6 +49,11 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) | |||
47 | return __generic_dma_ops(dev); | 49 | return __generic_dma_ops(dev); |
48 | } | 50 | } |
49 | 51 | ||
52 | static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | ||
53 | { | ||
54 | dev->archdata.dma_ops = ops; | ||
55 | } | ||
56 | |||
50 | #include <asm-generic/dma-mapping-common.h> | 57 | #include <asm-generic/dma-mapping-common.h> |
51 | 58 | ||
52 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 59 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index 6cddbb0c9f54..024c46183c3c 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h | |||
@@ -32,6 +32,12 @@ | |||
32 | #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) | 32 | #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) |
33 | #define COMPAT_HWCAP_EVTSTRM (1 << 21) | 33 | #define COMPAT_HWCAP_EVTSTRM (1 << 21) |
34 | 34 | ||
35 | #define COMPAT_HWCAP2_AES (1 << 0) | ||
36 | #define COMPAT_HWCAP2_PMULL (1 << 1) | ||
37 | #define COMPAT_HWCAP2_SHA1 (1 << 2) | ||
38 | #define COMPAT_HWCAP2_SHA2 (1 << 3) | ||
39 | #define COMPAT_HWCAP2_CRC32 (1 << 4) | ||
40 | |||
35 | #ifndef __ASSEMBLY__ | 41 | #ifndef __ASSEMBLY__ |
36 | /* | 42 | /* |
37 | * This yields a mask that user programs can use to figure out what | 43 | * This yields a mask that user programs can use to figure out what |
@@ -41,7 +47,8 @@ | |||
41 | 47 | ||
42 | #ifdef CONFIG_COMPAT | 48 | #ifdef CONFIG_COMPAT |
43 | #define COMPAT_ELF_HWCAP (compat_elf_hwcap) | 49 | #define COMPAT_ELF_HWCAP (compat_elf_hwcap) |
44 | extern unsigned int compat_elf_hwcap; | 50 | #define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2) |
51 | extern unsigned int compat_elf_hwcap, compat_elf_hwcap2; | ||
45 | #endif | 52 | #endif |
46 | 53 | ||
47 | extern unsigned long elf_hwcap; | 54 | extern unsigned long elf_hwcap; |
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 4cc813eddacb..7846a6bb0833 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h | |||
@@ -121,7 +121,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) | |||
121 | * I/O port access primitives. | 121 | * I/O port access primitives. |
122 | */ | 122 | */ |
123 | #define IO_SPACE_LIMIT 0xffff | 123 | #define IO_SPACE_LIMIT 0xffff |
124 | #define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_2M)) | 124 | #define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_32M)) |
125 | 125 | ||
126 | static inline u8 inb(unsigned long addr) | 126 | static inline u8 inb(unsigned long addr) |
127 | { | 127 | { |
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h index b2fcfbc51ecc..11cc941bd107 100644 --- a/arch/arm64/include/asm/irqflags.h +++ b/arch/arm64/include/asm/irqflags.h | |||
@@ -90,5 +90,28 @@ static inline int arch_irqs_disabled_flags(unsigned long flags) | |||
90 | return flags & PSR_I_BIT; | 90 | return flags & PSR_I_BIT; |
91 | } | 91 | } |
92 | 92 | ||
93 | /* | ||
94 | * save and restore debug state | ||
95 | */ | ||
96 | #define local_dbg_save(flags) \ | ||
97 | do { \ | ||
98 | typecheck(unsigned long, flags); \ | ||
99 | asm volatile( \ | ||
100 | "mrs %0, daif // local_dbg_save\n" \ | ||
101 | "msr daifset, #8" \ | ||
102 | : "=r" (flags) : : "memory"); \ | ||
103 | } while (0) | ||
104 | |||
105 | #define local_dbg_restore(flags) \ | ||
106 | do { \ | ||
107 | typecheck(unsigned long, flags); \ | ||
108 | asm volatile( \ | ||
109 | "msr daif, %0 // local_dbg_restore\n" \ | ||
110 | : : "r" (flags) : "memory"); \ | ||
111 | } while (0) | ||
112 | |||
113 | #define local_dbg_enable() asm("msr daifclr, #8" : : : "memory") | ||
114 | #define local_dbg_disable() asm("msr daifset, #8" : : : "memory") | ||
115 | |||
93 | #endif | 116 | #endif |
94 | #endif | 117 | #endif |
diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h new file mode 100644 index 000000000000..3c8aafc1082f --- /dev/null +++ b/arch/arm64/include/asm/kgdb.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * AArch64 KGDB support | ||
3 | * | ||
4 | * Based on arch/arm/include/kgdb.h | ||
5 | * | ||
6 | * Copyright (C) 2013 Cavium Inc. | ||
7 | * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #ifndef __ARM_KGDB_H | ||
23 | #define __ARM_KGDB_H | ||
24 | |||
25 | #include <linux/ptrace.h> | ||
26 | #include <asm/debug-monitors.h> | ||
27 | |||
28 | #ifndef __ASSEMBLY__ | ||
29 | |||
30 | static inline void arch_kgdb_breakpoint(void) | ||
31 | { | ||
32 | asm ("brk %0" : : "I" (KDBG_COMPILED_DBG_BRK_IMM)); | ||
33 | } | ||
34 | |||
35 | extern void kgdb_handle_bus_error(void); | ||
36 | extern int kgdb_fault_expected; | ||
37 | |||
38 | #endif /* !__ASSEMBLY__ */ | ||
39 | |||
40 | /* | ||
41 | * gdb is expecting the following registers layout. | ||
42 | * | ||
43 | * General purpose regs: | ||
44 | * r0-r30: 64 bit | ||
45 | * sp,pc : 64 bit | ||
46 | * pstate : 64 bit | ||
47 | * Total: 34 | ||
48 | * FPU regs: | ||
49 | * f0-f31: 128 bit | ||
50 | * Total: 32 | ||
51 | * Extra regs | ||
52 | * fpsr & fpcr: 32 bit | ||
53 | * Total: 2 | ||
54 | * | ||
55 | */ | ||
56 | |||
57 | #define _GP_REGS 34 | ||
58 | #define _FP_REGS 32 | ||
59 | #define _EXTRA_REGS 2 | ||
60 | /* | ||
61 | * general purpose registers size in bytes. | ||
62 | * pstate is only 4 bytes. subtract 4 bytes | ||
63 | */ | ||
64 | #define GP_REG_BYTES (_GP_REGS * 8) | ||
65 | #define DBG_MAX_REG_NUM (_GP_REGS + _FP_REGS + _EXTRA_REGS) | ||
66 | |||
67 | /* | ||
68 | * Size of I/O buffer for gdb packet. | ||
69 | * considering to hold all register contents, size is set | ||
70 | */ | ||
71 | |||
72 | #define BUFMAX 2048 | ||
73 | |||
74 | /* | ||
75 | * Number of bytes required for gdb_regs buffer. | ||
76 | * _GP_REGS: 8 bytes, _FP_REGS: 16 bytes and _EXTRA_REGS: 4 bytes each | ||
77 | * GDB fails to connect for size beyond this with error | ||
78 | * "'g' packet reply is too long" | ||
79 | */ | ||
80 | |||
81 | #define NUMREGBYTES ((_GP_REGS * 8) + (_FP_REGS * 16) + \ | ||
82 | (_EXTRA_REGS * 4)) | ||
83 | |||
84 | #endif /* __ASM_KGDB_H */ | ||
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 0eb398655378..21ef48d32ff2 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h | |||
@@ -106,7 +106,6 @@ | |||
106 | 106 | ||
107 | /* VTCR_EL2 Registers bits */ | 107 | /* VTCR_EL2 Registers bits */ |
108 | #define VTCR_EL2_PS_MASK (7 << 16) | 108 | #define VTCR_EL2_PS_MASK (7 << 16) |
109 | #define VTCR_EL2_PS_40B (2 << 16) | ||
110 | #define VTCR_EL2_TG0_MASK (1 << 14) | 109 | #define VTCR_EL2_TG0_MASK (1 << 14) |
111 | #define VTCR_EL2_TG0_4K (0 << 14) | 110 | #define VTCR_EL2_TG0_4K (0 << 14) |
112 | #define VTCR_EL2_TG0_64K (1 << 14) | 111 | #define VTCR_EL2_TG0_64K (1 << 14) |
@@ -129,10 +128,9 @@ | |||
129 | * 64kB pages (TG0 = 1) | 128 | * 64kB pages (TG0 = 1) |
130 | * 2 level page tables (SL = 1) | 129 | * 2 level page tables (SL = 1) |
131 | */ | 130 | */ |
132 | #define VTCR_EL2_FLAGS (VTCR_EL2_PS_40B | VTCR_EL2_TG0_64K | \ | 131 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \ |
133 | VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \ | 132 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ |
134 | VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LVL1 | \ | 133 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) |
135 | VTCR_EL2_T0SZ_40B) | ||
136 | #define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) | 134 | #define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) |
137 | #else | 135 | #else |
138 | /* | 136 | /* |
@@ -142,10 +140,9 @@ | |||
142 | * 4kB pages (TG0 = 0) | 140 | * 4kB pages (TG0 = 0) |
143 | * 3 level page tables (SL = 1) | 141 | * 3 level page tables (SL = 1) |
144 | */ | 142 | */ |
145 | #define VTCR_EL2_FLAGS (VTCR_EL2_PS_40B | VTCR_EL2_TG0_4K | \ | 143 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \ |
146 | VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \ | 144 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ |
147 | VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LVL1 | \ | 145 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) |
148 | VTCR_EL2_T0SZ_40B) | ||
149 | #define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) | 146 | #define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) |
150 | #endif | 147 | #endif |
151 | 148 | ||
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index b1d2e26c3c88..f7af66b54cb2 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h | |||
@@ -100,9 +100,9 @@ | |||
100 | #define PTE_HYP PTE_USER | 100 | #define PTE_HYP PTE_USER |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * 40-bit physical address supported. | 103 | * Highest possible physical address supported. |
104 | */ | 104 | */ |
105 | #define PHYS_MASK_SHIFT (40) | 105 | #define PHYS_MASK_SHIFT (48) |
106 | #define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) | 106 | #define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) |
107 | 107 | ||
108 | /* | 108 | /* |
@@ -122,7 +122,6 @@ | |||
122 | #define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) | 122 | #define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) |
123 | #define TCR_TG0_64K (UL(1) << 14) | 123 | #define TCR_TG0_64K (UL(1) << 14) |
124 | #define TCR_TG1_64K (UL(1) << 30) | 124 | #define TCR_TG1_64K (UL(1) << 30) |
125 | #define TCR_IPS_40BIT (UL(2) << 32) | ||
126 | #define TCR_ASID16 (UL(1) << 36) | 125 | #define TCR_ASID16 (UL(1) << 36) |
127 | #define TCR_TBI0 (UL(1) << 37) | 126 | #define TCR_TBI0 (UL(1) << 37) |
128 | 127 | ||
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index aa3917c8b623..90c811f05a2e 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -199,7 +199,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
199 | pte_t *ptep, pte_t pte) | 199 | pte_t *ptep, pte_t pte) |
200 | { | 200 | { |
201 | if (pte_valid_user(pte)) { | 201 | if (pte_valid_user(pte)) { |
202 | if (pte_exec(pte)) | 202 | if (!pte_special(pte) && pte_exec(pte)) |
203 | __sync_icache_dcache(pte, addr); | 203 | __sync_icache_dcache(pte, addr); |
204 | if (pte_dirty(pte) && pte_write(pte)) | 204 | if (pte_dirty(pte) && pte_write(pte)) |
205 | pte_val(pte) &= ~PTE_RDONLY; | 205 | pte_val(pte) &= ~PTE_RDONLY; |
@@ -227,36 +227,36 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
227 | 227 | ||
228 | #define __HAVE_ARCH_PTE_SPECIAL | 228 | #define __HAVE_ARCH_PTE_SPECIAL |
229 | 229 | ||
230 | /* | 230 | static inline pte_t pmd_pte(pmd_t pmd) |
231 | * Software PMD bits for THP | 231 | { |
232 | */ | 232 | return __pte(pmd_val(pmd)); |
233 | } | ||
233 | 234 | ||
234 | #define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) | 235 | static inline pmd_t pte_pmd(pte_t pte) |
235 | #define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57) | 236 | { |
237 | return __pmd(pte_val(pte)); | ||
238 | } | ||
236 | 239 | ||
237 | /* | 240 | /* |
238 | * THP definitions. | 241 | * THP definitions. |
239 | */ | 242 | */ |
240 | #define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) | ||
241 | |||
242 | #define __HAVE_ARCH_PMD_WRITE | ||
243 | #define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) | ||
244 | 243 | ||
245 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 244 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
246 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) | 245 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) |
247 | #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) | 246 | #define pmd_trans_splitting(pmd) pte_special(pmd_pte(pmd)) |
248 | #endif | 247 | #endif |
249 | 248 | ||
250 | #define PMD_BIT_FUNC(fn,op) \ | 249 | #define pmd_young(pmd) pte_young(pmd_pte(pmd)) |
251 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } | 250 | #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd))) |
251 | #define pmd_mksplitting(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd))) | ||
252 | #define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd))) | ||
253 | #define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) | ||
254 | #define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) | ||
255 | #define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) | ||
256 | #define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) &= ~PMD_TYPE_MASK)) | ||
252 | 257 | ||
253 | PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); | 258 | #define __HAVE_ARCH_PMD_WRITE |
254 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); | 259 | #define pmd_write(pmd) pte_write(pmd_pte(pmd)) |
255 | PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); | ||
256 | PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); | ||
257 | PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); | ||
258 | PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); | ||
259 | PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); | ||
260 | 260 | ||
261 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) | 261 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) |
262 | 262 | ||
@@ -266,15 +266,6 @@ PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); | |||
266 | 266 | ||
267 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | 267 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) |
268 | 268 | ||
269 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
270 | { | ||
271 | const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN | | ||
272 | PMD_SECT_RDONLY | PMD_SECT_PROT_NONE | | ||
273 | PMD_SECT_VALID; | ||
274 | pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); | ||
275 | return pmd; | ||
276 | } | ||
277 | |||
278 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) | 269 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) |
279 | 270 | ||
280 | static inline int has_transparent_hugepage(void) | 271 | static inline int has_transparent_hugepage(void) |
@@ -286,11 +277,9 @@ static inline int has_transparent_hugepage(void) | |||
286 | * Mark the prot value as uncacheable and unbufferable. | 277 | * Mark the prot value as uncacheable and unbufferable. |
287 | */ | 278 | */ |
288 | #define pgprot_noncached(prot) \ | 279 | #define pgprot_noncached(prot) \ |
289 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) | 280 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) |
290 | #define pgprot_writecombine(prot) \ | 281 | #define pgprot_writecombine(prot) \ |
291 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) | 282 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) |
292 | #define pgprot_dmacoherent(prot) \ | ||
293 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) | ||
294 | #define __HAVE_PHYS_MEM_ACCESS_PROT | 283 | #define __HAVE_PHYS_MEM_ACCESS_PROT |
295 | struct file; | 284 | struct file; |
296 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 285 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
@@ -383,6 +372,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
383 | return pte; | 372 | return pte; |
384 | } | 373 | } |
385 | 374 | ||
375 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
376 | { | ||
377 | return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); | ||
378 | } | ||
379 | |||
386 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 380 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
387 | extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | 381 | extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; |
388 | 382 | ||
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h index e5312ea0ec1a..d15ab8b46336 100644 --- a/arch/arm64/include/asm/psci.h +++ b/arch/arm64/include/asm/psci.h | |||
@@ -14,6 +14,6 @@ | |||
14 | #ifndef __ASM_PSCI_H | 14 | #ifndef __ASM_PSCI_H |
15 | #define __ASM_PSCI_H | 15 | #define __ASM_PSCI_H |
16 | 16 | ||
17 | int psci_init(void); | 17 | void psci_init(void); |
18 | 18 | ||
19 | #endif /* __ASM_PSCI_H */ | 19 | #endif /* __ASM_PSCI_H */ |
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index 0e7fa4963735..c7ba261dd4b3 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h | |||
@@ -68,6 +68,7 @@ | |||
68 | 68 | ||
69 | /* Architecturally defined mapping between AArch32 and AArch64 registers */ | 69 | /* Architecturally defined mapping between AArch32 and AArch64 registers */ |
70 | #define compat_usr(x) regs[(x)] | 70 | #define compat_usr(x) regs[(x)] |
71 | #define compat_fp regs[11] | ||
71 | #define compat_sp regs[13] | 72 | #define compat_sp regs[13] |
72 | #define compat_lr regs[14] | 73 | #define compat_lr regs[14] |
73 | #define compat_sp_hyp regs[15] | 74 | #define compat_sp_hyp regs[15] |
@@ -132,7 +133,7 @@ struct pt_regs { | |||
132 | (!((regs)->pstate & PSR_F_BIT)) | 133 | (!((regs)->pstate & PSR_F_BIT)) |
133 | 134 | ||
134 | #define user_stack_pointer(regs) \ | 135 | #define user_stack_pointer(regs) \ |
135 | ((regs)->sp) | 136 | (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp) |
136 | 137 | ||
137 | /* | 138 | /* |
138 | * Are the current registers suitable for user mode? (used to maintain | 139 | * Are the current registers suitable for user mode? (used to maintain |
@@ -164,7 +165,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs) | |||
164 | return 0; | 165 | return 0; |
165 | } | 166 | } |
166 | 167 | ||
167 | #define instruction_pointer(regs) (regs)->pc | 168 | #define instruction_pointer(regs) ((unsigned long)(regs)->pc) |
168 | 169 | ||
169 | #ifdef CONFIG_SMP | 170 | #ifdef CONFIG_SMP |
170 | extern unsigned long profile_pc(struct pt_regs *regs); | 171 | extern unsigned long profile_pc(struct pt_regs *regs); |
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h index 717031a762c2..72cadf52ca80 100644 --- a/arch/arm64/include/asm/tlb.h +++ b/arch/arm64/include/asm/tlb.h | |||
@@ -19,115 +19,44 @@ | |||
19 | #ifndef __ASM_TLB_H | 19 | #ifndef __ASM_TLB_H |
20 | #define __ASM_TLB_H | 20 | #define __ASM_TLB_H |
21 | 21 | ||
22 | #include <linux/pagemap.h> | ||
23 | #include <linux/swap.h> | ||
24 | 22 | ||
25 | #include <asm/pgalloc.h> | 23 | #include <asm-generic/tlb.h> |
26 | #include <asm/tlbflush.h> | ||
27 | |||
28 | #define MMU_GATHER_BUNDLE 8 | ||
29 | |||
30 | /* | ||
31 | * TLB handling. This allows us to remove pages from the page | ||
32 | * tables, and efficiently handle the TLB issues. | ||
33 | */ | ||
34 | struct mmu_gather { | ||
35 | struct mm_struct *mm; | ||
36 | unsigned int fullmm; | ||
37 | struct vm_area_struct *vma; | ||
38 | unsigned long start, end; | ||
39 | unsigned long range_start; | ||
40 | unsigned long range_end; | ||
41 | unsigned int nr; | ||
42 | unsigned int max; | ||
43 | struct page **pages; | ||
44 | struct page *local[MMU_GATHER_BUNDLE]; | ||
45 | }; | ||
46 | 24 | ||
47 | /* | 25 | /* |
48 | * This is unnecessarily complex. There's three ways the TLB shootdown | 26 | * There's three ways the TLB shootdown code is used: |
49 | * code is used: | ||
50 | * 1. Unmapping a range of vmas. See zap_page_range(), unmap_region(). | 27 | * 1. Unmapping a range of vmas. See zap_page_range(), unmap_region(). |
51 | * tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. | 28 | * tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. |
52 | * tlb->vma will be non-NULL. | ||
53 | * 2. Unmapping all vmas. See exit_mmap(). | 29 | * 2. Unmapping all vmas. See exit_mmap(). |
54 | * tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. | 30 | * tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. |
55 | * tlb->vma will be non-NULL. Additionally, page tables will be freed. | 31 | * Page tables will be freed. |
56 | * 3. Unmapping argument pages. See shift_arg_pages(). | 32 | * 3. Unmapping argument pages. See shift_arg_pages(). |
57 | * tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. | 33 | * tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. |
58 | * tlb->vma will be NULL. | ||
59 | */ | 34 | */ |
60 | static inline void tlb_flush(struct mmu_gather *tlb) | 35 | static inline void tlb_flush(struct mmu_gather *tlb) |
61 | { | 36 | { |
62 | if (tlb->fullmm || !tlb->vma) | 37 | if (tlb->fullmm) { |
63 | flush_tlb_mm(tlb->mm); | 38 | flush_tlb_mm(tlb->mm); |
64 | else if (tlb->range_end > 0) { | 39 | } else if (tlb->end > 0) { |
65 | flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end); | 40 | struct vm_area_struct vma = { .vm_mm = tlb->mm, }; |
66 | tlb->range_start = TASK_SIZE; | 41 | flush_tlb_range(&vma, tlb->start, tlb->end); |
67 | tlb->range_end = 0; | 42 | tlb->start = TASK_SIZE; |
43 | tlb->end = 0; | ||
68 | } | 44 | } |
69 | } | 45 | } |
70 | 46 | ||
71 | static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) | 47 | static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) |
72 | { | 48 | { |
73 | if (!tlb->fullmm) { | 49 | if (!tlb->fullmm) { |
74 | if (addr < tlb->range_start) | 50 | tlb->start = min(tlb->start, addr); |
75 | tlb->range_start = addr; | 51 | tlb->end = max(tlb->end, addr + PAGE_SIZE); |
76 | if (addr + PAGE_SIZE > tlb->range_end) | ||
77 | tlb->range_end = addr + PAGE_SIZE; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static inline void __tlb_alloc_page(struct mmu_gather *tlb) | ||
82 | { | ||
83 | unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); | ||
84 | |||
85 | if (addr) { | ||
86 | tlb->pages = (void *)addr; | ||
87 | tlb->max = PAGE_SIZE / sizeof(struct page *); | ||
88 | } | 52 | } |
89 | } | 53 | } |
90 | 54 | ||
91 | static inline void tlb_flush_mmu(struct mmu_gather *tlb) | ||
92 | { | ||
93 | tlb_flush(tlb); | ||
94 | free_pages_and_swap_cache(tlb->pages, tlb->nr); | ||
95 | tlb->nr = 0; | ||
96 | if (tlb->pages == tlb->local) | ||
97 | __tlb_alloc_page(tlb); | ||
98 | } | ||
99 | |||
100 | static inline void | ||
101 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) | ||
102 | { | ||
103 | tlb->mm = mm; | ||
104 | tlb->fullmm = !(start | (end+1)); | ||
105 | tlb->start = start; | ||
106 | tlb->end = end; | ||
107 | tlb->vma = NULL; | ||
108 | tlb->max = ARRAY_SIZE(tlb->local); | ||
109 | tlb->pages = tlb->local; | ||
110 | tlb->nr = 0; | ||
111 | __tlb_alloc_page(tlb); | ||
112 | } | ||
113 | |||
114 | static inline void | ||
115 | tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) | ||
116 | { | ||
117 | tlb_flush_mmu(tlb); | ||
118 | |||
119 | /* keep the page table cache within bounds */ | ||
120 | check_pgt_cache(); | ||
121 | |||
122 | if (tlb->pages != tlb->local) | ||
123 | free_pages((unsigned long)tlb->pages, 0); | ||
124 | } | ||
125 | |||
126 | /* | 55 | /* |
127 | * Memorize the range for the TLB flush. | 56 | * Memorize the range for the TLB flush. |
128 | */ | 57 | */ |
129 | static inline void | 58 | static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, |
130 | tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) | 59 | unsigned long addr) |
131 | { | 60 | { |
132 | tlb_add_flush(tlb, addr); | 61 | tlb_add_flush(tlb, addr); |
133 | } | 62 | } |
@@ -137,38 +66,24 @@ tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) | |||
137 | * case where we're doing a full MM flush. When we're doing a munmap, | 66 | * case where we're doing a full MM flush. When we're doing a munmap, |
138 | * the vmas are adjusted to only cover the region to be torn down. | 67 | * the vmas are adjusted to only cover the region to be torn down. |
139 | */ | 68 | */ |
140 | static inline void | 69 | static inline void tlb_start_vma(struct mmu_gather *tlb, |
141 | tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) | 70 | struct vm_area_struct *vma) |
142 | { | 71 | { |
143 | if (!tlb->fullmm) { | 72 | if (!tlb->fullmm) { |
144 | tlb->vma = vma; | 73 | tlb->start = TASK_SIZE; |
145 | tlb->range_start = TASK_SIZE; | 74 | tlb->end = 0; |
146 | tlb->range_end = 0; | ||
147 | } | 75 | } |
148 | } | 76 | } |
149 | 77 | ||
150 | static inline void | 78 | static inline void tlb_end_vma(struct mmu_gather *tlb, |
151 | tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) | 79 | struct vm_area_struct *vma) |
152 | { | 80 | { |
153 | if (!tlb->fullmm) | 81 | if (!tlb->fullmm) |
154 | tlb_flush(tlb); | 82 | tlb_flush(tlb); |
155 | } | 83 | } |
156 | 84 | ||
157 | static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) | ||
158 | { | ||
159 | tlb->pages[tlb->nr++] = page; | ||
160 | VM_BUG_ON(tlb->nr > tlb->max); | ||
161 | return tlb->max - tlb->nr; | ||
162 | } | ||
163 | |||
164 | static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | ||
165 | { | ||
166 | if (!__tlb_remove_page(tlb, page)) | ||
167 | tlb_flush_mmu(tlb); | ||
168 | } | ||
169 | |||
170 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | 85 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, |
171 | unsigned long addr) | 86 | unsigned long addr) |
172 | { | 87 | { |
173 | pgtable_page_dtor(pte); | 88 | pgtable_page_dtor(pte); |
174 | tlb_add_flush(tlb, addr); | 89 | tlb_add_flush(tlb, addr); |
@@ -184,16 +99,5 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, | |||
184 | } | 99 | } |
185 | #endif | 100 | #endif |
186 | 101 | ||
187 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) | ||
188 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) | ||
189 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) | ||
190 | |||
191 | #define tlb_migrate_finish(mm) do { } while (0) | ||
192 | |||
193 | static inline void | ||
194 | tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr) | ||
195 | { | ||
196 | tlb_add_flush(tlb, addr); | ||
197 | } | ||
198 | 102 | ||
199 | #endif | 103 | #endif |
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h new file mode 100644 index 000000000000..0172e6d76bf3 --- /dev/null +++ b/arch/arm64/include/asm/topology.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef __ASM_TOPOLOGY_H | ||
2 | #define __ASM_TOPOLOGY_H | ||
3 | |||
4 | #ifdef CONFIG_SMP | ||
5 | |||
6 | #include <linux/cpumask.h> | ||
7 | |||
8 | struct cpu_topology { | ||
9 | int thread_id; | ||
10 | int core_id; | ||
11 | int cluster_id; | ||
12 | cpumask_t thread_sibling; | ||
13 | cpumask_t core_sibling; | ||
14 | }; | ||
15 | |||
16 | extern struct cpu_topology cpu_topology[NR_CPUS]; | ||
17 | |||
18 | #define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id) | ||
19 | #define topology_core_id(cpu) (cpu_topology[cpu].core_id) | ||
20 | #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) | ||
21 | #define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) | ||
22 | |||
23 | #define mc_capable() (cpu_topology[0].cluster_id != -1) | ||
24 | #define smt_capable() (cpu_topology[0].thread_id != -1) | ||
25 | |||
26 | void init_cpu_topology(void); | ||
27 | void store_cpu_topology(unsigned int cpuid); | ||
28 | const struct cpumask *cpu_coregroup_mask(int cpu); | ||
29 | |||
30 | #else | ||
31 | |||
32 | static inline void init_cpu_topology(void) { } | ||
33 | static inline void store_cpu_topology(unsigned int cpuid) { } | ||
34 | |||
35 | #endif | ||
36 | |||
37 | #include <asm-generic/topology.h> | ||
38 | |||
39 | #endif /* _ASM_ARM_TOPOLOGY_H */ | ||
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 6c0f684aca81..3bf8f4e99a51 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h | |||
@@ -83,7 +83,7 @@ static inline void set_fs(mm_segment_t fs) | |||
83 | * Returns 1 if the range is valid, 0 otherwise. | 83 | * Returns 1 if the range is valid, 0 otherwise. |
84 | * | 84 | * |
85 | * This is equivalent to the following test: | 85 | * This is equivalent to the following test: |
86 | * (u65)addr + (u65)size < (u65)current->addr_limit | 86 | * (u65)addr + (u65)size <= current->addr_limit |
87 | * | 87 | * |
88 | * This needs 65-bit arithmetic. | 88 | * This needs 65-bit arithmetic. |
89 | */ | 89 | */ |
@@ -91,7 +91,7 @@ static inline void set_fs(mm_segment_t fs) | |||
91 | ({ \ | 91 | ({ \ |
92 | unsigned long flag, roksum; \ | 92 | unsigned long flag, roksum; \ |
93 | __chk_user_ptr(addr); \ | 93 | __chk_user_ptr(addr); \ |
94 | asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, cc" \ | 94 | asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ |
95 | : "=&r" (flag), "=&r" (roksum) \ | 95 | : "=&r" (flag), "=&r" (roksum) \ |
96 | : "1" (addr), "Ir" (size), \ | 96 | : "1" (addr), "Ir" (size), \ |
97 | "r" (current_thread_info()->addr_limit) \ | 97 | "r" (current_thread_info()->addr_limit) \ |
diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild index e4b78bdca19e..942376d37d22 100644 --- a/arch/arm64/include/uapi/asm/Kbuild +++ b/arch/arm64/include/uapi/asm/Kbuild | |||
@@ -9,6 +9,7 @@ header-y += byteorder.h | |||
9 | header-y += fcntl.h | 9 | header-y += fcntl.h |
10 | header-y += hwcap.h | 10 | header-y += hwcap.h |
11 | header-y += kvm_para.h | 11 | header-y += kvm_para.h |
12 | header-y += perf_regs.h | ||
12 | header-y += param.h | 13 | header-y += param.h |
13 | header-y += ptrace.h | 14 | header-y += ptrace.h |
14 | header-y += setup.h | 15 | header-y += setup.h |
diff --git a/arch/arm64/include/uapi/asm/perf_regs.h b/arch/arm64/include/uapi/asm/perf_regs.h new file mode 100644 index 000000000000..172b8317ee49 --- /dev/null +++ b/arch/arm64/include/uapi/asm/perf_regs.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef _ASM_ARM64_PERF_REGS_H | ||
2 | #define _ASM_ARM64_PERF_REGS_H | ||
3 | |||
4 | enum perf_event_arm_regs { | ||
5 | PERF_REG_ARM64_X0, | ||
6 | PERF_REG_ARM64_X1, | ||
7 | PERF_REG_ARM64_X2, | ||
8 | PERF_REG_ARM64_X3, | ||
9 | PERF_REG_ARM64_X4, | ||
10 | PERF_REG_ARM64_X5, | ||
11 | PERF_REG_ARM64_X6, | ||
12 | PERF_REG_ARM64_X7, | ||
13 | PERF_REG_ARM64_X8, | ||
14 | PERF_REG_ARM64_X9, | ||
15 | PERF_REG_ARM64_X10, | ||
16 | PERF_REG_ARM64_X11, | ||
17 | PERF_REG_ARM64_X12, | ||
18 | PERF_REG_ARM64_X13, | ||
19 | PERF_REG_ARM64_X14, | ||
20 | PERF_REG_ARM64_X15, | ||
21 | PERF_REG_ARM64_X16, | ||
22 | PERF_REG_ARM64_X17, | ||
23 | PERF_REG_ARM64_X18, | ||
24 | PERF_REG_ARM64_X19, | ||
25 | PERF_REG_ARM64_X20, | ||
26 | PERF_REG_ARM64_X21, | ||
27 | PERF_REG_ARM64_X22, | ||
28 | PERF_REG_ARM64_X23, | ||
29 | PERF_REG_ARM64_X24, | ||
30 | PERF_REG_ARM64_X25, | ||
31 | PERF_REG_ARM64_X26, | ||
32 | PERF_REG_ARM64_X27, | ||
33 | PERF_REG_ARM64_X28, | ||
34 | PERF_REG_ARM64_X29, | ||
35 | PERF_REG_ARM64_LR, | ||
36 | PERF_REG_ARM64_SP, | ||
37 | PERF_REG_ARM64_PC, | ||
38 | PERF_REG_ARM64_MAX, | ||
39 | }; | ||
40 | #endif /* _ASM_ARM64_PERF_REGS_H */ | ||
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 2d4554b13410..7d811d9522bc 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile | |||
@@ -14,12 +14,14 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ | |||
14 | arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ | 14 | arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ |
15 | sys_compat.o | 15 | sys_compat.o |
16 | arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o | 16 | arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o |
17 | arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o | 17 | arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o |
18 | arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o | ||
18 | arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | 19 | arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o |
19 | arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o | 20 | arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o |
20 | arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 21 | arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
21 | arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o | 22 | arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o |
22 | arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o | 23 | arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o |
24 | arm64-obj-$(CONFIG_KGDB) += kgdb.o | ||
23 | 25 | ||
24 | obj-y += $(arm64-obj-y) vdso/ | 26 | obj-y += $(arm64-obj-y) vdso/ |
25 | obj-m += $(arm64-obj-m) | 27 | obj-m += $(arm64-obj-m) |
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 636ba8b6240b..14ba23c61153 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c | |||
@@ -137,7 +137,6 @@ void disable_debug_monitors(enum debug_el el) | |||
137 | static void clear_os_lock(void *unused) | 137 | static void clear_os_lock(void *unused) |
138 | { | 138 | { |
139 | asm volatile("msr oslar_el1, %0" : : "r" (0)); | 139 | asm volatile("msr oslar_el1, %0" : : "r" (0)); |
140 | isb(); | ||
141 | } | 140 | } |
142 | 141 | ||
143 | static int os_lock_notify(struct notifier_block *self, | 142 | static int os_lock_notify(struct notifier_block *self, |
@@ -156,8 +155,9 @@ static struct notifier_block os_lock_nb = { | |||
156 | static int debug_monitors_init(void) | 155 | static int debug_monitors_init(void) |
157 | { | 156 | { |
158 | /* Clear the OS lock. */ | 157 | /* Clear the OS lock. */ |
159 | smp_call_function(clear_os_lock, NULL, 1); | 158 | on_each_cpu(clear_os_lock, NULL, 1); |
160 | clear_os_lock(NULL); | 159 | isb(); |
160 | local_dbg_enable(); | ||
161 | 161 | ||
162 | /* Register hotplug handler. */ | 162 | /* Register hotplug handler. */ |
163 | register_cpu_notifier(&os_lock_nb); | 163 | register_cpu_notifier(&os_lock_nb); |
@@ -189,7 +189,7 @@ static void clear_regs_spsr_ss(struct pt_regs *regs) | |||
189 | 189 | ||
190 | /* EL1 Single Step Handler hooks */ | 190 | /* EL1 Single Step Handler hooks */ |
191 | static LIST_HEAD(step_hook); | 191 | static LIST_HEAD(step_hook); |
192 | DEFINE_RWLOCK(step_hook_lock); | 192 | static DEFINE_RWLOCK(step_hook_lock); |
193 | 193 | ||
194 | void register_step_hook(struct step_hook *hook) | 194 | void register_step_hook(struct step_hook *hook) |
195 | { | 195 | { |
@@ -276,7 +276,7 @@ static int single_step_handler(unsigned long addr, unsigned int esr, | |||
276 | * Use reader/writer locks instead of plain spinlock. | 276 | * Use reader/writer locks instead of plain spinlock. |
277 | */ | 277 | */ |
278 | static LIST_HEAD(break_hook); | 278 | static LIST_HEAD(break_hook); |
279 | DEFINE_RWLOCK(break_hook_lock); | 279 | static DEFINE_RWLOCK(break_hook_lock); |
280 | 280 | ||
281 | void register_break_hook(struct break_hook *hook) | 281 | void register_break_hook(struct break_hook *hook) |
282 | { | 282 | { |
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 0b281fffda51..61035d6814cb 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
@@ -384,26 +384,18 @@ ENDPROC(__calc_phys_offset) | |||
384 | * Preserves: tbl, flags | 384 | * Preserves: tbl, flags |
385 | * Corrupts: phys, start, end, pstate | 385 | * Corrupts: phys, start, end, pstate |
386 | */ | 386 | */ |
387 | .macro create_block_map, tbl, flags, phys, start, end, idmap=0 | 387 | .macro create_block_map, tbl, flags, phys, start, end |
388 | lsr \phys, \phys, #BLOCK_SHIFT | 388 | lsr \phys, \phys, #BLOCK_SHIFT |
389 | .if \idmap | ||
390 | and \start, \phys, #PTRS_PER_PTE - 1 // table index | ||
391 | .else | ||
392 | lsr \start, \start, #BLOCK_SHIFT | 389 | lsr \start, \start, #BLOCK_SHIFT |
393 | and \start, \start, #PTRS_PER_PTE - 1 // table index | 390 | and \start, \start, #PTRS_PER_PTE - 1 // table index |
394 | .endif | ||
395 | orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry | 391 | orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry |
396 | .ifnc \start,\end | ||
397 | lsr \end, \end, #BLOCK_SHIFT | 392 | lsr \end, \end, #BLOCK_SHIFT |
398 | and \end, \end, #PTRS_PER_PTE - 1 // table end index | 393 | and \end, \end, #PTRS_PER_PTE - 1 // table end index |
399 | .endif | ||
400 | 9999: str \phys, [\tbl, \start, lsl #3] // store the entry | 394 | 9999: str \phys, [\tbl, \start, lsl #3] // store the entry |
401 | .ifnc \start,\end | ||
402 | add \start, \start, #1 // next entry | 395 | add \start, \start, #1 // next entry |
403 | add \phys, \phys, #BLOCK_SIZE // next block | 396 | add \phys, \phys, #BLOCK_SIZE // next block |
404 | cmp \start, \end | 397 | cmp \start, \end |
405 | b.ls 9999b | 398 | b.ls 9999b |
406 | .endif | ||
407 | .endm | 399 | .endm |
408 | 400 | ||
409 | /* | 401 | /* |
@@ -435,9 +427,13 @@ __create_page_tables: | |||
435 | * Create the identity mapping. | 427 | * Create the identity mapping. |
436 | */ | 428 | */ |
437 | add x0, x25, #PAGE_SIZE // section table address | 429 | add x0, x25, #PAGE_SIZE // section table address |
438 | adr x3, __turn_mmu_on // virtual/physical address | 430 | ldr x3, =KERNEL_START |
431 | add x3, x3, x28 // __pa(KERNEL_START) | ||
439 | create_pgd_entry x25, x0, x3, x5, x6 | 432 | create_pgd_entry x25, x0, x3, x5, x6 |
440 | create_block_map x0, x7, x3, x5, x5, idmap=1 | 433 | ldr x6, =KERNEL_END |
434 | mov x5, x3 // __pa(KERNEL_START) | ||
435 | add x6, x6, x28 // __pa(KERNEL_END) | ||
436 | create_block_map x0, x7, x3, x5, x6 | ||
441 | 437 | ||
442 | /* | 438 | /* |
443 | * Map the kernel image (starting with PHYS_OFFSET). | 439 | * Map the kernel image (starting with PHYS_OFFSET). |
@@ -445,7 +441,7 @@ __create_page_tables: | |||
445 | add x0, x26, #PAGE_SIZE // section table address | 441 | add x0, x26, #PAGE_SIZE // section table address |
446 | mov x5, #PAGE_OFFSET | 442 | mov x5, #PAGE_OFFSET |
447 | create_pgd_entry x26, x0, x5, x3, x6 | 443 | create_pgd_entry x26, x0, x5, x3, x6 |
448 | ldr x6, =KERNEL_END - 1 | 444 | ldr x6, =KERNEL_END |
449 | mov x3, x24 // phys offset | 445 | mov x3, x24 // phys offset |
450 | create_block_map x0, x7, x3, x5, x6 | 446 | create_block_map x0, x7, x3, x5, x6 |
451 | 447 | ||
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c new file mode 100644 index 000000000000..75c9cf1aafee --- /dev/null +++ b/arch/arm64/kernel/kgdb.c | |||
@@ -0,0 +1,336 @@ | |||
1 | /* | ||
2 | * AArch64 KGDB support | ||
3 | * | ||
4 | * Based on arch/arm/kernel/kgdb.c | ||
5 | * | ||
6 | * Copyright (C) 2013 Cavium Inc. | ||
7 | * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/irq.h> | ||
23 | #include <linux/kdebug.h> | ||
24 | #include <linux/kgdb.h> | ||
25 | #include <asm/traps.h> | ||
26 | |||
27 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { | ||
28 | { "x0", 8, offsetof(struct pt_regs, regs[0])}, | ||
29 | { "x1", 8, offsetof(struct pt_regs, regs[1])}, | ||
30 | { "x2", 8, offsetof(struct pt_regs, regs[2])}, | ||
31 | { "x3", 8, offsetof(struct pt_regs, regs[3])}, | ||
32 | { "x4", 8, offsetof(struct pt_regs, regs[4])}, | ||
33 | { "x5", 8, offsetof(struct pt_regs, regs[5])}, | ||
34 | { "x6", 8, offsetof(struct pt_regs, regs[6])}, | ||
35 | { "x7", 8, offsetof(struct pt_regs, regs[7])}, | ||
36 | { "x8", 8, offsetof(struct pt_regs, regs[8])}, | ||
37 | { "x9", 8, offsetof(struct pt_regs, regs[9])}, | ||
38 | { "x10", 8, offsetof(struct pt_regs, regs[10])}, | ||
39 | { "x11", 8, offsetof(struct pt_regs, regs[11])}, | ||
40 | { "x12", 8, offsetof(struct pt_regs, regs[12])}, | ||
41 | { "x13", 8, offsetof(struct pt_regs, regs[13])}, | ||
42 | { "x14", 8, offsetof(struct pt_regs, regs[14])}, | ||
43 | { "x15", 8, offsetof(struct pt_regs, regs[15])}, | ||
44 | { "x16", 8, offsetof(struct pt_regs, regs[16])}, | ||
45 | { "x17", 8, offsetof(struct pt_regs, regs[17])}, | ||
46 | { "x18", 8, offsetof(struct pt_regs, regs[18])}, | ||
47 | { "x19", 8, offsetof(struct pt_regs, regs[19])}, | ||
48 | { "x20", 8, offsetof(struct pt_regs, regs[20])}, | ||
49 | { "x21", 8, offsetof(struct pt_regs, regs[21])}, | ||
50 | { "x22", 8, offsetof(struct pt_regs, regs[22])}, | ||
51 | { "x23", 8, offsetof(struct pt_regs, regs[23])}, | ||
52 | { "x24", 8, offsetof(struct pt_regs, regs[24])}, | ||
53 | { "x25", 8, offsetof(struct pt_regs, regs[25])}, | ||
54 | { "x26", 8, offsetof(struct pt_regs, regs[26])}, | ||
55 | { "x27", 8, offsetof(struct pt_regs, regs[27])}, | ||
56 | { "x28", 8, offsetof(struct pt_regs, regs[28])}, | ||
57 | { "x29", 8, offsetof(struct pt_regs, regs[29])}, | ||
58 | { "x30", 8, offsetof(struct pt_regs, regs[30])}, | ||
59 | { "sp", 8, offsetof(struct pt_regs, sp)}, | ||
60 | { "pc", 8, offsetof(struct pt_regs, pc)}, | ||
61 | { "pstate", 8, offsetof(struct pt_regs, pstate)}, | ||
62 | { "v0", 16, -1 }, | ||
63 | { "v1", 16, -1 }, | ||
64 | { "v2", 16, -1 }, | ||
65 | { "v3", 16, -1 }, | ||
66 | { "v4", 16, -1 }, | ||
67 | { "v5", 16, -1 }, | ||
68 | { "v6", 16, -1 }, | ||
69 | { "v7", 16, -1 }, | ||
70 | { "v8", 16, -1 }, | ||
71 | { "v9", 16, -1 }, | ||
72 | { "v10", 16, -1 }, | ||
73 | { "v11", 16, -1 }, | ||
74 | { "v12", 16, -1 }, | ||
75 | { "v13", 16, -1 }, | ||
76 | { "v14", 16, -1 }, | ||
77 | { "v15", 16, -1 }, | ||
78 | { "v16", 16, -1 }, | ||
79 | { "v17", 16, -1 }, | ||
80 | { "v18", 16, -1 }, | ||
81 | { "v19", 16, -1 }, | ||
82 | { "v20", 16, -1 }, | ||
83 | { "v21", 16, -1 }, | ||
84 | { "v22", 16, -1 }, | ||
85 | { "v23", 16, -1 }, | ||
86 | { "v24", 16, -1 }, | ||
87 | { "v25", 16, -1 }, | ||
88 | { "v26", 16, -1 }, | ||
89 | { "v27", 16, -1 }, | ||
90 | { "v28", 16, -1 }, | ||
91 | { "v29", 16, -1 }, | ||
92 | { "v30", 16, -1 }, | ||
93 | { "v31", 16, -1 }, | ||
94 | { "fpsr", 4, -1 }, | ||
95 | { "fpcr", 4, -1 }, | ||
96 | }; | ||
97 | |||
98 | char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) | ||
99 | { | ||
100 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
101 | return NULL; | ||
102 | |||
103 | if (dbg_reg_def[regno].offset != -1) | ||
104 | memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, | ||
105 | dbg_reg_def[regno].size); | ||
106 | else | ||
107 | memset(mem, 0, dbg_reg_def[regno].size); | ||
108 | return dbg_reg_def[regno].name; | ||
109 | } | ||
110 | |||
111 | int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) | ||
112 | { | ||
113 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
114 | return -EINVAL; | ||
115 | |||
116 | if (dbg_reg_def[regno].offset != -1) | ||
117 | memcpy((void *)regs + dbg_reg_def[regno].offset, mem, | ||
118 | dbg_reg_def[regno].size); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | void | ||
123 | sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) | ||
124 | { | ||
125 | struct pt_regs *thread_regs; | ||
126 | |||
127 | /* Initialize to zero */ | ||
128 | memset((char *)gdb_regs, 0, NUMREGBYTES); | ||
129 | thread_regs = task_pt_regs(task); | ||
130 | memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES); | ||
131 | } | ||
132 | |||
133 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) | ||
134 | { | ||
135 | regs->pc = pc; | ||
136 | } | ||
137 | |||
138 | static int compiled_break; | ||
139 | |||
140 | static void kgdb_arch_update_addr(struct pt_regs *regs, | ||
141 | char *remcom_in_buffer) | ||
142 | { | ||
143 | unsigned long addr; | ||
144 | char *ptr; | ||
145 | |||
146 | ptr = &remcom_in_buffer[1]; | ||
147 | if (kgdb_hex2long(&ptr, &addr)) | ||
148 | kgdb_arch_set_pc(regs, addr); | ||
149 | else if (compiled_break == 1) | ||
150 | kgdb_arch_set_pc(regs, regs->pc + 4); | ||
151 | |||
152 | compiled_break = 0; | ||
153 | } | ||
154 | |||
155 | int kgdb_arch_handle_exception(int exception_vector, int signo, | ||
156 | int err_code, char *remcom_in_buffer, | ||
157 | char *remcom_out_buffer, | ||
158 | struct pt_regs *linux_regs) | ||
159 | { | ||
160 | int err; | ||
161 | |||
162 | switch (remcom_in_buffer[0]) { | ||
163 | case 'D': | ||
164 | case 'k': | ||
165 | /* | ||
166 | * Packet D (Detach), k (kill). No special handling | ||
167 | * is required here. Handle same as c packet. | ||
168 | */ | ||
169 | case 'c': | ||
170 | /* | ||
171 | * Packet c (Continue) to continue executing. | ||
172 | * Set pc to required address. | ||
173 | * Try to read optional parameter and set pc. | ||
174 | * If this was a compiled breakpoint, we need to move | ||
175 | * to the next instruction else we will just breakpoint | ||
176 | * over and over again. | ||
177 | */ | ||
178 | kgdb_arch_update_addr(linux_regs, remcom_in_buffer); | ||
179 | atomic_set(&kgdb_cpu_doing_single_step, -1); | ||
180 | kgdb_single_step = 0; | ||
181 | |||
182 | /* | ||
183 | * Received continue command, disable single step | ||
184 | */ | ||
185 | if (kernel_active_single_step()) | ||
186 | kernel_disable_single_step(); | ||
187 | |||
188 | err = 0; | ||
189 | break; | ||
190 | case 's': | ||
191 | /* | ||
192 | * Update step address value with address passed | ||
193 | * with step packet. | ||
194 | * On debug exception return PC is copied to ELR | ||
195 | * So just update PC. | ||
196 | * If no step address is passed, resume from the address | ||
197 | * pointed by PC. Do not update PC | ||
198 | */ | ||
199 | kgdb_arch_update_addr(linux_regs, remcom_in_buffer); | ||
200 | atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); | ||
201 | kgdb_single_step = 1; | ||
202 | |||
203 | /* | ||
204 | * Enable single step handling | ||
205 | */ | ||
206 | if (!kernel_active_single_step()) | ||
207 | kernel_enable_single_step(linux_regs); | ||
208 | err = 0; | ||
209 | break; | ||
210 | default: | ||
211 | err = -1; | ||
212 | } | ||
213 | return err; | ||
214 | } | ||
215 | |||
216 | static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) | ||
217 | { | ||
218 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) | ||
223 | { | ||
224 | compiled_break = 1; | ||
225 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) | ||
231 | { | ||
232 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct break_hook kgdb_brkpt_hook = { | ||
237 | .esr_mask = 0xffffffff, | ||
238 | .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM), | ||
239 | .fn = kgdb_brk_fn | ||
240 | }; | ||
241 | |||
242 | static struct break_hook kgdb_compiled_brkpt_hook = { | ||
243 | .esr_mask = 0xffffffff, | ||
244 | .esr_val = DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM), | ||
245 | .fn = kgdb_compiled_brk_fn | ||
246 | }; | ||
247 | |||
248 | static struct step_hook kgdb_step_hook = { | ||
249 | .fn = kgdb_step_brk_fn | ||
250 | }; | ||
251 | |||
252 | static void kgdb_call_nmi_hook(void *ignored) | ||
253 | { | ||
254 | kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); | ||
255 | } | ||
256 | |||
257 | void kgdb_roundup_cpus(unsigned long flags) | ||
258 | { | ||
259 | local_irq_enable(); | ||
260 | smp_call_function(kgdb_call_nmi_hook, NULL, 0); | ||
261 | local_irq_disable(); | ||
262 | } | ||
263 | |||
264 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
265 | { | ||
266 | struct pt_regs *regs = args->regs; | ||
267 | |||
268 | if (kgdb_handle_exception(1, args->signr, cmd, regs)) | ||
269 | return NOTIFY_DONE; | ||
270 | return NOTIFY_STOP; | ||
271 | } | ||
272 | |||
273 | static int | ||
274 | kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) | ||
275 | { | ||
276 | unsigned long flags; | ||
277 | int ret; | ||
278 | |||
279 | local_irq_save(flags); | ||
280 | ret = __kgdb_notify(ptr, cmd); | ||
281 | local_irq_restore(flags); | ||
282 | |||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | static struct notifier_block kgdb_notifier = { | ||
287 | .notifier_call = kgdb_notify, | ||
288 | /* | ||
289 | * Want to be lowest priority | ||
290 | */ | ||
291 | .priority = -INT_MAX, | ||
292 | }; | ||
293 | |||
294 | /* | ||
295 | * kgdb_arch_init - Perform any architecture specific initalization. | ||
296 | * This function will handle the initalization of any architecture | ||
297 | * specific callbacks. | ||
298 | */ | ||
299 | int kgdb_arch_init(void) | ||
300 | { | ||
301 | int ret = register_die_notifier(&kgdb_notifier); | ||
302 | |||
303 | if (ret != 0) | ||
304 | return ret; | ||
305 | |||
306 | register_break_hook(&kgdb_brkpt_hook); | ||
307 | register_break_hook(&kgdb_compiled_brkpt_hook); | ||
308 | register_step_hook(&kgdb_step_hook); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * kgdb_arch_exit - Perform any architecture specific uninitalization. | ||
314 | * This function will handle the uninitalization of any architecture | ||
315 | * specific callbacks, for dynamic registration and unregistration. | ||
316 | */ | ||
317 | void kgdb_arch_exit(void) | ||
318 | { | ||
319 | unregister_break_hook(&kgdb_brkpt_hook); | ||
320 | unregister_break_hook(&kgdb_compiled_brkpt_hook); | ||
321 | unregister_step_hook(&kgdb_step_hook); | ||
322 | unregister_die_notifier(&kgdb_notifier); | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * ARM instructions are always in LE. | ||
327 | * Break instruction is encoded in LE format | ||
328 | */ | ||
329 | struct kgdb_arch arch_kgdb_ops = { | ||
330 | .gdb_bpt_instr = { | ||
331 | KGDB_DYN_BRK_INS_BYTE0, | ||
332 | KGDB_DYN_BRK_INS_BYTE1, | ||
333 | KGDB_DYN_BRK_INS_BYTE2, | ||
334 | KGDB_DYN_BRK_INS_BYTE3, | ||
335 | } | ||
336 | }; | ||
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 5b1cd792274a..e868c72a7938 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c | |||
@@ -1348,8 +1348,8 @@ early_initcall(init_hw_perf_events); | |||
1348 | * Callchain handling code. | 1348 | * Callchain handling code. |
1349 | */ | 1349 | */ |
1350 | struct frame_tail { | 1350 | struct frame_tail { |
1351 | struct frame_tail __user *fp; | 1351 | struct frame_tail __user *fp; |
1352 | unsigned long lr; | 1352 | unsigned long lr; |
1353 | } __attribute__((packed)); | 1353 | } __attribute__((packed)); |
1354 | 1354 | ||
1355 | /* | 1355 | /* |
@@ -1386,22 +1386,80 @@ user_backtrace(struct frame_tail __user *tail, | |||
1386 | return buftail.fp; | 1386 | return buftail.fp; |
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | /* | ||
1390 | * The registers we're interested in are at the end of the variable | ||
1391 | * length saved register structure. The fp points at the end of this | ||
1392 | * structure so the address of this struct is: | ||
1393 | * (struct compat_frame_tail *)(xxx->fp)-1 | ||
1394 | * | ||
1395 | * This code has been adapted from the ARM OProfile support. | ||
1396 | */ | ||
1397 | struct compat_frame_tail { | ||
1398 | compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */ | ||
1399 | u32 sp; | ||
1400 | u32 lr; | ||
1401 | } __attribute__((packed)); | ||
1402 | |||
1403 | static struct compat_frame_tail __user * | ||
1404 | compat_user_backtrace(struct compat_frame_tail __user *tail, | ||
1405 | struct perf_callchain_entry *entry) | ||
1406 | { | ||
1407 | struct compat_frame_tail buftail; | ||
1408 | unsigned long err; | ||
1409 | |||
1410 | /* Also check accessibility of one struct frame_tail beyond */ | ||
1411 | if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) | ||
1412 | return NULL; | ||
1413 | |||
1414 | pagefault_disable(); | ||
1415 | err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); | ||
1416 | pagefault_enable(); | ||
1417 | |||
1418 | if (err) | ||
1419 | return NULL; | ||
1420 | |||
1421 | perf_callchain_store(entry, buftail.lr); | ||
1422 | |||
1423 | /* | ||
1424 | * Frame pointers should strictly progress back up the stack | ||
1425 | * (towards higher addresses). | ||
1426 | */ | ||
1427 | if (tail + 1 >= (struct compat_frame_tail __user *) | ||
1428 | compat_ptr(buftail.fp)) | ||
1429 | return NULL; | ||
1430 | |||
1431 | return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1; | ||
1432 | } | ||
1433 | |||
1389 | void perf_callchain_user(struct perf_callchain_entry *entry, | 1434 | void perf_callchain_user(struct perf_callchain_entry *entry, |
1390 | struct pt_regs *regs) | 1435 | struct pt_regs *regs) |
1391 | { | 1436 | { |
1392 | struct frame_tail __user *tail; | ||
1393 | |||
1394 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { | 1437 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { |
1395 | /* We don't support guest os callchain now */ | 1438 | /* We don't support guest os callchain now */ |
1396 | return; | 1439 | return; |
1397 | } | 1440 | } |
1398 | 1441 | ||
1399 | perf_callchain_store(entry, regs->pc); | 1442 | perf_callchain_store(entry, regs->pc); |
1400 | tail = (struct frame_tail __user *)regs->regs[29]; | ||
1401 | 1443 | ||
1402 | while (entry->nr < PERF_MAX_STACK_DEPTH && | 1444 | if (!compat_user_mode(regs)) { |
1403 | tail && !((unsigned long)tail & 0xf)) | 1445 | /* AARCH64 mode */ |
1404 | tail = user_backtrace(tail, entry); | 1446 | struct frame_tail __user *tail; |
1447 | |||
1448 | tail = (struct frame_tail __user *)regs->regs[29]; | ||
1449 | |||
1450 | while (entry->nr < PERF_MAX_STACK_DEPTH && | ||
1451 | tail && !((unsigned long)tail & 0xf)) | ||
1452 | tail = user_backtrace(tail, entry); | ||
1453 | } else { | ||
1454 | /* AARCH32 compat mode */ | ||
1455 | struct compat_frame_tail __user *tail; | ||
1456 | |||
1457 | tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; | ||
1458 | |||
1459 | while ((entry->nr < PERF_MAX_STACK_DEPTH) && | ||
1460 | tail && !((unsigned long)tail & 0x3)) | ||
1461 | tail = compat_user_backtrace(tail, entry); | ||
1462 | } | ||
1405 | } | 1463 | } |
1406 | 1464 | ||
1407 | /* | 1465 | /* |
@@ -1429,6 +1487,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, | |||
1429 | frame.fp = regs->regs[29]; | 1487 | frame.fp = regs->regs[29]; |
1430 | frame.sp = regs->sp; | 1488 | frame.sp = regs->sp; |
1431 | frame.pc = regs->pc; | 1489 | frame.pc = regs->pc; |
1490 | |||
1432 | walk_stackframe(&frame, callchain_trace, entry); | 1491 | walk_stackframe(&frame, callchain_trace, entry); |
1433 | } | 1492 | } |
1434 | 1493 | ||
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c new file mode 100644 index 000000000000..f2d6f0a36d63 --- /dev/null +++ b/arch/arm64/kernel/perf_regs.c | |||
@@ -0,0 +1,44 @@ | |||
1 | #include <linux/errno.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/perf_event.h> | ||
4 | #include <linux/bug.h> | ||
5 | #include <asm/perf_regs.h> | ||
6 | #include <asm/ptrace.h> | ||
7 | |||
8 | u64 perf_reg_value(struct pt_regs *regs, int idx) | ||
9 | { | ||
10 | if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX)) | ||
11 | return 0; | ||
12 | |||
13 | /* | ||
14 | * Compat (i.e. 32 bit) mode: | ||
15 | * - PC has been set in the pt_regs struct in kernel_entry, | ||
16 | * - Handle SP and LR here. | ||
17 | */ | ||
18 | if (compat_user_mode(regs)) { | ||
19 | if ((u32)idx == PERF_REG_ARM64_SP) | ||
20 | return regs->compat_sp; | ||
21 | if ((u32)idx == PERF_REG_ARM64_LR) | ||
22 | return regs->compat_lr; | ||
23 | } | ||
24 | |||
25 | return regs->regs[idx]; | ||
26 | } | ||
27 | |||
28 | #define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1)) | ||
29 | |||
30 | int perf_reg_validate(u64 mask) | ||
31 | { | ||
32 | if (!mask || mask & REG_RESERVED) | ||
33 | return -EINVAL; | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | u64 perf_reg_abi(struct task_struct *task) | ||
39 | { | ||
40 | if (is_compat_thread(task_thread_info(task))) | ||
41 | return PERF_SAMPLE_REGS_ABI_32; | ||
42 | else | ||
43 | return PERF_SAMPLE_REGS_ABI_64; | ||
44 | } | ||
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 9cce0098f4cd..6391485f342d 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
@@ -71,8 +71,17 @@ static void setup_restart(void) | |||
71 | 71 | ||
72 | void soft_restart(unsigned long addr) | 72 | void soft_restart(unsigned long addr) |
73 | { | 73 | { |
74 | typedef void (*phys_reset_t)(unsigned long); | ||
75 | phys_reset_t phys_reset; | ||
76 | |||
74 | setup_restart(); | 77 | setup_restart(); |
75 | cpu_reset(addr); | 78 | |
79 | /* Switch to the identity mapping */ | ||
80 | phys_reset = (phys_reset_t)virt_to_phys(cpu_reset); | ||
81 | phys_reset(addr); | ||
82 | |||
83 | /* Should never get here */ | ||
84 | BUG(); | ||
76 | } | 85 | } |
77 | 86 | ||
78 | /* | 87 | /* |
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 4f97db3d7363..ea4828a4aa96 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c | |||
@@ -176,22 +176,20 @@ static const struct of_device_id psci_of_match[] __initconst = { | |||
176 | {}, | 176 | {}, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | int __init psci_init(void) | 179 | void __init psci_init(void) |
180 | { | 180 | { |
181 | struct device_node *np; | 181 | struct device_node *np; |
182 | const char *method; | 182 | const char *method; |
183 | u32 id; | 183 | u32 id; |
184 | int err = 0; | ||
185 | 184 | ||
186 | np = of_find_matching_node(NULL, psci_of_match); | 185 | np = of_find_matching_node(NULL, psci_of_match); |
187 | if (!np) | 186 | if (!np) |
188 | return -ENODEV; | 187 | return; |
189 | 188 | ||
190 | pr_info("probing function IDs from device-tree\n"); | 189 | pr_info("probing function IDs from device-tree\n"); |
191 | 190 | ||
192 | if (of_property_read_string(np, "method", &method)) { | 191 | if (of_property_read_string(np, "method", &method)) { |
193 | pr_warning("missing \"method\" property\n"); | 192 | pr_warning("missing \"method\" property\n"); |
194 | err = -ENXIO; | ||
195 | goto out_put_node; | 193 | goto out_put_node; |
196 | } | 194 | } |
197 | 195 | ||
@@ -201,7 +199,6 @@ int __init psci_init(void) | |||
201 | invoke_psci_fn = __invoke_psci_fn_smc; | 199 | invoke_psci_fn = __invoke_psci_fn_smc; |
202 | } else { | 200 | } else { |
203 | pr_warning("invalid \"method\" property: %s\n", method); | 201 | pr_warning("invalid \"method\" property: %s\n", method); |
204 | err = -EINVAL; | ||
205 | goto out_put_node; | 202 | goto out_put_node; |
206 | } | 203 | } |
207 | 204 | ||
@@ -227,7 +224,7 @@ int __init psci_init(void) | |||
227 | 224 | ||
228 | out_put_node: | 225 | out_put_node: |
229 | of_node_put(np); | 226 | of_node_put(np); |
230 | return err; | 227 | return; |
231 | } | 228 | } |
232 | 229 | ||
233 | #ifdef CONFIG_SMP | 230 | #ifdef CONFIG_SMP |
@@ -251,7 +248,7 @@ static int cpu_psci_cpu_boot(unsigned int cpu) | |||
251 | { | 248 | { |
252 | int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry)); | 249 | int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry)); |
253 | if (err) | 250 | if (err) |
254 | pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err); | 251 | pr_err("failed to boot CPU%d (%d)\n", cpu, err); |
255 | 252 | ||
256 | return err; | 253 | return err; |
257 | } | 254 | } |
@@ -278,7 +275,7 @@ static void cpu_psci_cpu_die(unsigned int cpu) | |||
278 | 275 | ||
279 | ret = psci_ops.cpu_off(state); | 276 | ret = psci_ops.cpu_off(state); |
280 | 277 | ||
281 | pr_crit("psci: unable to power off CPU%u (%d)\n", cpu, ret); | 278 | pr_crit("unable to power off CPU%u (%d)\n", cpu, ret); |
282 | } | 279 | } |
283 | #endif | 280 | #endif |
284 | 281 | ||
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index c8e9effe52e1..67da30741a1b 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -69,6 +69,7 @@ EXPORT_SYMBOL_GPL(elf_hwcap); | |||
69 | COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ | 69 | COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ |
70 | COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) | 70 | COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) |
71 | unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; | 71 | unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; |
72 | unsigned int compat_elf_hwcap2 __read_mostly; | ||
72 | #endif | 73 | #endif |
73 | 74 | ||
74 | static const char *cpu_name; | 75 | static const char *cpu_name; |
@@ -242,6 +243,38 @@ static void __init setup_processor(void) | |||
242 | block = (features >> 16) & 0xf; | 243 | block = (features >> 16) & 0xf; |
243 | if (block && !(block & 0x8)) | 244 | if (block && !(block & 0x8)) |
244 | elf_hwcap |= HWCAP_CRC32; | 245 | elf_hwcap |= HWCAP_CRC32; |
246 | |||
247 | #ifdef CONFIG_COMPAT | ||
248 | /* | ||
249 | * ID_ISAR5_EL1 carries similar information as above, but pertaining to | ||
250 | * the Aarch32 32-bit execution state. | ||
251 | */ | ||
252 | features = read_cpuid(ID_ISAR5_EL1); | ||
253 | block = (features >> 4) & 0xf; | ||
254 | if (!(block & 0x8)) { | ||
255 | switch (block) { | ||
256 | default: | ||
257 | case 2: | ||
258 | compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL; | ||
259 | case 1: | ||
260 | compat_elf_hwcap2 |= COMPAT_HWCAP2_AES; | ||
261 | case 0: | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | block = (features >> 8) & 0xf; | ||
267 | if (block && !(block & 0x8)) | ||
268 | compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; | ||
269 | |||
270 | block = (features >> 12) & 0xf; | ||
271 | if (block && !(block & 0x8)) | ||
272 | compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; | ||
273 | |||
274 | block = (features >> 16) & 0xf; | ||
275 | if (block && !(block & 0x8)) | ||
276 | compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; | ||
277 | #endif | ||
245 | } | 278 | } |
246 | 279 | ||
247 | static void __init setup_machine_fdt(phys_addr_t dt_phys) | 280 | static void __init setup_machine_fdt(phys_addr_t dt_phys) |
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 7cfb92a4ab66..f0a141dd5655 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c | |||
@@ -114,6 +114,11 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
114 | return ret; | 114 | return ret; |
115 | } | 115 | } |
116 | 116 | ||
117 | static void smp_store_cpu_info(unsigned int cpuid) | ||
118 | { | ||
119 | store_cpu_topology(cpuid); | ||
120 | } | ||
121 | |||
117 | /* | 122 | /* |
118 | * This is the secondary CPU boot entry. We're using this CPUs | 123 | * This is the secondary CPU boot entry. We're using this CPUs |
119 | * idle thread stack, but a set of temporary page tables. | 124 | * idle thread stack, but a set of temporary page tables. |
@@ -152,6 +157,8 @@ asmlinkage void secondary_start_kernel(void) | |||
152 | */ | 157 | */ |
153 | notify_cpu_starting(cpu); | 158 | notify_cpu_starting(cpu); |
154 | 159 | ||
160 | smp_store_cpu_info(cpu); | ||
161 | |||
155 | /* | 162 | /* |
156 | * OK, now it's safe to let the boot CPU continue. Wait for | 163 | * OK, now it's safe to let the boot CPU continue. Wait for |
157 | * the CPU migration code to notice that the CPU is online | 164 | * the CPU migration code to notice that the CPU is online |
@@ -160,6 +167,7 @@ asmlinkage void secondary_start_kernel(void) | |||
160 | set_cpu_online(cpu, true); | 167 | set_cpu_online(cpu, true); |
161 | complete(&cpu_running); | 168 | complete(&cpu_running); |
162 | 169 | ||
170 | local_dbg_enable(); | ||
163 | local_irq_enable(); | 171 | local_irq_enable(); |
164 | local_async_enable(); | 172 | local_async_enable(); |
165 | 173 | ||
@@ -390,6 +398,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
390 | int err; | 398 | int err; |
391 | unsigned int cpu, ncores = num_possible_cpus(); | 399 | unsigned int cpu, ncores = num_possible_cpus(); |
392 | 400 | ||
401 | init_cpu_topology(); | ||
402 | |||
403 | smp_store_cpu_info(smp_processor_id()); | ||
404 | |||
393 | /* | 405 | /* |
394 | * are we trying to boot more cores than exist? | 406 | * are we trying to boot more cores than exist? |
395 | */ | 407 | */ |
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c index 44c22805d2e2..7a530d2cc807 100644 --- a/arch/arm64/kernel/smp_spin_table.c +++ b/arch/arm64/kernel/smp_spin_table.c | |||
@@ -128,7 +128,7 @@ static int smp_spin_table_cpu_boot(unsigned int cpu) | |||
128 | return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0; | 128 | return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | void smp_spin_table_cpu_postboot(void) | 131 | static void smp_spin_table_cpu_postboot(void) |
132 | { | 132 | { |
133 | /* | 133 | /* |
134 | * Let the primary processor know we're out of the pen. | 134 | * Let the primary processor know we're out of the pen. |
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c new file mode 100644 index 000000000000..3e06b0be4ec8 --- /dev/null +++ b/arch/arm64/kernel/topology.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * arch/arm64/kernel/topology.c | ||
3 | * | ||
4 | * Copyright (C) 2011,2013,2014 Linaro Limited. | ||
5 | * | ||
6 | * Based on the arm32 version written by Vincent Guittot in turn based on | ||
7 | * arch/sh/kernel/topology.c | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/cpu.h> | ||
15 | #include <linux/cpumask.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/percpu.h> | ||
18 | #include <linux/node.h> | ||
19 | #include <linux/nodemask.h> | ||
20 | #include <linux/sched.h> | ||
21 | |||
22 | #include <asm/topology.h> | ||
23 | |||
24 | /* | ||
25 | * cpu topology table | ||
26 | */ | ||
27 | struct cpu_topology cpu_topology[NR_CPUS]; | ||
28 | EXPORT_SYMBOL_GPL(cpu_topology); | ||
29 | |||
30 | const struct cpumask *cpu_coregroup_mask(int cpu) | ||
31 | { | ||
32 | return &cpu_topology[cpu].core_sibling; | ||
33 | } | ||
34 | |||
35 | static void update_siblings_masks(unsigned int cpuid) | ||
36 | { | ||
37 | struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; | ||
38 | int cpu; | ||
39 | |||
40 | if (cpuid_topo->cluster_id == -1) { | ||
41 | /* | ||
42 | * DT does not contain topology information for this cpu | ||
43 | * reset it to default behaviour | ||
44 | */ | ||
45 | pr_debug("CPU%u: No topology information configured\n", cpuid); | ||
46 | cpuid_topo->core_id = 0; | ||
47 | cpumask_set_cpu(cpuid, &cpuid_topo->core_sibling); | ||
48 | cpumask_set_cpu(cpuid, &cpuid_topo->thread_sibling); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | /* update core and thread sibling masks */ | ||
53 | for_each_possible_cpu(cpu) { | ||
54 | cpu_topo = &cpu_topology[cpu]; | ||
55 | |||
56 | if (cpuid_topo->cluster_id != cpu_topo->cluster_id) | ||
57 | continue; | ||
58 | |||
59 | cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | ||
60 | if (cpu != cpuid) | ||
61 | cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); | ||
62 | |||
63 | if (cpuid_topo->core_id != cpu_topo->core_id) | ||
64 | continue; | ||
65 | |||
66 | cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); | ||
67 | if (cpu != cpuid) | ||
68 | cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | void store_cpu_topology(unsigned int cpuid) | ||
73 | { | ||
74 | update_siblings_masks(cpuid); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * init_cpu_topology is called at boot when only one cpu is running | ||
79 | * which prevent simultaneous write access to cpu_topology array | ||
80 | */ | ||
81 | void __init init_cpu_topology(void) | ||
82 | { | ||
83 | unsigned int cpu; | ||
84 | |||
85 | /* init core mask and power*/ | ||
86 | for_each_possible_cpu(cpu) { | ||
87 | struct cpu_topology *cpu_topo = &cpu_topology[cpu]; | ||
88 | |||
89 | cpu_topo->thread_id = -1; | ||
90 | cpu_topo->core_id = -1; | ||
91 | cpu_topo->cluster_id = -1; | ||
92 | cpumask_clear(&cpu_topo->core_sibling); | ||
93 | cpumask_clear(&cpu_topo->thread_sibling); | ||
94 | } | ||
95 | } | ||
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index a7149cae1615..50384fec56c4 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c | |||
@@ -106,49 +106,31 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) | |||
106 | 106 | ||
107 | static int __init vdso_init(void) | 107 | static int __init vdso_init(void) |
108 | { | 108 | { |
109 | struct page *pg; | 109 | int i; |
110 | char *vbase; | 110 | |
111 | int i, ret = 0; | 111 | if (memcmp(&vdso_start, "\177ELF", 4)) { |
112 | pr_err("vDSO is not a valid ELF object!\n"); | ||
113 | return -EINVAL; | ||
114 | } | ||
112 | 115 | ||
113 | vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; | 116 | vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; |
114 | pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n", | 117 | pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n", |
115 | vdso_pages + 1, vdso_pages, 1L, &vdso_start); | 118 | vdso_pages + 1, vdso_pages, 1L, &vdso_start); |
116 | 119 | ||
117 | /* Allocate the vDSO pagelist, plus a page for the data. */ | 120 | /* Allocate the vDSO pagelist, plus a page for the data. */ |
118 | vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1), | 121 | vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *), |
119 | GFP_KERNEL); | 122 | GFP_KERNEL); |
120 | if (vdso_pagelist == NULL) { | 123 | if (vdso_pagelist == NULL) |
121 | pr_err("Failed to allocate vDSO pagelist!\n"); | ||
122 | return -ENOMEM; | 124 | return -ENOMEM; |
123 | } | ||
124 | 125 | ||
125 | /* Grab the vDSO code pages. */ | 126 | /* Grab the vDSO code pages. */ |
126 | for (i = 0; i < vdso_pages; i++) { | 127 | for (i = 0; i < vdso_pages; i++) |
127 | pg = virt_to_page(&vdso_start + i*PAGE_SIZE); | 128 | vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE); |
128 | ClearPageReserved(pg); | ||
129 | get_page(pg); | ||
130 | vdso_pagelist[i] = pg; | ||
131 | } | ||
132 | |||
133 | /* Sanity check the shared object header. */ | ||
134 | vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL); | ||
135 | if (vbase == NULL) { | ||
136 | pr_err("Failed to map vDSO pagelist!\n"); | ||
137 | return -ENOMEM; | ||
138 | } else if (memcmp(vbase, "\177ELF", 4)) { | ||
139 | pr_err("vDSO is not a valid ELF object!\n"); | ||
140 | ret = -EINVAL; | ||
141 | goto unmap; | ||
142 | } | ||
143 | 129 | ||
144 | /* Grab the vDSO data page. */ | 130 | /* Grab the vDSO data page. */ |
145 | pg = virt_to_page(vdso_data); | 131 | vdso_pagelist[i] = virt_to_page(vdso_data); |
146 | get_page(pg); | ||
147 | vdso_pagelist[i] = pg; | ||
148 | 132 | ||
149 | unmap: | 133 | return 0; |
150 | vunmap(vbase); | ||
151 | return ret; | ||
152 | } | 134 | } |
153 | arch_initcall(vdso_init); | 135 | arch_initcall(vdso_init); |
154 | 136 | ||
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 2b0244d65c16..d968796f4b2d 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S | |||
@@ -68,6 +68,12 @@ __do_hyp_init: | |||
68 | msr tcr_el2, x4 | 68 | msr tcr_el2, x4 |
69 | 69 | ||
70 | ldr x4, =VTCR_EL2_FLAGS | 70 | ldr x4, =VTCR_EL2_FLAGS |
71 | /* | ||
72 | * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in | ||
73 | * VTCR_EL2. | ||
74 | */ | ||
75 | mrs x5, ID_AA64MMFR0_EL1 | ||
76 | bfi x4, x5, #16, #3 | ||
71 | msr vtcr_el2, x4 | 77 | msr vtcr_el2, x4 |
72 | 78 | ||
73 | mrs x4, mair_el1 | 79 | mrs x4, mair_el1 |
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index 1ea9f26d1b70..c46f48b33c14 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S | |||
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * Corrupted registers: x0-x7, x9-x11 | 31 | * Corrupted registers: x0-x7, x9-x11 |
32 | */ | 32 | */ |
33 | ENTRY(__flush_dcache_all) | 33 | __flush_dcache_all: |
34 | dsb sy // ensure ordering with previous memory accesses | 34 | dsb sy // ensure ordering with previous memory accesses |
35 | mrs x0, clidr_el1 // read clidr | 35 | mrs x0, clidr_el1 // read clidr |
36 | and x3, x0, #0x7000000 // extract loc from clidr | 36 | and x3, x0, #0x7000000 // extract loc from clidr |
@@ -166,3 +166,81 @@ ENTRY(__flush_dcache_area) | |||
166 | dsb sy | 166 | dsb sy |
167 | ret | 167 | ret |
168 | ENDPROC(__flush_dcache_area) | 168 | ENDPROC(__flush_dcache_area) |
169 | |||
170 | /* | ||
171 | * __dma_inv_range(start, end) | ||
172 | * - start - virtual start address of region | ||
173 | * - end - virtual end address of region | ||
174 | */ | ||
175 | __dma_inv_range: | ||
176 | dcache_line_size x2, x3 | ||
177 | sub x3, x2, #1 | ||
178 | bic x0, x0, x3 | ||
179 | bic x1, x1, x3 | ||
180 | 1: dc ivac, x0 // invalidate D / U line | ||
181 | add x0, x0, x2 | ||
182 | cmp x0, x1 | ||
183 | b.lo 1b | ||
184 | dsb sy | ||
185 | ret | ||
186 | ENDPROC(__dma_inv_range) | ||
187 | |||
188 | /* | ||
189 | * __dma_clean_range(start, end) | ||
190 | * - start - virtual start address of region | ||
191 | * - end - virtual end address of region | ||
192 | */ | ||
193 | __dma_clean_range: | ||
194 | dcache_line_size x2, x3 | ||
195 | sub x3, x2, #1 | ||
196 | bic x0, x0, x3 | ||
197 | 1: dc cvac, x0 // clean D / U line | ||
198 | add x0, x0, x2 | ||
199 | cmp x0, x1 | ||
200 | b.lo 1b | ||
201 | dsb sy | ||
202 | ret | ||
203 | ENDPROC(__dma_clean_range) | ||
204 | |||
205 | /* | ||
206 | * __dma_flush_range(start, end) | ||
207 | * - start - virtual start address of region | ||
208 | * - end - virtual end address of region | ||
209 | */ | ||
210 | ENTRY(__dma_flush_range) | ||
211 | dcache_line_size x2, x3 | ||
212 | sub x3, x2, #1 | ||
213 | bic x0, x0, x3 | ||
214 | 1: dc civac, x0 // clean & invalidate D / U line | ||
215 | add x0, x0, x2 | ||
216 | cmp x0, x1 | ||
217 | b.lo 1b | ||
218 | dsb sy | ||
219 | ret | ||
220 | ENDPROC(__dma_flush_range) | ||
221 | |||
222 | /* | ||
223 | * __dma_map_area(start, size, dir) | ||
224 | * - start - kernel virtual start address | ||
225 | * - size - size of region | ||
226 | * - dir - DMA direction | ||
227 | */ | ||
228 | ENTRY(__dma_map_area) | ||
229 | add x1, x1, x0 | ||
230 | cmp w2, #DMA_FROM_DEVICE | ||
231 | b.eq __dma_inv_range | ||
232 | b __dma_clean_range | ||
233 | ENDPROC(__dma_map_area) | ||
234 | |||
235 | /* | ||
236 | * __dma_unmap_area(start, size, dir) | ||
237 | * - start - kernel virtual start address | ||
238 | * - size - size of region | ||
239 | * - dir - DMA direction | ||
240 | */ | ||
241 | ENTRY(__dma_unmap_area) | ||
242 | add x1, x1, x0 | ||
243 | cmp w2, #DMA_TO_DEVICE | ||
244 | b.ne __dma_inv_range | ||
245 | ret | ||
246 | ENDPROC(__dma_unmap_area) | ||
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index fbd76785c5db..0ba347e59f06 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c | |||
@@ -30,18 +30,26 @@ | |||
30 | struct dma_map_ops *dma_ops; | 30 | struct dma_map_ops *dma_ops; |
31 | EXPORT_SYMBOL(dma_ops); | 31 | EXPORT_SYMBOL(dma_ops); |
32 | 32 | ||
33 | static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, | 33 | static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, |
34 | dma_addr_t *dma_handle, gfp_t flags, | 34 | bool coherent) |
35 | struct dma_attrs *attrs) | 35 | { |
36 | if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) | ||
37 | return pgprot_writecombine(prot); | ||
38 | return prot; | ||
39 | } | ||
40 | |||
41 | static void *__dma_alloc_coherent(struct device *dev, size_t size, | ||
42 | dma_addr_t *dma_handle, gfp_t flags, | ||
43 | struct dma_attrs *attrs) | ||
36 | { | 44 | { |
37 | if (dev == NULL) { | 45 | if (dev == NULL) { |
38 | WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); | 46 | WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); |
39 | return NULL; | 47 | return NULL; |
40 | } | 48 | } |
41 | 49 | ||
42 | if (IS_ENABLED(CONFIG_ZONE_DMA32) && | 50 | if (IS_ENABLED(CONFIG_ZONE_DMA) && |
43 | dev->coherent_dma_mask <= DMA_BIT_MASK(32)) | 51 | dev->coherent_dma_mask <= DMA_BIT_MASK(32)) |
44 | flags |= GFP_DMA32; | 52 | flags |= GFP_DMA; |
45 | if (IS_ENABLED(CONFIG_DMA_CMA)) { | 53 | if (IS_ENABLED(CONFIG_DMA_CMA)) { |
46 | struct page *page; | 54 | struct page *page; |
47 | 55 | ||
@@ -58,9 +66,9 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, | |||
58 | } | 66 | } |
59 | } | 67 | } |
60 | 68 | ||
61 | static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, | 69 | static void __dma_free_coherent(struct device *dev, size_t size, |
62 | void *vaddr, dma_addr_t dma_handle, | 70 | void *vaddr, dma_addr_t dma_handle, |
63 | struct dma_attrs *attrs) | 71 | struct dma_attrs *attrs) |
64 | { | 72 | { |
65 | if (dev == NULL) { | 73 | if (dev == NULL) { |
66 | WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); | 74 | WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); |
@@ -78,9 +86,212 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, | |||
78 | } | 86 | } |
79 | } | 87 | } |
80 | 88 | ||
81 | static struct dma_map_ops arm64_swiotlb_dma_ops = { | 89 | static void *__dma_alloc_noncoherent(struct device *dev, size_t size, |
82 | .alloc = arm64_swiotlb_alloc_coherent, | 90 | dma_addr_t *dma_handle, gfp_t flags, |
83 | .free = arm64_swiotlb_free_coherent, | 91 | struct dma_attrs *attrs) |
92 | { | ||
93 | struct page *page, **map; | ||
94 | void *ptr, *coherent_ptr; | ||
95 | int order, i; | ||
96 | |||
97 | size = PAGE_ALIGN(size); | ||
98 | order = get_order(size); | ||
99 | |||
100 | ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs); | ||
101 | if (!ptr) | ||
102 | goto no_mem; | ||
103 | map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA); | ||
104 | if (!map) | ||
105 | goto no_map; | ||
106 | |||
107 | /* remove any dirty cache lines on the kernel alias */ | ||
108 | __dma_flush_range(ptr, ptr + size); | ||
109 | |||
110 | /* create a coherent mapping */ | ||
111 | page = virt_to_page(ptr); | ||
112 | for (i = 0; i < (size >> PAGE_SHIFT); i++) | ||
113 | map[i] = page + i; | ||
114 | coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP, | ||
115 | __get_dma_pgprot(attrs, pgprot_default, false)); | ||
116 | kfree(map); | ||
117 | if (!coherent_ptr) | ||
118 | goto no_map; | ||
119 | |||
120 | return coherent_ptr; | ||
121 | |||
122 | no_map: | ||
123 | __dma_free_coherent(dev, size, ptr, *dma_handle, attrs); | ||
124 | no_mem: | ||
125 | *dma_handle = ~0; | ||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | static void __dma_free_noncoherent(struct device *dev, size_t size, | ||
130 | void *vaddr, dma_addr_t dma_handle, | ||
131 | struct dma_attrs *attrs) | ||
132 | { | ||
133 | void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle)); | ||
134 | |||
135 | vunmap(vaddr); | ||
136 | __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs); | ||
137 | } | ||
138 | |||
139 | static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page, | ||
140 | unsigned long offset, size_t size, | ||
141 | enum dma_data_direction dir, | ||
142 | struct dma_attrs *attrs) | ||
143 | { | ||
144 | dma_addr_t dev_addr; | ||
145 | |||
146 | dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs); | ||
147 | __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
148 | |||
149 | return dev_addr; | ||
150 | } | ||
151 | |||
152 | |||
153 | static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr, | ||
154 | size_t size, enum dma_data_direction dir, | ||
155 | struct dma_attrs *attrs) | ||
156 | { | ||
157 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
158 | swiotlb_unmap_page(dev, dev_addr, size, dir, attrs); | ||
159 | } | ||
160 | |||
161 | static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl, | ||
162 | int nelems, enum dma_data_direction dir, | ||
163 | struct dma_attrs *attrs) | ||
164 | { | ||
165 | struct scatterlist *sg; | ||
166 | int i, ret; | ||
167 | |||
168 | ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs); | ||
169 | for_each_sg(sgl, sg, ret, i) | ||
170 | __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
171 | sg->length, dir); | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static void __swiotlb_unmap_sg_attrs(struct device *dev, | ||
177 | struct scatterlist *sgl, int nelems, | ||
178 | enum dma_data_direction dir, | ||
179 | struct dma_attrs *attrs) | ||
180 | { | ||
181 | struct scatterlist *sg; | ||
182 | int i; | ||
183 | |||
184 | for_each_sg(sgl, sg, nelems, i) | ||
185 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
186 | sg->length, dir); | ||
187 | swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs); | ||
188 | } | ||
189 | |||
190 | static void __swiotlb_sync_single_for_cpu(struct device *dev, | ||
191 | dma_addr_t dev_addr, size_t size, | ||
192 | enum dma_data_direction dir) | ||
193 | { | ||
194 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
195 | swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir); | ||
196 | } | ||
197 | |||
198 | static void __swiotlb_sync_single_for_device(struct device *dev, | ||
199 | dma_addr_t dev_addr, size_t size, | ||
200 | enum dma_data_direction dir) | ||
201 | { | ||
202 | swiotlb_sync_single_for_device(dev, dev_addr, size, dir); | ||
203 | __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); | ||
204 | } | ||
205 | |||
206 | static void __swiotlb_sync_sg_for_cpu(struct device *dev, | ||
207 | struct scatterlist *sgl, int nelems, | ||
208 | enum dma_data_direction dir) | ||
209 | { | ||
210 | struct scatterlist *sg; | ||
211 | int i; | ||
212 | |||
213 | for_each_sg(sgl, sg, nelems, i) | ||
214 | __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
215 | sg->length, dir); | ||
216 | swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir); | ||
217 | } | ||
218 | |||
219 | static void __swiotlb_sync_sg_for_device(struct device *dev, | ||
220 | struct scatterlist *sgl, int nelems, | ||
221 | enum dma_data_direction dir) | ||
222 | { | ||
223 | struct scatterlist *sg; | ||
224 | int i; | ||
225 | |||
226 | swiotlb_sync_sg_for_device(dev, sgl, nelems, dir); | ||
227 | for_each_sg(sgl, sg, nelems, i) | ||
228 | __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), | ||
229 | sg->length, dir); | ||
230 | } | ||
231 | |||
232 | /* vma->vm_page_prot must be set appropriately before calling this function */ | ||
233 | static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, | ||
234 | void *cpu_addr, dma_addr_t dma_addr, size_t size) | ||
235 | { | ||
236 | int ret = -ENXIO; | ||
237 | unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> | ||
238 | PAGE_SHIFT; | ||
239 | unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
240 | unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT; | ||
241 | unsigned long off = vma->vm_pgoff; | ||
242 | |||
243 | if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) | ||
244 | return ret; | ||
245 | |||
246 | if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) { | ||
247 | ret = remap_pfn_range(vma, vma->vm_start, | ||
248 | pfn + off, | ||
249 | vma->vm_end - vma->vm_start, | ||
250 | vma->vm_page_prot); | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static int __swiotlb_mmap_noncoherent(struct device *dev, | ||
257 | struct vm_area_struct *vma, | ||
258 | void *cpu_addr, dma_addr_t dma_addr, size_t size, | ||
259 | struct dma_attrs *attrs) | ||
260 | { | ||
261 | vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false); | ||
262 | return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); | ||
263 | } | ||
264 | |||
265 | static int __swiotlb_mmap_coherent(struct device *dev, | ||
266 | struct vm_area_struct *vma, | ||
267 | void *cpu_addr, dma_addr_t dma_addr, size_t size, | ||
268 | struct dma_attrs *attrs) | ||
269 | { | ||
270 | /* Just use whatever page_prot attributes were specified */ | ||
271 | return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); | ||
272 | } | ||
273 | |||
274 | struct dma_map_ops noncoherent_swiotlb_dma_ops = { | ||
275 | .alloc = __dma_alloc_noncoherent, | ||
276 | .free = __dma_free_noncoherent, | ||
277 | .mmap = __swiotlb_mmap_noncoherent, | ||
278 | .map_page = __swiotlb_map_page, | ||
279 | .unmap_page = __swiotlb_unmap_page, | ||
280 | .map_sg = __swiotlb_map_sg_attrs, | ||
281 | .unmap_sg = __swiotlb_unmap_sg_attrs, | ||
282 | .sync_single_for_cpu = __swiotlb_sync_single_for_cpu, | ||
283 | .sync_single_for_device = __swiotlb_sync_single_for_device, | ||
284 | .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu, | ||
285 | .sync_sg_for_device = __swiotlb_sync_sg_for_device, | ||
286 | .dma_supported = swiotlb_dma_supported, | ||
287 | .mapping_error = swiotlb_dma_mapping_error, | ||
288 | }; | ||
289 | EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops); | ||
290 | |||
291 | struct dma_map_ops coherent_swiotlb_dma_ops = { | ||
292 | .alloc = __dma_alloc_coherent, | ||
293 | .free = __dma_free_coherent, | ||
294 | .mmap = __swiotlb_mmap_coherent, | ||
84 | .map_page = swiotlb_map_page, | 295 | .map_page = swiotlb_map_page, |
85 | .unmap_page = swiotlb_unmap_page, | 296 | .unmap_page = swiotlb_unmap_page, |
86 | .map_sg = swiotlb_map_sg_attrs, | 297 | .map_sg = swiotlb_map_sg_attrs, |
@@ -92,12 +303,19 @@ static struct dma_map_ops arm64_swiotlb_dma_ops = { | |||
92 | .dma_supported = swiotlb_dma_supported, | 303 | .dma_supported = swiotlb_dma_supported, |
93 | .mapping_error = swiotlb_dma_mapping_error, | 304 | .mapping_error = swiotlb_dma_mapping_error, |
94 | }; | 305 | }; |
306 | EXPORT_SYMBOL(coherent_swiotlb_dma_ops); | ||
307 | |||
308 | extern int swiotlb_late_init_with_default_size(size_t default_size); | ||
95 | 309 | ||
96 | void __init arm64_swiotlb_init(void) | 310 | static int __init swiotlb_late_init(void) |
97 | { | 311 | { |
98 | dma_ops = &arm64_swiotlb_dma_ops; | 312 | size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); |
99 | swiotlb_init(1); | 313 | |
314 | dma_ops = &coherent_swiotlb_dma_ops; | ||
315 | |||
316 | return swiotlb_late_init_with_default_size(swiotlb_size); | ||
100 | } | 317 | } |
318 | subsys_initcall(swiotlb_late_init); | ||
101 | 319 | ||
102 | #define PREALLOC_DMA_DEBUG_ENTRIES 4096 | 320 | #define PREALLOC_DMA_DEBUG_ENTRIES 4096 |
103 | 321 | ||
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index d0b4c2efda90..88627c450a6c 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/memblock.h> | 30 | #include <linux/memblock.h> |
31 | #include <linux/sort.h> | 31 | #include <linux/sort.h> |
32 | #include <linux/of_fdt.h> | 32 | #include <linux/of_fdt.h> |
33 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/dma-contiguous.h> | 34 | #include <linux/dma-contiguous.h> |
34 | 35 | ||
35 | #include <asm/sections.h> | 36 | #include <asm/sections.h> |
@@ -59,22 +60,22 @@ static int __init early_initrd(char *p) | |||
59 | early_param("initrd", early_initrd); | 60 | early_param("initrd", early_initrd); |
60 | #endif | 61 | #endif |
61 | 62 | ||
62 | #define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) | ||
63 | |||
64 | static void __init zone_sizes_init(unsigned long min, unsigned long max) | 63 | static void __init zone_sizes_init(unsigned long min, unsigned long max) |
65 | { | 64 | { |
66 | struct memblock_region *reg; | 65 | struct memblock_region *reg; |
67 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; | 66 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; |
68 | unsigned long max_dma32 = min; | 67 | unsigned long max_dma = min; |
69 | 68 | ||
70 | memset(zone_size, 0, sizeof(zone_size)); | 69 | memset(zone_size, 0, sizeof(zone_size)); |
71 | 70 | ||
72 | #ifdef CONFIG_ZONE_DMA32 | ||
73 | /* 4GB maximum for 32-bit only capable devices */ | 71 | /* 4GB maximum for 32-bit only capable devices */ |
74 | max_dma32 = max(min, min(max, MAX_DMA32_PFN)); | 72 | if (IS_ENABLED(CONFIG_ZONE_DMA)) { |
75 | zone_size[ZONE_DMA32] = max_dma32 - min; | 73 | unsigned long max_dma_phys = |
76 | #endif | 74 | (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1); |
77 | zone_size[ZONE_NORMAL] = max - max_dma32; | 75 | max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT)); |
76 | zone_size[ZONE_DMA] = max_dma - min; | ||
77 | } | ||
78 | zone_size[ZONE_NORMAL] = max - max_dma; | ||
78 | 79 | ||
79 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); | 80 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); |
80 | 81 | ||
@@ -84,15 +85,15 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) | |||
84 | 85 | ||
85 | if (start >= max) | 86 | if (start >= max) |
86 | continue; | 87 | continue; |
87 | #ifdef CONFIG_ZONE_DMA32 | 88 | |
88 | if (start < max_dma32) { | 89 | if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) { |
89 | unsigned long dma_end = min(end, max_dma32); | 90 | unsigned long dma_end = min(end, max_dma); |
90 | zhole_size[ZONE_DMA32] -= dma_end - start; | 91 | zhole_size[ZONE_DMA] -= dma_end - start; |
91 | } | 92 | } |
92 | #endif | 93 | |
93 | if (end > max_dma32) { | 94 | if (end > max_dma) { |
94 | unsigned long normal_end = min(end, max); | 95 | unsigned long normal_end = min(end, max); |
95 | unsigned long normal_start = max(start, max_dma32); | 96 | unsigned long normal_start = max(start, max_dma); |
96 | zhole_size[ZONE_NORMAL] -= normal_end - normal_start; | 97 | zhole_size[ZONE_NORMAL] -= normal_end - normal_start; |
97 | } | 98 | } |
98 | } | 99 | } |
@@ -261,8 +262,6 @@ static void __init free_unused_memmap(void) | |||
261 | */ | 262 | */ |
262 | void __init mem_init(void) | 263 | void __init mem_init(void) |
263 | { | 264 | { |
264 | arm64_swiotlb_init(); | ||
265 | |||
266 | max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; | 265 | max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; |
267 | 266 | ||
268 | #ifndef CONFIG_SPARSEMEM_VMEMMAP | 267 | #ifndef CONFIG_SPARSEMEM_VMEMMAP |
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 1333e6f9a8e5..e085ee6ef4e2 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S | |||
@@ -173,12 +173,6 @@ ENDPROC(cpu_do_switch_mm) | |||
173 | * value of the SCTLR_EL1 register. | 173 | * value of the SCTLR_EL1 register. |
174 | */ | 174 | */ |
175 | ENTRY(__cpu_setup) | 175 | ENTRY(__cpu_setup) |
176 | /* | ||
177 | * Preserve the link register across the function call. | ||
178 | */ | ||
179 | mov x28, lr | ||
180 | bl __flush_dcache_all | ||
181 | mov lr, x28 | ||
182 | ic iallu // I+BTB cache invalidate | 176 | ic iallu // I+BTB cache invalidate |
183 | tlbi vmalle1is // invalidate I + D TLBs | 177 | tlbi vmalle1is // invalidate I + D TLBs |
184 | dsb sy | 178 | dsb sy |
@@ -215,8 +209,14 @@ ENTRY(__cpu_setup) | |||
215 | * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for | 209 | * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for |
216 | * both user and kernel. | 210 | * both user and kernel. |
217 | */ | 211 | */ |
218 | ldr x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \ | 212 | ldr x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | \ |
219 | TCR_ASID16 | TCR_TBI0 | (1 << 31) | 213 | TCR_ASID16 | TCR_TBI0 | (1 << 31) |
214 | /* | ||
215 | * Read the PARange bits from ID_AA64MMFR0_EL1 and set the IPS bits in | ||
216 | * TCR_EL1. | ||
217 | */ | ||
218 | mrs x9, ID_AA64MMFR0_EL1 | ||
219 | bfi x10, x9, #32, #3 | ||
220 | #ifdef CONFIG_ARM64_64K_PAGES | 220 | #ifdef CONFIG_ARM64_64K_PAGES |
221 | orr x10, x10, TCR_TG0_64K | 221 | orr x10, x10, TCR_TG0_64K |
222 | orr x10, x10, TCR_TG1_64K | 222 | orr x10, x10, TCR_TG1_64K |
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 4b029c0944af..1fbe11f2a146 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86" | |||
200 | endmenu | 200 | endmenu |
201 | 201 | ||
202 | menu "ARM CPU frequency scaling drivers" | 202 | menu "ARM CPU frequency scaling drivers" |
203 | depends on ARM | 203 | depends on ARM || ARM64 |
204 | source "drivers/cpufreq/Kconfig.arm" | 204 | source "drivers/cpufreq/Kconfig.arm" |
205 | endmenu | 205 | endmenu |
206 | 206 | ||
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index a81147e2e4ef..4d24d17bcfc1 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c | |||
@@ -88,6 +88,11 @@ static void cputime_to_compat_timeval(const cputime_t cputime, | |||
88 | #define ELF_HWCAP COMPAT_ELF_HWCAP | 88 | #define ELF_HWCAP COMPAT_ELF_HWCAP |
89 | #endif | 89 | #endif |
90 | 90 | ||
91 | #ifdef COMPAT_ELF_HWCAP2 | ||
92 | #undef ELF_HWCAP2 | ||
93 | #define ELF_HWCAP2 COMPAT_ELF_HWCAP2 | ||
94 | #endif | ||
95 | |||
91 | #ifdef COMPAT_ARCH_DLINFO | 96 | #ifdef COMPAT_ARCH_DLINFO |
92 | #undef ARCH_DLINFO | 97 | #undef ARCH_DLINFO |
93 | #define ARCH_DLINFO COMPAT_ARCH_DLINFO | 98 | #define ARCH_DLINFO COMPAT_ARCH_DLINFO |
diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h index bb1e2cdeb9bf..d48bf5a95cc1 100644 --- a/include/asm-generic/rwsem.h +++ b/include/asm-generic/rwsem.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _ASM_POWERPC_RWSEM_H | 1 | #ifndef _ASM_GENERIC_RWSEM_H |
2 | #define _ASM_POWERPC_RWSEM_H | 2 | #define _ASM_GENERIC_RWSEM_H |
3 | 3 | ||
4 | #ifndef _LINUX_RWSEM_H | 4 | #ifndef _LINUX_RWSEM_H |
5 | #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead." | 5 | #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead." |
@@ -8,7 +8,7 @@ | |||
8 | #ifdef __KERNEL__ | 8 | #ifdef __KERNEL__ |
9 | 9 | ||
10 | /* | 10 | /* |
11 | * R/W semaphores for PPC using the stuff in lib/rwsem.c. | 11 | * R/W semaphores originally for PPC using the stuff in lib/rwsem.c. |
12 | * Adapted largely from include/asm-i386/rwsem.h | 12 | * Adapted largely from include/asm-i386/rwsem.h |
13 | * by Paul Mackerras <paulus@samba.org>. | 13 | * by Paul Mackerras <paulus@samba.org>. |
14 | */ | 14 | */ |
@@ -16,7 +16,7 @@ | |||
16 | /* | 16 | /* |
17 | * the semaphore definition | 17 | * the semaphore definition |
18 | */ | 18 | */ |
19 | #ifdef CONFIG_PPC64 | 19 | #ifdef CONFIG_64BIT |
20 | # define RWSEM_ACTIVE_MASK 0xffffffffL | 20 | # define RWSEM_ACTIVE_MASK 0xffffffffL |
21 | #else | 21 | #else |
22 | # define RWSEM_ACTIVE_MASK 0x0000ffffL | 22 | # define RWSEM_ACTIVE_MASK 0x0000ffffL |
@@ -129,4 +129,4 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | #endif /* __KERNEL__ */ | 131 | #endif /* __KERNEL__ */ |
132 | #endif /* _ASM_POWERPC_RWSEM_H */ | 132 | #endif /* _ASM_GENERIC_RWSEM_H */ |
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 334b3980ffc1..99982a70ddad 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
@@ -1035,7 +1035,7 @@ int dbg_io_get_char(void) | |||
1035 | * otherwise as a quick means to stop program execution and "break" into | 1035 | * otherwise as a quick means to stop program execution and "break" into |
1036 | * the debugger. | 1036 | * the debugger. |
1037 | */ | 1037 | */ |
1038 | void kgdb_breakpoint(void) | 1038 | noinline void kgdb_breakpoint(void) |
1039 | { | 1039 | { |
1040 | atomic_inc(&kgdb_setting_breakpoint); | 1040 | atomic_inc(&kgdb_setting_breakpoint); |
1041 | wmb(); /* Sync point before breakpoint */ | 1041 | wmb(); /* Sync point before breakpoint */ |