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 */ |
