Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 updates from Will Deacon:

- Support for new architectural features introduced in ARMv8.1:
* Privileged Access Never (PAN) to catch user pointer dereferences in
the kernel
* Large System Extension (LSE) for building scalable atomics and locks
(depends on locking/arch-atomic from tip, which is included here)
* Hardware Dirty Bit Management (DBM) for updating clean PTEs
automatically

- Move our PSCI implementation out into drivers/firmware/, where it can
be shared with arch/arm/. RMK has also pulled this component branch
and has additional patches moving arch/arm/ over. MAINTAINERS is
updated accordingly.

- Better BUG implementation based on the BRK instruction for trapping

- Leaf TLB invalidation for unmapping user pages

- Support for PROBE_ONLY PCI configurations

- Various cleanups and non-critical fixes, including:
* Always flush FP/SIMD state over exec()
* Restrict memblock additions based on range of linear mapping
* Ensure *(LIST_POISON) generates a fatal fault
* Context-tracking syscall return no longer corrupts return value when
not forced on.
* Alternatives patching synchronisation/stability improvements
* Signed sub-word cmpxchg compare fix (tickled by HAVE_CMPXCHG_LOCAL)
* Force SMP=y
* Hide direct DCC access from userspace
* Fix EFI stub memory allocation when DRAM starts at 0x0

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (92 commits)
arm64: flush FP/SIMD state correctly after execve()
arm64: makefile: fix perf_callchain.o kconfig dependency
arm64: set MAX_MEMBLOCK_ADDR according to linear region size
of/fdt: make memblock maximum physical address arch configurable
arm64: Fix source code file path in comments
arm64: entry: always restore x0 from the stack on syscall return
arm64: mdscr_el1: avoid exposing DCC to userspace
arm64: kconfig: Move LIST_POISON to a safe value
arm64: Add __exception_irq_entry definition for function graph
arm64: mm: ensure patched kernel text is fetched from PoU
arm64: alternatives: ensure secondary CPUs execute ISB after patching
arm64: make ll/sc __cmpxchg_case_##name asm consistent
arm64: dma-mapping: Simplify pgprot handling
arm64: restore cpu suspend/resume functionality
ARM64: PCI: do not enable resources on PROBE_ONLY systems
arm64: cmpxchg: truncate sub-word signed types before comparison
arm64: alternative: put secondary CPUs into polling loop during patch
arm64/Documentation: clarify wording regarding memory below the Image
arm64: lse: fix lse cmpxchg code indentation
arm64: remove redundant object file list
...

+2331 -1155
+7 -4
Documentation/arm64/booting.txt
··· 81 81 u64 res3 = 0; /* reserved */ 82 82 u64 res4 = 0; /* reserved */ 83 83 u32 magic = 0x644d5241; /* Magic number, little endian, "ARM\x64" */ 84 - u32 res5; /* reserved (used for PE COFF offset) */ 84 + u32 res5; /* reserved (used for PE COFF offset) */ 85 85 86 86 87 87 Header notes: ··· 103 103 104 104 - The flags field (introduced in v3.17) is a little-endian 64-bit field 105 105 composed as follows: 106 - Bit 0: Kernel endianness. 1 if BE, 0 if LE. 106 + Bit 0: Kernel endianness. 1 if BE, 0 if LE. 107 107 Bits 1-63: Reserved. 108 108 109 109 - When image_size is zero, a bootloader should attempt to keep as much ··· 115 115 address near the start of usable system RAM and called there. Memory 116 116 below that base address is currently unusable by Linux, and therefore it 117 117 is strongly recommended that this location is the start of system RAM. 118 + The region between the 2 MB aligned base address and the start of the 119 + image has no special significance to the kernel, and may be used for 120 + other purposes. 118 121 At least image_size bytes from the start of the image must be free for 119 122 use by the kernel. 120 123 121 - Any memory described to the kernel (even that below the 2MB aligned base 122 - address) which is not marked as reserved from the kernel e.g. with a 124 + Any memory described to the kernel (even that below the start of the 125 + image) which is not marked as reserved from the kernel (e.g., with a 123 126 memreserve region in the device tree) will be considered as available to 124 127 the kernel. 125 128
+64 -22
arch/arm64/Kconfig
··· 29 29 select EDAC_SUPPORT 30 30 select GENERIC_ALLOCATOR 31 31 select GENERIC_CLOCKEVENTS 32 - select GENERIC_CLOCKEVENTS_BROADCAST if SMP 32 + select GENERIC_CLOCKEVENTS_BROADCAST 33 33 select GENERIC_CPU_AUTOPROBE 34 34 select GENERIC_EARLY_IOREMAP 35 35 select GENERIC_IRQ_PROBE ··· 54 54 select HAVE_C_RECORDMCOUNT 55 55 select HAVE_CC_STACKPROTECTOR 56 56 select HAVE_CMPXCHG_DOUBLE 57 + select HAVE_CMPXCHG_LOCAL 57 58 select HAVE_DEBUG_BUGVERBOSE 58 59 select HAVE_DEBUG_KMEMLEAK 59 60 select HAVE_DMA_API_DEBUG ··· 106 105 config STACKTRACE_SUPPORT 107 106 def_bool y 108 107 108 + config ILLEGAL_POINTER_VALUE 109 + hex 110 + default 0xdead000000000000 111 + 109 112 config LOCKDEP_SUPPORT 110 113 def_bool y 111 114 ··· 118 113 119 114 config RWSEM_XCHGADD_ALGORITHM 120 115 def_bool y 116 + 117 + config GENERIC_BUG 118 + def_bool y 119 + depends on BUG 120 + 121 + config GENERIC_BUG_RELATIVE_POINTERS 122 + def_bool y 123 + depends on GENERIC_BUG 121 124 122 125 config GENERIC_HWEIGHT 123 126 def_bool y ··· 149 136 def_bool y 150 137 151 138 config NEED_SG_DMA_LENGTH 139 + def_bool y 140 + 141 + config SMP 152 142 def_bool y 153 143 154 144 config SWIOTLB ··· 388 372 help 389 373 Say Y if you plan on running a kernel in big-endian mode. 390 374 391 - config SMP 392 - bool "Symmetric Multi-Processing" 393 - help 394 - This enables support for systems with more than one CPU. If 395 - you say N here, the kernel will run on single and 396 - multiprocessor machines, but will use only one CPU of a 397 - multiprocessor machine. If you say Y here, the kernel will run 398 - on many, but not all, single processor machines. On a single 399 - processor machine, the kernel will run faster if you say N 400 - here. 401 - 402 - If you don't know what to do here, say N. 403 - 404 375 config SCHED_MC 405 376 bool "Multi-core scheduler support" 406 - depends on SMP 407 377 help 408 378 Multi-core scheduler support improves the CPU scheduler's decision 409 379 making when dealing with multi-core CPU chips at a cost of slightly ··· 397 395 398 396 config SCHED_SMT 399 397 bool "SMT scheduler support" 400 - depends on SMP 401 398 help 402 399 Improves the CPU scheduler's decision making when dealing with 403 400 MultiThreading at a cost of slightly increased overhead in some ··· 405 404 config NR_CPUS 406 405 int "Maximum number of CPUs (2-4096)" 407 406 range 2 4096 408 - depends on SMP 409 407 # These have to remain sorted largest to smallest 410 408 default "64" 411 409 412 410 config HOTPLUG_CPU 413 411 bool "Support for hot-pluggable CPUs" 414 - depends on SMP 415 412 help 416 413 Say Y here to experiment with turning CPUs off and on. CPUs 417 414 can be controlled through /sys/devices/system/cpu. 418 415 419 416 source kernel/Kconfig.preempt 420 - 421 - config UP_LATE_INIT 422 - def_bool y 423 - depends on !SMP 424 417 425 418 config HZ 426 419 int ··· 556 561 557 562 If unsure, say Y 558 563 endif 564 + 565 + menu "ARMv8.1 architectural features" 566 + 567 + config ARM64_HW_AFDBM 568 + bool "Support for hardware updates of the Access and Dirty page flags" 569 + default y 570 + help 571 + The ARMv8.1 architecture extensions introduce support for 572 + hardware updates of the access and dirty information in page 573 + table entries. When enabled in TCR_EL1 (HA and HD bits) on 574 + capable processors, accesses to pages with PTE_AF cleared will 575 + set this bit instead of raising an access flag fault. 576 + Similarly, writes to read-only pages with the DBM bit set will 577 + clear the read-only bit (AP[2]) instead of raising a 578 + permission fault. 579 + 580 + Kernels built with this configuration option enabled continue 581 + to work on pre-ARMv8.1 hardware and the performance impact is 582 + minimal. If unsure, say Y. 583 + 584 + config ARM64_PAN 585 + bool "Enable support for Privileged Access Never (PAN)" 586 + default y 587 + help 588 + Privileged Access Never (PAN; part of the ARMv8.1 Extensions) 589 + prevents the kernel or hypervisor from accessing user-space (EL0) 590 + memory directly. 591 + 592 + Choosing this option will cause any unprotected (not using 593 + copy_to_user et al) memory access to fail with a permission fault. 594 + 595 + The feature is detected at runtime, and will remain as a 'nop' 596 + instruction if the cpu does not implement the feature. 597 + 598 + config ARM64_LSE_ATOMICS 599 + bool "Atomic instructions" 600 + help 601 + As part of the Large System Extensions, ARMv8.1 introduces new 602 + atomic instructions that are designed specifically to scale in 603 + very large systems. 604 + 605 + Say Y here to make use of these instructions for the in-kernel 606 + atomic routines. This incurs a small overhead on CPUs that do 607 + not support these instructions and requires the kernel to be 608 + built with binutils >= 2.25. 609 + 610 + endmenu 559 611 560 612 endmenu 561 613
+16 -2
arch/arm64/Makefile
··· 17 17 18 18 KBUILD_DEFCONFIG := defconfig 19 19 20 - KBUILD_CFLAGS += -mgeneral-regs-only 20 + # Check for binutils support for specific extensions 21 + lseinstr := $(call as-instr,.arch_extension lse,-DCONFIG_AS_LSE=1) 22 + 23 + ifeq ($(CONFIG_ARM64_LSE_ATOMICS), y) 24 + ifeq ($(lseinstr),) 25 + $(warning LSE atomics not supported by binutils) 26 + endif 27 + endif 28 + 29 + KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) 30 + KBUILD_AFLAGS += $(lseinstr) 31 + 21 32 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) 22 33 KBUILD_CPPFLAGS += -mbig-endian 23 34 AS += -EB ··· 69 58 70 59 boot := arch/arm64/boot 71 60 72 - Image Image.gz: vmlinux 61 + Image: vmlinux 62 + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ 63 + 64 + Image.%: vmlinux 73 65 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ 74 66 75 67 zinstall install: vmlinux
+12
arch/arm64/boot/Makefile
··· 19 19 $(obj)/Image: vmlinux FORCE 20 20 $(call if_changed,objcopy) 21 21 22 + $(obj)/Image.bz2: $(obj)/Image FORCE 23 + $(call if_changed,bzip2) 24 + 22 25 $(obj)/Image.gz: $(obj)/Image FORCE 23 26 $(call if_changed,gzip) 27 + 28 + $(obj)/Image.lz4: $(obj)/Image FORCE 29 + $(call if_changed,lz4) 30 + 31 + $(obj)/Image.lzma: $(obj)/Image FORCE 32 + $(call if_changed,lzma) 33 + 34 + $(obj)/Image.lzo: $(obj)/Image FORCE 35 + $(call if_changed,lzo) 24 36 25 37 install: $(obj)/Image 26 38 $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+74 -4
arch/arm64/include/asm/alternative.h
··· 3 3 4 4 #ifndef __ASSEMBLY__ 5 5 6 + #include <linux/init.h> 7 + #include <linux/kconfig.h> 6 8 #include <linux/types.h> 7 9 #include <linux/stddef.h> 8 10 #include <linux/stringify.h> ··· 17 15 u8 alt_len; /* size of new instruction(s), <= orig_len */ 18 16 }; 19 17 20 - void apply_alternatives_all(void); 18 + void __init apply_alternatives_all(void); 21 19 void apply_alternatives(void *start, size_t length); 22 20 void free_alternatives_memory(void); 23 21 ··· 42 40 * be fixed in a binutils release posterior to 2.25.51.0.2 (anything 43 41 * containing commit 4e4d08cf7399b606 or c1baaddf8861). 44 42 */ 45 - #define ALTERNATIVE(oldinstr, newinstr, feature) \ 43 + #define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ 44 + ".if "__stringify(cfg_enabled)" == 1\n" \ 46 45 "661:\n\t" \ 47 46 oldinstr "\n" \ 48 47 "662:\n" \ ··· 56 53 "664:\n\t" \ 57 54 ".popsection\n\t" \ 58 55 ".org . - (664b-663b) + (662b-661b)\n\t" \ 59 - ".org . - (662b-661b) + (664b-663b)\n" 56 + ".org . - (662b-661b) + (664b-663b)\n" \ 57 + ".endif\n" 58 + 59 + #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ 60 + __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) 60 61 61 62 #else 62 63 ··· 72 65 .byte \alt_len 73 66 .endm 74 67 75 - .macro alternative_insn insn1 insn2 cap 68 + .macro alternative_insn insn1, insn2, cap, enable = 1 69 + .if \enable 76 70 661: \insn1 77 71 662: .pushsection .altinstructions, "a" 78 72 altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f ··· 83 75 664: .popsection 84 76 .org . - (664b-663b) + (662b-661b) 85 77 .org . - (662b-661b) + (664b-663b) 78 + .endif 86 79 .endm 87 80 81 + /* 82 + * Begin an alternative code sequence. 83 + * 84 + * The code that follows this macro will be assembled and linked as 85 + * normal. There are no restrictions on this code. 86 + */ 87 + .macro alternative_if_not cap, enable = 1 88 + .if \enable 89 + .pushsection .altinstructions, "a" 90 + altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f 91 + .popsection 92 + 661: 93 + .endif 94 + .endm 95 + 96 + /* 97 + * Provide the alternative code sequence. 98 + * 99 + * The code that follows this macro is assembled into a special 100 + * section to be used for dynamic patching. Code that follows this 101 + * macro must: 102 + * 103 + * 1. Be exactly the same length (in bytes) as the default code 104 + * sequence. 105 + * 106 + * 2. Not contain a branch target that is used outside of the 107 + * alternative sequence it is defined in (branches into an 108 + * alternative sequence are not fixed up). 109 + */ 110 + .macro alternative_else, enable = 1 111 + .if \enable 112 + 662: .pushsection .altinstr_replacement, "ax" 113 + 663: 114 + .endif 115 + .endm 116 + 117 + /* 118 + * Complete an alternative code sequence. 119 + */ 120 + .macro alternative_endif, enable = 1 121 + .if \enable 122 + 664: .popsection 123 + .org . - (664b-663b) + (662b-661b) 124 + .org . - (662b-661b) + (664b-663b) 125 + .endif 126 + .endm 127 + 128 + #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \ 129 + alternative_insn insn1, insn2, cap, IS_ENABLED(cfg) 130 + 131 + 88 132 #endif /* __ASSEMBLY__ */ 133 + 134 + /* 135 + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature)); 136 + * 137 + * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO)); 138 + * N.B. If CONFIG_FOO is specified, but not selected, the whole block 139 + * will be omitted, including oldinstr. 140 + */ 141 + #define ALTERNATIVE(oldinstr, newinstr, ...) \ 142 + _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1) 89 143 90 144 #endif /* __ASM_ALTERNATIVE_H */
-14
arch/arm64/include/asm/assembler.h
··· 50 50 .endm 51 51 52 52 /* 53 - * Save/disable and restore interrupts. 54 - */ 55 - .macro save_and_disable_irqs, olddaif 56 - mrs \olddaif, daif 57 - disable_irq 58 - .endm 59 - 60 - .macro restore_irqs, olddaif 61 - msr daif, \olddaif 62 - .endm 63 - 64 - /* 65 53 * Enable and disable debug exceptions. 66 54 */ 67 55 .macro disable_dbg ··· 91 103 * SMP data memory barrier 92 104 */ 93 105 .macro smp_dmb, opt 94 - #ifdef CONFIG_SMP 95 106 dmb \opt 96 - #endif 97 107 .endm 98 108 99 109 #define USER(l, x...) \
+51 -226
arch/arm64/include/asm/atomic.h
··· 24 24 #include <linux/types.h> 25 25 26 26 #include <asm/barrier.h> 27 - #include <asm/cmpxchg.h> 28 - 29 - #define ATOMIC_INIT(i) { (i) } 27 + #include <asm/lse.h> 30 28 31 29 #ifdef __KERNEL__ 32 30 33 - /* 34 - * On ARM, ordinary assignment (str instruction) doesn't clear the local 35 - * strex/ldrex monitor on some implementations. The reason we can use it for 36 - * atomic_set() is the clrex or dummy strex done on every exception return. 37 - */ 38 - #define atomic_read(v) ACCESS_ONCE((v)->counter) 39 - #define atomic_set(v,i) (((v)->counter) = (i)) 31 + #define __ARM64_IN_ATOMIC_IMPL 40 32 41 - /* 42 - * AArch64 UP and SMP safe atomic ops. We use load exclusive and 43 - * store exclusive to ensure that these are atomic. We may loop 44 - * to ensure that the update happens. 45 - */ 33 + #if defined(CONFIG_ARM64_LSE_ATOMICS) && defined(CONFIG_AS_LSE) 34 + #include <asm/atomic_lse.h> 35 + #else 36 + #include <asm/atomic_ll_sc.h> 37 + #endif 46 38 47 - #define ATOMIC_OP(op, asm_op) \ 48 - static inline void atomic_##op(int i, atomic_t *v) \ 49 - { \ 50 - unsigned long tmp; \ 51 - int result; \ 39 + #undef __ARM64_IN_ATOMIC_IMPL 40 + 41 + #include <asm/cmpxchg.h> 42 + 43 + #define ___atomic_add_unless(v, a, u, sfx) \ 44 + ({ \ 45 + typeof((v)->counter) c, old; \ 52 46 \ 53 - asm volatile("// atomic_" #op "\n" \ 54 - "1: ldxr %w0, %2\n" \ 55 - " " #asm_op " %w0, %w0, %w3\n" \ 56 - " stxr %w1, %w0, %2\n" \ 57 - " cbnz %w1, 1b" \ 58 - : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 59 - : "Ir" (i)); \ 60 - } \ 47 + c = atomic##sfx##_read(v); \ 48 + while (c != (u) && \ 49 + (old = atomic##sfx##_cmpxchg((v), c, c + (a))) != c) \ 50 + c = old; \ 51 + c; \ 52 + }) 61 53 62 - #define ATOMIC_OP_RETURN(op, asm_op) \ 63 - static inline int atomic_##op##_return(int i, atomic_t *v) \ 64 - { \ 65 - unsigned long tmp; \ 66 - int result; \ 67 - \ 68 - asm volatile("// atomic_" #op "_return\n" \ 69 - "1: ldxr %w0, %2\n" \ 70 - " " #asm_op " %w0, %w0, %w3\n" \ 71 - " stlxr %w1, %w0, %2\n" \ 72 - " cbnz %w1, 1b" \ 73 - : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 74 - : "Ir" (i) \ 75 - : "memory"); \ 76 - \ 77 - smp_mb(); \ 78 - return result; \ 79 - } 54 + #define ATOMIC_INIT(i) { (i) } 80 55 81 - #define ATOMIC_OPS(op, asm_op) \ 82 - ATOMIC_OP(op, asm_op) \ 83 - ATOMIC_OP_RETURN(op, asm_op) 56 + #define atomic_read(v) READ_ONCE((v)->counter) 57 + #define atomic_set(v, i) (((v)->counter) = (i)) 58 + #define atomic_xchg(v, new) xchg(&((v)->counter), (new)) 59 + #define atomic_cmpxchg(v, old, new) cmpxchg(&((v)->counter), (old), (new)) 84 60 85 - ATOMIC_OPS(add, add) 86 - ATOMIC_OPS(sub, sub) 87 - 88 - #define atomic_andnot atomic_andnot 89 - 90 - ATOMIC_OP(and, and) 91 - ATOMIC_OP(andnot, bic) 92 - ATOMIC_OP(or, orr) 93 - ATOMIC_OP(xor, eor) 94 - 95 - #undef ATOMIC_OPS 96 - #undef ATOMIC_OP_RETURN 97 - #undef ATOMIC_OP 98 - 99 - static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) 100 - { 101 - unsigned long tmp; 102 - int oldval; 103 - 104 - smp_mb(); 105 - 106 - asm volatile("// atomic_cmpxchg\n" 107 - "1: ldxr %w1, %2\n" 108 - " cmp %w1, %w3\n" 109 - " b.ne 2f\n" 110 - " stxr %w0, %w4, %2\n" 111 - " cbnz %w0, 1b\n" 112 - "2:" 113 - : "=&r" (tmp), "=&r" (oldval), "+Q" (ptr->counter) 114 - : "Ir" (old), "r" (new) 115 - : "cc"); 116 - 117 - smp_mb(); 118 - return oldval; 119 - } 120 - 121 - #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 122 - 123 - static inline int __atomic_add_unless(atomic_t *v, int a, int u) 124 - { 125 - int c, old; 126 - 127 - c = atomic_read(v); 128 - while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) 129 - c = old; 130 - return c; 131 - } 132 - 133 - #define atomic_inc(v) atomic_add(1, v) 134 - #define atomic_dec(v) atomic_sub(1, v) 135 - 136 - #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) 137 - #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) 138 - #define atomic_inc_return(v) (atomic_add_return(1, v)) 139 - #define atomic_dec_return(v) (atomic_sub_return(1, v)) 140 - #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) 141 - 142 - #define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0) 61 + #define atomic_inc(v) atomic_add(1, (v)) 62 + #define atomic_dec(v) atomic_sub(1, (v)) 63 + #define atomic_inc_return(v) atomic_add_return(1, (v)) 64 + #define atomic_dec_return(v) atomic_sub_return(1, (v)) 65 + #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) 66 + #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) 67 + #define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) 68 + #define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) 69 + #define __atomic_add_unless(v, a, u) ___atomic_add_unless(v, a, u,) 70 + #define atomic_andnot atomic_andnot 143 71 144 72 /* 145 73 * 64-bit atomic operations. 146 74 */ 147 - #define ATOMIC64_INIT(i) { (i) } 75 + #define ATOMIC64_INIT ATOMIC_INIT 76 + #define atomic64_read atomic_read 77 + #define atomic64_set atomic_set 78 + #define atomic64_xchg atomic_xchg 79 + #define atomic64_cmpxchg atomic_cmpxchg 148 80 149 - #define atomic64_read(v) ACCESS_ONCE((v)->counter) 150 - #define atomic64_set(v,i) (((v)->counter) = (i)) 151 - 152 - #define ATOMIC64_OP(op, asm_op) \ 153 - static inline void atomic64_##op(long i, atomic64_t *v) \ 154 - { \ 155 - long result; \ 156 - unsigned long tmp; \ 157 - \ 158 - asm volatile("// atomic64_" #op "\n" \ 159 - "1: ldxr %0, %2\n" \ 160 - " " #asm_op " %0, %0, %3\n" \ 161 - " stxr %w1, %0, %2\n" \ 162 - " cbnz %w1, 1b" \ 163 - : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 164 - : "Ir" (i)); \ 165 - } \ 166 - 167 - #define ATOMIC64_OP_RETURN(op, asm_op) \ 168 - static inline long atomic64_##op##_return(long i, atomic64_t *v) \ 169 - { \ 170 - long result; \ 171 - unsigned long tmp; \ 172 - \ 173 - asm volatile("// atomic64_" #op "_return\n" \ 174 - "1: ldxr %0, %2\n" \ 175 - " " #asm_op " %0, %0, %3\n" \ 176 - " stlxr %w1, %0, %2\n" \ 177 - " cbnz %w1, 1b" \ 178 - : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 179 - : "Ir" (i) \ 180 - : "memory"); \ 181 - \ 182 - smp_mb(); \ 183 - return result; \ 184 - } 185 - 186 - #define ATOMIC64_OPS(op, asm_op) \ 187 - ATOMIC64_OP(op, asm_op) \ 188 - ATOMIC64_OP_RETURN(op, asm_op) 189 - 190 - ATOMIC64_OPS(add, add) 191 - ATOMIC64_OPS(sub, sub) 192 - 193 - #define atomic64_andnot atomic64_andnot 194 - 195 - ATOMIC64_OP(and, and) 196 - ATOMIC64_OP(andnot, bic) 197 - ATOMIC64_OP(or, orr) 198 - ATOMIC64_OP(xor, eor) 199 - 200 - #undef ATOMIC64_OPS 201 - #undef ATOMIC64_OP_RETURN 202 - #undef ATOMIC64_OP 203 - 204 - static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new) 205 - { 206 - long oldval; 207 - unsigned long res; 208 - 209 - smp_mb(); 210 - 211 - asm volatile("// atomic64_cmpxchg\n" 212 - "1: ldxr %1, %2\n" 213 - " cmp %1, %3\n" 214 - " b.ne 2f\n" 215 - " stxr %w0, %4, %2\n" 216 - " cbnz %w0, 1b\n" 217 - "2:" 218 - : "=&r" (res), "=&r" (oldval), "+Q" (ptr->counter) 219 - : "Ir" (old), "r" (new) 220 - : "cc"); 221 - 222 - smp_mb(); 223 - return oldval; 224 - } 225 - 226 - #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) 227 - 228 - static inline long atomic64_dec_if_positive(atomic64_t *v) 229 - { 230 - long result; 231 - unsigned long tmp; 232 - 233 - asm volatile("// atomic64_dec_if_positive\n" 234 - "1: ldxr %0, %2\n" 235 - " subs %0, %0, #1\n" 236 - " b.mi 2f\n" 237 - " stlxr %w1, %0, %2\n" 238 - " cbnz %w1, 1b\n" 239 - " dmb ish\n" 240 - "2:" 241 - : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) 242 - : 243 - : "cc", "memory"); 244 - 245 - return result; 246 - } 247 - 248 - static inline int atomic64_add_unless(atomic64_t *v, long a, long u) 249 - { 250 - long c, old; 251 - 252 - c = atomic64_read(v); 253 - while (c != u && (old = atomic64_cmpxchg((v), c, c + a)) != c) 254 - c = old; 255 - 256 - return c != u; 257 - } 258 - 259 - #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) 260 - #define atomic64_inc(v) atomic64_add(1LL, (v)) 261 - #define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) 81 + #define atomic64_inc(v) atomic64_add(1, (v)) 82 + #define atomic64_dec(v) atomic64_sub(1, (v)) 83 + #define atomic64_inc_return(v) atomic64_add_return(1, (v)) 84 + #define atomic64_dec_return(v) atomic64_sub_return(1, (v)) 262 85 #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) 263 - #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) 264 - #define atomic64_dec(v) atomic64_sub(1LL, (v)) 265 - #define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) 266 - #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) 267 - #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) 86 + #define atomic64_dec_and_test(v) (atomic64_dec_return(v) == 0) 87 + #define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0) 88 + #define atomic64_add_negative(i, v) (atomic64_add_return((i), (v)) < 0) 89 + #define atomic64_add_unless(v, a, u) (___atomic_add_unless(v, a, u, 64) != u) 90 + #define atomic64_andnot atomic64_andnot 91 + 92 + #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) 268 93 269 94 #endif 270 95 #endif
+247
arch/arm64/include/asm/atomic_ll_sc.h
··· 1 + /* 2 + * Based on arch/arm/include/asm/atomic.h 3 + * 4 + * Copyright (C) 1996 Russell King. 5 + * Copyright (C) 2002 Deep Blue Solutions Ltd. 6 + * Copyright (C) 2012 ARM Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 + */ 20 + 21 + #ifndef __ASM_ATOMIC_LL_SC_H 22 + #define __ASM_ATOMIC_LL_SC_H 23 + 24 + #ifndef __ARM64_IN_ATOMIC_IMPL 25 + #error "please don't include this file directly" 26 + #endif 27 + 28 + /* 29 + * AArch64 UP and SMP safe atomic ops. We use load exclusive and 30 + * store exclusive to ensure that these are atomic. We may loop 31 + * to ensure that the update happens. 32 + * 33 + * NOTE: these functions do *not* follow the PCS and must explicitly 34 + * save any clobbered registers other than x0 (regardless of return 35 + * value). This is achieved through -fcall-saved-* compiler flags for 36 + * this file, which unfortunately don't work on a per-function basis 37 + * (the optimize attribute silently ignores these options). 38 + */ 39 + 40 + #define ATOMIC_OP(op, asm_op) \ 41 + __LL_SC_INLINE void \ 42 + __LL_SC_PREFIX(atomic_##op(int i, atomic_t *v)) \ 43 + { \ 44 + unsigned long tmp; \ 45 + int result; \ 46 + \ 47 + asm volatile("// atomic_" #op "\n" \ 48 + " prfm pstl1strm, %2\n" \ 49 + "1: ldxr %w0, %2\n" \ 50 + " " #asm_op " %w0, %w0, %w3\n" \ 51 + " stxr %w1, %w0, %2\n" \ 52 + " cbnz %w1, 1b" \ 53 + : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 54 + : "Ir" (i)); \ 55 + } \ 56 + __LL_SC_EXPORT(atomic_##op); 57 + 58 + #define ATOMIC_OP_RETURN(op, asm_op) \ 59 + __LL_SC_INLINE int \ 60 + __LL_SC_PREFIX(atomic_##op##_return(int i, atomic_t *v)) \ 61 + { \ 62 + unsigned long tmp; \ 63 + int result; \ 64 + \ 65 + asm volatile("// atomic_" #op "_return\n" \ 66 + " prfm pstl1strm, %2\n" \ 67 + "1: ldxr %w0, %2\n" \ 68 + " " #asm_op " %w0, %w0, %w3\n" \ 69 + " stlxr %w1, %w0, %2\n" \ 70 + " cbnz %w1, 1b" \ 71 + : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 72 + : "Ir" (i) \ 73 + : "memory"); \ 74 + \ 75 + smp_mb(); \ 76 + return result; \ 77 + } \ 78 + __LL_SC_EXPORT(atomic_##op##_return); 79 + 80 + #define ATOMIC_OPS(op, asm_op) \ 81 + ATOMIC_OP(op, asm_op) \ 82 + ATOMIC_OP_RETURN(op, asm_op) 83 + 84 + ATOMIC_OPS(add, add) 85 + ATOMIC_OPS(sub, sub) 86 + 87 + ATOMIC_OP(and, and) 88 + ATOMIC_OP(andnot, bic) 89 + ATOMIC_OP(or, orr) 90 + ATOMIC_OP(xor, eor) 91 + 92 + #undef ATOMIC_OPS 93 + #undef ATOMIC_OP_RETURN 94 + #undef ATOMIC_OP 95 + 96 + #define ATOMIC64_OP(op, asm_op) \ 97 + __LL_SC_INLINE void \ 98 + __LL_SC_PREFIX(atomic64_##op(long i, atomic64_t *v)) \ 99 + { \ 100 + long result; \ 101 + unsigned long tmp; \ 102 + \ 103 + asm volatile("// atomic64_" #op "\n" \ 104 + " prfm pstl1strm, %2\n" \ 105 + "1: ldxr %0, %2\n" \ 106 + " " #asm_op " %0, %0, %3\n" \ 107 + " stxr %w1, %0, %2\n" \ 108 + " cbnz %w1, 1b" \ 109 + : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 110 + : "Ir" (i)); \ 111 + } \ 112 + __LL_SC_EXPORT(atomic64_##op); 113 + 114 + #define ATOMIC64_OP_RETURN(op, asm_op) \ 115 + __LL_SC_INLINE long \ 116 + __LL_SC_PREFIX(atomic64_##op##_return(long i, atomic64_t *v)) \ 117 + { \ 118 + long result; \ 119 + unsigned long tmp; \ 120 + \ 121 + asm volatile("// atomic64_" #op "_return\n" \ 122 + " prfm pstl1strm, %2\n" \ 123 + "1: ldxr %0, %2\n" \ 124 + " " #asm_op " %0, %0, %3\n" \ 125 + " stlxr %w1, %0, %2\n" \ 126 + " cbnz %w1, 1b" \ 127 + : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 128 + : "Ir" (i) \ 129 + : "memory"); \ 130 + \ 131 + smp_mb(); \ 132 + return result; \ 133 + } \ 134 + __LL_SC_EXPORT(atomic64_##op##_return); 135 + 136 + #define ATOMIC64_OPS(op, asm_op) \ 137 + ATOMIC64_OP(op, asm_op) \ 138 + ATOMIC64_OP_RETURN(op, asm_op) 139 + 140 + ATOMIC64_OPS(add, add) 141 + ATOMIC64_OPS(sub, sub) 142 + 143 + ATOMIC64_OP(and, and) 144 + ATOMIC64_OP(andnot, bic) 145 + ATOMIC64_OP(or, orr) 146 + ATOMIC64_OP(xor, eor) 147 + 148 + #undef ATOMIC64_OPS 149 + #undef ATOMIC64_OP_RETURN 150 + #undef ATOMIC64_OP 151 + 152 + __LL_SC_INLINE long 153 + __LL_SC_PREFIX(atomic64_dec_if_positive(atomic64_t *v)) 154 + { 155 + long result; 156 + unsigned long tmp; 157 + 158 + asm volatile("// atomic64_dec_if_positive\n" 159 + " prfm pstl1strm, %2\n" 160 + "1: ldxr %0, %2\n" 161 + " subs %0, %0, #1\n" 162 + " b.lt 2f\n" 163 + " stlxr %w1, %0, %2\n" 164 + " cbnz %w1, 1b\n" 165 + " dmb ish\n" 166 + "2:" 167 + : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) 168 + : 169 + : "cc", "memory"); 170 + 171 + return result; 172 + } 173 + __LL_SC_EXPORT(atomic64_dec_if_positive); 174 + 175 + #define __CMPXCHG_CASE(w, sz, name, mb, rel, cl) \ 176 + __LL_SC_INLINE unsigned long \ 177 + __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr, \ 178 + unsigned long old, \ 179 + unsigned long new)) \ 180 + { \ 181 + unsigned long tmp, oldval; \ 182 + \ 183 + asm volatile( \ 184 + " prfm pstl1strm, %[v]\n" \ 185 + "1: ldxr" #sz "\t%" #w "[oldval], %[v]\n" \ 186 + " eor %" #w "[tmp], %" #w "[oldval], %" #w "[old]\n" \ 187 + " cbnz %" #w "[tmp], 2f\n" \ 188 + " st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \ 189 + " cbnz %w[tmp], 1b\n" \ 190 + " " #mb "\n" \ 191 + " mov %" #w "[oldval], %" #w "[old]\n" \ 192 + "2:" \ 193 + : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \ 194 + [v] "+Q" (*(unsigned long *)ptr) \ 195 + : [old] "Lr" (old), [new] "r" (new) \ 196 + : cl); \ 197 + \ 198 + return oldval; \ 199 + } \ 200 + __LL_SC_EXPORT(__cmpxchg_case_##name); 201 + 202 + __CMPXCHG_CASE(w, b, 1, , , ) 203 + __CMPXCHG_CASE(w, h, 2, , , ) 204 + __CMPXCHG_CASE(w, , 4, , , ) 205 + __CMPXCHG_CASE( , , 8, , , ) 206 + __CMPXCHG_CASE(w, b, mb_1, dmb ish, l, "memory") 207 + __CMPXCHG_CASE(w, h, mb_2, dmb ish, l, "memory") 208 + __CMPXCHG_CASE(w, , mb_4, dmb ish, l, "memory") 209 + __CMPXCHG_CASE( , , mb_8, dmb ish, l, "memory") 210 + 211 + #undef __CMPXCHG_CASE 212 + 213 + #define __CMPXCHG_DBL(name, mb, rel, cl) \ 214 + __LL_SC_INLINE int \ 215 + __LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1, \ 216 + unsigned long old2, \ 217 + unsigned long new1, \ 218 + unsigned long new2, \ 219 + volatile void *ptr)) \ 220 + { \ 221 + unsigned long tmp, ret; \ 222 + \ 223 + asm volatile("// __cmpxchg_double" #name "\n" \ 224 + " prfm pstl1strm, %2\n" \ 225 + "1: ldxp %0, %1, %2\n" \ 226 + " eor %0, %0, %3\n" \ 227 + " eor %1, %1, %4\n" \ 228 + " orr %1, %0, %1\n" \ 229 + " cbnz %1, 2f\n" \ 230 + " st" #rel "xp %w0, %5, %6, %2\n" \ 231 + " cbnz %w0, 1b\n" \ 232 + " " #mb "\n" \ 233 + "2:" \ 234 + : "=&r" (tmp), "=&r" (ret), "+Q" (*(unsigned long *)ptr) \ 235 + : "r" (old1), "r" (old2), "r" (new1), "r" (new2) \ 236 + : cl); \ 237 + \ 238 + return ret; \ 239 + } \ 240 + __LL_SC_EXPORT(__cmpxchg_double##name); 241 + 242 + __CMPXCHG_DBL( , , , ) 243 + __CMPXCHG_DBL(_mb, dmb ish, l, "memory") 244 + 245 + #undef __CMPXCHG_DBL 246 + 247 + #endif /* __ASM_ATOMIC_LL_SC_H */
+391
arch/arm64/include/asm/atomic_lse.h
··· 1 + /* 2 + * Based on arch/arm/include/asm/atomic.h 3 + * 4 + * Copyright (C) 1996 Russell King. 5 + * Copyright (C) 2002 Deep Blue Solutions Ltd. 6 + * Copyright (C) 2012 ARM Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 + */ 20 + 21 + #ifndef __ASM_ATOMIC_LSE_H 22 + #define __ASM_ATOMIC_LSE_H 23 + 24 + #ifndef __ARM64_IN_ATOMIC_IMPL 25 + #error "please don't include this file directly" 26 + #endif 27 + 28 + #define __LL_SC_ATOMIC(op) __LL_SC_CALL(atomic_##op) 29 + 30 + static inline void atomic_andnot(int i, atomic_t *v) 31 + { 32 + register int w0 asm ("w0") = i; 33 + register atomic_t *x1 asm ("x1") = v; 34 + 35 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(andnot), 36 + " stclr %w[i], %[v]\n") 37 + : [i] "+r" (w0), [v] "+Q" (v->counter) 38 + : "r" (x1) 39 + : "x30"); 40 + } 41 + 42 + static inline void atomic_or(int i, atomic_t *v) 43 + { 44 + register int w0 asm ("w0") = i; 45 + register atomic_t *x1 asm ("x1") = v; 46 + 47 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(or), 48 + " stset %w[i], %[v]\n") 49 + : [i] "+r" (w0), [v] "+Q" (v->counter) 50 + : "r" (x1) 51 + : "x30"); 52 + } 53 + 54 + static inline void atomic_xor(int i, atomic_t *v) 55 + { 56 + register int w0 asm ("w0") = i; 57 + register atomic_t *x1 asm ("x1") = v; 58 + 59 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(xor), 60 + " steor %w[i], %[v]\n") 61 + : [i] "+r" (w0), [v] "+Q" (v->counter) 62 + : "r" (x1) 63 + : "x30"); 64 + } 65 + 66 + static inline void atomic_add(int i, atomic_t *v) 67 + { 68 + register int w0 asm ("w0") = i; 69 + register atomic_t *x1 asm ("x1") = v; 70 + 71 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(add), 72 + " stadd %w[i], %[v]\n") 73 + : [i] "+r" (w0), [v] "+Q" (v->counter) 74 + : "r" (x1) 75 + : "x30"); 76 + } 77 + 78 + static inline int atomic_add_return(int i, atomic_t *v) 79 + { 80 + register int w0 asm ("w0") = i; 81 + register atomic_t *x1 asm ("x1") = v; 82 + 83 + asm volatile(ARM64_LSE_ATOMIC_INSN( 84 + /* LL/SC */ 85 + " nop\n" 86 + __LL_SC_ATOMIC(add_return), 87 + /* LSE atomics */ 88 + " ldaddal %w[i], w30, %[v]\n" 89 + " add %w[i], %w[i], w30") 90 + : [i] "+r" (w0), [v] "+Q" (v->counter) 91 + : "r" (x1) 92 + : "x30", "memory"); 93 + 94 + return w0; 95 + } 96 + 97 + static inline void atomic_and(int i, atomic_t *v) 98 + { 99 + register int w0 asm ("w0") = i; 100 + register atomic_t *x1 asm ("x1") = v; 101 + 102 + asm volatile(ARM64_LSE_ATOMIC_INSN( 103 + /* LL/SC */ 104 + " nop\n" 105 + __LL_SC_ATOMIC(and), 106 + /* LSE atomics */ 107 + " mvn %w[i], %w[i]\n" 108 + " stclr %w[i], %[v]") 109 + : [i] "+r" (w0), [v] "+Q" (v->counter) 110 + : "r" (x1) 111 + : "x30"); 112 + } 113 + 114 + static inline void atomic_sub(int i, atomic_t *v) 115 + { 116 + register int w0 asm ("w0") = i; 117 + register atomic_t *x1 asm ("x1") = v; 118 + 119 + asm volatile(ARM64_LSE_ATOMIC_INSN( 120 + /* LL/SC */ 121 + " nop\n" 122 + __LL_SC_ATOMIC(sub), 123 + /* LSE atomics */ 124 + " neg %w[i], %w[i]\n" 125 + " stadd %w[i], %[v]") 126 + : [i] "+r" (w0), [v] "+Q" (v->counter) 127 + : "r" (x1) 128 + : "x30"); 129 + } 130 + 131 + static inline int atomic_sub_return(int i, atomic_t *v) 132 + { 133 + register int w0 asm ("w0") = i; 134 + register atomic_t *x1 asm ("x1") = v; 135 + 136 + asm volatile(ARM64_LSE_ATOMIC_INSN( 137 + /* LL/SC */ 138 + " nop\n" 139 + __LL_SC_ATOMIC(sub_return) 140 + " nop", 141 + /* LSE atomics */ 142 + " neg %w[i], %w[i]\n" 143 + " ldaddal %w[i], w30, %[v]\n" 144 + " add %w[i], %w[i], w30") 145 + : [i] "+r" (w0), [v] "+Q" (v->counter) 146 + : "r" (x1) 147 + : "x30", "memory"); 148 + 149 + return w0; 150 + } 151 + 152 + #undef __LL_SC_ATOMIC 153 + 154 + #define __LL_SC_ATOMIC64(op) __LL_SC_CALL(atomic64_##op) 155 + 156 + static inline void atomic64_andnot(long i, atomic64_t *v) 157 + { 158 + register long x0 asm ("x0") = i; 159 + register atomic64_t *x1 asm ("x1") = v; 160 + 161 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(andnot), 162 + " stclr %[i], %[v]\n") 163 + : [i] "+r" (x0), [v] "+Q" (v->counter) 164 + : "r" (x1) 165 + : "x30"); 166 + } 167 + 168 + static inline void atomic64_or(long i, atomic64_t *v) 169 + { 170 + register long x0 asm ("x0") = i; 171 + register atomic64_t *x1 asm ("x1") = v; 172 + 173 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(or), 174 + " stset %[i], %[v]\n") 175 + : [i] "+r" (x0), [v] "+Q" (v->counter) 176 + : "r" (x1) 177 + : "x30"); 178 + } 179 + 180 + static inline void atomic64_xor(long i, atomic64_t *v) 181 + { 182 + register long x0 asm ("x0") = i; 183 + register atomic64_t *x1 asm ("x1") = v; 184 + 185 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(xor), 186 + " steor %[i], %[v]\n") 187 + : [i] "+r" (x0), [v] "+Q" (v->counter) 188 + : "r" (x1) 189 + : "x30"); 190 + } 191 + 192 + static inline void atomic64_add(long i, atomic64_t *v) 193 + { 194 + register long x0 asm ("x0") = i; 195 + register atomic64_t *x1 asm ("x1") = v; 196 + 197 + asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(add), 198 + " stadd %[i], %[v]\n") 199 + : [i] "+r" (x0), [v] "+Q" (v->counter) 200 + : "r" (x1) 201 + : "x30"); 202 + } 203 + 204 + static inline long atomic64_add_return(long i, atomic64_t *v) 205 + { 206 + register long x0 asm ("x0") = i; 207 + register atomic64_t *x1 asm ("x1") = v; 208 + 209 + asm volatile(ARM64_LSE_ATOMIC_INSN( 210 + /* LL/SC */ 211 + " nop\n" 212 + __LL_SC_ATOMIC64(add_return), 213 + /* LSE atomics */ 214 + " ldaddal %[i], x30, %[v]\n" 215 + " add %[i], %[i], x30") 216 + : [i] "+r" (x0), [v] "+Q" (v->counter) 217 + : "r" (x1) 218 + : "x30", "memory"); 219 + 220 + return x0; 221 + } 222 + 223 + static inline void atomic64_and(long i, atomic64_t *v) 224 + { 225 + register long x0 asm ("x0") = i; 226 + register atomic64_t *x1 asm ("x1") = v; 227 + 228 + asm volatile(ARM64_LSE_ATOMIC_INSN( 229 + /* LL/SC */ 230 + " nop\n" 231 + __LL_SC_ATOMIC64(and), 232 + /* LSE atomics */ 233 + " mvn %[i], %[i]\n" 234 + " stclr %[i], %[v]") 235 + : [i] "+r" (x0), [v] "+Q" (v->counter) 236 + : "r" (x1) 237 + : "x30"); 238 + } 239 + 240 + static inline void atomic64_sub(long i, atomic64_t *v) 241 + { 242 + register long x0 asm ("x0") = i; 243 + register atomic64_t *x1 asm ("x1") = v; 244 + 245 + asm volatile(ARM64_LSE_ATOMIC_INSN( 246 + /* LL/SC */ 247 + " nop\n" 248 + __LL_SC_ATOMIC64(sub), 249 + /* LSE atomics */ 250 + " neg %[i], %[i]\n" 251 + " stadd %[i], %[v]") 252 + : [i] "+r" (x0), [v] "+Q" (v->counter) 253 + : "r" (x1) 254 + : "x30"); 255 + } 256 + 257 + static inline long atomic64_sub_return(long i, atomic64_t *v) 258 + { 259 + register long x0 asm ("x0") = i; 260 + register atomic64_t *x1 asm ("x1") = v; 261 + 262 + asm volatile(ARM64_LSE_ATOMIC_INSN( 263 + /* LL/SC */ 264 + " nop\n" 265 + __LL_SC_ATOMIC64(sub_return) 266 + " nop", 267 + /* LSE atomics */ 268 + " neg %[i], %[i]\n" 269 + " ldaddal %[i], x30, %[v]\n" 270 + " add %[i], %[i], x30") 271 + : [i] "+r" (x0), [v] "+Q" (v->counter) 272 + : "r" (x1) 273 + : "x30", "memory"); 274 + 275 + return x0; 276 + } 277 + 278 + static inline long atomic64_dec_if_positive(atomic64_t *v) 279 + { 280 + register long x0 asm ("x0") = (long)v; 281 + 282 + asm volatile(ARM64_LSE_ATOMIC_INSN( 283 + /* LL/SC */ 284 + " nop\n" 285 + __LL_SC_ATOMIC64(dec_if_positive) 286 + " nop\n" 287 + " nop\n" 288 + " nop\n" 289 + " nop\n" 290 + " nop", 291 + /* LSE atomics */ 292 + "1: ldr x30, %[v]\n" 293 + " subs %[ret], x30, #1\n" 294 + " b.lt 2f\n" 295 + " casal x30, %[ret], %[v]\n" 296 + " sub x30, x30, #1\n" 297 + " sub x30, x30, %[ret]\n" 298 + " cbnz x30, 1b\n" 299 + "2:") 300 + : [ret] "+&r" (x0), [v] "+Q" (v->counter) 301 + : 302 + : "x30", "cc", "memory"); 303 + 304 + return x0; 305 + } 306 + 307 + #undef __LL_SC_ATOMIC64 308 + 309 + #define __LL_SC_CMPXCHG(op) __LL_SC_CALL(__cmpxchg_case_##op) 310 + 311 + #define __CMPXCHG_CASE(w, sz, name, mb, cl...) \ 312 + static inline unsigned long __cmpxchg_case_##name(volatile void *ptr, \ 313 + unsigned long old, \ 314 + unsigned long new) \ 315 + { \ 316 + register unsigned long x0 asm ("x0") = (unsigned long)ptr; \ 317 + register unsigned long x1 asm ("x1") = old; \ 318 + register unsigned long x2 asm ("x2") = new; \ 319 + \ 320 + asm volatile(ARM64_LSE_ATOMIC_INSN( \ 321 + /* LL/SC */ \ 322 + " nop\n" \ 323 + __LL_SC_CMPXCHG(name) \ 324 + " nop", \ 325 + /* LSE atomics */ \ 326 + " mov " #w "30, %" #w "[old]\n" \ 327 + " cas" #mb #sz "\t" #w "30, %" #w "[new], %[v]\n" \ 328 + " mov %" #w "[ret], " #w "30") \ 329 + : [ret] "+r" (x0), [v] "+Q" (*(unsigned long *)ptr) \ 330 + : [old] "r" (x1), [new] "r" (x2) \ 331 + : "x30" , ##cl); \ 332 + \ 333 + return x0; \ 334 + } 335 + 336 + __CMPXCHG_CASE(w, b, 1, ) 337 + __CMPXCHG_CASE(w, h, 2, ) 338 + __CMPXCHG_CASE(w, , 4, ) 339 + __CMPXCHG_CASE(x, , 8, ) 340 + __CMPXCHG_CASE(w, b, mb_1, al, "memory") 341 + __CMPXCHG_CASE(w, h, mb_2, al, "memory") 342 + __CMPXCHG_CASE(w, , mb_4, al, "memory") 343 + __CMPXCHG_CASE(x, , mb_8, al, "memory") 344 + 345 + #undef __LL_SC_CMPXCHG 346 + #undef __CMPXCHG_CASE 347 + 348 + #define __LL_SC_CMPXCHG_DBL(op) __LL_SC_CALL(__cmpxchg_double##op) 349 + 350 + #define __CMPXCHG_DBL(name, mb, cl...) \ 351 + static inline int __cmpxchg_double##name(unsigned long old1, \ 352 + unsigned long old2, \ 353 + unsigned long new1, \ 354 + unsigned long new2, \ 355 + volatile void *ptr) \ 356 + { \ 357 + unsigned long oldval1 = old1; \ 358 + unsigned long oldval2 = old2; \ 359 + register unsigned long x0 asm ("x0") = old1; \ 360 + register unsigned long x1 asm ("x1") = old2; \ 361 + register unsigned long x2 asm ("x2") = new1; \ 362 + register unsigned long x3 asm ("x3") = new2; \ 363 + register unsigned long x4 asm ("x4") = (unsigned long)ptr; \ 364 + \ 365 + asm volatile(ARM64_LSE_ATOMIC_INSN( \ 366 + /* LL/SC */ \ 367 + " nop\n" \ 368 + " nop\n" \ 369 + " nop\n" \ 370 + __LL_SC_CMPXCHG_DBL(name), \ 371 + /* LSE atomics */ \ 372 + " casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\ 373 + " eor %[old1], %[old1], %[oldval1]\n" \ 374 + " eor %[old2], %[old2], %[oldval2]\n" \ 375 + " orr %[old1], %[old1], %[old2]") \ 376 + : [old1] "+r" (x0), [old2] "+r" (x1), \ 377 + [v] "+Q" (*(unsigned long *)ptr) \ 378 + : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \ 379 + [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \ 380 + : "x30" , ##cl); \ 381 + \ 382 + return x0; \ 383 + } 384 + 385 + __CMPXCHG_DBL( , ) 386 + __CMPXCHG_DBL(_mb, al, "memory") 387 + 388 + #undef __LL_SC_CMPXCHG_DBL 389 + #undef __CMPXCHG_DBL 390 + 391 + #endif /* __ASM_ATOMIC_LSE_H */
-24
arch/arm64/include/asm/barrier.h
··· 35 35 #define dma_rmb() dmb(oshld) 36 36 #define dma_wmb() dmb(oshst) 37 37 38 - #ifndef CONFIG_SMP 39 - #define smp_mb() barrier() 40 - #define smp_rmb() barrier() 41 - #define smp_wmb() barrier() 42 - 43 - #define smp_store_release(p, v) \ 44 - do { \ 45 - compiletime_assert_atomic_type(*p); \ 46 - barrier(); \ 47 - WRITE_ONCE(*p, v); \ 48 - } while (0) 49 - 50 - #define smp_load_acquire(p) \ 51 - ({ \ 52 - typeof(*p) ___p1 = READ_ONCE(*p); \ 53 - compiletime_assert_atomic_type(*p); \ 54 - barrier(); \ 55 - ___p1; \ 56 - }) 57 - 58 - #else 59 - 60 38 #define smp_mb() dmb(ish) 61 39 #define smp_rmb() dmb(ishld) 62 40 #define smp_wmb() dmb(ishst) ··· 86 108 } \ 87 109 ___p1; \ 88 110 }) 89 - 90 - #endif 91 111 92 112 #define read_barrier_depends() do { } while(0) 93 113 #define smp_read_barrier_depends() do { } while(0)
+64
arch/arm64/include/asm/bug.h
··· 1 + /* 2 + * Copyright (C) 2015 ARM Limited 3 + * Author: Dave Martin <Dave.Martin@arm.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #ifndef _ARCH_ARM64_ASM_BUG_H 19 + #define _ARCH_ARM64_ASM_BUG_H 20 + 21 + #include <asm/debug-monitors.h> 22 + 23 + #ifdef CONFIG_GENERIC_BUG 24 + #define HAVE_ARCH_BUG 25 + 26 + #ifdef CONFIG_DEBUG_BUGVERBOSE 27 + #define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line) 28 + #define __BUGVERBOSE_LOCATION(file, line) \ 29 + ".pushsection .rodata.str,\"aMS\",@progbits,1\n" \ 30 + "2: .string \"" file "\"\n\t" \ 31 + ".popsection\n\t" \ 32 + \ 33 + ".long 2b - 0b\n\t" \ 34 + ".short " #line "\n\t" 35 + #else 36 + #define _BUGVERBOSE_LOCATION(file, line) 37 + #endif 38 + 39 + #define _BUG_FLAGS(flags) __BUG_FLAGS(flags) 40 + 41 + #define __BUG_FLAGS(flags) asm volatile ( \ 42 + ".pushsection __bug_table,\"a\"\n\t" \ 43 + ".align 2\n\t" \ 44 + "0: .long 1f - 0b\n\t" \ 45 + _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ 46 + ".short " #flags "\n\t" \ 47 + ".popsection\n" \ 48 + \ 49 + "1: brk %[imm]" \ 50 + :: [imm] "i" (BUG_BRK_IMM) \ 51 + ) 52 + 53 + #define BUG() do { \ 54 + _BUG_FLAGS(0); \ 55 + unreachable(); \ 56 + } while (0) 57 + 58 + #define __WARN_TAINT(taint) _BUG_FLAGS(BUGFLAG_TAINT(taint)) 59 + 60 + #endif /* ! CONFIG_GENERIC_BUG */ 61 + 62 + #include <asm-generic/bug.h> 63 + 64 + #endif /* ! _ARCH_ARM64_ASM_BUG_H */
+77 -121
arch/arm64/include/asm/cmpxchg.h
··· 21 21 #include <linux/bug.h> 22 22 #include <linux/mmdebug.h> 23 23 24 + #include <asm/atomic.h> 24 25 #include <asm/barrier.h> 26 + #include <asm/lse.h> 25 27 26 28 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) 27 29 { ··· 31 29 32 30 switch (size) { 33 31 case 1: 34 - asm volatile("// __xchg1\n" 32 + asm volatile(ARM64_LSE_ATOMIC_INSN( 33 + /* LL/SC */ 34 + " prfm pstl1strm, %2\n" 35 35 "1: ldxrb %w0, %2\n" 36 36 " stlxrb %w1, %w3, %2\n" 37 37 " cbnz %w1, 1b\n" 38 + " dmb ish", 39 + /* LSE atomics */ 40 + " nop\n" 41 + " nop\n" 42 + " swpalb %w3, %w0, %2\n" 43 + " nop\n" 44 + " nop") 38 45 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) 39 46 : "r" (x) 40 47 : "memory"); 41 48 break; 42 49 case 2: 43 - asm volatile("// __xchg2\n" 50 + asm volatile(ARM64_LSE_ATOMIC_INSN( 51 + /* LL/SC */ 52 + " prfm pstl1strm, %2\n" 44 53 "1: ldxrh %w0, %2\n" 45 54 " stlxrh %w1, %w3, %2\n" 46 55 " cbnz %w1, 1b\n" 56 + " dmb ish", 57 + /* LSE atomics */ 58 + " nop\n" 59 + " nop\n" 60 + " swpalh %w3, %w0, %2\n" 61 + " nop\n" 62 + " nop") 47 63 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr) 48 64 : "r" (x) 49 65 : "memory"); 50 66 break; 51 67 case 4: 52 - asm volatile("// __xchg4\n" 68 + asm volatile(ARM64_LSE_ATOMIC_INSN( 69 + /* LL/SC */ 70 + " prfm pstl1strm, %2\n" 53 71 "1: ldxr %w0, %2\n" 54 72 " stlxr %w1, %w3, %2\n" 55 73 " cbnz %w1, 1b\n" 74 + " dmb ish", 75 + /* LSE atomics */ 76 + " nop\n" 77 + " nop\n" 78 + " swpal %w3, %w0, %2\n" 79 + " nop\n" 80 + " nop") 56 81 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr) 57 82 : "r" (x) 58 83 : "memory"); 59 84 break; 60 85 case 8: 61 - asm volatile("// __xchg8\n" 86 + asm volatile(ARM64_LSE_ATOMIC_INSN( 87 + /* LL/SC */ 88 + " prfm pstl1strm, %2\n" 62 89 "1: ldxr %0, %2\n" 63 90 " stlxr %w1, %3, %2\n" 64 91 " cbnz %w1, 1b\n" 92 + " dmb ish", 93 + /* LSE atomics */ 94 + " nop\n" 95 + " nop\n" 96 + " swpal %3, %0, %2\n" 97 + " nop\n" 98 + " nop") 65 99 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr) 66 100 : "r" (x) 67 101 : "memory"); ··· 106 68 BUILD_BUG(); 107 69 } 108 70 109 - smp_mb(); 110 71 return ret; 111 72 } 112 73 ··· 120 83 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 121 84 unsigned long new, int size) 122 85 { 123 - unsigned long oldval = 0, res; 124 - 125 86 switch (size) { 126 87 case 1: 127 - do { 128 - asm volatile("// __cmpxchg1\n" 129 - " ldxrb %w1, %2\n" 130 - " mov %w0, #0\n" 131 - " cmp %w1, %w3\n" 132 - " b.ne 1f\n" 133 - " stxrb %w0, %w4, %2\n" 134 - "1:\n" 135 - : "=&r" (res), "=&r" (oldval), "+Q" (*(u8 *)ptr) 136 - : "Ir" (old), "r" (new) 137 - : "cc"); 138 - } while (res); 139 - break; 140 - 88 + return __cmpxchg_case_1(ptr, (u8)old, new); 141 89 case 2: 142 - do { 143 - asm volatile("// __cmpxchg2\n" 144 - " ldxrh %w1, %2\n" 145 - " mov %w0, #0\n" 146 - " cmp %w1, %w3\n" 147 - " b.ne 1f\n" 148 - " stxrh %w0, %w4, %2\n" 149 - "1:\n" 150 - : "=&r" (res), "=&r" (oldval), "+Q" (*(u16 *)ptr) 151 - : "Ir" (old), "r" (new) 152 - : "cc"); 153 - } while (res); 154 - break; 155 - 90 + return __cmpxchg_case_2(ptr, (u16)old, new); 156 91 case 4: 157 - do { 158 - asm volatile("// __cmpxchg4\n" 159 - " ldxr %w1, %2\n" 160 - " mov %w0, #0\n" 161 - " cmp %w1, %w3\n" 162 - " b.ne 1f\n" 163 - " stxr %w0, %w4, %2\n" 164 - "1:\n" 165 - : "=&r" (res), "=&r" (oldval), "+Q" (*(u32 *)ptr) 166 - : "Ir" (old), "r" (new) 167 - : "cc"); 168 - } while (res); 169 - break; 170 - 92 + return __cmpxchg_case_4(ptr, old, new); 171 93 case 8: 172 - do { 173 - asm volatile("// __cmpxchg8\n" 174 - " ldxr %1, %2\n" 175 - " mov %w0, #0\n" 176 - " cmp %1, %3\n" 177 - " b.ne 1f\n" 178 - " stxr %w0, %4, %2\n" 179 - "1:\n" 180 - : "=&r" (res), "=&r" (oldval), "+Q" (*(u64 *)ptr) 181 - : "Ir" (old), "r" (new) 182 - : "cc"); 183 - } while (res); 184 - break; 185 - 94 + return __cmpxchg_case_8(ptr, old, new); 186 95 default: 187 96 BUILD_BUG(); 188 97 } 189 98 190 - return oldval; 191 - } 192 - 193 - #define system_has_cmpxchg_double() 1 194 - 195 - static inline int __cmpxchg_double(volatile void *ptr1, volatile void *ptr2, 196 - unsigned long old1, unsigned long old2, 197 - unsigned long new1, unsigned long new2, int size) 198 - { 199 - unsigned long loop, lost; 200 - 201 - switch (size) { 202 - case 8: 203 - VM_BUG_ON((unsigned long *)ptr2 - (unsigned long *)ptr1 != 1); 204 - do { 205 - asm volatile("// __cmpxchg_double8\n" 206 - " ldxp %0, %1, %2\n" 207 - " eor %0, %0, %3\n" 208 - " eor %1, %1, %4\n" 209 - " orr %1, %0, %1\n" 210 - " mov %w0, #0\n" 211 - " cbnz %1, 1f\n" 212 - " stxp %w0, %5, %6, %2\n" 213 - "1:\n" 214 - : "=&r"(loop), "=&r"(lost), "+Q" (*(u64 *)ptr1) 215 - : "r" (old1), "r"(old2), "r"(new1), "r"(new2)); 216 - } while (loop); 217 - break; 218 - default: 219 - BUILD_BUG(); 220 - } 221 - 222 - return !lost; 223 - } 224 - 225 - static inline int __cmpxchg_double_mb(volatile void *ptr1, volatile void *ptr2, 226 - unsigned long old1, unsigned long old2, 227 - unsigned long new1, unsigned long new2, int size) 228 - { 229 - int ret; 230 - 231 - smp_mb(); 232 - ret = __cmpxchg_double(ptr1, ptr2, old1, old2, new1, new2, size); 233 - smp_mb(); 234 - 235 - return ret; 99 + unreachable(); 236 100 } 237 101 238 102 static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, 239 103 unsigned long new, int size) 240 104 { 241 - unsigned long ret; 105 + switch (size) { 106 + case 1: 107 + return __cmpxchg_case_mb_1(ptr, (u8)old, new); 108 + case 2: 109 + return __cmpxchg_case_mb_2(ptr, (u16)old, new); 110 + case 4: 111 + return __cmpxchg_case_mb_4(ptr, old, new); 112 + case 8: 113 + return __cmpxchg_case_mb_8(ptr, old, new); 114 + default: 115 + BUILD_BUG(); 116 + } 242 117 243 - smp_mb(); 244 - ret = __cmpxchg(ptr, old, new, size); 245 - smp_mb(); 246 - 247 - return ret; 118 + unreachable(); 248 119 } 249 120 250 121 #define cmpxchg(ptr, o, n) \ ··· 173 228 __ret; \ 174 229 }) 175 230 231 + #define system_has_cmpxchg_double() 1 232 + 233 + #define __cmpxchg_double_check(ptr1, ptr2) \ 234 + ({ \ 235 + if (sizeof(*(ptr1)) != 8) \ 236 + BUILD_BUG(); \ 237 + VM_BUG_ON((unsigned long *)(ptr2) - (unsigned long *)(ptr1) != 1); \ 238 + }) 239 + 176 240 #define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \ 177 241 ({\ 178 242 int __ret;\ 179 - __ret = __cmpxchg_double_mb((ptr1), (ptr2), (unsigned long)(o1), \ 180 - (unsigned long)(o2), (unsigned long)(n1), \ 181 - (unsigned long)(n2), sizeof(*(ptr1)));\ 243 + __cmpxchg_double_check(ptr1, ptr2); \ 244 + __ret = !__cmpxchg_double_mb((unsigned long)(o1), (unsigned long)(o2), \ 245 + (unsigned long)(n1), (unsigned long)(n2), \ 246 + ptr1); \ 182 247 __ret; \ 183 248 }) 184 249 185 250 #define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \ 186 251 ({\ 187 252 int __ret;\ 188 - __ret = __cmpxchg_double((ptr1), (ptr2), (unsigned long)(o1), \ 189 - (unsigned long)(o2), (unsigned long)(n1), \ 190 - (unsigned long)(n2), sizeof(*(ptr1)));\ 253 + __cmpxchg_double_check(ptr1, ptr2); \ 254 + __ret = !__cmpxchg_double((unsigned long)(o1), (unsigned long)(o2), \ 255 + (unsigned long)(n1), (unsigned long)(n2), \ 256 + ptr1); \ 191 257 __ret; \ 192 258 }) 193 259
+15 -3
arch/arm64/include/asm/cpufeature.h
··· 25 25 #define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 26 26 #define ARM64_WORKAROUND_845719 2 27 27 #define ARM64_HAS_SYSREG_GIC_CPUIF 3 28 + #define ARM64_HAS_PAN 4 29 + #define ARM64_HAS_LSE_ATOMICS 5 28 30 29 - #define ARM64_NCAPS 4 31 + #define ARM64_NCAPS 6 30 32 31 33 #ifndef __ASSEMBLY__ 34 + 35 + #include <linux/kernel.h> 32 36 33 37 struct arm64_cpu_capabilities { 34 38 const char *desc; 35 39 u16 capability; 36 40 bool (*matches)(const struct arm64_cpu_capabilities *); 41 + void (*enable)(void); 37 42 union { 38 43 struct { /* To be used for erratum handling only */ 39 44 u32 midr_model; ··· 46 41 }; 47 42 48 43 struct { /* Feature register checking */ 49 - u64 register_mask; 50 - u64 register_value; 44 + int field_pos; 45 + int min_field_value; 51 46 }; 52 47 }; 53 48 }; ··· 74 69 else 75 70 __set_bit(num, cpu_hwcaps); 76 71 } 72 + 73 + static inline int __attribute_const__ cpuid_feature_extract_field(u64 features, 74 + int field) 75 + { 76 + return (s64)(features << (64 - 4 - field)) >> (64 - 4); 77 + } 78 + 77 79 78 80 void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps, 79 81 const char *info);
-3
arch/arm64/include/asm/cputype.h
··· 81 81 #define ID_AA64MMFR0_BIGEND(mmfr0) \ 82 82 (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT) 83 83 84 - #define SCTLR_EL1_CP15BEN (0x1 << 5) 85 - #define SCTLR_EL1_SED (0x1 << 8) 86 - 87 84 #ifndef __ASSEMBLY__ 88 85 89 86 /*
+16 -28
arch/arm64/include/asm/debug-monitors.h
··· 18 18 19 19 #ifdef __KERNEL__ 20 20 21 + #include <linux/errno.h> 22 + #include <linux/types.h> 23 + #include <asm/esr.h> 24 + #include <asm/insn.h> 25 + #include <asm/ptrace.h> 26 + 21 27 /* Low-level stepping controls. */ 22 28 #define DBG_MDSCR_SS (1 << 0) 23 29 #define DBG_SPSR_SS (1 << 21) ··· 44 38 /* 45 39 * Break point instruction encoding 46 40 */ 47 - #define BREAK_INSTR_SIZE 4 48 - 49 - /* 50 - * ESR values expected for dynamic and compile time BRK instruction 51 - */ 52 - #define DBG_ESR_VAL_BRK(x) (0xf2000000 | ((x) & 0xfffff)) 41 + #define BREAK_INSTR_SIZE AARCH64_INSN_SIZE 53 42 54 43 /* 55 44 * #imm16 values used for BRK instruction generation ··· 52 51 * 0x100: for triggering a fault on purpose (reserved) 53 52 * 0x400: for dynamic BRK instruction 54 53 * 0x401: for compile time BRK instruction 54 + * 0x800: kernel-mode BUG() and WARN() traps 55 55 */ 56 56 #define FAULT_BRK_IMM 0x100 57 57 #define KGDB_DYN_DBG_BRK_IMM 0x400 58 58 #define KGDB_COMPILED_DBG_BRK_IMM 0x401 59 + #define BUG_BRK_IMM 0x800 59 60 60 61 /* 61 62 * BRK instruction encoding ··· 71 68 */ 72 69 #define AARCH64_BREAK_FAULT (AARCH64_BREAK_MON | (FAULT_BRK_IMM << 5)) 73 70 74 - /* 75 - * Extract byte from BRK instruction 76 - */ 77 - #define KGDB_DYN_DBG_BRK_INS_BYTE(x) \ 78 - ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff) 79 - 80 - /* 81 - * Extract byte from BRK #imm16 82 - */ 83 - #define KGBD_DYN_DBG_BRK_IMM_BYTE(x) \ 84 - (((((KGDB_DYN_DBG_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff) 85 - 86 - #define KGDB_DYN_DBG_BRK_BYTE(x) \ 87 - (KGDB_DYN_DBG_BRK_INS_BYTE(x) | KGBD_DYN_DBG_BRK_IMM_BYTE(x)) 88 - 89 - #define KGDB_DYN_BRK_INS_BYTE0 KGDB_DYN_DBG_BRK_BYTE(0) 90 - #define KGDB_DYN_BRK_INS_BYTE1 KGDB_DYN_DBG_BRK_BYTE(1) 91 - #define KGDB_DYN_BRK_INS_BYTE2 KGDB_DYN_DBG_BRK_BYTE(2) 92 - #define KGDB_DYN_BRK_INS_BYTE3 KGDB_DYN_DBG_BRK_BYTE(3) 71 + #define AARCH64_BREAK_KGDB_DYN_DBG \ 72 + (AARCH64_BREAK_MON | (KGDB_DYN_DBG_BRK_IMM << 5)) 73 + #define KGDB_DYN_BRK_INS_BYTE(x) \ 74 + ((AARCH64_BREAK_KGDB_DYN_DBG >> (8 * (x))) & 0xff) 93 75 94 76 #define CACHE_FLUSH_IS_SAFE 1 95 77 ··· 115 127 116 128 u8 debug_monitors_arch(void); 117 129 118 - enum debug_el { 130 + enum dbg_active_el { 119 131 DBG_ACTIVE_EL0 = 0, 120 132 DBG_ACTIVE_EL1, 121 133 }; 122 134 123 - void enable_debug_monitors(enum debug_el el); 124 - void disable_debug_monitors(enum debug_el el); 135 + void enable_debug_monitors(enum dbg_active_el el); 136 + void disable_debug_monitors(enum dbg_active_el el); 125 137 126 138 void user_rewind_single_step(struct task_struct *task); 127 139 void user_fastforward_single_step(struct task_struct *task);
+9
arch/arm64/include/asm/esr.h
··· 18 18 #ifndef __ASM_ESR_H 19 19 #define __ASM_ESR_H 20 20 21 + #include <asm/memory.h> 22 + 21 23 #define ESR_ELx_EC_UNKNOWN (0x00) 22 24 #define ESR_ELx_EC_WFx (0x01) 23 25 /* Unallocated EC: 0x02 */ ··· 100 98 #define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT) 101 99 #define ESR_ELx_WFx_ISS_WFE (UL(1) << 0) 102 100 #define ESR_ELx_xVC_IMM_MASK ((1UL << 16) - 1) 101 + 102 + /* ESR value templates for specific events */ 103 + 104 + /* BRK instruction trap from AArch64 state */ 105 + #define ESR_ELx_VAL_BRK64(imm) \ 106 + ((ESR_ELx_EC_BRK64 << ESR_ELx_EC_SHIFT) | ESR_ELx_IL | \ 107 + ((imm) & 0xffff)) 103 108 104 109 #ifndef __ASSEMBLY__ 105 110 #include <asm/types.h>
+6
arch/arm64/include/asm/exception.h
··· 18 18 #ifndef __ASM_EXCEPTION_H 19 19 #define __ASM_EXCEPTION_H 20 20 21 + #include <linux/ftrace.h> 22 + 21 23 #define __exception __attribute__((section(".exception.text"))) 24 + #ifdef CONFIG_FUNCTION_GRAPH_TRACER 25 + #define __exception_irq_entry __irq_entry 26 + #else 22 27 #define __exception_irq_entry __exception 28 + #endif 23 29 24 30 #endif /* __ASM_EXCEPTION_H */
+1 -1
arch/arm64/include/asm/fixmap.h
··· 8 8 * Copyright (C) 1998 Ingo Molnar 9 9 * Copyright (C) 2013 Mark Salter <msalter@redhat.com> 10 10 * 11 - * Adapted from arch/x86_64 version. 11 + * Adapted from arch/x86 version. 12 12 * 13 13 */ 14 14
+10
arch/arm64/include/asm/futex.h
··· 20 20 21 21 #include <linux/futex.h> 22 22 #include <linux/uaccess.h> 23 + 24 + #include <asm/alternative.h> 25 + #include <asm/cpufeature.h> 23 26 #include <asm/errno.h> 27 + #include <asm/sysreg.h> 24 28 25 29 #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ 26 30 asm volatile( \ 31 + ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ 32 + CONFIG_ARM64_PAN) \ 33 + " prfm pstl1strm, %2\n" \ 27 34 "1: ldxr %w1, %2\n" \ 28 35 insn "\n" \ 29 36 "2: stlxr %w3, %w0, %2\n" \ ··· 46 39 " .align 3\n" \ 47 40 " .quad 1b, 4b, 2b, 4b\n" \ 48 41 " .popsection\n" \ 42 + ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 43 + CONFIG_ARM64_PAN) \ 49 44 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ 50 45 : "r" (oparg), "Ir" (-EFAULT) \ 51 46 : "memory") ··· 121 112 return -EFAULT; 122 113 123 114 asm volatile("// futex_atomic_cmpxchg_inatomic\n" 115 + " prfm pstl1strm, %2\n" 124 116 "1: ldxr %w1, %2\n" 125 117 " sub %w3, %w1, %w4\n" 126 118 " cbnz %w3, 3f\n"
-4
arch/arm64/include/asm/hardirq.h
··· 24 24 25 25 typedef struct { 26 26 unsigned int __softirq_pending; 27 - #ifdef CONFIG_SMP 28 27 unsigned int ipi_irqs[NR_IPI]; 29 - #endif 30 28 } ____cacheline_aligned irq_cpustat_t; 31 29 32 30 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ ··· 32 34 #define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ 33 35 #define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) 34 36 35 - #ifdef CONFIG_SMP 36 37 u64 smp_irq_stat_cpu(unsigned int cpu); 37 38 #define arch_irq_stat_cpu smp_irq_stat_cpu 38 - #endif 39 39 40 40 #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 41 41
-4
arch/arm64/include/asm/hugetlb.h
··· 13 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 * GNU General Public License for more details. 16 - * 17 - * You should have received a copy of the GNU General Public License 18 - * along with this program; if not, write to the Free Software 19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 16 */ 21 17 22 18 #ifndef __ASM_HUGETLB_H
-11
arch/arm64/include/asm/irq_work.h
··· 1 1 #ifndef __ASM_IRQ_WORK_H 2 2 #define __ASM_IRQ_WORK_H 3 3 4 - #ifdef CONFIG_SMP 5 - 6 4 #include <asm/smp.h> 7 5 8 6 static inline bool arch_irq_work_has_interrupt(void) 9 7 { 10 8 return !!__smp_cross_call; 11 9 } 12 - 13 - #else 14 - 15 - static inline bool arch_irq_work_has_interrupt(void) 16 - { 17 - return false; 18 - } 19 - 20 - #endif 21 10 22 11 #endif /* __ASM_IRQ_WORK_H */
+53
arch/arm64/include/asm/lse.h
··· 1 + #ifndef __ASM_LSE_H 2 + #define __ASM_LSE_H 3 + 4 + #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS) 5 + 6 + #include <linux/stringify.h> 7 + #include <asm/alternative.h> 8 + #include <asm/cpufeature.h> 9 + 10 + #ifdef __ASSEMBLER__ 11 + 12 + .arch_extension lse 13 + 14 + .macro alt_lse, llsc, lse 15 + alternative_insn "\llsc", "\lse", ARM64_HAS_LSE_ATOMICS 16 + .endm 17 + 18 + #else /* __ASSEMBLER__ */ 19 + 20 + __asm__(".arch_extension lse"); 21 + 22 + /* Move the ll/sc atomics out-of-line */ 23 + #define __LL_SC_INLINE 24 + #define __LL_SC_PREFIX(x) __ll_sc_##x 25 + #define __LL_SC_EXPORT(x) EXPORT_SYMBOL(__LL_SC_PREFIX(x)) 26 + 27 + /* Macro for constructing calls to out-of-line ll/sc atomics */ 28 + #define __LL_SC_CALL(op) "bl\t" __stringify(__LL_SC_PREFIX(op)) "\n" 29 + 30 + /* In-line patching at runtime */ 31 + #define ARM64_LSE_ATOMIC_INSN(llsc, lse) \ 32 + ALTERNATIVE(llsc, lse, ARM64_HAS_LSE_ATOMICS) 33 + 34 + #endif /* __ASSEMBLER__ */ 35 + #else /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ 36 + 37 + #ifdef __ASSEMBLER__ 38 + 39 + .macro alt_lse, llsc, lse 40 + \llsc 41 + .endm 42 + 43 + #else /* __ASSEMBLER__ */ 44 + 45 + #define __LL_SC_INLINE static inline 46 + #define __LL_SC_PREFIX(x) x 47 + #define __LL_SC_EXPORT(x) 48 + 49 + #define ARM64_LSE_ATOMIC_INSN(llsc, lse) llsc 50 + 51 + #endif /* __ASSEMBLER__ */ 52 + #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ 53 + #endif /* __ASM_LSE_H */
+8
arch/arm64/include/asm/memory.h
··· 114 114 #define PHYS_OFFSET ({ memstart_addr; }) 115 115 116 116 /* 117 + * The maximum physical address that the linear direct mapping 118 + * of system RAM can cover. (PAGE_OFFSET can be interpreted as 119 + * a 2's complement signed quantity and negated to derive the 120 + * maximum size of the linear mapping.) 121 + */ 122 + #define MAX_MEMBLOCK_ADDR ({ memstart_addr - PAGE_OFFSET - 1; }) 123 + 124 + /* 117 125 * PFNs are used to describe any physical page; this means 118 126 * PFN 0 == physical address 0. 119 127 *
-1
arch/arm64/include/asm/mmu.h
··· 28 28 #define ASID(mm) ((mm)->context.id & 0xffff) 29 29 30 30 extern void paging_init(void); 31 - extern void setup_mm_for_reboot(void); 32 31 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); 33 32 extern void init_mem_pgprot(void); 34 33 extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
-8
arch/arm64/include/asm/percpu.h
··· 16 16 #ifndef __ASM_PERCPU_H 17 17 #define __ASM_PERCPU_H 18 18 19 - #ifdef CONFIG_SMP 20 - 21 19 static inline void set_my_cpu_offset(unsigned long off) 22 20 { 23 21 asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory"); ··· 35 37 return off; 36 38 } 37 39 #define __my_cpu_offset __my_cpu_offset() 38 - 39 - #else /* !CONFIG_SMP */ 40 - 41 - #define set_my_cpu_offset(x) do { } while (0) 42 - 43 - #endif /* CONFIG_SMP */ 44 40 45 41 #define PERCPU_OP(op, asm_op) \ 46 42 static inline unsigned long __percpu_##op(void *ptr, \
+1 -1
arch/arm64/include/asm/perf_event.h
··· 17 17 #ifndef __ASM_PERF_EVENT_H 18 18 #define __ASM_PERF_EVENT_H 19 19 20 - #ifdef CONFIG_HW_PERF_EVENTS 20 + #ifdef CONFIG_PERF_EVENTS 21 21 struct pt_regs; 22 22 extern unsigned long perf_instruction_pointer(struct pt_regs *regs); 23 23 extern unsigned long perf_misc_flags(struct pt_regs *regs);
+3
arch/arm64/include/asm/pgtable-hwdef.h
··· 104 104 #define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ 105 105 #define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ 106 106 #define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */ 107 + #define PTE_DBM (_AT(pteval_t, 1) << 51) /* Dirty Bit Management */ 107 108 #define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */ 108 109 #define PTE_UXN (_AT(pteval_t, 1) << 54) /* User XN */ 109 110 ··· 169 168 #define TCR_TG1_64K (UL(3) << 30) 170 169 #define TCR_ASID16 (UL(1) << 36) 171 170 #define TCR_TBI0 (UL(1) << 37) 171 + #define TCR_HA (UL(1) << 39) 172 + #define TCR_HD (UL(1) << 40) 172 173 173 174 #endif
+160 -7
arch/arm64/include/asm/pgtable.h
··· 16 16 #ifndef __ASM_PGTABLE_H 17 17 #define __ASM_PGTABLE_H 18 18 19 + #include <asm/bug.h> 19 20 #include <asm/proc-fns.h> 20 21 21 22 #include <asm/memory.h> ··· 28 27 #define PTE_VALID (_AT(pteval_t, 1) << 0) 29 28 #define PTE_DIRTY (_AT(pteval_t, 1) << 55) 30 29 #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) 30 + #ifdef CONFIG_ARM64_HW_AFDBM 31 + #define PTE_WRITE (PTE_DBM) /* same as DBM */ 32 + #else 31 33 #define PTE_WRITE (_AT(pteval_t, 1) << 57) 34 + #endif 32 35 #define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */ 33 36 34 37 /* ··· 53 48 #define FIRST_USER_ADDRESS 0UL 54 49 55 50 #ifndef __ASSEMBLY__ 51 + 52 + #include <linux/mmdebug.h> 53 + 56 54 extern void __pte_error(const char *file, int line, unsigned long val); 57 55 extern void __pmd_error(const char *file, int line, unsigned long val); 58 56 extern void __pud_error(const char *file, int line, unsigned long val); 59 57 extern void __pgd_error(const char *file, int line, unsigned long val); 60 58 61 - #ifdef CONFIG_SMP 62 59 #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) 63 60 #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) 64 - #else 65 - #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF) 66 - #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF) 67 - #endif 68 61 69 62 #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) 70 63 #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC)) ··· 140 137 * The following only work if pte_present(). Undefined behaviour otherwise. 141 138 */ 142 139 #define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))) 143 - #define pte_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY)) 144 140 #define pte_young(pte) (!!(pte_val(pte) & PTE_AF)) 145 141 #define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL)) 146 142 #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) 147 143 #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) 148 144 145 + #ifdef CONFIG_ARM64_HW_AFDBM 146 + #define pte_hw_dirty(pte) (!(pte_val(pte) & PTE_RDONLY)) 147 + #else 148 + #define pte_hw_dirty(pte) (0) 149 + #endif 150 + #define pte_sw_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY)) 151 + #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte)) 152 + 153 + #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) 149 154 #define pte_valid_user(pte) \ 150 155 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) 151 156 #define pte_valid_not_user(pte) \ ··· 220 209 } 221 210 } 222 211 212 + struct mm_struct; 213 + struct vm_area_struct; 214 + 223 215 extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); 224 216 217 + /* 218 + * PTE bits configuration in the presence of hardware Dirty Bit Management 219 + * (PTE_WRITE == PTE_DBM): 220 + * 221 + * Dirty Writable | PTE_RDONLY PTE_WRITE PTE_DIRTY (sw) 222 + * 0 0 | 1 0 0 223 + * 0 1 | 1 1 0 224 + * 1 0 | 1 0 1 225 + * 1 1 | 0 1 x 226 + * 227 + * When hardware DBM is not present, the sofware PTE_DIRTY bit is updated via 228 + * the page fault mechanism. Checking the dirty status of a pte becomes: 229 + * 230 + * PTE_DIRTY || !PTE_RDONLY 231 + */ 225 232 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 226 233 pte_t *ptep, pte_t pte) 227 234 { 228 235 if (pte_valid_user(pte)) { 229 236 if (!pte_special(pte) && pte_exec(pte)) 230 237 __sync_icache_dcache(pte, addr); 231 - if (pte_dirty(pte) && pte_write(pte)) 238 + if (pte_sw_dirty(pte) && pte_write(pte)) 232 239 pte_val(pte) &= ~PTE_RDONLY; 233 240 else 234 241 pte_val(pte) |= PTE_RDONLY; 242 + } 243 + 244 + /* 245 + * If the existing pte is valid, check for potential race with 246 + * hardware updates of the pte (ptep_set_access_flags safely changes 247 + * valid ptes without going through an invalid entry). 248 + */ 249 + if (IS_ENABLED(CONFIG_DEBUG_VM) && IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && 250 + pte_valid(*ptep)) { 251 + BUG_ON(!pte_young(pte)); 252 + BUG_ON(pte_write(*ptep) && !pte_dirty(pte)); 235 253 } 236 254 237 255 set_pte(ptep, pte); ··· 501 461 { 502 462 const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | 503 463 PTE_PROT_NONE | PTE_WRITE | PTE_TYPE_MASK; 464 + /* preserve the hardware dirty information */ 465 + if (pte_hw_dirty(pte)) 466 + newprot |= PTE_DIRTY; 504 467 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); 505 468 return pte; 506 469 } ··· 512 469 { 513 470 return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); 514 471 } 472 + 473 + #ifdef CONFIG_ARM64_HW_AFDBM 474 + /* 475 + * Atomic pte/pmd modifications. 476 + */ 477 + #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 478 + static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 479 + unsigned long address, 480 + pte_t *ptep) 481 + { 482 + pteval_t pteval; 483 + unsigned int tmp, res; 484 + 485 + asm volatile("// ptep_test_and_clear_young\n" 486 + " prfm pstl1strm, %2\n" 487 + "1: ldxr %0, %2\n" 488 + " ubfx %w3, %w0, %5, #1 // extract PTE_AF (young)\n" 489 + " and %0, %0, %4 // clear PTE_AF\n" 490 + " stxr %w1, %0, %2\n" 491 + " cbnz %w1, 1b\n" 492 + : "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)), "=&r" (res) 493 + : "L" (~PTE_AF), "I" (ilog2(PTE_AF))); 494 + 495 + return res; 496 + } 497 + 498 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 499 + #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG 500 + static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, 501 + unsigned long address, 502 + pmd_t *pmdp) 503 + { 504 + return ptep_test_and_clear_young(vma, address, (pte_t *)pmdp); 505 + } 506 + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 507 + 508 + #define __HAVE_ARCH_PTEP_GET_AND_CLEAR 509 + static inline pte_t ptep_get_and_clear(struct mm_struct *mm, 510 + unsigned long address, pte_t *ptep) 511 + { 512 + pteval_t old_pteval; 513 + unsigned int tmp; 514 + 515 + asm volatile("// ptep_get_and_clear\n" 516 + " prfm pstl1strm, %2\n" 517 + "1: ldxr %0, %2\n" 518 + " stxr %w1, xzr, %2\n" 519 + " cbnz %w1, 1b\n" 520 + : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))); 521 + 522 + return __pte(old_pteval); 523 + } 524 + 525 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 526 + #define __HAVE_ARCH_PMDP_GET_AND_CLEAR 527 + static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, 528 + unsigned long address, pmd_t *pmdp) 529 + { 530 + return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp)); 531 + } 532 + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 533 + 534 + /* 535 + * ptep_set_wrprotect - mark read-only while trasferring potential hardware 536 + * dirty status (PTE_DBM && !PTE_RDONLY) to the software PTE_DIRTY bit. 537 + */ 538 + #define __HAVE_ARCH_PTEP_SET_WRPROTECT 539 + static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) 540 + { 541 + pteval_t pteval; 542 + unsigned long tmp; 543 + 544 + asm volatile("// ptep_set_wrprotect\n" 545 + " prfm pstl1strm, %2\n" 546 + "1: ldxr %0, %2\n" 547 + " tst %0, %4 // check for hw dirty (!PTE_RDONLY)\n" 548 + " csel %1, %3, xzr, eq // set PTE_DIRTY|PTE_RDONLY if dirty\n" 549 + " orr %0, %0, %1 // if !dirty, PTE_RDONLY is already set\n" 550 + " and %0, %0, %5 // clear PTE_WRITE/PTE_DBM\n" 551 + " stxr %w1, %0, %2\n" 552 + " cbnz %w1, 1b\n" 553 + : "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)) 554 + : "r" (PTE_DIRTY|PTE_RDONLY), "L" (PTE_RDONLY), "L" (~PTE_WRITE) 555 + : "cc"); 556 + } 557 + 558 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 559 + #define __HAVE_ARCH_PMDP_SET_WRPROTECT 560 + static inline void pmdp_set_wrprotect(struct mm_struct *mm, 561 + unsigned long address, pmd_t *pmdp) 562 + { 563 + ptep_set_wrprotect(mm, address, (pte_t *)pmdp); 564 + } 565 + #endif 566 + #endif /* CONFIG_ARM64_HW_AFDBM */ 515 567 516 568 extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 517 569 extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; ··· 642 504 #include <asm-generic/pgtable.h> 643 505 644 506 #define pgtable_cache_init() do { } while (0) 507 + 508 + /* 509 + * On AArch64, the cache coherency is handled via the set_pte_at() function. 510 + */ 511 + static inline void update_mmu_cache(struct vm_area_struct *vma, 512 + unsigned long addr, pte_t *ptep) 513 + { 514 + /* 515 + * set_pte() does not have a DSB for user mappings, so make sure that 516 + * the page table write is visible. 517 + */ 518 + dsb(ishst); 519 + } 520 + 521 + #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) 645 522 646 523 #endif /* !__ASSEMBLY__ */ 647 524
+2
arch/arm64/include/asm/processor.h
··· 186 186 187 187 #endif 188 188 189 + void cpu_enable_pan(void); 190 + 189 191 #endif /* __ASM_PROCESSOR_H */
-4
arch/arm64/include/asm/ptrace.h
··· 183 183 184 184 #define instruction_pointer(regs) ((unsigned long)(regs)->pc) 185 185 186 - #ifdef CONFIG_SMP 187 186 extern unsigned long profile_pc(struct pt_regs *regs); 188 - #else 189 - #define profile_pc(regs) instruction_pointer(regs) 190 - #endif 191 187 192 188 #endif /* __ASSEMBLY__ */ 193 189 #endif
-4
arch/arm64/include/asm/smp.h
··· 20 20 #include <linux/cpumask.h> 21 21 #include <linux/thread_info.h> 22 22 23 - #ifndef CONFIG_SMP 24 - # error "<asm/smp.h> included in non-SMP build" 25 - #endif 26 - 27 23 #define raw_smp_processor_id() (current_thread_info()->cpu) 28 24 29 25 struct seq_file;
-2
arch/arm64/include/asm/smp_plat.h
··· 56 56 return -EINVAL; 57 57 } 58 58 59 - void __init do_post_cpus_up_work(void); 60 - 61 59 #endif /* __ASM_SMP_PLAT_H */
+114 -33
arch/arm64/include/asm/spinlock.h
··· 16 16 #ifndef __ASM_SPINLOCK_H 17 17 #define __ASM_SPINLOCK_H 18 18 19 + #include <asm/lse.h> 19 20 #include <asm/spinlock_types.h> 20 21 #include <asm/processor.h> 21 22 ··· 39 38 40 39 asm volatile( 41 40 /* Atomically increment the next ticket. */ 41 + ARM64_LSE_ATOMIC_INSN( 42 + /* LL/SC */ 42 43 " prfm pstl1strm, %3\n" 43 44 "1: ldaxr %w0, %3\n" 44 45 " add %w1, %w0, %w5\n" 45 46 " stxr %w2, %w1, %3\n" 46 - " cbnz %w2, 1b\n" 47 + " cbnz %w2, 1b\n", 48 + /* LSE atomics */ 49 + " mov %w2, %w5\n" 50 + " ldadda %w2, %w0, %3\n" 51 + " nop\n" 52 + " nop\n" 53 + " nop\n" 54 + ) 55 + 47 56 /* Did we get the lock? */ 48 57 " eor %w1, %w0, %w0, ror #16\n" 49 58 " cbz %w1, 3f\n" ··· 78 67 unsigned int tmp; 79 68 arch_spinlock_t lockval; 80 69 81 - asm volatile( 82 - " prfm pstl1strm, %2\n" 83 - "1: ldaxr %w0, %2\n" 84 - " eor %w1, %w0, %w0, ror #16\n" 85 - " cbnz %w1, 2f\n" 86 - " add %w0, %w0, %3\n" 87 - " stxr %w1, %w0, %2\n" 88 - " cbnz %w1, 1b\n" 89 - "2:" 70 + asm volatile(ARM64_LSE_ATOMIC_INSN( 71 + /* LL/SC */ 72 + " prfm pstl1strm, %2\n" 73 + "1: ldaxr %w0, %2\n" 74 + " eor %w1, %w0, %w0, ror #16\n" 75 + " cbnz %w1, 2f\n" 76 + " add %w0, %w0, %3\n" 77 + " stxr %w1, %w0, %2\n" 78 + " cbnz %w1, 1b\n" 79 + "2:", 80 + /* LSE atomics */ 81 + " ldr %w0, %2\n" 82 + " eor %w1, %w0, %w0, ror #16\n" 83 + " cbnz %w1, 1f\n" 84 + " add %w1, %w0, %3\n" 85 + " casa %w0, %w1, %2\n" 86 + " and %w1, %w1, #0xffff\n" 87 + " eor %w1, %w1, %w0, lsr #16\n" 88 + "1:") 90 89 : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock) 91 90 : "I" (1 << TICKET_SHIFT) 92 91 : "memory"); ··· 106 85 107 86 static inline void arch_spin_unlock(arch_spinlock_t *lock) 108 87 { 109 - asm volatile( 110 - " stlrh %w1, %0\n" 111 - : "=Q" (lock->owner) 112 - : "r" (lock->owner + 1) 88 + unsigned long tmp; 89 + 90 + asm volatile(ARM64_LSE_ATOMIC_INSN( 91 + /* LL/SC */ 92 + " ldrh %w1, %0\n" 93 + " add %w1, %w1, #1\n" 94 + " stlrh %w1, %0", 95 + /* LSE atomics */ 96 + " mov %w1, #1\n" 97 + " nop\n" 98 + " staddlh %w1, %0") 99 + : "=Q" (lock->owner), "=&r" (tmp) 100 + : 113 101 : "memory"); 114 102 } 115 103 ··· 153 123 { 154 124 unsigned int tmp; 155 125 156 - asm volatile( 126 + asm volatile(ARM64_LSE_ATOMIC_INSN( 127 + /* LL/SC */ 157 128 " sevl\n" 158 129 "1: wfe\n" 159 130 "2: ldaxr %w0, %1\n" 160 131 " cbnz %w0, 1b\n" 161 132 " stxr %w0, %w2, %1\n" 162 133 " cbnz %w0, 2b\n" 134 + " nop", 135 + /* LSE atomics */ 136 + "1: mov %w0, wzr\n" 137 + "2: casa %w0, %w2, %1\n" 138 + " cbz %w0, 3f\n" 139 + " ldxr %w0, %1\n" 140 + " cbz %w0, 2b\n" 141 + " wfe\n" 142 + " b 1b\n" 143 + "3:") 163 144 : "=&r" (tmp), "+Q" (rw->lock) 164 145 : "r" (0x80000000) 165 146 : "memory"); ··· 180 139 { 181 140 unsigned int tmp; 182 141 183 - asm volatile( 184 - " ldaxr %w0, %1\n" 185 - " cbnz %w0, 1f\n" 142 + asm volatile(ARM64_LSE_ATOMIC_INSN( 143 + /* LL/SC */ 144 + "1: ldaxr %w0, %1\n" 145 + " cbnz %w0, 2f\n" 186 146 " stxr %w0, %w2, %1\n" 187 - "1:\n" 147 + " cbnz %w0, 1b\n" 148 + "2:", 149 + /* LSE atomics */ 150 + " mov %w0, wzr\n" 151 + " casa %w0, %w2, %1\n" 152 + " nop\n" 153 + " nop") 188 154 : "=&r" (tmp), "+Q" (rw->lock) 189 155 : "r" (0x80000000) 190 156 : "memory"); ··· 201 153 202 154 static inline void arch_write_unlock(arch_rwlock_t *rw) 203 155 { 204 - asm volatile( 205 - " stlr %w1, %0\n" 206 - : "=Q" (rw->lock) : "r" (0) : "memory"); 156 + asm volatile(ARM64_LSE_ATOMIC_INSN( 157 + " stlr wzr, %0", 158 + " swpl wzr, wzr, %0") 159 + : "=Q" (rw->lock) :: "memory"); 207 160 } 208 161 209 162 /* write_can_lock - would write_trylock() succeed? */ ··· 221 172 * 222 173 * The memory barriers are implicit with the load-acquire and store-release 223 174 * instructions. 175 + * 176 + * Note that in UNDEFINED cases, such as unlocking a lock twice, the LL/SC 177 + * and LSE implementations may exhibit different behaviour (although this 178 + * will have no effect on lockdep). 224 179 */ 225 180 static inline void arch_read_lock(arch_rwlock_t *rw) 226 181 { ··· 232 179 233 180 asm volatile( 234 181 " sevl\n" 182 + ARM64_LSE_ATOMIC_INSN( 183 + /* LL/SC */ 235 184 "1: wfe\n" 236 185 "2: ldaxr %w0, %2\n" 237 186 " add %w0, %w0, #1\n" 238 187 " tbnz %w0, #31, 1b\n" 239 188 " stxr %w1, %w0, %2\n" 240 - " cbnz %w1, 2b\n" 189 + " nop\n" 190 + " cbnz %w1, 2b", 191 + /* LSE atomics */ 192 + "1: wfe\n" 193 + "2: ldxr %w0, %2\n" 194 + " adds %w1, %w0, #1\n" 195 + " tbnz %w1, #31, 1b\n" 196 + " casa %w0, %w1, %2\n" 197 + " sbc %w0, %w1, %w0\n" 198 + " cbnz %w0, 2b") 241 199 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock) 242 200 : 243 - : "memory"); 201 + : "cc", "memory"); 244 202 } 245 203 246 204 static inline void arch_read_unlock(arch_rwlock_t *rw) 247 205 { 248 206 unsigned int tmp, tmp2; 249 207 250 - asm volatile( 208 + asm volatile(ARM64_LSE_ATOMIC_INSN( 209 + /* LL/SC */ 251 210 "1: ldxr %w0, %2\n" 252 211 " sub %w0, %w0, #1\n" 253 212 " stlxr %w1, %w0, %2\n" 254 - " cbnz %w1, 1b\n" 213 + " cbnz %w1, 1b", 214 + /* LSE atomics */ 215 + " movn %w0, #0\n" 216 + " nop\n" 217 + " nop\n" 218 + " staddl %w0, %2") 255 219 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock) 256 220 : 257 221 : "memory"); ··· 276 206 277 207 static inline int arch_read_trylock(arch_rwlock_t *rw) 278 208 { 279 - unsigned int tmp, tmp2 = 1; 209 + unsigned int tmp, tmp2; 280 210 281 - asm volatile( 282 - " ldaxr %w0, %2\n" 211 + asm volatile(ARM64_LSE_ATOMIC_INSN( 212 + /* LL/SC */ 213 + " mov %w1, #1\n" 214 + "1: ldaxr %w0, %2\n" 283 215 " add %w0, %w0, #1\n" 284 - " tbnz %w0, #31, 1f\n" 216 + " tbnz %w0, #31, 2f\n" 285 217 " stxr %w1, %w0, %2\n" 286 - "1:\n" 287 - : "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock) 218 + " cbnz %w1, 1b\n" 219 + "2:", 220 + /* LSE atomics */ 221 + " ldr %w0, %2\n" 222 + " adds %w1, %w0, #1\n" 223 + " tbnz %w1, #31, 1f\n" 224 + " casa %w0, %w1, %2\n" 225 + " sbc %w1, %w1, %w0\n" 226 + " nop\n" 227 + "1:") 228 + : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock) 288 229 : 289 - : "memory"); 230 + : "cc", "memory"); 290 231 291 232 return !tmp2; 292 233 }
+2
arch/arm64/include/asm/spinlock_types.h
··· 20 20 # error "please don't include this file directly" 21 21 #endif 22 22 23 + #include <linux/types.h> 24 + 23 25 #define TICKET_SHIFT 16 24 26 25 27 typedef struct {
+35 -5
arch/arm64/include/asm/sysreg.h
··· 20 20 #ifndef __ASM_SYSREG_H 21 21 #define __ASM_SYSREG_H 22 22 23 + #include <asm/opcodes.h> 24 + 25 + #define SCTLR_EL1_CP15BEN (0x1 << 5) 26 + #define SCTLR_EL1_SED (0x1 << 8) 27 + 28 + /* 29 + * ARMv8 ARM reserves the following encoding for system registers: 30 + * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview", 31 + * C5.2, version:ARM DDI 0487A.f) 32 + * [20-19] : Op0 33 + * [18-16] : Op1 34 + * [15-12] : CRn 35 + * [11-8] : CRm 36 + * [7-5] : Op2 37 + */ 23 38 #define sys_reg(op0, op1, crn, crm, op2) \ 24 - ((((op0)-2)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5)) 39 + ((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5)) 40 + 41 + #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) 42 + #define SCTLR_EL1_SPAN (1 << 23) 43 + 44 + #define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\ 45 + (!!x)<<8 | 0x1f) 25 46 26 47 #ifdef __ASSEMBLY__ 27 48 ··· 52 31 .equ __reg_num_xzr, 31 53 32 54 33 .macro mrs_s, rt, sreg 55 - .inst 0xd5300000|(\sreg)|(__reg_num_\rt) 34 + .inst 0xd5200000|(\sreg)|(__reg_num_\rt) 56 35 .endm 57 36 58 37 .macro msr_s, sreg, rt 59 - .inst 0xd5100000|(\sreg)|(__reg_num_\rt) 38 + .inst 0xd5000000|(\sreg)|(__reg_num_\rt) 60 39 .endm 61 40 62 41 #else ··· 68 47 " .equ __reg_num_xzr, 31\n" 69 48 "\n" 70 49 " .macro mrs_s, rt, sreg\n" 71 - " .inst 0xd5300000|(\\sreg)|(__reg_num_\\rt)\n" 50 + " .inst 0xd5200000|(\\sreg)|(__reg_num_\\rt)\n" 72 51 " .endm\n" 73 52 "\n" 74 53 " .macro msr_s, sreg, rt\n" 75 - " .inst 0xd5100000|(\\sreg)|(__reg_num_\\rt)\n" 54 + " .inst 0xd5000000|(\\sreg)|(__reg_num_\\rt)\n" 76 55 " .endm\n" 77 56 ); 78 57 58 + static inline void config_sctlr_el1(u32 clear, u32 set) 59 + { 60 + u32 val; 61 + 62 + asm volatile("mrs %0, sctlr_el1" : "=r" (val)); 63 + val &= ~clear; 64 + val |= set; 65 + asm volatile("msr sctlr_el1, %0" : : "r" (val)); 66 + } 79 67 #endif 80 68 81 69 #endif /* __ASM_SYSREG_H */
+6 -1
arch/arm64/include/asm/tlb.h
··· 41 41 flush_tlb_mm(tlb->mm); 42 42 } else { 43 43 struct vm_area_struct vma = { .vm_mm = tlb->mm, }; 44 - flush_tlb_range(&vma, tlb->start, tlb->end); 44 + /* 45 + * The intermediate page table levels are already handled by 46 + * the __(pte|pmd|pud)_free_tlb() functions, so last level 47 + * TLBI is sufficient here. 48 + */ 49 + __flush_tlb_range(&vma, tlb->start, tlb->end, true); 45 50 } 46 51 } 47 52
+41 -49
arch/arm64/include/asm/tlbflush.h
··· 87 87 ((unsigned long)ASID(vma->vm_mm) << 48); 88 88 89 89 dsb(ishst); 90 - asm("tlbi vae1is, %0" : : "r" (addr)); 90 + asm("tlbi vale1is, %0" : : "r" (addr)); 91 91 dsb(ish); 92 - } 93 - 94 - static inline void __flush_tlb_range(struct vm_area_struct *vma, 95 - unsigned long start, unsigned long end) 96 - { 97 - unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48; 98 - unsigned long addr; 99 - start = asid | (start >> 12); 100 - end = asid | (end >> 12); 101 - 102 - dsb(ishst); 103 - for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) 104 - asm("tlbi vae1is, %0" : : "r"(addr)); 105 - dsb(ish); 106 - } 107 - 108 - static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long end) 109 - { 110 - unsigned long addr; 111 - start >>= 12; 112 - end >>= 12; 113 - 114 - dsb(ishst); 115 - for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) 116 - asm("tlbi vaae1is, %0" : : "r"(addr)); 117 - dsb(ish); 118 - isb(); 119 92 } 120 93 121 94 /* ··· 97 124 */ 98 125 #define MAX_TLB_RANGE (1024UL << PAGE_SHIFT) 99 126 127 + static inline void __flush_tlb_range(struct vm_area_struct *vma, 128 + unsigned long start, unsigned long end, 129 + bool last_level) 130 + { 131 + unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48; 132 + unsigned long addr; 133 + 134 + if ((end - start) > MAX_TLB_RANGE) { 135 + flush_tlb_mm(vma->vm_mm); 136 + return; 137 + } 138 + 139 + start = asid | (start >> 12); 140 + end = asid | (end >> 12); 141 + 142 + dsb(ishst); 143 + for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { 144 + if (last_level) 145 + asm("tlbi vale1is, %0" : : "r"(addr)); 146 + else 147 + asm("tlbi vae1is, %0" : : "r"(addr)); 148 + } 149 + dsb(ish); 150 + } 151 + 100 152 static inline void flush_tlb_range(struct vm_area_struct *vma, 101 153 unsigned long start, unsigned long end) 102 154 { 103 - if ((end - start) <= MAX_TLB_RANGE) 104 - __flush_tlb_range(vma, start, end); 105 - else 106 - flush_tlb_mm(vma->vm_mm); 155 + __flush_tlb_range(vma, start, end, false); 107 156 } 108 157 109 158 static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) 110 159 { 111 - if ((end - start) <= MAX_TLB_RANGE) 112 - __flush_tlb_kernel_range(start, end); 113 - else 160 + unsigned long addr; 161 + 162 + if ((end - start) > MAX_TLB_RANGE) { 114 163 flush_tlb_all(); 164 + return; 165 + } 166 + 167 + start >>= 12; 168 + end >>= 12; 169 + 170 + dsb(ishst); 171 + for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) 172 + asm("tlbi vaae1is, %0" : : "r"(addr)); 173 + dsb(ish); 174 + isb(); 115 175 } 116 176 117 177 /* ··· 160 154 asm("tlbi vae1is, %0" : : "r" (addr)); 161 155 dsb(ish); 162 156 } 163 - /* 164 - * On AArch64, the cache coherency is handled via the set_pte_at() function. 165 - */ 166 - static inline void update_mmu_cache(struct vm_area_struct *vma, 167 - unsigned long addr, pte_t *ptep) 168 - { 169 - /* 170 - * set_pte() does not have a DSB for user mappings, so make sure that 171 - * the page table write is visible. 172 - */ 173 - dsb(ishst); 174 - } 175 - 176 - #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) 177 157 178 158 #endif 179 159
-9
arch/arm64/include/asm/topology.h
··· 1 1 #ifndef __ASM_TOPOLOGY_H 2 2 #define __ASM_TOPOLOGY_H 3 3 4 - #ifdef CONFIG_SMP 5 - 6 4 #include <linux/cpumask.h> 7 5 8 6 struct cpu_topology { ··· 21 23 void init_cpu_topology(void); 22 24 void store_cpu_topology(unsigned int cpuid); 23 25 const struct cpumask *cpu_coregroup_mask(int cpu); 24 - 25 - #else 26 - 27 - static inline void init_cpu_topology(void) { } 28 - static inline void store_cpu_topology(unsigned int cpuid) { } 29 - 30 - #endif 31 26 32 27 #include <asm-generic/topology.h> 33 28
+21 -2
arch/arm64/include/asm/traps.h
··· 34 34 void register_undef_hook(struct undef_hook *hook); 35 35 void unregister_undef_hook(struct undef_hook *hook); 36 36 37 + #ifdef CONFIG_FUNCTION_GRAPH_TRACER 38 + static inline int __in_irqentry_text(unsigned long ptr) 39 + { 40 + extern char __irqentry_text_start[]; 41 + extern char __irqentry_text_end[]; 42 + 43 + return ptr >= (unsigned long)&__irqentry_text_start && 44 + ptr < (unsigned long)&__irqentry_text_end; 45 + } 46 + #else 47 + static inline int __in_irqentry_text(unsigned long ptr) 48 + { 49 + return 0; 50 + } 51 + #endif 52 + 37 53 static inline int in_exception_text(unsigned long ptr) 38 54 { 39 55 extern char __exception_text_start[]; 40 56 extern char __exception_text_end[]; 57 + int in; 41 58 42 - return ptr >= (unsigned long)&__exception_text_start && 43 - ptr < (unsigned long)&__exception_text_end; 59 + in = ptr >= (unsigned long)&__exception_text_start && 60 + ptr < (unsigned long)&__exception_text_end; 61 + 62 + return in ? : __in_irqentry_text(ptr); 44 63 } 45 64 46 65 #endif
+11
arch/arm64/include/asm/uaccess.h
··· 24 24 #include <linux/string.h> 25 25 #include <linux/thread_info.h> 26 26 27 + #include <asm/alternative.h> 28 + #include <asm/cpufeature.h> 27 29 #include <asm/ptrace.h> 30 + #include <asm/sysreg.h> 28 31 #include <asm/errno.h> 29 32 #include <asm/memory.h> 30 33 #include <asm/compiler.h> ··· 134 131 do { \ 135 132 unsigned long __gu_val; \ 136 133 __chk_user_ptr(ptr); \ 134 + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ 135 + CONFIG_ARM64_PAN)); \ 137 136 switch (sizeof(*(ptr))) { \ 138 137 case 1: \ 139 138 __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \ ··· 153 148 BUILD_BUG(); \ 154 149 } \ 155 150 (x) = (__force __typeof__(*(ptr)))__gu_val; \ 151 + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 152 + CONFIG_ARM64_PAN)); \ 156 153 } while (0) 157 154 158 155 #define __get_user(x, ptr) \ ··· 201 194 do { \ 202 195 __typeof__(*(ptr)) __pu_val = (x); \ 203 196 __chk_user_ptr(ptr); \ 197 + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ 198 + CONFIG_ARM64_PAN)); \ 204 199 switch (sizeof(*(ptr))) { \ 205 200 case 1: \ 206 201 __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \ ··· 219 210 default: \ 220 211 BUILD_BUG(); \ 221 212 } \ 213 + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 214 + CONFIG_ARM64_PAN)); \ 222 215 } while (0) 223 216 224 217 #define __put_user(x, ptr) \
+1
arch/arm64/include/uapi/asm/hwcap.h
··· 27 27 #define HWCAP_SHA1 (1 << 5) 28 28 #define HWCAP_SHA2 (1 << 6) 29 29 #define HWCAP_CRC32 (1 << 7) 30 + #define HWCAP_ATOMICS (1 << 8) 30 31 31 32 #endif /* _UAPI__ASM_HWCAP_H */
+1
arch/arm64/include/uapi/asm/ptrace.h
··· 44 44 #define PSR_I_BIT 0x00000080 45 45 #define PSR_A_BIT 0x00000100 46 46 #define PSR_D_BIT 0x00000200 47 + #define PSR_PAN_BIT 0x00400000 47 48 #define PSR_Q_BIT 0x08000000 48 49 #define PSR_V_BIT 0x10000000 49 50 #define PSR_C_BIT 0x20000000
+3 -3
arch/arm64/kernel/Makefile
··· 17 17 sys.o stacktrace.o time.o traps.o io.o vdso.o \ 18 18 hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \ 19 19 return_address.o cpuinfo.o cpu_errata.o \ 20 - cpufeature.o alternative.o cacheinfo.o 20 + cpufeature.o alternative.o cacheinfo.o \ 21 + smp.o smp_spin_table.o topology.o 21 22 22 23 arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ 23 24 sys_compat.o entry32.o \ 24 25 ../../arm/kernel/opcodes.o 25 26 arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o 26 27 arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o 27 - arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o 28 - arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o 28 + arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o 29 29 arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 30 30 arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o 31 31 arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
+25 -5
arch/arm64/kernel/alternative.c
··· 85 85 return insn; 86 86 } 87 87 88 - static int __apply_alternatives(void *alt_region) 88 + static void __apply_alternatives(void *alt_region) 89 89 { 90 90 struct alt_instr *alt; 91 91 struct alt_region *region = alt_region; ··· 114 114 flush_icache_range((uintptr_t)origptr, 115 115 (uintptr_t)(origptr + nr_inst)); 116 116 } 117 - 118 - return 0; 119 117 } 120 118 121 - void apply_alternatives_all(void) 119 + /* 120 + * We might be patching the stop_machine state machine, so implement a 121 + * really simple polling protocol here. 122 + */ 123 + static int __apply_alternatives_multi_stop(void *unused) 122 124 { 125 + static int patched = 0; 123 126 struct alt_region region = { 124 127 .begin = __alt_instructions, 125 128 .end = __alt_instructions_end, 126 129 }; 127 130 131 + /* We always have a CPU 0 at this point (__init) */ 132 + if (smp_processor_id()) { 133 + while (!READ_ONCE(patched)) 134 + cpu_relax(); 135 + isb(); 136 + } else { 137 + BUG_ON(patched); 138 + __apply_alternatives(&region); 139 + /* Barriers provided by the cache flushing */ 140 + WRITE_ONCE(patched, 1); 141 + } 142 + 143 + return 0; 144 + } 145 + 146 + void __init apply_alternatives_all(void) 147 + { 128 148 /* better not try code patching on a live SMP system */ 129 - stop_machine(__apply_alternatives, &region, NULL); 149 + stop_machine(__apply_alternatives_multi_stop, NULL, cpu_online_mask); 130 150 } 131 151 132 152 void apply_alternatives(void *start, size_t length)
+8 -11
arch/arm64/kernel/armv8_deprecated.c
··· 14 14 #include <linux/slab.h> 15 15 #include <linux/sysctl.h> 16 16 17 + #include <asm/alternative.h> 18 + #include <asm/cpufeature.h> 17 19 #include <asm/insn.h> 18 20 #include <asm/opcodes.h> 21 + #include <asm/sysreg.h> 19 22 #include <asm/system_misc.h> 20 23 #include <asm/traps.h> 21 24 #include <asm/uaccess.h> ··· 282 279 */ 283 280 #define __user_swpX_asm(data, addr, res, temp, B) \ 284 281 __asm__ __volatile__( \ 282 + ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ 283 + CONFIG_ARM64_PAN) \ 285 284 " mov %w2, %w1\n" \ 286 285 "0: ldxr"B" %w1, [%3]\n" \ 287 286 "1: stxr"B" %w0, %w2, [%3]\n" \ ··· 299 294 " .align 3\n" \ 300 295 " .quad 0b, 3b\n" \ 301 296 " .quad 1b, 3b\n" \ 302 - " .popsection" \ 297 + " .popsection\n" \ 298 + ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ 299 + CONFIG_ARM64_PAN) \ 303 300 : "=&r" (res), "+r" (data), "=&r" (temp) \ 304 301 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ 305 302 : "memory") ··· 509 502 510 503 regs->pc += 4; 511 504 return 0; 512 - } 513 - 514 - static inline void config_sctlr_el1(u32 clear, u32 set) 515 - { 516 - u32 val; 517 - 518 - asm volatile("mrs %0, sctlr_el1" : "=r" (val)); 519 - val &= ~clear; 520 - val |= set; 521 - asm volatile("msr sctlr_el1, %0" : : "r" (val)); 522 505 } 523 506 524 507 static int cp15_barrier_set_hw_mode(bool enable)
-2
arch/arm64/kernel/cpu_ops.c
··· 30 30 const struct cpu_operations *cpu_ops[NR_CPUS]; 31 31 32 32 static const struct cpu_operations *supported_cpu_ops[] __initconst = { 33 - #ifdef CONFIG_SMP 34 33 &smp_spin_table_ops, 35 - #endif 36 34 &cpu_psci_ops, 37 35 NULL, 38 36 };
+46 -7
arch/arm64/kernel/cpufeature.c
··· 21 21 #include <linux/types.h> 22 22 #include <asm/cpu.h> 23 23 #include <asm/cpufeature.h> 24 + #include <asm/processor.h> 24 25 25 26 static bool 26 - has_id_aa64pfr0_feature(const struct arm64_cpu_capabilities *entry) 27 + feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry) 27 28 { 28 - u64 val; 29 + int val = cpuid_feature_extract_field(reg, entry->field_pos); 29 30 30 - val = read_cpuid(id_aa64pfr0_el1); 31 - return (val & entry->register_mask) == entry->register_value; 31 + return val >= entry->min_field_value; 32 32 } 33 + 34 + #define __ID_FEAT_CHK(reg) \ 35 + static bool __maybe_unused \ 36 + has_##reg##_feature(const struct arm64_cpu_capabilities *entry) \ 37 + { \ 38 + u64 val; \ 39 + \ 40 + val = read_cpuid(reg##_el1); \ 41 + return feature_matches(val, entry); \ 42 + } 43 + 44 + __ID_FEAT_CHK(id_aa64pfr0); 45 + __ID_FEAT_CHK(id_aa64mmfr1); 46 + __ID_FEAT_CHK(id_aa64isar0); 33 47 34 48 static const struct arm64_cpu_capabilities arm64_features[] = { 35 49 { 36 50 .desc = "GIC system register CPU interface", 37 51 .capability = ARM64_HAS_SYSREG_GIC_CPUIF, 38 52 .matches = has_id_aa64pfr0_feature, 39 - .register_mask = (0xf << 24), 40 - .register_value = (1 << 24), 53 + .field_pos = 24, 54 + .min_field_value = 1, 41 55 }, 56 + #ifdef CONFIG_ARM64_PAN 57 + { 58 + .desc = "Privileged Access Never", 59 + .capability = ARM64_HAS_PAN, 60 + .matches = has_id_aa64mmfr1_feature, 61 + .field_pos = 20, 62 + .min_field_value = 1, 63 + .enable = cpu_enable_pan, 64 + }, 65 + #endif /* CONFIG_ARM64_PAN */ 66 + #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS) 67 + { 68 + .desc = "LSE atomic instructions", 69 + .capability = ARM64_HAS_LSE_ATOMICS, 70 + .matches = has_id_aa64isar0_feature, 71 + .field_pos = 20, 72 + .min_field_value = 2, 73 + }, 74 + #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ 42 75 {}, 43 76 }; 44 77 ··· 88 55 pr_info("%s %s\n", info, caps[i].desc); 89 56 cpus_set_cap(caps[i].capability); 90 57 } 58 + 59 + /* second pass allows enable() to consider interacting capabilities */ 60 + for (i = 0; caps[i].desc; i++) { 61 + if (cpus_have_cap(caps[i].capability) && caps[i].enable) 62 + caps[i].enable(); 63 + } 91 64 } 92 65 93 66 void check_local_cpu_features(void) 94 67 { 95 - check_cpu_capabilities(arm64_features, "detected feature"); 68 + check_cpu_capabilities(arm64_features, "detected feature:"); 96 69 }
+2 -2
arch/arm64/kernel/debug-monitors.c
··· 82 82 static DEFINE_PER_CPU(int, mde_ref_count); 83 83 static DEFINE_PER_CPU(int, kde_ref_count); 84 84 85 - void enable_debug_monitors(enum debug_el el) 85 + void enable_debug_monitors(enum dbg_active_el el) 86 86 { 87 87 u32 mdscr, enable = 0; 88 88 ··· 102 102 } 103 103 } 104 104 105 - void disable_debug_monitors(enum debug_el el) 105 + void disable_debug_monitors(enum dbg_active_el el) 106 106 { 107 107 u32 mdscr, disable = 0; 108 108
+32 -9
arch/arm64/kernel/efi-stub.c
··· 13 13 #include <asm/efi.h> 14 14 #include <asm/sections.h> 15 15 16 - efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, 16 + efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, 17 17 unsigned long *image_addr, 18 18 unsigned long *image_size, 19 19 unsigned long *reserve_addr, ··· 23 23 { 24 24 efi_status_t status; 25 25 unsigned long kernel_size, kernel_memsize = 0; 26 + unsigned long nr_pages; 27 + void *old_image_addr = (void *)*image_addr; 26 28 27 29 /* Relocate the image, if required. */ 28 30 kernel_size = _edata - _text; 29 31 if (*image_addr != (dram_base + TEXT_OFFSET)) { 30 32 kernel_memsize = kernel_size + (_end - _edata); 31 - status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET, 32 - SZ_2M, reserve_addr); 33 + 34 + /* 35 + * First, try a straight allocation at the preferred offset. 36 + * This will work around the issue where, if dram_base == 0x0, 37 + * efi_low_alloc() refuses to allocate at 0x0 (to prevent the 38 + * address of the allocation to be mistaken for a FAIL return 39 + * value or a NULL pointer). It will also ensure that, on 40 + * platforms where the [dram_base, dram_base + TEXT_OFFSET) 41 + * interval is partially occupied by the firmware (like on APM 42 + * Mustang), we can still place the kernel at the address 43 + * 'dram_base + TEXT_OFFSET'. 44 + */ 45 + *image_addr = *reserve_addr = dram_base + TEXT_OFFSET; 46 + nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) / 47 + EFI_PAGE_SIZE; 48 + status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, 49 + EFI_LOADER_DATA, nr_pages, 50 + (efi_physical_addr_t *)reserve_addr); 33 51 if (status != EFI_SUCCESS) { 34 - pr_efi_err(sys_table, "Failed to relocate kernel\n"); 35 - return status; 52 + kernel_memsize += TEXT_OFFSET; 53 + status = efi_low_alloc(sys_table_arg, kernel_memsize, 54 + SZ_2M, reserve_addr); 55 + 56 + if (status != EFI_SUCCESS) { 57 + pr_efi_err(sys_table_arg, "Failed to relocate kernel\n"); 58 + return status; 59 + } 60 + *image_addr = *reserve_addr + TEXT_OFFSET; 36 61 } 37 - memcpy((void *)*reserve_addr + TEXT_OFFSET, (void *)*image_addr, 38 - kernel_size); 39 - *image_addr = *reserve_addr + TEXT_OFFSET; 40 - *reserve_size = kernel_memsize + TEXT_OFFSET; 62 + memcpy((void *)*image_addr, old_image_addr, kernel_size); 63 + *reserve_size = kernel_memsize; 41 64 } 42 65 43 66
+20 -28
arch/arm64/kernel/entry.S
··· 116 116 */ 117 117 .endm 118 118 119 - .macro kernel_exit, el, ret = 0 119 + .macro kernel_exit, el 120 120 ldp x21, x22, [sp, #S_PC] // load ELR, SPSR 121 121 .if \el == 0 122 122 ct_user_enter 123 123 ldr x23, [sp, #S_SP] // load return stack pointer 124 124 msr sp_el0, x23 125 - 126 125 #ifdef CONFIG_ARM64_ERRATUM_845719 127 - 128 - #undef SEQUENCE_ORG 129 - #undef SEQUENCE_ALT 130 - 126 + alternative_if_not ARM64_WORKAROUND_845719 127 + nop 128 + nop 131 129 #ifdef CONFIG_PID_IN_CONTEXTIDR 132 - 133 - #define SEQUENCE_ORG "nop ; nop ; nop" 134 - #define SEQUENCE_ALT "tbz x22, #4, 1f ; mrs x29, contextidr_el1; msr contextidr_el1, x29; 1:" 135 - 136 - #else 137 - 138 - #define SEQUENCE_ORG "nop ; nop" 139 - #define SEQUENCE_ALT "tbz x22, #4, 1f ; msr contextidr_el1, xzr; 1:" 140 - 130 + nop 141 131 #endif 142 - 143 - alternative_insn SEQUENCE_ORG, SEQUENCE_ALT, ARM64_WORKAROUND_845719 144 - 132 + alternative_else 133 + tbz x22, #4, 1f 134 + #ifdef CONFIG_PID_IN_CONTEXTIDR 135 + mrs x29, contextidr_el1 136 + msr contextidr_el1, x29 137 + #else 138 + msr contextidr_el1, xzr 139 + #endif 140 + 1: 141 + alternative_endif 145 142 #endif 146 143 .endif 147 144 msr elr_el1, x21 // set up the return data 148 145 msr spsr_el1, x22 149 - .if \ret 150 - ldr x1, [sp, #S_X1] // preserve x0 (syscall return) 151 - .else 152 146 ldp x0, x1, [sp, #16 * 0] 153 - .endif 154 147 ldp x2, x3, [sp, #16 * 1] 155 148 ldp x4, x5, [sp, #16 * 2] 156 149 ldp x6, x7, [sp, #16 * 3] ··· 606 613 */ 607 614 ret_fast_syscall: 608 615 disable_irq // disable interrupts 616 + str x0, [sp, #S_X0] // returned x0 609 617 ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing 610 618 and x2, x1, #_TIF_SYSCALL_WORK 611 619 cbnz x2, ret_fast_syscall_trace 612 620 and x2, x1, #_TIF_WORK_MASK 613 - cbnz x2, fast_work_pending 621 + cbnz x2, work_pending 614 622 enable_step_tsk x1, x2 615 - kernel_exit 0, ret = 1 623 + kernel_exit 0 616 624 ret_fast_syscall_trace: 617 625 enable_irq // enable interrupts 618 - b __sys_trace_return 626 + b __sys_trace_return_skipped // we already saved x0 619 627 620 628 /* 621 629 * Ok, we need to do extra processing, enter the slow path. 622 630 */ 623 - fast_work_pending: 624 - str x0, [sp, #S_X0] // returned x0 625 631 work_pending: 626 632 tbnz x1, #TIF_NEED_RESCHED, work_resched 627 633 /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */ ··· 644 652 cbnz x2, work_pending 645 653 enable_step_tsk x1, x2 646 654 no_work_pending: 647 - kernel_exit 0, ret = 0 655 + kernel_exit 0 648 656 ENDPROC(ret_to_user) 649 657 650 658 /*
+1
arch/arm64/kernel/fpsimd.c
··· 158 158 void fpsimd_flush_thread(void) 159 159 { 160 160 memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); 161 + fpsimd_flush_task_state(current); 161 162 set_thread_flag(TIF_FOREIGN_FPSTATE); 162 163 } 163 164
+8 -7
arch/arm64/kernel/head.S
··· 62 62 /* 63 63 * Initial memory map attributes. 64 64 */ 65 - #ifndef CONFIG_SMP 66 - #define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF 67 - #define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF 68 - #else 69 65 #define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | PTE_SHARED 70 66 #define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S 71 - #endif 72 67 73 68 #ifdef CONFIG_ARM64_64K_PAGES 74 69 #define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS ··· 569 574 .long BOOT_CPU_MODE_EL1 570 575 .popsection 571 576 572 - #ifdef CONFIG_SMP 573 577 /* 574 578 * This provides a "holding pen" for platforms to hold all secondary 575 579 * cores are held until we're ready for them to initialise. ··· 616 622 mov x29, #0 617 623 b secondary_start_kernel 618 624 ENDPROC(__secondary_switched) 619 - #endif /* CONFIG_SMP */ 620 625 621 626 /* 622 627 * Enable the MMU. ··· 633 640 msr ttbr1_el1, x26 // load TTBR1 634 641 isb 635 642 msr sctlr_el1, x0 643 + isb 644 + /* 645 + * Invalidate the local I-cache so that any instructions fetched 646 + * speculatively from the PoC are discarded, since they may have 647 + * been dynamically patched at the PoU. 648 + */ 649 + ic iallu 650 + dsb nsh 636 651 isb 637 652 br x27 638 653 ENDPROC(__enable_mmu)
+3 -3
arch/arm64/kernel/hw_breakpoint.c
··· 156 156 * Convert a breakpoint privilege level to the corresponding exception 157 157 * level. 158 158 */ 159 - static enum debug_el debug_exception_level(int privilege) 159 + static enum dbg_active_el debug_exception_level(int privilege) 160 160 { 161 161 switch (privilege) { 162 162 case AARCH64_BREAKPOINT_EL0: ··· 230 230 struct perf_event **slots; 231 231 struct debug_info *debug_info = &current->thread.debug; 232 232 int i, max_slots, ctrl_reg, val_reg, reg_enable; 233 - enum debug_el dbg_el = debug_exception_level(info->ctrl.privilege); 233 + enum dbg_active_el dbg_el = debug_exception_level(info->ctrl.privilege); 234 234 u32 ctrl; 235 235 236 236 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { ··· 537 537 * exception level at the register level. 538 538 * This is used when single-stepping after a breakpoint exception. 539 539 */ 540 - static void toggle_bp_registers(int reg, enum debug_el el, int enable) 540 + static void toggle_bp_registers(int reg, enum dbg_active_el el, int enable) 541 541 { 542 542 int i, max_slots, privilege; 543 543 u32 ctrl;
+2 -3
arch/arm64/kernel/insn.c
··· 101 101 return addr; 102 102 103 103 BUG_ON(!page); 104 - set_fixmap(fixmap, page_to_phys(page)); 105 - 106 - return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); 104 + return (void *)set_fixmap_offset(fixmap, page_to_phys(page) + 105 + (uintaddr & ~PAGE_MASK)); 107 106 } 108 107 109 108 static void __kprobes patch_unmap(int fixmap)
-2
arch/arm64/kernel/irq.c
··· 33 33 34 34 int arch_show_interrupts(struct seq_file *p, int prec) 35 35 { 36 - #ifdef CONFIG_SMP 37 36 show_ipi_list(p, prec); 38 - #endif 39 37 seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); 40 38 return 0; 41 39 }
+6 -6
arch/arm64/kernel/kgdb.c
··· 235 235 236 236 static struct break_hook kgdb_brkpt_hook = { 237 237 .esr_mask = 0xffffffff, 238 - .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DBG_BRK_IMM), 238 + .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_DYN_DBG_BRK_IMM), 239 239 .fn = kgdb_brk_fn 240 240 }; 241 241 242 242 static struct break_hook kgdb_compiled_brkpt_hook = { 243 243 .esr_mask = 0xffffffff, 244 - .esr_val = DBG_ESR_VAL_BRK(KGDB_COMPILED_DBG_BRK_IMM), 244 + .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_COMPILED_DBG_BRK_IMM), 245 245 .fn = kgdb_compiled_brk_fn 246 246 }; 247 247 ··· 328 328 */ 329 329 struct kgdb_arch arch_kgdb_ops = { 330 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, 331 + KGDB_DYN_BRK_INS_BYTE(0), 332 + KGDB_DYN_BRK_INS_BYTE(1), 333 + KGDB_DYN_BRK_INS_BYTE(2), 334 + KGDB_DYN_BRK_INS_BYTE(3), 335 335 } 336 336 };
+13
arch/arm64/kernel/pci.c
··· 38 38 return res->start; 39 39 } 40 40 41 + /** 42 + * pcibios_enable_device - Enable I/O and memory. 43 + * @dev: PCI device to be enabled 44 + * @mask: bitmask of BARs to enable 45 + */ 46 + int pcibios_enable_device(struct pci_dev *dev, int mask) 47 + { 48 + if (pci_has_flag(PCI_PROBE_ONLY)) 49 + return 0; 50 + 51 + return pci_enable_resources(dev, mask); 52 + } 53 + 41 54 /* 42 55 * Try to assign the IRQ number from DT when adding a new device 43 56 */
+196
arch/arm64/kernel/perf_callchain.c
··· 1 + /* 2 + * arm64 callchain support 3 + * 4 + * Copyright (C) 2015 ARM Limited 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 + */ 18 + #include <linux/perf_event.h> 19 + #include <linux/uaccess.h> 20 + 21 + #include <asm/stacktrace.h> 22 + 23 + struct frame_tail { 24 + struct frame_tail __user *fp; 25 + unsigned long lr; 26 + } __attribute__((packed)); 27 + 28 + /* 29 + * Get the return address for a single stackframe and return a pointer to the 30 + * next frame tail. 31 + */ 32 + static struct frame_tail __user * 33 + user_backtrace(struct frame_tail __user *tail, 34 + struct perf_callchain_entry *entry) 35 + { 36 + struct frame_tail buftail; 37 + unsigned long err; 38 + 39 + /* Also check accessibility of one struct frame_tail beyond */ 40 + if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) 41 + return NULL; 42 + 43 + pagefault_disable(); 44 + err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); 45 + pagefault_enable(); 46 + 47 + if (err) 48 + return NULL; 49 + 50 + perf_callchain_store(entry, buftail.lr); 51 + 52 + /* 53 + * Frame pointers should strictly progress back up the stack 54 + * (towards higher addresses). 55 + */ 56 + if (tail >= buftail.fp) 57 + return NULL; 58 + 59 + return buftail.fp; 60 + } 61 + 62 + #ifdef CONFIG_COMPAT 63 + /* 64 + * The registers we're interested in are at the end of the variable 65 + * length saved register structure. The fp points at the end of this 66 + * structure so the address of this struct is: 67 + * (struct compat_frame_tail *)(xxx->fp)-1 68 + * 69 + * This code has been adapted from the ARM OProfile support. 70 + */ 71 + struct compat_frame_tail { 72 + compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */ 73 + u32 sp; 74 + u32 lr; 75 + } __attribute__((packed)); 76 + 77 + static struct compat_frame_tail __user * 78 + compat_user_backtrace(struct compat_frame_tail __user *tail, 79 + struct perf_callchain_entry *entry) 80 + { 81 + struct compat_frame_tail buftail; 82 + unsigned long err; 83 + 84 + /* Also check accessibility of one struct frame_tail beyond */ 85 + if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) 86 + return NULL; 87 + 88 + pagefault_disable(); 89 + err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); 90 + pagefault_enable(); 91 + 92 + if (err) 93 + return NULL; 94 + 95 + perf_callchain_store(entry, buftail.lr); 96 + 97 + /* 98 + * Frame pointers should strictly progress back up the stack 99 + * (towards higher addresses). 100 + */ 101 + if (tail + 1 >= (struct compat_frame_tail __user *) 102 + compat_ptr(buftail.fp)) 103 + return NULL; 104 + 105 + return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1; 106 + } 107 + #endif /* CONFIG_COMPAT */ 108 + 109 + void perf_callchain_user(struct perf_callchain_entry *entry, 110 + struct pt_regs *regs) 111 + { 112 + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 113 + /* We don't support guest os callchain now */ 114 + return; 115 + } 116 + 117 + perf_callchain_store(entry, regs->pc); 118 + 119 + if (!compat_user_mode(regs)) { 120 + /* AARCH64 mode */ 121 + struct frame_tail __user *tail; 122 + 123 + tail = (struct frame_tail __user *)regs->regs[29]; 124 + 125 + while (entry->nr < PERF_MAX_STACK_DEPTH && 126 + tail && !((unsigned long)tail & 0xf)) 127 + tail = user_backtrace(tail, entry); 128 + } else { 129 + #ifdef CONFIG_COMPAT 130 + /* AARCH32 compat mode */ 131 + struct compat_frame_tail __user *tail; 132 + 133 + tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; 134 + 135 + while ((entry->nr < PERF_MAX_STACK_DEPTH) && 136 + tail && !((unsigned long)tail & 0x3)) 137 + tail = compat_user_backtrace(tail, entry); 138 + #endif 139 + } 140 + } 141 + 142 + /* 143 + * Gets called by walk_stackframe() for every stackframe. This will be called 144 + * whist unwinding the stackframe and is like a subroutine return so we use 145 + * the PC. 146 + */ 147 + static int callchain_trace(struct stackframe *frame, void *data) 148 + { 149 + struct perf_callchain_entry *entry = data; 150 + perf_callchain_store(entry, frame->pc); 151 + return 0; 152 + } 153 + 154 + void perf_callchain_kernel(struct perf_callchain_entry *entry, 155 + struct pt_regs *regs) 156 + { 157 + struct stackframe frame; 158 + 159 + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 160 + /* We don't support guest os callchain now */ 161 + return; 162 + } 163 + 164 + frame.fp = regs->regs[29]; 165 + frame.sp = regs->sp; 166 + frame.pc = regs->pc; 167 + 168 + walk_stackframe(&frame, callchain_trace, entry); 169 + } 170 + 171 + unsigned long perf_instruction_pointer(struct pt_regs *regs) 172 + { 173 + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) 174 + return perf_guest_cbs->get_guest_ip(); 175 + 176 + return instruction_pointer(regs); 177 + } 178 + 179 + unsigned long perf_misc_flags(struct pt_regs *regs) 180 + { 181 + int misc = 0; 182 + 183 + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 184 + if (perf_guest_cbs->is_user_mode()) 185 + misc |= PERF_RECORD_MISC_GUEST_USER; 186 + else 187 + misc |= PERF_RECORD_MISC_GUEST_KERNEL; 188 + } else { 189 + if (user_mode(regs)) 190 + misc |= PERF_RECORD_MISC_USER; 191 + else 192 + misc |= PERF_RECORD_MISC_KERNEL; 193 + } 194 + 195 + return misc; 196 + }
+25 -285
arch/arm64/kernel/perf_event.c
··· 25 25 #include <linux/irq.h> 26 26 #include <linux/kernel.h> 27 27 #include <linux/export.h> 28 - #include <linux/of.h> 28 + #include <linux/of_device.h> 29 29 #include <linux/perf_event.h> 30 30 #include <linux/platform_device.h> 31 31 #include <linux/slab.h> ··· 36 36 #include <asm/irq.h> 37 37 #include <asm/irq_regs.h> 38 38 #include <asm/pmu.h> 39 - #include <asm/stacktrace.h> 40 39 41 40 /* 42 41 * ARMv8 supports a maximum of 32 events. ··· 76 77 PERF_COUNT_HW_CACHE_##_x 77 78 78 79 #define CACHE_OP_UNSUPPORTED 0xFFFF 80 + 81 + #define PERF_MAP_ALL_UNSUPPORTED \ 82 + [0 ... PERF_COUNT_HW_MAX - 1] = HW_OP_UNSUPPORTED 83 + 84 + #define PERF_CACHE_MAP_ALL_UNSUPPORTED \ 85 + [0 ... C(MAX) - 1] = { \ 86 + [0 ... C(OP_MAX) - 1] = { \ 87 + [0 ... C(RESULT_MAX) - 1] = CACHE_OP_UNSUPPORTED, \ 88 + }, \ 89 + } 79 90 80 91 static int 81 92 armpmu_map_cache_event(const unsigned (*cache_map) ··· 444 435 unsigned int i, irqs; 445 436 struct platform_device *pmu_device = armpmu->plat_device; 446 437 447 - if (!pmu_device) { 448 - pr_err("no PMU device registered\n"); 438 + if (!pmu_device) 449 439 return -ENODEV; 450 - } 451 440 452 441 irqs = min(pmu_device->num_resources, num_possible_cpus()); 453 442 if (!irqs) { ··· 710 703 711 704 /* PMUv3 HW events mapping. */ 712 705 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { 706 + PERF_MAP_ALL_UNSUPPORTED, 713 707 [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, 714 708 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, 715 709 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, 716 710 [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, 717 - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED, 718 711 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, 719 - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, 720 - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, 721 - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, 722 712 }; 723 713 724 714 static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] 725 715 [PERF_COUNT_HW_CACHE_OP_MAX] 726 716 [PERF_COUNT_HW_CACHE_RESULT_MAX] = { 727 - [C(L1D)] = { 728 - [C(OP_READ)] = { 729 - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, 730 - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, 731 - }, 732 - [C(OP_WRITE)] = { 733 - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, 734 - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, 735 - }, 736 - [C(OP_PREFETCH)] = { 737 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 738 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 739 - }, 740 - }, 741 - [C(L1I)] = { 742 - [C(OP_READ)] = { 743 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 744 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 745 - }, 746 - [C(OP_WRITE)] = { 747 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 748 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 749 - }, 750 - [C(OP_PREFETCH)] = { 751 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 752 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 753 - }, 754 - }, 755 - [C(LL)] = { 756 - [C(OP_READ)] = { 757 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 758 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 759 - }, 760 - [C(OP_WRITE)] = { 761 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 762 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 763 - }, 764 - [C(OP_PREFETCH)] = { 765 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 766 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 767 - }, 768 - }, 769 - [C(DTLB)] = { 770 - [C(OP_READ)] = { 771 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 772 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 773 - }, 774 - [C(OP_WRITE)] = { 775 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 776 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 777 - }, 778 - [C(OP_PREFETCH)] = { 779 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 780 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 781 - }, 782 - }, 783 - [C(ITLB)] = { 784 - [C(OP_READ)] = { 785 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 786 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 787 - }, 788 - [C(OP_WRITE)] = { 789 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 790 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 791 - }, 792 - [C(OP_PREFETCH)] = { 793 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 794 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 795 - }, 796 - }, 797 - [C(BPU)] = { 798 - [C(OP_READ)] = { 799 - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, 800 - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, 801 - }, 802 - [C(OP_WRITE)] = { 803 - [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, 804 - [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, 805 - }, 806 - [C(OP_PREFETCH)] = { 807 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 808 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 809 - }, 810 - }, 811 - [C(NODE)] = { 812 - [C(OP_READ)] = { 813 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 814 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 815 - }, 816 - [C(OP_WRITE)] = { 817 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 818 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 819 - }, 820 - [C(OP_PREFETCH)] = { 821 - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, 822 - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, 823 - }, 824 - }, 717 + PERF_CACHE_MAP_ALL_UNSUPPORTED, 718 + 719 + [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, 720 + [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, 721 + [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, 722 + [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, 723 + 724 + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, 725 + [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, 726 + [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, 727 + [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, 825 728 }; 826 729 827 730 /* ··· 1254 1337 } 1255 1338 1256 1339 for_each_possible_cpu(cpu) 1257 - if (arch_find_n_match_cpu_physical_id(dn, cpu, NULL)) 1340 + if (dn == of_cpu_device_node_get(cpu)) 1258 1341 break; 1259 1342 1260 1343 if (cpu >= nr_cpu_ids) { ··· 1332 1415 } 1333 1416 early_initcall(init_hw_perf_events); 1334 1417 1335 - /* 1336 - * Callchain handling code. 1337 - */ 1338 - struct frame_tail { 1339 - struct frame_tail __user *fp; 1340 - unsigned long lr; 1341 - } __attribute__((packed)); 1342 - 1343 - /* 1344 - * Get the return address for a single stackframe and return a pointer to the 1345 - * next frame tail. 1346 - */ 1347 - static struct frame_tail __user * 1348 - user_backtrace(struct frame_tail __user *tail, 1349 - struct perf_callchain_entry *entry) 1350 - { 1351 - struct frame_tail buftail; 1352 - unsigned long err; 1353 - 1354 - /* Also check accessibility of one struct frame_tail beyond */ 1355 - if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) 1356 - return NULL; 1357 - 1358 - pagefault_disable(); 1359 - err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); 1360 - pagefault_enable(); 1361 - 1362 - if (err) 1363 - return NULL; 1364 - 1365 - perf_callchain_store(entry, buftail.lr); 1366 - 1367 - /* 1368 - * Frame pointers should strictly progress back up the stack 1369 - * (towards higher addresses). 1370 - */ 1371 - if (tail >= buftail.fp) 1372 - return NULL; 1373 - 1374 - return buftail.fp; 1375 - } 1376 - 1377 - #ifdef CONFIG_COMPAT 1378 - /* 1379 - * The registers we're interested in are at the end of the variable 1380 - * length saved register structure. The fp points at the end of this 1381 - * structure so the address of this struct is: 1382 - * (struct compat_frame_tail *)(xxx->fp)-1 1383 - * 1384 - * This code has been adapted from the ARM OProfile support. 1385 - */ 1386 - struct compat_frame_tail { 1387 - compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */ 1388 - u32 sp; 1389 - u32 lr; 1390 - } __attribute__((packed)); 1391 - 1392 - static struct compat_frame_tail __user * 1393 - compat_user_backtrace(struct compat_frame_tail __user *tail, 1394 - struct perf_callchain_entry *entry) 1395 - { 1396 - struct compat_frame_tail buftail; 1397 - unsigned long err; 1398 - 1399 - /* Also check accessibility of one struct frame_tail beyond */ 1400 - if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) 1401 - return NULL; 1402 - 1403 - pagefault_disable(); 1404 - err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); 1405 - pagefault_enable(); 1406 - 1407 - if (err) 1408 - return NULL; 1409 - 1410 - perf_callchain_store(entry, buftail.lr); 1411 - 1412 - /* 1413 - * Frame pointers should strictly progress back up the stack 1414 - * (towards higher addresses). 1415 - */ 1416 - if (tail + 1 >= (struct compat_frame_tail __user *) 1417 - compat_ptr(buftail.fp)) 1418 - return NULL; 1419 - 1420 - return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1; 1421 - } 1422 - #endif /* CONFIG_COMPAT */ 1423 - 1424 - void perf_callchain_user(struct perf_callchain_entry *entry, 1425 - struct pt_regs *regs) 1426 - { 1427 - if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 1428 - /* We don't support guest os callchain now */ 1429 - return; 1430 - } 1431 - 1432 - perf_callchain_store(entry, regs->pc); 1433 - 1434 - if (!compat_user_mode(regs)) { 1435 - /* AARCH64 mode */ 1436 - struct frame_tail __user *tail; 1437 - 1438 - tail = (struct frame_tail __user *)regs->regs[29]; 1439 - 1440 - while (entry->nr < PERF_MAX_STACK_DEPTH && 1441 - tail && !((unsigned long)tail & 0xf)) 1442 - tail = user_backtrace(tail, entry); 1443 - } else { 1444 - #ifdef CONFIG_COMPAT 1445 - /* AARCH32 compat mode */ 1446 - struct compat_frame_tail __user *tail; 1447 - 1448 - tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; 1449 - 1450 - while ((entry->nr < PERF_MAX_STACK_DEPTH) && 1451 - tail && !((unsigned long)tail & 0x3)) 1452 - tail = compat_user_backtrace(tail, entry); 1453 - #endif 1454 - } 1455 - } 1456 - 1457 - /* 1458 - * Gets called by walk_stackframe() for every stackframe. This will be called 1459 - * whist unwinding the stackframe and is like a subroutine return so we use 1460 - * the PC. 1461 - */ 1462 - static int callchain_trace(struct stackframe *frame, void *data) 1463 - { 1464 - struct perf_callchain_entry *entry = data; 1465 - perf_callchain_store(entry, frame->pc); 1466 - return 0; 1467 - } 1468 - 1469 - void perf_callchain_kernel(struct perf_callchain_entry *entry, 1470 - struct pt_regs *regs) 1471 - { 1472 - struct stackframe frame; 1473 - 1474 - if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 1475 - /* We don't support guest os callchain now */ 1476 - return; 1477 - } 1478 - 1479 - frame.fp = regs->regs[29]; 1480 - frame.sp = regs->sp; 1481 - frame.pc = regs->pc; 1482 - 1483 - walk_stackframe(&frame, callchain_trace, entry); 1484 - } 1485 - 1486 - unsigned long perf_instruction_pointer(struct pt_regs *regs) 1487 - { 1488 - if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) 1489 - return perf_guest_cbs->get_guest_ip(); 1490 - 1491 - return instruction_pointer(regs); 1492 - } 1493 - 1494 - unsigned long perf_misc_flags(struct pt_regs *regs) 1495 - { 1496 - int misc = 0; 1497 - 1498 - if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 1499 - if (perf_guest_cbs->is_user_mode()) 1500 - misc |= PERF_RECORD_MISC_GUEST_USER; 1501 - else 1502 - misc |= PERF_RECORD_MISC_GUEST_KERNEL; 1503 - } else { 1504 - if (user_mode(regs)) 1505 - misc |= PERF_RECORD_MISC_USER; 1506 - else 1507 - misc |= PERF_RECORD_MISC_KERNEL; 1508 - } 1509 - 1510 - return misc; 1511 - }
-5
arch/arm64/kernel/psci.c
··· 110 110 return ret; 111 111 } 112 112 113 - #ifdef CONFIG_SMP 114 - 115 113 static int __init cpu_psci_cpu_init(unsigned int cpu) 116 114 { 117 115 return 0; ··· 191 193 return -ETIMEDOUT; 192 194 } 193 195 #endif 194 - #endif 195 196 196 197 static int psci_suspend_finisher(unsigned long index) 197 198 { ··· 225 228 .cpu_init_idle = cpu_psci_cpu_init_idle, 226 229 .cpu_suspend = cpu_psci_cpu_suspend, 227 230 #endif 228 - #ifdef CONFIG_SMP 229 231 .cpu_init = cpu_psci_cpu_init, 230 232 .cpu_prepare = cpu_psci_cpu_prepare, 231 233 .cpu_boot = cpu_psci_cpu_boot, ··· 232 236 .cpu_disable = cpu_psci_cpu_disable, 233 237 .cpu_die = cpu_psci_cpu_die, 234 238 .cpu_kill = cpu_psci_cpu_kill, 235 - #endif 236 239 #endif 237 240 }; 238 241
+91 -1
arch/arm64/kernel/ptrace.c
··· 826 826 return ret; 827 827 } 828 828 829 + static int compat_tls_get(struct task_struct *target, 830 + const struct user_regset *regset, unsigned int pos, 831 + unsigned int count, void *kbuf, void __user *ubuf) 832 + { 833 + compat_ulong_t tls = (compat_ulong_t)target->thread.tp_value; 834 + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); 835 + } 836 + 837 + static int compat_tls_set(struct task_struct *target, 838 + const struct user_regset *regset, unsigned int pos, 839 + unsigned int count, const void *kbuf, 840 + const void __user *ubuf) 841 + { 842 + int ret; 843 + compat_ulong_t tls; 844 + 845 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); 846 + if (ret) 847 + return ret; 848 + 849 + target->thread.tp_value = tls; 850 + return ret; 851 + } 852 + 829 853 static const struct user_regset aarch32_regsets[] = { 830 854 [REGSET_COMPAT_GPR] = { 831 855 .core_note_type = NT_PRSTATUS, ··· 872 848 static const struct user_regset_view user_aarch32_view = { 873 849 .name = "aarch32", .e_machine = EM_ARM, 874 850 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) 851 + }; 852 + 853 + static const struct user_regset aarch32_ptrace_regsets[] = { 854 + [REGSET_GPR] = { 855 + .core_note_type = NT_PRSTATUS, 856 + .n = COMPAT_ELF_NGREG, 857 + .size = sizeof(compat_elf_greg_t), 858 + .align = sizeof(compat_elf_greg_t), 859 + .get = compat_gpr_get, 860 + .set = compat_gpr_set 861 + }, 862 + [REGSET_FPR] = { 863 + .core_note_type = NT_ARM_VFP, 864 + .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), 865 + .size = sizeof(compat_ulong_t), 866 + .align = sizeof(compat_ulong_t), 867 + .get = compat_vfp_get, 868 + .set = compat_vfp_set 869 + }, 870 + [REGSET_TLS] = { 871 + .core_note_type = NT_ARM_TLS, 872 + .n = 1, 873 + .size = sizeof(compat_ulong_t), 874 + .align = sizeof(compat_ulong_t), 875 + .get = compat_tls_get, 876 + .set = compat_tls_set, 877 + }, 878 + #ifdef CONFIG_HAVE_HW_BREAKPOINT 879 + [REGSET_HW_BREAK] = { 880 + .core_note_type = NT_ARM_HW_BREAK, 881 + .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 882 + .size = sizeof(u32), 883 + .align = sizeof(u32), 884 + .get = hw_break_get, 885 + .set = hw_break_set, 886 + }, 887 + [REGSET_HW_WATCH] = { 888 + .core_note_type = NT_ARM_HW_WATCH, 889 + .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 890 + .size = sizeof(u32), 891 + .align = sizeof(u32), 892 + .get = hw_break_get, 893 + .set = hw_break_set, 894 + }, 895 + #endif 896 + [REGSET_SYSTEM_CALL] = { 897 + .core_note_type = NT_ARM_SYSTEM_CALL, 898 + .n = 1, 899 + .size = sizeof(int), 900 + .align = sizeof(int), 901 + .get = system_call_get, 902 + .set = system_call_set, 903 + }, 904 + }; 905 + 906 + static const struct user_regset_view user_aarch32_ptrace_view = { 907 + .name = "aarch32", .e_machine = EM_ARM, 908 + .regsets = aarch32_ptrace_regsets, .n = ARRAY_SIZE(aarch32_ptrace_regsets) 875 909 }; 876 910 877 911 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, ··· 1191 1109 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 1192 1110 { 1193 1111 #ifdef CONFIG_COMPAT 1194 - if (is_compat_thread(task_thread_info(task))) 1112 + /* 1113 + * Core dumping of 32-bit tasks or compat ptrace requests must use the 1114 + * user_aarch32_view compatible with arm32. Native ptrace requests on 1115 + * 32-bit children use an extended user_aarch32_ptrace_view to allow 1116 + * access to the TLS register. 1117 + */ 1118 + if (is_compat_task()) 1195 1119 return &user_aarch32_view; 1120 + else if (is_compat_thread(task_thread_info(task))) 1121 + return &user_aarch32_ptrace_view; 1196 1122 #endif 1197 1123 return &user_aarch64_view; 1198 1124 }
+34 -51
arch/arm64/kernel/setup.c
··· 62 62 #include <asm/traps.h> 63 63 #include <asm/memblock.h> 64 64 #include <asm/efi.h> 65 - #include <asm/virt.h> 66 65 #include <asm/xen/hypervisor.h> 67 66 68 67 unsigned long elf_hwcap __read_mostly; ··· 129 130 } 130 131 131 132 struct mpidr_hash mpidr_hash; 132 - #ifdef CONFIG_SMP 133 133 /** 134 134 * smp_build_mpidr_hash - Pre-compute shifts required at each affinity 135 135 * level in order to build a linear index from an ··· 194 196 pr_warn("Large number of MPIDR hash buckets detected\n"); 195 197 __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash)); 196 198 } 197 - #endif 198 - 199 - static void __init hyp_mode_check(void) 200 - { 201 - if (is_hyp_mode_available()) 202 - pr_info("CPU: All CPU(s) started at EL2\n"); 203 - else if (is_hyp_mode_mismatched()) 204 - WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC, 205 - "CPU: CPUs started in inconsistent modes"); 206 - else 207 - pr_info("CPU: All CPU(s) started at EL1\n"); 208 - } 209 - 210 - void __init do_post_cpus_up_work(void) 211 - { 212 - hyp_mode_check(); 213 - apply_alternatives_all(); 214 - } 215 - 216 - #ifdef CONFIG_UP_LATE_INIT 217 - void __init up_late_init(void) 218 - { 219 - do_post_cpus_up_work(); 220 - } 221 - #endif /* CONFIG_UP_LATE_INIT */ 222 199 223 200 static void __init setup_processor(void) 224 201 { 225 - u64 features, block; 202 + u64 features; 203 + s64 block; 226 204 u32 cwg; 227 205 int cls; 228 206 ··· 228 254 * for non-negative values. Negative values are reserved. 229 255 */ 230 256 features = read_cpuid(ID_AA64ISAR0_EL1); 231 - block = (features >> 4) & 0xf; 232 - if (!(block & 0x8)) { 257 + block = cpuid_feature_extract_field(features, 4); 258 + if (block > 0) { 233 259 switch (block) { 234 260 default: 235 261 case 2: ··· 241 267 } 242 268 } 243 269 244 - block = (features >> 8) & 0xf; 245 - if (block && !(block & 0x8)) 270 + if (cpuid_feature_extract_field(features, 8) > 0) 246 271 elf_hwcap |= HWCAP_SHA1; 247 272 248 - block = (features >> 12) & 0xf; 249 - if (block && !(block & 0x8)) 273 + if (cpuid_feature_extract_field(features, 12) > 0) 250 274 elf_hwcap |= HWCAP_SHA2; 251 275 252 - block = (features >> 16) & 0xf; 253 - if (block && !(block & 0x8)) 276 + if (cpuid_feature_extract_field(features, 16) > 0) 254 277 elf_hwcap |= HWCAP_CRC32; 278 + 279 + block = cpuid_feature_extract_field(features, 20); 280 + if (block > 0) { 281 + switch (block) { 282 + default: 283 + case 2: 284 + elf_hwcap |= HWCAP_ATOMICS; 285 + case 1: 286 + /* RESERVED */ 287 + case 0: 288 + break; 289 + } 290 + } 255 291 256 292 #ifdef CONFIG_COMPAT 257 293 /* 258 294 * ID_ISAR5_EL1 carries similar information as above, but pertaining to 259 - * the Aarch32 32-bit execution state. 295 + * the AArch32 32-bit execution state. 260 296 */ 261 297 features = read_cpuid(ID_ISAR5_EL1); 262 - block = (features >> 4) & 0xf; 263 - if (!(block & 0x8)) { 298 + block = cpuid_feature_extract_field(features, 4); 299 + if (block > 0) { 264 300 switch (block) { 265 301 default: 266 302 case 2: ··· 282 298 } 283 299 } 284 300 285 - block = (features >> 8) & 0xf; 286 - if (block && !(block & 0x8)) 301 + if (cpuid_feature_extract_field(features, 8) > 0) 287 302 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; 288 303 289 - block = (features >> 12) & 0xf; 290 - if (block && !(block & 0x8)) 304 + if (cpuid_feature_extract_field(features, 12) > 0) 291 305 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; 292 306 293 - block = (features >> 16) & 0xf; 294 - if (block && !(block & 0x8)) 307 + if (cpuid_feature_extract_field(features, 16) > 0) 295 308 compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; 296 309 #endif 297 310 } ··· 385 404 xen_early_init(); 386 405 387 406 cpu_read_bootcpu_ops(); 388 - #ifdef CONFIG_SMP 389 407 smp_init_cpus(); 390 408 smp_build_mpidr_hash(); 391 - #endif 392 409 393 410 #ifdef CONFIG_VT 394 411 #if defined(CONFIG_VGA_CONSOLE) ··· 405 426 406 427 static int __init arm64_device_init(void) 407 428 { 408 - of_iommu_init(); 409 - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 429 + if (of_have_populated_dt()) { 430 + of_iommu_init(); 431 + of_platform_populate(NULL, of_default_bus_match_table, 432 + NULL, NULL); 433 + } else if (acpi_disabled) { 434 + pr_crit("Device tree not populated\n"); 435 + } 410 436 return 0; 411 437 } 412 438 arch_initcall_sync(arm64_device_init); ··· 439 455 "sha1", 440 456 "sha2", 441 457 "crc32", 458 + "atomics", 442 459 NULL 443 460 }; 444 461 ··· 492 507 * online processors, looking for lines beginning with 493 508 * "processor". Give glibc what it expects. 494 509 */ 495 - #ifdef CONFIG_SMP 496 510 seq_printf(m, "processor\t: %d\n", i); 497 - #endif 498 511 499 512 /* 500 513 * Dump out the common processor features in a single line.
+8 -6
arch/arm64/kernel/sleep.S
··· 82 82 str x2, [x0, #CPU_CTX_SP] 83 83 ldr x1, =sleep_save_sp 84 84 ldr x1, [x1, #SLEEP_SAVE_SP_VIRT] 85 - #ifdef CONFIG_SMP 86 85 mrs x7, mpidr_el1 87 86 ldr x9, =mpidr_hash 88 87 ldr x10, [x9, #MPIDR_HASH_MASK] ··· 93 94 ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)] 94 95 compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10 95 96 add x1, x1, x8, lsl #3 96 - #endif 97 97 bl __cpu_suspend_save 98 98 /* 99 99 * Grab suspend finisher in x20 and its argument in x19 ··· 133 135 ldr x3, =cpu_resume_after_mmu 134 136 msr sctlr_el1, x0 // restore sctlr_el1 135 137 isb 138 + /* 139 + * Invalidate the local I-cache so that any instructions fetched 140 + * speculatively from the PoC are discarded, since they may have 141 + * been dynamically patched at the PoU. 142 + */ 143 + ic iallu 144 + dsb nsh 145 + isb 136 146 br x3 // global jump to virtual address 137 147 ENDPROC(cpu_resume_mmu) 138 148 .popsection ··· 157 151 158 152 ENTRY(cpu_resume) 159 153 bl el2_setup // if in EL2 drop to EL1 cleanly 160 - #ifdef CONFIG_SMP 161 154 mrs x1, mpidr_el1 162 155 adrp x8, mpidr_hash 163 156 add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address ··· 166 161 ldp w5, w6, [x8, #(MPIDR_HASH_SHIFTS + 8)] 167 162 compute_mpidr_hash x7, x3, x4, x5, x6, x1, x2 168 163 /* x7 contains hash index, let's use it to grab context pointer */ 169 - #else 170 - mov x7, xzr 171 - #endif 172 164 ldr_l x0, sleep_save_sp + SLEEP_SAVE_SP_PHYS 173 165 ldr x0, [x0, x7, lsl #3] 174 166 /* load sp from context */
+14 -1
arch/arm64/kernel/smp.c
··· 52 52 #include <asm/sections.h> 53 53 #include <asm/tlbflush.h> 54 54 #include <asm/ptrace.h> 55 + #include <asm/virt.h> 55 56 56 57 #define CREATE_TRACE_POINTS 57 58 #include <trace/events/ipi.h> ··· 311 310 } 312 311 #endif 313 312 313 + static void __init hyp_mode_check(void) 314 + { 315 + if (is_hyp_mode_available()) 316 + pr_info("CPU: All CPU(s) started at EL2\n"); 317 + else if (is_hyp_mode_mismatched()) 318 + WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC, 319 + "CPU: CPUs started in inconsistent modes"); 320 + else 321 + pr_info("CPU: All CPU(s) started at EL1\n"); 322 + } 323 + 314 324 void __init smp_cpus_done(unsigned int max_cpus) 315 325 { 316 326 pr_info("SMP: Total of %d processors activated.\n", num_online_cpus()); 317 - do_post_cpus_up_work(); 327 + hyp_mode_check(); 328 + apply_alternatives_all(); 318 329 } 319 330 320 331 void __init smp_prepare_boot_cpu(void)
-2
arch/arm64/kernel/time.c
··· 42 42 #include <asm/thread_info.h> 43 43 #include <asm/stacktrace.h> 44 44 45 - #ifdef CONFIG_SMP 46 45 unsigned long profile_pc(struct pt_regs *regs) 47 46 { 48 47 struct stackframe frame; ··· 61 62 return frame.pc; 62 63 } 63 64 EXPORT_SYMBOL(profile_pc); 64 - #endif 65 65 66 66 void __init time_init(void) 67 67 {
+1 -1
arch/arm64/kernel/topology.c
··· 300 300 * Discard anything that was parsed if we hit an error so we 301 301 * don't use partial information. 302 302 */ 303 - if (parse_dt_topology()) 303 + if (of_have_populated_dt() && parse_dt_topology()) 304 304 reset_cpu_topology(); 305 305 }
+80 -14
arch/arm64/kernel/traps.c
··· 17 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 18 */ 19 19 20 + #include <linux/bug.h> 20 21 #include <linux/signal.h> 21 22 #include <linux/personality.h> 22 23 #include <linux/kallsyms.h> ··· 33 32 #include <linux/syscalls.h> 34 33 35 34 #include <asm/atomic.h> 35 + #include <asm/bug.h> 36 36 #include <asm/debug-monitors.h> 37 37 #include <asm/esr.h> 38 + #include <asm/insn.h> 38 39 #include <asm/traps.h> 39 40 #include <asm/stacktrace.h> 40 41 #include <asm/exception.h> ··· 55 52 * Dump out the contents of some memory nicely... 56 53 */ 57 54 static void dump_mem(const char *lvl, const char *str, unsigned long bottom, 58 - unsigned long top) 55 + unsigned long top, bool compat) 59 56 { 60 57 unsigned long first; 61 58 mm_segment_t fs; 62 59 int i; 60 + unsigned int width = compat ? 4 : 8; 63 61 64 62 /* 65 63 * We need to switch to kernel mode so that we can use __get_user ··· 79 75 memset(str, ' ', sizeof(str)); 80 76 str[sizeof(str) - 1] = '\0'; 81 77 82 - for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { 78 + for (p = first, i = 0; i < (32 / width) 79 + && p < top; i++, p += width) { 83 80 if (p >= bottom && p < top) { 84 - unsigned int val; 85 - if (__get_user(val, (unsigned int *)p) == 0) 86 - sprintf(str + i * 9, " %08x", val); 87 - else 88 - sprintf(str + i * 9, " ????????"); 81 + unsigned long val; 82 + 83 + if (width == 8) { 84 + if (__get_user(val, (unsigned long *)p) == 0) 85 + sprintf(str + i * 17, " %016lx", val); 86 + else 87 + sprintf(str + i * 17, " ????????????????"); 88 + } else { 89 + if (__get_user(val, (unsigned int *)p) == 0) 90 + sprintf(str + i * 9, " %08lx", val); 91 + else 92 + sprintf(str + i * 9, " ????????"); 93 + } 89 94 } 90 95 } 91 96 printk("%s%04lx:%s\n", lvl, first & 0xffff, str); ··· 108 95 print_ip_sym(where); 109 96 if (in_exception_text(where)) 110 97 dump_mem("", "Exception stack", stack, 111 - stack + sizeof(struct pt_regs)); 98 + stack + sizeof(struct pt_regs), false); 112 99 } 113 100 114 101 static void dump_instr(const char *lvl, struct pt_regs *regs) ··· 192 179 #else 193 180 #define S_PREEMPT "" 194 181 #endif 195 - #ifdef CONFIG_SMP 196 182 #define S_SMP " SMP" 197 - #else 198 - #define S_SMP "" 199 - #endif 200 183 201 184 static int __die(const char *str, int err, struct thread_info *thread, 202 185 struct pt_regs *regs) ··· 216 207 217 208 if (!user_mode(regs) || in_interrupt()) { 218 209 dump_mem(KERN_EMERG, "Stack: ", regs->sp, 219 - THREAD_SIZE + (unsigned long)task_stack_page(tsk)); 210 + THREAD_SIZE + (unsigned long)task_stack_page(tsk), 211 + compat_user_mode(regs)); 220 212 dump_backtrace(regs, tsk); 221 213 dump_instr(KERN_EMERG, regs); 222 214 } ··· 469 459 pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val); 470 460 } 471 461 462 + /* GENERIC_BUG traps */ 463 + 464 + int is_valid_bugaddr(unsigned long addr) 465 + { 466 + /* 467 + * bug_handler() only called for BRK #BUG_BRK_IMM. 468 + * So the answer is trivial -- any spurious instances with no 469 + * bug table entry will be rejected by report_bug() and passed 470 + * back to the debug-monitors code and handled as a fatal 471 + * unexpected debug exception. 472 + */ 473 + return 1; 474 + } 475 + 476 + static int bug_handler(struct pt_regs *regs, unsigned int esr) 477 + { 478 + if (user_mode(regs)) 479 + return DBG_HOOK_ERROR; 480 + 481 + switch (report_bug(regs->pc, regs)) { 482 + case BUG_TRAP_TYPE_BUG: 483 + die("Oops - BUG", regs, 0); 484 + break; 485 + 486 + case BUG_TRAP_TYPE_WARN: 487 + /* Ideally, report_bug() should backtrace for us... but no. */ 488 + dump_backtrace(regs, NULL); 489 + break; 490 + 491 + default: 492 + /* unknown/unrecognised bug trap type */ 493 + return DBG_HOOK_ERROR; 494 + } 495 + 496 + /* If thread survives, skip over the BUG instruction and continue: */ 497 + regs->pc += AARCH64_INSN_SIZE; /* skip BRK and resume */ 498 + return DBG_HOOK_HANDLED; 499 + } 500 + 501 + static struct break_hook bug_break_hook = { 502 + .esr_val = 0xf2000000 | BUG_BRK_IMM, 503 + .esr_mask = 0xffffffff, 504 + .fn = bug_handler, 505 + }; 506 + 507 + /* 508 + * Initial handler for AArch64 BRK exceptions 509 + * This handler only used until debug_traps_init(). 510 + */ 511 + int __init early_brk64(unsigned long addr, unsigned int esr, 512 + struct pt_regs *regs) 513 + { 514 + return bug_handler(regs, esr) != DBG_HOOK_HANDLED; 515 + } 516 + 517 + /* This registration must happen early, before debug_traps_init(). */ 472 518 void __init trap_init(void) 473 519 { 474 - return; 520 + register_break_hook(&bug_break_hook); 475 521 }
+10 -2
arch/arm64/kvm/hyp.S
··· 810 810 * Call into the vgic backend for state saving 811 811 */ 812 812 .macro save_vgic_state 813 - alternative_insn "bl __save_vgic_v2_state", "bl __save_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF 813 + alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF 814 + bl __save_vgic_v2_state 815 + alternative_else 816 + bl __save_vgic_v3_state 817 + alternative_endif 814 818 mrs x24, hcr_el2 815 819 mov x25, #HCR_INT_OVERRIDE 816 820 neg x25, x25 ··· 831 827 orr x24, x24, #HCR_INT_OVERRIDE 832 828 orr x24, x24, x25 833 829 msr hcr_el2, x24 834 - alternative_insn "bl __restore_vgic_v2_state", "bl __restore_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF 830 + alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF 831 + bl __restore_vgic_v2_state 832 + alternative_else 833 + bl __restore_vgic_v3_state 834 + alternative_endif 835 835 .endm 836 836 837 837 .macro save_timer_state
+13
arch/arm64/lib/Makefile
··· 3 3 clear_page.o memchr.o memcpy.o memmove.o memset.o \ 4 4 memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \ 5 5 strchr.o strrchr.o 6 + 7 + # Tell the compiler to treat all general purpose registers as 8 + # callee-saved, which allows for efficient runtime patching of the bl 9 + # instruction in the caller with an atomic instruction when supported by 10 + # the CPU. Result and argument registers are handled correctly, based on 11 + # the function prototype. 12 + lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o 13 + CFLAGS_atomic_ll_sc.o := -fcall-used-x0 -ffixed-x1 -ffixed-x2 \ 14 + -ffixed-x3 -ffixed-x4 -ffixed-x5 -ffixed-x6 \ 15 + -ffixed-x7 -fcall-saved-x8 -fcall-saved-x9 \ 16 + -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12 \ 17 + -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \ 18 + -fcall-saved-x16 -fcall-saved-x17 -fcall-saved-x18
+3
arch/arm64/lib/atomic_ll_sc.c
··· 1 + #include <asm/atomic.h> 2 + #define __ARM64_IN_ATOMIC_IMPL 3 + #include <asm/atomic_ll_sc.h>
+26 -19
arch/arm64/lib/bitops.S
··· 18 18 19 19 #include <linux/linkage.h> 20 20 #include <asm/assembler.h> 21 + #include <asm/lse.h> 21 22 22 23 /* 23 24 * x0: bits 5:0 bit offset 24 25 * bits 31:6 word offset 25 26 * x1: address 26 27 */ 27 - .macro bitop, name, instr 28 + .macro bitop, name, llsc, lse 28 29 ENTRY( \name ) 29 30 and w3, w0, #63 // Get bit offset 30 31 eor w0, w0, w3 // Clear low bits 31 32 mov x2, #1 32 33 add x1, x1, x0, lsr #3 // Get word offset 34 + alt_lse " prfm pstl1strm, [x1]", "nop" 33 35 lsl x3, x2, x3 // Create mask 34 - 1: ldxr x2, [x1] 35 - \instr x2, x2, x3 36 - stxr w0, x2, [x1] 37 - cbnz w0, 1b 36 + 37 + alt_lse "1: ldxr x2, [x1]", "\lse x3, [x1]" 38 + alt_lse " \llsc x2, x2, x3", "nop" 39 + alt_lse " stxr w0, x2, [x1]", "nop" 40 + alt_lse " cbnz w0, 1b", "nop" 41 + 38 42 ret 39 43 ENDPROC(\name ) 40 44 .endm 41 45 42 - .macro testop, name, instr 46 + .macro testop, name, llsc, lse 43 47 ENTRY( \name ) 44 48 and w3, w0, #63 // Get bit offset 45 49 eor w0, w0, w3 // Clear low bits 46 50 mov x2, #1 47 51 add x1, x1, x0, lsr #3 // Get word offset 52 + alt_lse " prfm pstl1strm, [x1]", "nop" 48 53 lsl x4, x2, x3 // Create mask 49 - 1: ldxr x2, [x1] 50 - lsr x0, x2, x3 // Save old value of bit 51 - \instr x2, x2, x4 // toggle bit 52 - stlxr w5, x2, [x1] 53 - cbnz w5, 1b 54 - dmb ish 54 + 55 + alt_lse "1: ldxr x2, [x1]", "\lse x4, x2, [x1]" 56 + lsr x0, x2, x3 57 + alt_lse " \llsc x2, x2, x4", "nop" 58 + alt_lse " stlxr w5, x2, [x1]", "nop" 59 + alt_lse " cbnz w5, 1b", "nop" 60 + alt_lse " dmb ish", "nop" 61 + 55 62 and x0, x0, #1 56 - 3: ret 63 + ret 57 64 ENDPROC(\name ) 58 65 .endm 59 66 60 67 /* 61 68 * Atomic bit operations. 62 69 */ 63 - bitop change_bit, eor 64 - bitop clear_bit, bic 65 - bitop set_bit, orr 70 + bitop change_bit, eor, steor 71 + bitop clear_bit, bic, stclr 72 + bitop set_bit, orr, stset 66 73 67 - testop test_and_change_bit, eor 68 - testop test_and_clear_bit, bic 69 - testop test_and_set_bit, orr 74 + testop test_and_change_bit, eor, ldeoral 75 + testop test_and_clear_bit, bic, ldclral 76 + testop test_and_set_bit, orr, ldsetal
+8
arch/arm64/lib/clear_user.S
··· 16 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 17 */ 18 18 #include <linux/linkage.h> 19 + 20 + #include <asm/alternative.h> 19 21 #include <asm/assembler.h> 22 + #include <asm/cpufeature.h> 23 + #include <asm/sysreg.h> 20 24 21 25 .text 22 26 ··· 33 29 * Alignment fixed up by hardware. 34 30 */ 35 31 ENTRY(__clear_user) 32 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \ 33 + CONFIG_ARM64_PAN) 36 34 mov x2, x1 // save the size for fixup return 37 35 subs x1, x1, #8 38 36 b.mi 2f ··· 54 48 b.mi 5f 55 49 USER(9f, strb wzr, [x0] ) 56 50 5: mov x0, #0 51 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \ 52 + CONFIG_ARM64_PAN) 57 53 ret 58 54 ENDPROC(__clear_user) 59 55
+19 -6
arch/arm64/lib/copy_from_user.S
··· 15 15 */ 16 16 17 17 #include <linux/linkage.h> 18 + 19 + #include <asm/alternative.h> 18 20 #include <asm/assembler.h> 21 + #include <asm/cpufeature.h> 22 + #include <asm/sysreg.h> 19 23 20 24 /* 21 25 * Copy from user space to a kernel buffer (alignment handled by the hardware) ··· 32 28 * x0 - bytes not copied 33 29 */ 34 30 ENTRY(__copy_from_user) 35 - add x4, x1, x2 // upper user buffer boundary 36 - subs x2, x2, #8 31 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \ 32 + CONFIG_ARM64_PAN) 33 + add x5, x1, x2 // upper user buffer boundary 34 + subs x2, x2, #16 35 + b.mi 1f 36 + 0: 37 + USER(9f, ldp x3, x4, [x1], #16) 38 + subs x2, x2, #16 39 + stp x3, x4, [x0], #16 40 + b.pl 0b 41 + 1: adds x2, x2, #8 37 42 b.mi 2f 38 - 1: 39 43 USER(9f, ldr x3, [x1], #8 ) 40 - subs x2, x2, #8 44 + sub x2, x2, #8 41 45 str x3, [x0], #8 42 - b.pl 1b 43 46 2: adds x2, x2, #4 44 47 b.mi 3f 45 48 USER(9f, ldr w3, [x1], #4 ) ··· 62 51 USER(9f, ldrb w3, [x1] ) 63 52 strb w3, [x0] 64 53 5: mov x0, #0 54 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \ 55 + CONFIG_ARM64_PAN) 65 56 ret 66 57 ENDPROC(__copy_from_user) 67 58 68 59 .section .fixup,"ax" 69 60 .align 2 70 - 9: sub x2, x4, x1 61 + 9: sub x2, x5, x1 71 62 mov x3, x2 72 63 10: strb wzr, [x0], #1 // zero remaining buffer space 73 64 subs x3, x3, #1
+19 -6
arch/arm64/lib/copy_in_user.S
··· 17 17 */ 18 18 19 19 #include <linux/linkage.h> 20 + 21 + #include <asm/alternative.h> 20 22 #include <asm/assembler.h> 23 + #include <asm/cpufeature.h> 24 + #include <asm/sysreg.h> 21 25 22 26 /* 23 27 * Copy from user space to user space (alignment handled by the hardware) ··· 34 30 * x0 - bytes not copied 35 31 */ 36 32 ENTRY(__copy_in_user) 37 - add x4, x0, x2 // upper user buffer boundary 38 - subs x2, x2, #8 33 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \ 34 + CONFIG_ARM64_PAN) 35 + add x5, x0, x2 // upper user buffer boundary 36 + subs x2, x2, #16 37 + b.mi 1f 38 + 0: 39 + USER(9f, ldp x3, x4, [x1], #16) 40 + subs x2, x2, #16 41 + USER(9f, stp x3, x4, [x0], #16) 42 + b.pl 0b 43 + 1: adds x2, x2, #8 39 44 b.mi 2f 40 - 1: 41 45 USER(9f, ldr x3, [x1], #8 ) 42 - subs x2, x2, #8 46 + sub x2, x2, #8 43 47 USER(9f, str x3, [x0], #8 ) 44 - b.pl 1b 45 48 2: adds x2, x2, #4 46 49 b.mi 3f 47 50 USER(9f, ldr w3, [x1], #4 ) ··· 64 53 USER(9f, ldrb w3, [x1] ) 65 54 USER(9f, strb w3, [x0] ) 66 55 5: mov x0, #0 56 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \ 57 + CONFIG_ARM64_PAN) 67 58 ret 68 59 ENDPROC(__copy_in_user) 69 60 70 61 .section .fixup,"ax" 71 62 .align 2 72 - 9: sub x0, x4, x0 // bytes not copied 63 + 9: sub x0, x5, x0 // bytes not copied 73 64 ret 74 65 .previous
+19 -6
arch/arm64/lib/copy_to_user.S
··· 15 15 */ 16 16 17 17 #include <linux/linkage.h> 18 + 19 + #include <asm/alternative.h> 18 20 #include <asm/assembler.h> 21 + #include <asm/cpufeature.h> 22 + #include <asm/sysreg.h> 19 23 20 24 /* 21 25 * Copy to user space from a kernel buffer (alignment handled by the hardware) ··· 32 28 * x0 - bytes not copied 33 29 */ 34 30 ENTRY(__copy_to_user) 35 - add x4, x0, x2 // upper user buffer boundary 36 - subs x2, x2, #8 31 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \ 32 + CONFIG_ARM64_PAN) 33 + add x5, x0, x2 // upper user buffer boundary 34 + subs x2, x2, #16 35 + b.mi 1f 36 + 0: 37 + ldp x3, x4, [x1], #16 38 + subs x2, x2, #16 39 + USER(9f, stp x3, x4, [x0], #16) 40 + b.pl 0b 41 + 1: adds x2, x2, #8 37 42 b.mi 2f 38 - 1: 39 43 ldr x3, [x1], #8 40 - subs x2, x2, #8 44 + sub x2, x2, #8 41 45 USER(9f, str x3, [x0], #8 ) 42 - b.pl 1b 43 46 2: adds x2, x2, #4 44 47 b.mi 3f 45 48 ldr w3, [x1], #4 ··· 62 51 ldrb w3, [x1] 63 52 USER(9f, strb w3, [x0] ) 64 53 5: mov x0, #0 54 + ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \ 55 + CONFIG_ARM64_PAN) 65 56 ret 66 57 ENDPROC(__copy_to_user) 67 58 68 59 .section .fixup,"ax" 69 60 .align 2 70 - 9: sub x0, x4, x0 // bytes not copied 61 + 9: sub x0, x5, x0 // bytes not copied 71 62 ret 72 63 .previous
+6 -1
arch/arm64/mm/cache.S
··· 143 143 dcache_line_size x2, x3 144 144 sub x3, x2, #1 145 145 bic x0, x0, x3 146 - 1: alternative_insn "dc cvac, x0", "dc civac, x0", ARM64_WORKAROUND_CLEAN_CACHE 146 + 1: 147 + alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE 148 + dc cvac, x0 149 + alternative_else 150 + dc civac, x0 151 + alternative_endif 147 152 add x0, x0, x2 148 153 cmp x0, x1 149 154 b.lo 1b
-16
arch/arm64/mm/context.c
··· 53 53 __flush_icache_all(); 54 54 } 55 55 56 - #ifdef CONFIG_SMP 57 - 58 56 static void set_mm_context(struct mm_struct *mm, unsigned int asid) 59 57 { 60 58 unsigned long flags; ··· 108 110 cpu_switch_mm(mm->pgd, mm); 109 111 } 110 112 111 - #else 112 - 113 - static inline void set_mm_context(struct mm_struct *mm, unsigned int asid) 114 - { 115 - mm->context.id = asid; 116 - cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); 117 - } 118 - 119 - #endif 120 - 121 113 void __new_context(struct mm_struct *mm) 122 114 { 123 115 unsigned int asid; 124 116 unsigned int bits = asid_bits(); 125 117 126 118 raw_spin_lock(&cpu_asid_lock); 127 - #ifdef CONFIG_SMP 128 119 /* 129 120 * Check the ASID again, in case the change was broadcast from another 130 121 * CPU before we acquired the lock. ··· 123 136 raw_spin_unlock(&cpu_asid_lock); 124 137 return; 125 138 } 126 - #endif 127 139 /* 128 140 * At this point, it is guaranteed that the current mm (with an old 129 141 * ASID) isn't active on any other CPU since the ASIDs are changed ··· 141 155 cpu_last_asid = ASID_FIRST_VERSION; 142 156 asid = cpu_last_asid + smp_processor_id(); 143 157 flush_context(); 144 - #ifdef CONFIG_SMP 145 158 smp_wmb(); 146 159 smp_call_function(reset_context, NULL, 1); 147 - #endif 148 160 cpu_last_asid += NR_CPUS - 1; 149 161 } 150 162
+20 -13
arch/arm64/mm/dma-mapping.c
··· 144 144 struct page *page; 145 145 void *ptr, *coherent_ptr; 146 146 bool coherent = is_device_dma_coherent(dev); 147 + pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false); 147 148 148 149 size = PAGE_ALIGN(size); 149 150 ··· 172 171 /* create a coherent mapping */ 173 172 page = virt_to_page(ptr); 174 173 coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP, 175 - __get_dma_pgprot(attrs, 176 - __pgprot(PROT_NORMAL_NC), false), 177 - NULL); 174 + prot, NULL); 178 175 if (!coherent_ptr) 179 176 goto no_map; 180 177 ··· 302 303 sg->length, dir); 303 304 } 304 305 305 - /* vma->vm_page_prot must be set appropriately before calling this function */ 306 - static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, 307 - void *cpu_addr, dma_addr_t dma_addr, size_t size) 306 + static int __swiotlb_mmap(struct device *dev, 307 + struct vm_area_struct *vma, 308 + void *cpu_addr, dma_addr_t dma_addr, size_t size, 309 + struct dma_attrs *attrs) 308 310 { 309 311 int ret = -ENXIO; 310 312 unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> ··· 313 313 unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; 314 314 unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT; 315 315 unsigned long off = vma->vm_pgoff; 316 + 317 + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, 318 + is_device_dma_coherent(dev)); 316 319 317 320 if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) 318 321 return ret; ··· 330 327 return ret; 331 328 } 332 329 333 - static int __swiotlb_mmap(struct device *dev, 334 - struct vm_area_struct *vma, 335 - void *cpu_addr, dma_addr_t dma_addr, size_t size, 336 - struct dma_attrs *attrs) 330 + static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt, 331 + void *cpu_addr, dma_addr_t handle, size_t size, 332 + struct dma_attrs *attrs) 337 333 { 338 - vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, 339 - is_device_dma_coherent(dev)); 340 - return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); 334 + int ret = sg_alloc_table(sgt, 1, GFP_KERNEL); 335 + 336 + if (!ret) 337 + sg_set_page(sgt->sgl, phys_to_page(dma_to_phys(dev, handle)), 338 + PAGE_ALIGN(size), 0); 339 + 340 + return ret; 341 341 } 342 342 343 343 static struct dma_map_ops swiotlb_dma_ops = { 344 344 .alloc = __dma_alloc, 345 345 .free = __dma_free, 346 346 .mmap = __swiotlb_mmap, 347 + .get_sgtable = __swiotlb_get_sgtable, 347 348 .map_page = __swiotlb_map_page, 348 349 .unmap_page = __swiotlb_unmap_page, 349 350 .map_sg = __swiotlb_map_sg_attrs,
+26 -2
arch/arm64/mm/fault.c
··· 30 30 #include <linux/highmem.h> 31 31 #include <linux/perf_event.h> 32 32 33 + #include <asm/cpufeature.h> 33 34 #include <asm/exception.h> 34 35 #include <asm/debug-monitors.h> 35 36 #include <asm/esr.h> 37 + #include <asm/sysreg.h> 36 38 #include <asm/system_misc.h> 37 39 #include <asm/pgtable.h> 38 40 #include <asm/tlbflush.h> ··· 224 222 vm_flags = VM_WRITE; 225 223 mm_flags |= FAULT_FLAG_WRITE; 226 224 } 225 + 226 + /* 227 + * PAN bit set implies the fault happened in kernel space, but not 228 + * in the arch's user access functions. 229 + */ 230 + if (IS_ENABLED(CONFIG_ARM64_PAN) && (regs->pstate & PSR_PAN_BIT)) 231 + goto no_context; 227 232 228 233 /* 229 234 * As per x86, we may deadlock here. However, since the kernel only ··· 501 492 arm64_notify_die("Oops - SP/PC alignment exception", regs, &info, esr); 502 493 } 503 494 504 - static struct fault_info debug_fault_info[] = { 495 + int __init early_brk64(unsigned long addr, unsigned int esr, 496 + struct pt_regs *regs); 497 + 498 + /* 499 + * __refdata because early_brk64 is __init, but the reference to it is 500 + * clobbered at arch_initcall time. 501 + * See traps.c and debug-monitors.c:debug_traps_init(). 502 + */ 503 + static struct fault_info __refdata debug_fault_info[] = { 505 504 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" }, 506 505 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" }, 507 506 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" }, 508 507 { do_bad, SIGBUS, 0, "unknown 3" }, 509 508 { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" }, 510 509 { do_bad, SIGTRAP, 0, "aarch32 vector catch" }, 511 - { do_bad, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" }, 510 + { early_brk64, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" }, 512 511 { do_bad, SIGBUS, 0, "unknown 7" }, 513 512 }; 514 513 ··· 553 536 554 537 return 0; 555 538 } 539 + 540 + #ifdef CONFIG_ARM64_PAN 541 + void cpu_enable_pan(void) 542 + { 543 + config_sctlr_el1(SCTLR_EL1_SPAN, 0); 544 + } 545 + #endif /* CONFIG_ARM64_PAN */
-4
arch/arm64/mm/flush.c
··· 60 60 unsigned long uaddr, void *dst, const void *src, 61 61 unsigned long len) 62 62 { 63 - #ifdef CONFIG_SMP 64 63 preempt_disable(); 65 - #endif 66 64 memcpy(dst, src, len); 67 65 flush_ptrace_access(vma, page, uaddr, dst, len); 68 - #ifdef CONFIG_SMP 69 66 preempt_enable(); 70 - #endif 71 67 } 72 68 73 69 void __sync_icache_dcache(pte_t pte, unsigned long addr)
-4
arch/arm64/mm/hugetlbpage.c
··· 13 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 * GNU General Public License for more details. 16 - * 17 - * You should have received a copy of the GNU General Public License 18 - * along with this program; if not, write to the Free Software 19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 16 */ 21 17 22 18 #include <linux/init.h>
+2 -2
arch/arm64/mm/init.c
··· 358 358 359 359 #ifdef CONFIG_BLK_DEV_INITRD 360 360 361 - static int keep_initrd; 361 + static int keep_initrd __initdata; 362 362 363 - void free_initrd_mem(unsigned long start, unsigned long end) 363 + void __init free_initrd_mem(unsigned long start, unsigned long end) 364 364 { 365 365 if (!keep_initrd) 366 366 free_reserved_area((void *)start, (void *)end, 0, "initrd");
+1 -12
arch/arm64/mm/mmu.c
··· 267 267 return ptr; 268 268 } 269 269 270 - static void __ref create_mapping(phys_addr_t phys, unsigned long virt, 270 + static void __init create_mapping(phys_addr_t phys, unsigned long virt, 271 271 phys_addr_t size, pgprot_t prot) 272 272 { 273 273 if (virt < VMALLOC_START) { ··· 458 458 cpu_set_reserved_ttbr0(); 459 459 flush_tlb_all(); 460 460 cpu_set_default_tcr_t0sz(); 461 - } 462 - 463 - /* 464 - * Enable the identity mapping to allow the MMU disabling. 465 - */ 466 - void setup_mm_for_reboot(void) 467 - { 468 - cpu_set_reserved_ttbr0(); 469 - flush_tlb_all(); 470 - cpu_set_idmap_tcr_t0sz(); 471 - cpu_switch_mm(idmap_pg_dir, &init_mm); 472 461 } 473 462 474 463 /*
+15 -6
arch/arm64/mm/proc.S
··· 34 34 #define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K 35 35 #endif 36 36 37 - #ifdef CONFIG_SMP 38 37 #define TCR_SMP_FLAGS TCR_SHARED 39 - #else 40 - #define TCR_SMP_FLAGS 0 41 - #endif 42 38 43 39 /* PTWs cacheable, inner/outer WBWA */ 44 40 #define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA ··· 146 150 * value of the SCTLR_EL1 register. 147 151 */ 148 152 ENTRY(__cpu_setup) 149 - ic iallu // I+BTB cache invalidate 150 153 tlbi vmalle1is // invalidate I + D TLBs 151 154 dsb ish 152 155 153 156 mov x0, #3 << 20 154 157 msr cpacr_el1, x0 // Enable FP/ASIMD 155 - msr mdscr_el1, xzr // Reset mdscr_el1 158 + mov x0, #1 << 12 // Reset mdscr_el1 and disable 159 + msr mdscr_el1, x0 // access to the DCC from EL0 156 160 /* 157 161 * Memory region attributes for LPAE: 158 162 * ··· 192 196 */ 193 197 mrs x9, ID_AA64MMFR0_EL1 194 198 bfi x10, x9, #32, #3 199 + #ifdef CONFIG_ARM64_HW_AFDBM 200 + /* 201 + * Hardware update of the Access and Dirty bits. 202 + */ 203 + mrs x9, ID_AA64MMFR1_EL1 204 + and x9, x9, #0xf 205 + cbz x9, 2f 206 + cmp x9, #2 207 + b.lt 1f 208 + orr x10, x10, #TCR_HD // hardware Dirty flag update 209 + 1: orr x10, x10, #TCR_HA // hardware Access flag update 210 + 2: 211 + #endif /* CONFIG_ARM64_HW_AFDBM */ 195 212 msr tcr_el1, x10 196 213 ret // return to head.S 197 214 ENDPROC(__cpu_setup)
+7 -5
drivers/of/fdt.c
··· 967 967 } 968 968 969 969 #ifdef CONFIG_HAVE_MEMBLOCK 970 - #define MAX_PHYS_ADDR ((phys_addr_t)~0) 970 + #ifndef MAX_MEMBLOCK_ADDR 971 + #define MAX_MEMBLOCK_ADDR ((phys_addr_t)~0) 972 + #endif 971 973 972 974 void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) 973 975 { ··· 986 984 } 987 985 size &= PAGE_MASK; 988 986 989 - if (base > MAX_PHYS_ADDR) { 987 + if (base > MAX_MEMBLOCK_ADDR) { 990 988 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", 991 989 base, base + size); 992 990 return; 993 991 } 994 992 995 - if (base + size - 1 > MAX_PHYS_ADDR) { 993 + if (base + size - 1 > MAX_MEMBLOCK_ADDR) { 996 994 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n", 997 - ((u64)MAX_PHYS_ADDR) + 1, base + size); 998 - size = MAX_PHYS_ADDR - base + 1; 995 + ((u64)MAX_MEMBLOCK_ADDR) + 1, base + size); 996 + size = MAX_MEMBLOCK_ADDR - base + 1; 999 997 } 1000 998 1001 999 if (base + size < phys_offset) {