History

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 ...

Linus Torvalds committed 11 years ago

Commit a4fdb2a2 parents 807249d 674c24286 files · +2321 −1145Browse files

Unified · Split

86 files
  1. Documentation/arm64/booting.txt +7 −4
  2. arch/arm64/Kconfig +64 −22
  3. arch/arm64/Makefile +16 −2
  4. arch/arm64/boot/Makefile +12 −0
  5. arch/arm64/include/asm/alternative.h +74 −4
  6. arch/arm64/include/asm/assembler.h +0 −14
  7. arch/arm64/include/asm/atomic.h +52 −227
  8. arch/arm64/include/asm/atomic_ll_sc.h +247 −0
  9. arch/arm64/include/asm/atomic_lse.h +391 −0
  10. arch/arm64/include/asm/barrier.h +0 −24
  11. arch/arm64/include/asm/bug.h +64 −0
  12. arch/arm64/include/asm/cmpxchg.h +74 −118
  13. arch/arm64/include/asm/cpufeature.h +15 −3
  14. arch/arm64/include/asm/cputype.h +0 −3
  15. arch/arm64/include/asm/debug-monitors.h +16 −28
  16. arch/arm64/include/asm/esr.h +9 −0
  17. arch/arm64/include/asm/exception.h +6 −0
  18. arch/arm64/include/asm/fixmap.h +1 −1
  19. arch/arm64/include/asm/futex.h +10 −0
  20. arch/arm64/include/asm/hardirq.h +0 −4
  21. arch/arm64/include/asm/hugetlb.h +0 −4
  22. arch/arm64/include/asm/irq_work.h +0 −11
  23. arch/arm64/include/asm/lse.h +53 −0
  24. arch/arm64/include/asm/memory.h +8 −0
  25. arch/arm64/include/asm/mmu.h +0 −1
  26. arch/arm64/include/asm/percpu.h +0 −8
  27. arch/arm64/include/asm/perf_event.h +1 −1
  28. arch/arm64/include/asm/pgtable-hwdef.h +3 −0
  29. arch/arm64/include/asm/pgtable.h +160 −7
  30. arch/arm64/include/asm/processor.h +2 −0
  31. arch/arm64/include/asm/ptrace.h +0 −4
  32. arch/arm64/include/asm/smp.h +0 −4
  33. arch/arm64/include/asm/smp_plat.h +0 −2
  34. arch/arm64/include/asm/spinlock.h +114 −33
  35. arch/arm64/include/asm/spinlock_types.h +2 −0
  36. arch/arm64/include/asm/sysreg.h +35 −5
  37. arch/arm64/include/asm/tlb.h +6 −1
  38. arch/arm64/include/asm/tlbflush.h +34 −42
  39. arch/arm64/include/asm/topology.h +0 −9
  40. arch/arm64/include/asm/traps.h +21 −2
  41. arch/arm64/include/asm/uaccess.h +11 −0
  42. arch/arm64/include/uapi/asm/hwcap.h +1 −0
  43. arch/arm64/include/uapi/asm/ptrace.h +1 −0
  44. arch/arm64/kernel/Makefile +3 −3
  45. arch/arm64/kernel/alternative.c +25 −5
  46. arch/arm64/kernel/armv8_deprecated.c +8 −11
  47. arch/arm64/kernel/cpu_ops.c +0 −2
  48. arch/arm64/kernel/cpufeature.c +46 −7
  49. arch/arm64/kernel/debug-monitors.c +2 −2
  50. arch/arm64/kernel/efi-stub.c +32 −9
  51. arch/arm64/kernel/entry.S +19 −27
  52. arch/arm64/kernel/fpsimd.c +1 −0
  53. arch/arm64/kernel/head.S +8 −7
  54. arch/arm64/kernel/hw_breakpoint.c +3 −3
  55. arch/arm64/kernel/insn.c +2 −3
  56. arch/arm64/kernel/irq.c +0 −2
  57. arch/arm64/kernel/kgdb.c +6 −6
  58. arch/arm64/kernel/pci.c +13 −0
  59. arch/arm64/kernel/perf_callchain.c +196 −0
  60. arch/arm64/kernel/perf_event.c +25 −285
  61. arch/arm64/kernel/psci.c +0 −5
  62. arch/arm64/kernel/ptrace.c +91 −1
  63. arch/arm64/kernel/setup.c +34 −51
  64. arch/arm64/kernel/sleep.S +8 −6
  65. arch/arm64/kernel/smp.c +14 −1
  66. arch/arm64/kernel/time.c +0 −2
  67. arch/arm64/kernel/topology.c +1 −1
  68. arch/arm64/kernel/traps.c +80 −14
  69. arch/arm64/kvm/hyp.S +10 −2
  70. arch/arm64/lib/Makefile +13 −0
  71. arch/arm64/lib/atomic_ll_sc.c +3 −0
  72. arch/arm64/lib/bitops.S +26 −19
  73. arch/arm64/lib/clear_user.S +8 −0
  74. arch/arm64/lib/copy_from_user.S +19 −6
  75. arch/arm64/lib/copy_in_user.S +19 −6
  76. arch/arm64/lib/copy_to_user.S +19 −6
  77. arch/arm64/mm/cache.S +6 −1
  78. arch/arm64/mm/context.c +0 −16
  79. arch/arm64/mm/dma-mapping.c +20 −13
  80. arch/arm64/mm/fault.c +26 −2
  81. arch/arm64/mm/flush.c +0 −4
  82. arch/arm64/mm/hugetlbpage.c +0 −4
  83. arch/arm64/mm/init.c +2 −2
  84. arch/arm64/mm/mmu.c +1 −12
  85. arch/arm64/mm/proc.S +15 −6
  86. drivers/of/fdt.c +7 −5
Documentation/arm64/booting.txt+7−4
@@ -81,7 +81,7 @@ The decompressed kernel image contains a 64-byte header as follows: · 80 unmodified lines
81 u64 res3 = 0; /* reserved */81 u64 res3 = 0; /* reserved */
82 u64 res4 = 0; /* reserved */82 u64 res4 = 0; /* reserved */
83 u32 magic = 0x644d5241; /* Magic number, little endian, "ARM\x64" */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
87Header notes:87Header notes:
@@ -103,7 +103,7 @@ Header notes: · 15 unmodified lines
103 103
104- The flags field (introduced in v3.17) is a little-endian 64-bit field104- The flags field (introduced in v3.17) is a little-endian 64-bit field
105 composed as follows: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 Bits 1-63: Reserved.107 Bits 1-63: Reserved.
108 108
109- When image_size is zero, a bootloader should attempt to keep as much109- When image_size is zero, a bootloader should attempt to keep as much
@@ -115,11 +115,14 @@ The Image must be placed text_offset bytes from a 2MB aligned base · 5 unmodified lines
115address near the start of usable system RAM and called there. Memory115address near the start of usable system RAM and called there. Memory
116below that base address is currently unusable by Linux, and therefore it116below that base address is currently unusable by Linux, and therefore it
117is strongly recommended that this location is the start of system RAM.117is strongly recommended that this location is the start of system RAM.
118The region between the 2 MB aligned base address and the start of the
119image has no special significance to the kernel, and may be used for
120other purposes.
118At least image_size bytes from the start of the image must be free for121At least image_size bytes from the start of the image must be free for
119use by the kernel.122use by the kernel.
120 123
121Any memory described to the kernel (even that below the 2MB aligned base124Any memory described to the kernel (even that below the start of the
122address) which is not marked as reserved from the kernel e.g. with a125image) which is not marked as reserved from the kernel (e.g., with a
123memreserve region in the device tree) will be considered as available to126memreserve region in the device tree) will be considered as available to
124the kernel.127the kernel.
125 128
arch/arm64/Kconfig+64−22
@@ -29,7 +29,7 @@ config ARM64 · 28 unmodified lines
29 select EDAC_SUPPORT29 select EDAC_SUPPORT
30 select GENERIC_ALLOCATOR30 select GENERIC_ALLOCATOR
31 select GENERIC_CLOCKEVENTS31 select GENERIC_CLOCKEVENTS
32 select GENERIC_CLOCKEVENTS_BROADCAST if SMP32 select GENERIC_CLOCKEVENTS_BROADCAST
33 select GENERIC_CPU_AUTOPROBE33 select GENERIC_CPU_AUTOPROBE
34 select GENERIC_EARLY_IOREMAP34 select GENERIC_EARLY_IOREMAP
35 select GENERIC_IRQ_PROBE35 select GENERIC_IRQ_PROBE
@@ -54,6 +54,7 @@ config ARM64 · 18 unmodified lines
54 select HAVE_C_RECORDMCOUNT54 select HAVE_C_RECORDMCOUNT
55 select HAVE_CC_STACKPROTECTOR55 select HAVE_CC_STACKPROTECTOR
56 select HAVE_CMPXCHG_DOUBLE56 select HAVE_CMPXCHG_DOUBLE
57 select HAVE_CMPXCHG_LOCAL
57 select HAVE_DEBUG_BUGVERBOSE58 select HAVE_DEBUG_BUGVERBOSE
58 select HAVE_DEBUG_KMEMLEAK59 select HAVE_DEBUG_KMEMLEAK
59 select HAVE_DMA_API_DEBUG60 select HAVE_DMA_API_DEBUG
@@ -105,6 +106,10 @@ config NO_IOPORT_MAP · 45 unmodified lines
105config STACKTRACE_SUPPORT106config STACKTRACE_SUPPORT
106 def_bool y107 def_bool y
107 108
109config ILLEGAL_POINTER_VALUE
110 hex
111 default 0xdead000000000000
112
108config LOCKDEP_SUPPORT113config LOCKDEP_SUPPORT
109 def_bool y114 def_bool y
110 115
@@ -114,6 +119,14 @@ config TRACE_IRQFLAGS_SUPPORT · 3 unmodified lines
114config RWSEM_XCHGADD_ALGORITHM119config RWSEM_XCHGADD_ALGORITHM
115 def_bool y120 def_bool y
116 121
122config GENERIC_BUG
123 def_bool y
124 depends on BUG
125
126config GENERIC_BUG_RELATIVE_POINTERS
127 def_bool y
128 depends on GENERIC_BUG
129
117config GENERIC_HWEIGHT130config GENERIC_HWEIGHT
118 def_bool y131 def_bool y
119 132
@@ -138,6 +151,9 @@ config NEED_DMA_MAP_STATE · 18 unmodified lines
138config NEED_SG_DMA_LENGTH151config NEED_SG_DMA_LENGTH
139 def_bool y152 def_bool y
140 153
154config SMP
155 def_bool y
156
141config SWIOTLB157config SWIOTLB
142 def_bool y158 def_bool y
143 159
@@ -372,22 +388,8 @@ config CPU_BIG_ENDIAN · 228 unmodified lines
372 help388 help
373 Say Y if you plan on running a kernel in big-endian mode.389 Say Y if you plan on running a kernel in big-endian mode.
374 390
375config SMP
376 bool "Symmetric Multi-Processing"
377 help
378 This enables support for systems with more than one CPU. If
379 you say N here, the kernel will run on single and
380 multiprocessor machines, but will use only one CPU of a
381 multiprocessor machine. If you say Y here, the kernel will run
382 on many, but not all, single processor machines. On a single
383 processor machine, the kernel will run faster if you say N
384 here.
385
386 If you don't know what to do here, say N.
387
388config SCHED_MC391config SCHED_MC
389 bool "Multi-core scheduler support"392 bool "Multi-core scheduler support"
390 depends on SMP
391 help393 help
392 Multi-core scheduler support improves the CPU scheduler's decision394 Multi-core scheduler support improves the CPU scheduler's decision
393 making when dealing with multi-core CPU chips at a cost of slightly395 making when dealing with multi-core CPU chips at a cost of slightly
@@ -395,7 +397,6 @@ config SCHED_MC · 1 unmodified line
395 397
396config SCHED_SMT398config SCHED_SMT
397 bool "SMT scheduler support"399 bool "SMT scheduler support"
398 depends on SMP
399 help400 help
400 Improves the CPU scheduler's decision making when dealing with401 Improves the CPU scheduler's decision making when dealing with
401 MultiThreading at a cost of slightly increased overhead in some402 MultiThreading at a cost of slightly increased overhead in some
@@ -404,23 +405,17 @@ config SCHED_SMT · 2 unmodified lines
404config NR_CPUS405config NR_CPUS
405 int "Maximum number of CPUs (2-4096)"406 int "Maximum number of CPUs (2-4096)"
406 range 2 4096407 range 2 4096
407 depends on SMP
408 # These have to remain sorted largest to smallest408 # These have to remain sorted largest to smallest
409 default "64"409 default "64"
410 410
411config HOTPLUG_CPU411config HOTPLUG_CPU
412 bool "Support for hot-pluggable CPUs"412 bool "Support for hot-pluggable CPUs"
413 depends on SMP
414 help413 help
415 Say Y here to experiment with turning CPUs off and on. CPUs414 Say Y here to experiment with turning CPUs off and on. CPUs
416 can be controlled through /sys/devices/system/cpu.415 can be controlled through /sys/devices/system/cpu.
417 416
418source kernel/Kconfig.preempt417source kernel/Kconfig.preempt
419 418
420config UP_LATE_INIT
421 def_bool y
422 depends on !SMP
423
424config HZ419config HZ
425 int420 int
426 default 100421 default 100
@@ -562,6 +557,53 @@ config SETEND_EMULATION · 135 unmodified lines
562 If unsure, say Y557 If unsure, say Y
563endif558endif
564 559
560menu "ARMv8.1 architectural features"
561
562config ARM64_HW_AFDBM
563 bool "Support for hardware updates of the Access and Dirty page flags"
564 default y
565 help
566 The ARMv8.1 architecture extensions introduce support for
567 hardware updates of the access and dirty information in page
568 table entries. When enabled in TCR_EL1 (HA and HD bits) on
569 capable processors, accesses to pages with PTE_AF cleared will
570 set this bit instead of raising an access flag fault.
571 Similarly, writes to read-only pages with the DBM bit set will
572 clear the read-only bit (AP[2]) instead of raising a
573 permission fault.
574
575 Kernels built with this configuration option enabled continue
576 to work on pre-ARMv8.1 hardware and the performance impact is
577 minimal. If unsure, say Y.
578
579config ARM64_PAN
580 bool "Enable support for Privileged Access Never (PAN)"
581 default y
582 help
583 Privileged Access Never (PAN; part of the ARMv8.1 Extensions)
584 prevents the kernel or hypervisor from accessing user-space (EL0)
585 memory directly.
586
587 Choosing this option will cause any unprotected (not using
588 copy_to_user et al) memory access to fail with a permission fault.
589
590 The feature is detected at runtime, and will remain as a 'nop'
591 instruction if the cpu does not implement the feature.
592
593config ARM64_LSE_ATOMICS
594 bool "Atomic instructions"
595 help
596 As part of the Large System Extensions, ARMv8.1 introduces new
597 atomic instructions that are designed specifically to scale in
598 very large systems.
599
600 Say Y here to make use of these instructions for the in-kernel
601 atomic routines. This incurs a small overhead on CPUs that do
602 not support these instructions and requires the kernel to be
603 built with binutils >= 2.25.
604
605endmenu
606
565endmenu607endmenu
566 608
567menu "Boot options"609menu "Boot options"
arch/arm64/Makefile+16−2
@@ -17,7 +17,18 @@ GZFLAGS :=-9 · 16 unmodified lines
17 17
18KBUILD_DEFCONFIG := defconfig18KBUILD_DEFCONFIG := defconfig
19 19
20KBUILD_CFLAGS += -mgeneral-regs-only20# Check for binutils support for specific extensions
21lseinstr := $(call as-instr,.arch_extension lse,-DCONFIG_AS_LSE=1)
22
23ifeq ($(CONFIG_ARM64_LSE_ATOMICS), y)
24 ifeq ($(lseinstr),)
25$(warning LSE atomics not supported by binutils)
26 endif
27endif
28
29KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr)
30KBUILD_AFLAGS += $(lseinstr)
31
21ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)32ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
22KBUILD_CPPFLAGS += -mbig-endian33KBUILD_CPPFLAGS += -mbig-endian
23AS += -EB34AS += -EB
@@ -58,7 +69,10 @@ all: $(KBUILD_IMAGE) $(KBUILD_DTBS) · 34 unmodified lines
58 69
59boot := arch/arm64/boot70boot := arch/arm64/boot
60 71
61Image Image.gz: vmlinux72Image: vmlinux
73 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
74
75Image.%: vmlinux
62 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@76 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
63 77
64zinstall install: vmlinux78zinstall install: vmlinux
arch/arm64/boot/Makefile+12−0
@@ -19,9 +19,21 @@ targets := Image Image.gz · 18 unmodified lines
19$(obj)/Image: vmlinux FORCE19$(obj)/Image: vmlinux FORCE
20 $(call if_changed,objcopy)20 $(call if_changed,objcopy)
21 21
22$(obj)/Image.bz2: $(obj)/Image FORCE
23 $(call if_changed,bzip2)
24
22$(obj)/Image.gz: $(obj)/Image FORCE25$(obj)/Image.gz: $(obj)/Image FORCE
23 $(call if_changed,gzip)26 $(call if_changed,gzip)
24 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)
36
25install: $(obj)/Image37install: $(obj)/Image
26 $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \38 $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
27 $(obj)/Image System.map "$(INSTALL_PATH)"39 $(obj)/Image System.map "$(INSTALL_PATH)"
arch/arm64/include/asm/alternative.h+74−4
@@ -3,6 +3,8 @@ · 2 unmodified lines
3 3
4#ifndef __ASSEMBLY__4#ifndef __ASSEMBLY__
5 5
6#include <linux/init.h>
7#include <linux/kconfig.h>
6#include <linux/types.h>8#include <linux/types.h>
7#include <linux/stddef.h>9#include <linux/stddef.h>
8#include <linux/stringify.h>10#include <linux/stringify.h>
@@ -15,7 +17,7 @@ struct alt_instr { · 6 unmodified lines
15 u8 alt_len; /* size of new instruction(s), <= orig_len */17 u8 alt_len; /* size of new instruction(s), <= orig_len */
16};18};
17 19
18void apply_alternatives_all(void);20void __init apply_alternatives_all(void);
19void apply_alternatives(void *start, size_t length);21void apply_alternatives(void *start, size_t length);
20void free_alternatives_memory(void);22void free_alternatives_memory(void);
21 23
@@ -40,7 +42,8 @@ void free_alternatives_memory(void); · 18 unmodified lines
40 * be fixed in a binutils release posterior to 2.25.51.0.2 (anything42 * be fixed in a binutils release posterior to 2.25.51.0.2 (anything
41 * containing commit 4e4d08cf7399b606 or c1baaddf8861).43 * containing commit 4e4d08cf7399b606 or c1baaddf8861).
42 */44 */
43#define ALTERNATIVE(oldinstr, newinstr, feature) \45#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \
46 ".if "__stringify(cfg_enabled)" == 1\n" \
44 "661:\n\t" \47 "661:\n\t" \
45 oldinstr "\n" \48 oldinstr "\n" \
46 "662:\n" \49 "662:\n" \
@@ -53,7 +56,11 @@ void free_alternatives_memory(void); · 6 unmodified lines
53 "664:\n\t" \56 "664:\n\t" \
54 ".popsection\n\t" \57 ".popsection\n\t" \
55 ".org . - (664b-663b) + (662b-661b)\n\t" \58 ".org . - (664b-663b) + (662b-661b)\n\t" \
56 ".org . - (662b-661b) + (664b-663b)\n"59 ".org . - (662b-661b) + (664b-663b)\n" \
60 ".endif\n"
61
62#define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \
63 __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
57 64
58#else65#else
59 66
@@ -65,7 +72,8 @@ void free_alternatives_memory(void); · 5 unmodified lines
65 .byte \alt_len72 .byte \alt_len
66.endm73.endm
67 74
68.macro alternative_insn insn1 insn2 cap75.macro alternative_insn insn1, insn2, cap, enable = 1
76 .if \enable
69661: \insn177661: \insn1
70662: .pushsection .altinstructions, "a"78662: .pushsection .altinstructions, "a"
71 altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f79 altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
@@ -75,8 +83,70 @@ void free_alternatives_memory(void); · 3 unmodified lines
75664: .popsection83664: .popsection
76 .org . - (664b-663b) + (662b-661b)84 .org . - (664b-663b) + (662b-661b)
77 .org . - (662b-661b) + (664b-663b)85 .org . - (662b-661b) + (664b-663b)
86 .endif
87.endm
88
89/*
90 * Begin an alternative code sequence.
91 *
92 * The code that follows this macro will be assembled and linked as
93 * normal. There are no restrictions on this code.
94 */
95.macro alternative_if_not cap, enable = 1
96 .if \enable
97 .pushsection .altinstructions, "a"
98 altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
99 .popsection
100661:
101 .endif
102.endm
103
104/*
105 * Provide the alternative code sequence.
106 *
107 * The code that follows this macro is assembled into a special
108 * section to be used for dynamic patching. Code that follows this
109 * macro must:
110 *
111 * 1. Be exactly the same length (in bytes) as the default code
112 * sequence.
113 *
114 * 2. Not contain a branch target that is used outside of the
115 * alternative sequence it is defined in (branches into an
116 * alternative sequence are not fixed up).
117 */
118.macro alternative_else, enable = 1
119 .if \enable
120662: .pushsection .altinstr_replacement, "ax"
121663:
122 .endif
78.endm123.endm
79 124
125/*
126 * Complete an alternative code sequence.
127 */
128.macro alternative_endif, enable = 1
129 .if \enable
130664: .popsection
131 .org . - (664b-663b) + (662b-661b)
132 .org . - (662b-661b) + (664b-663b)
133 .endif
134.endm
135
136#define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \
137 alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
138
139
80#endif /* __ASSEMBLY__ */140#endif /* __ASSEMBLY__ */
81 141
142/*
143 * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature));
144 *
145 * Usage: asm(ALTERNATIVE(oldinstr, newinstr, feature, CONFIG_FOO));
146 * N.B. If CONFIG_FOO is specified, but not selected, the whole block
147 * will be omitted, including oldinstr.
148 */
149#define ALTERNATIVE(oldinstr, newinstr, ...) \
150 _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
151
82#endif /* __ASM_ALTERNATIVE_H */152#endif /* __ASM_ALTERNATIVE_H */
arch/arm64/include/asm/assembler.h+0−14
@@ -49,18 +49,6 @@ · 48 unmodified lines
49 msr daifclr, #249 msr daifclr, #2
50 .endm50 .endm
51 51
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/*52/*
65 * Enable and disable debug exceptions.53 * Enable and disable debug exceptions.
66 */54 */
@@ -103,9 +91,7 @@ · 36 unmodified lines
103 * SMP data memory barrier91 * SMP data memory barrier
104 */92 */
105 .macro smp_dmb, opt93 .macro smp_dmb, opt
106#ifdef CONFIG_SMP
107 dmb \opt94 dmb \opt
108#endif
109 .endm95 .endm
110 96
111#define USER(l, x...) \97#define USER(l, x...) \
arch/arm64/include/asm/atomic.h+52−227
@@ -24,247 +24,72 @@ · 23 unmodified lines
24#include <linux/types.h>24#include <linux/types.h>
25 25
26#include <asm/barrier.h>26#include <asm/barrier.h>
27#include <asm/cmpxchg.h>27#include <asm/lse.h>
28
29#define ATOMIC_INIT(i) { (i) }
30 28
31#ifdef __KERNEL__29#ifdef __KERNEL__
32 30
33/*31#define __ARM64_IN_ATOMIC_IMPL
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))
40
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 */
46
47#define ATOMIC_OP(op, asm_op) \
48static inline void atomic_##op(int i, atomic_t *v) \
49{ \
50 unsigned long tmp; \
51 int result; \
52 \
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} \
61
62#define ATOMIC_OP_RETURN(op, asm_op) \
63static 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}
80 32
81#define ATOMIC_OPS(op, asm_op) \33#if defined(CONFIG_ARM64_LSE_ATOMICS) && defined(CONFIG_AS_LSE)
82 ATOMIC_OP(op, asm_op) \34#include <asm/atomic_lse.h>
83 ATOMIC_OP_RETURN(op, asm_op)35#else
84 36#include <asm/atomic_ll_sc.h>
85ATOMIC_OPS(add, add)37#endif
86ATOMIC_OPS(sub, sub)
87
88#define atomic_andnot atomic_andnot
89
90ATOMIC_OP(and, and)
91ATOMIC_OP(andnot, bic)
92ATOMIC_OP(or, orr)
93ATOMIC_OP(xor, eor)
94
95#undef ATOMIC_OPS
96#undef ATOMIC_OP_RETURN
97#undef ATOMIC_OP
98
99static 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 38
123static inline int __atomic_add_unless(atomic_t *v, int a, int u)39#undef __ARM64_IN_ATOMIC_IMPL
124{
125 int c, old;
126 40
127 c = atomic_read(v);41#include <asm/cmpxchg.h>
128 while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
129 c = old;
130 return c;
131}
132 42
133#define atomic_inc(v) atomic_add(1, v)43#define ___atomic_add_unless(v, a, u, sfx) \
134#define atomic_dec(v) atomic_sub(1, v)44({ \
45 typeof((v)->counter) c, old; \
46 \
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 })
135 53
136#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)54#define ATOMIC_INIT(i) { (i) }
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 55
142#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)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))
60
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 * 64-bit atomic operations.73 * 64-bit atomic operations.
146 */74 */
147#define ATOMIC64_INIT(i) { (i) }75#define ATOMIC64_INIT ATOMIC_INIT
148 76#define atomic64_read atomic_read
149#define atomic64_read(v) ACCESS_ONCE((v)->counter)77#define atomic64_set atomic_set
150#define atomic64_set(v,i) (((v)->counter) = (i))78#define atomic64_xchg atomic_xchg
151 79#define atomic64_cmpxchg atomic_cmpxchg
152#define ATOMIC64_OP(op, asm_op) \80
153static inline void atomic64_##op(long i, atomic64_t *v) \81#define atomic64_inc(v) atomic64_add(1, (v))
154{ \82#define atomic64_dec(v) atomic64_sub(1, (v))
155 long result; \83#define atomic64_inc_return(v) atomic64_add_return(1, (v))
156 unsigned long tmp; \84#define atomic64_dec_return(v) atomic64_sub_return(1, (v))
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) \
168static 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
190ATOMIC64_OPS(add, add)
191ATOMIC64_OPS(sub, sub)
192
193#define atomic64_andnot atomic64_andnot
194
195ATOMIC64_OP(and, and)
196ATOMIC64_OP(andnot, bic)
197ATOMIC64_OP(or, orr)
198ATOMIC64_OP(xor, eor)
199
200#undef ATOMIC64_OPS
201#undef ATOMIC64_OP_RETURN
202#undef ATOMIC64_OP
203
204static 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
228static 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
248static 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))
262#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)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)86#define atomic64_dec_and_test(v) (atomic64_dec_return(v) == 0)
264#define atomic64_dec(v) atomic64_sub(1LL, (v))87#define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0)
265#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))88#define atomic64_add_negative(i, v) (atomic64_add_return((i), (v)) < 0)
266#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)89#define atomic64_add_unless(v, a, u) (___atomic_add_unless(v, a, u, 64) != u)
267#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)90#define atomic64_andnot atomic64_andnot
91
92#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
268 93
269#endif94#endif
270#endif95#endif
arch/arm64/include/asm/atomic_ll_sc.h+247−0
@@ -0,0 +1,247 @@
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
84ATOMIC_OPS(add, add)
85ATOMIC_OPS(sub, sub)
86
87ATOMIC_OP(and, and)
88ATOMIC_OP(andnot, bic)
89ATOMIC_OP(or, orr)
90ATOMIC_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
140ATOMIC64_OPS(add, add)
141ATOMIC64_OPS(sub, sub)
142
143ATOMIC64_OP(and, and)
144ATOMIC64_OP(andnot, bic)
145ATOMIC64_OP(or, orr)
146ATOMIC64_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 */
arch/arm64/include/asm/atomic_lse.h+391−0
@@ -0,0 +1,391 @@
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
30static 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
42static 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
54static 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
66static 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
78static 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
97static 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
114static 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
131static 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
156static 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
168static 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
180static 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
192static 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
204static 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
223static 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
240static 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
257static 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
278static 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...) \
312static 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...) \
351static 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 */
arch/arm64/include/asm/barrier.h+0−24
@@ -35,28 +35,6 @@ · 34 unmodified lines
35#define dma_rmb() dmb(oshld)35#define dma_rmb() dmb(oshld)
36#define dma_wmb() dmb(oshst)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) \
44do { \
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#define smp_mb() dmb(ish)38#define smp_mb() dmb(ish)
61#define smp_rmb() dmb(ishld)39#define smp_rmb() dmb(ishld)
62#define smp_wmb() dmb(ishst)40#define smp_wmb() dmb(ishst)
@@ -109,8 +87,6 @@ do { \ · 46 unmodified lines
109 ___p1; \87 ___p1; \
110})88})
111 89
112#endif
113
114#define read_barrier_depends() do { } while(0)90#define read_barrier_depends() do { } while(0)
115#define smp_read_barrier_depends() do { } while(0)91#define smp_read_barrier_depends() do { } while(0)
116 92
arch/arm64/include/asm/bug.h+64−0
@@ -0,0 +1,64 @@
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 */
arch/arm64/include/asm/cmpxchg.h+74−118
@@ -21,7 +21,9 @@ · 20 unmodified lines
21#include <linux/bug.h>21#include <linux/bug.h>
22#include <linux/mmdebug.h>22#include <linux/mmdebug.h>
23 23
24#include <asm/atomic.h>
24#include <asm/barrier.h>25#include <asm/barrier.h>
26#include <asm/lse.h>
25 27
26static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)28static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
27{29{
@@ -29,37 +31,73 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 1 unmodified line
29 31
30 switch (size) {32 switch (size) {
31 case 1:33 case 1:
32 asm volatile("// __xchg1\n"34 asm volatile(ARM64_LSE_ATOMIC_INSN(
35 /* LL/SC */
36 " prfm pstl1strm, %2\n"
33 "1: ldxrb %w0, %2\n"37 "1: ldxrb %w0, %2\n"
34 " stlxrb %w1, %w3, %2\n"38 " stlxrb %w1, %w3, %2\n"
35 " cbnz %w1, 1b\n"39 " cbnz %w1, 1b\n"
40 " dmb ish",
41 /* LSE atomics */
42 " nop\n"
43 " nop\n"
44 " swpalb %w3, %w0, %2\n"
45 " nop\n"
46 " nop")
36 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)47 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
37 : "r" (x)48 : "r" (x)
38 : "memory");49 : "memory");
39 break;50 break;
40 case 2:51 case 2:
41 asm volatile("// __xchg2\n"52 asm volatile(ARM64_LSE_ATOMIC_INSN(
53 /* LL/SC */
54 " prfm pstl1strm, %2\n"
42 "1: ldxrh %w0, %2\n"55 "1: ldxrh %w0, %2\n"
43 " stlxrh %w1, %w3, %2\n"56 " stlxrh %w1, %w3, %2\n"
44 " cbnz %w1, 1b\n"57 " cbnz %w1, 1b\n"
58 " dmb ish",
59 /* LSE atomics */
60 " nop\n"
61 " nop\n"
62 " swpalh %w3, %w0, %2\n"
63 " nop\n"
64 " nop")
45 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)65 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
46 : "r" (x)66 : "r" (x)
47 : "memory");67 : "memory");
48 break;68 break;
49 case 4:69 case 4:
50 asm volatile("// __xchg4\n"70 asm volatile(ARM64_LSE_ATOMIC_INSN(
71 /* LL/SC */
72 " prfm pstl1strm, %2\n"
51 "1: ldxr %w0, %2\n"73 "1: ldxr %w0, %2\n"
52 " stlxr %w1, %w3, %2\n"74 " stlxr %w1, %w3, %2\n"
53 " cbnz %w1, 1b\n"75 " cbnz %w1, 1b\n"
76 " dmb ish",
77 /* LSE atomics */
78 " nop\n"
79 " nop\n"
80 " swpal %w3, %w0, %2\n"
81 " nop\n"
82 " nop")
54 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)83 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
55 : "r" (x)84 : "r" (x)
56 : "memory");85 : "memory");
57 break;86 break;
58 case 8:87 case 8:
59 asm volatile("// __xchg8\n"88 asm volatile(ARM64_LSE_ATOMIC_INSN(
89 /* LL/SC */
90 " prfm pstl1strm, %2\n"
60 "1: ldxr %0, %2\n"91 "1: ldxr %0, %2\n"
61 " stlxr %w1, %3, %2\n"92 " stlxr %w1, %3, %2\n"
62 " cbnz %w1, 1b\n"93 " cbnz %w1, 1b\n"
94 " dmb ish",
95 /* LSE atomics */
96 " nop\n"
97 " nop\n"
98 " swpal %3, %0, %2\n"
99 " nop\n"
100 " nop")
63 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)101 : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
64 : "r" (x)102 : "r" (x)
65 : "memory");103 : "memory");
@@ -68,7 +106,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 2 unmodified lines
68 BUILD_BUG();106 BUILD_BUG();
69 }107 }
70 108
71 smp_mb();
72 return ret;109 return ret;
73}110}
74 111
@@ -83,131 +120,39 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 8 unmodified lines
83static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,120static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
84 unsigned long new, int size)121 unsigned long new, int size)
85{122{
86 unsigned long oldval = 0, res;
87
88 switch (size) {123 switch (size) {
89 case 1:124 case 1:
90 do {125 return __cmpxchg_case_1(ptr, (u8)old, new);
91 asm volatile("// __cmpxchg1\n"
92 " ldxrb %w1, %2\n"
93 " mov %w0, #0\n"
94 " cmp %w1, %w3\n"
95 " b.ne 1f\n"
96 " stxrb %w0, %w4, %2\n"
97 "1:\n"
98 : "=&r" (res), "=&r" (oldval), "+Q" (*(u8 *)ptr)
99 : "Ir" (old), "r" (new)
100 : "cc");
101 } while (res);
102 break;
103
104 case 2:126 case 2:
105 do {127 return __cmpxchg_case_2(ptr, (u16)old, new);
106 asm volatile("// __cmpxchg2\n"
107 " ldxrh %w1, %2\n"
108 " mov %w0, #0\n"
109 " cmp %w1, %w3\n"
110 " b.ne 1f\n"
111 " stxrh %w0, %w4, %2\n"
112 "1:\n"
113 : "=&r" (res), "=&r" (oldval), "+Q" (*(u16 *)ptr)
114 : "Ir" (old), "r" (new)
115 : "cc");
116 } while (res);
117 break;
118
119 case 4:128 case 4:
120 do {129 return __cmpxchg_case_4(ptr, old, new);
121 asm volatile("// __cmpxchg4\n"
122 " ldxr %w1, %2\n"
123 " mov %w0, #0\n"
124 " cmp %w1, %w3\n"
125 " b.ne 1f\n"
126 " stxr %w0, %w4, %2\n"
127 "1:\n"
128 : "=&r" (res), "=&r" (oldval), "+Q" (*(u32 *)ptr)
129 : "Ir" (old), "r" (new)
130 : "cc");
131 } while (res);
132 break;
133
134 case 8:130 case 8:
135 do {131 return __cmpxchg_case_8(ptr, old, new);
136 asm volatile("// __cmpxchg8\n"
137 " ldxr %1, %2\n"
138 " mov %w0, #0\n"
139 " cmp %1, %3\n"
140 " b.ne 1f\n"
141 " stxr %w0, %4, %2\n"
142 "1:\n"
143 : "=&r" (res), "=&r" (oldval), "+Q" (*(u64 *)ptr)
144 : "Ir" (old), "r" (new)
145 : "cc");
146 } while (res);
147 break;
148
149 default:132 default:
150 BUILD_BUG();133 BUILD_BUG();
151 }134 }
152 135
153 return oldval;136 unreachable();
154}137}
155 138
156#define system_has_cmpxchg_double() 1139static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
157 140 unsigned long new, int size)
158static inline int __cmpxchg_double(volatile void *ptr1, volatile void *ptr2,
159 unsigned long old1, unsigned long old2,
160 unsigned long new1, unsigned long new2, int size)
161{141{
162 unsigned long loop, lost;
163
164 switch (size) {142 switch (size) {
143 case 1:
144 return __cmpxchg_case_mb_1(ptr, (u8)old, new);
145 case 2:
146 return __cmpxchg_case_mb_2(ptr, (u16)old, new);
147 case 4:
148 return __cmpxchg_case_mb_4(ptr, old, new);
165 case 8:149 case 8:
166 VM_BUG_ON((unsigned long *)ptr2 - (unsigned long *)ptr1 != 1);150 return __cmpxchg_case_mb_8(ptr, old, new);
167 do {
168 asm volatile("// __cmpxchg_double8\n"
169 " ldxp %0, %1, %2\n"
170 " eor %0, %0, %3\n"
171 " eor %1, %1, %4\n"
172 " orr %1, %0, %1\n"
173 " mov %w0, #0\n"
174 " cbnz %1, 1f\n"
175 " stxp %w0, %5, %6, %2\n"
176 "1:\n"
177 : "=&r"(loop), "=&r"(lost), "+Q" (*(u64 *)ptr1)
178 : "r" (old1), "r"(old2), "r"(new1), "r"(new2));
179 } while (loop);
180 break;
181 default:151 default:
182 BUILD_BUG();152 BUILD_BUG();
183 }153 }
184 154
185 return !lost;155 unreachable();
186}
187
188static inline int __cmpxchg_double_mb(volatile void *ptr1, volatile void *ptr2,
189 unsigned long old1, unsigned long old2,
190 unsigned long new1, unsigned long new2, int size)
191{
192 int ret;
193
194 smp_mb();
195 ret = __cmpxchg_double(ptr1, ptr2, old1, old2, new1, new2, size);
196 smp_mb();
197
198 return ret;
199}
200
201static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
202 unsigned long new, int size)
203{
204 unsigned long ret;
205
206 smp_mb();
207 ret = __cmpxchg(ptr, old, new, size);
208 smp_mb();
209
210 return ret;
211}156}
212 157
213#define cmpxchg(ptr, o, n) \158#define cmpxchg(ptr, o, n) \
@@ -228,21 +173,32 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, · 14 unmodified lines
228 __ret; \173 __ret; \
229})174})
230 175
176#define system_has_cmpxchg_double() 1
177
178#define __cmpxchg_double_check(ptr1, ptr2) \
179({ \
180 if (sizeof(*(ptr1)) != 8) \
181 BUILD_BUG(); \
182 VM_BUG_ON((unsigned long *)(ptr2) - (unsigned long *)(ptr1) != 1); \
183})
184
231#define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \185#define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \
232({\186({\
233 int __ret;\187 int __ret;\
234 __ret = __cmpxchg_double_mb((ptr1), (ptr2), (unsigned long)(o1), \188 __cmpxchg_double_check(ptr1, ptr2); \
235 (unsigned long)(o2), (unsigned long)(n1), \189 __ret = !__cmpxchg_double_mb((unsigned long)(o1), (unsigned long)(o2), \
236 (unsigned long)(n2), sizeof(*(ptr1)));\190 (unsigned long)(n1), (unsigned long)(n2), \
191 ptr1); \
237 __ret; \192 __ret; \
238})193})
239 194
240#define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \195#define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \
241({\196({\
242 int __ret;\197 int __ret;\
243 __ret = __cmpxchg_double((ptr1), (ptr2), (unsigned long)(o1), \198 __cmpxchg_double_check(ptr1, ptr2); \
244 (unsigned long)(o2), (unsigned long)(n1), \199 __ret = !__cmpxchg_double((unsigned long)(o1), (unsigned long)(o2), \
245 (unsigned long)(n2), sizeof(*(ptr1)));\200 (unsigned long)(n1), (unsigned long)(n2), \
201 ptr1); \
246 __ret; \202 __ret; \
247})203})
248 204
arch/arm64/include/asm/cpufeature.h+15−3
@@ -25,15 +25,20 @@ · 24 unmodified lines
25#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 125#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1
26#define ARM64_WORKAROUND_845719 226#define ARM64_WORKAROUND_845719 2
27#define ARM64_HAS_SYSREG_GIC_CPUIF 327#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 431#define ARM64_NCAPS 6
30 32
31#ifndef __ASSEMBLY__33#ifndef __ASSEMBLY__
32 34
35#include <linux/kernel.h>
36
33struct arm64_cpu_capabilities {37struct arm64_cpu_capabilities {
34 const char *desc;38 const char *desc;
35 u16 capability;39 u16 capability;
36 bool (*matches)(const struct arm64_cpu_capabilities *);40 bool (*matches)(const struct arm64_cpu_capabilities *);
41 void (*enable)(void);
37 union {42 union {
38 struct { /* To be used for erratum handling only */43 struct { /* To be used for erratum handling only */
39 u32 midr_model;44 u32 midr_model;
@@ -41,8 +46,8 @@ struct arm64_cpu_capabilities { · 1 unmodified line
41 };46 };
42 47
43 struct { /* Feature register checking */48 struct { /* Feature register checking */
44 u64 register_mask;49 int field_pos;
45 u64 register_value;50 int min_field_value;
46 };51 };
47 };52 };
48};53};
@@ -70,6 +75,13 @@ static inline void cpus_set_cap(unsigned int num) · 21 unmodified lines
70 __set_bit(num, cpu_hwcaps);75 __set_bit(num, cpu_hwcaps);
71}76}
72 77
78static inline int __attribute_const__ cpuid_feature_extract_field(u64 features,
79 int field)
80{
81 return (s64)(features << (64 - 4 - field)) >> (64 - 4);
82}
83
84
73void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps,85void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
74 const char *info);86 const char *info);
75void check_local_cpu_errata(void);87void check_local_cpu_errata(void);
arch/arm64/include/asm/cputype.h+0−3
@@ -81,9 +81,6 @@ · 80 unmodified lines
81#define ID_AA64MMFR0_BIGEND(mmfr0) \81#define ID_AA64MMFR0_BIGEND(mmfr0) \
82 (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT)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#ifndef __ASSEMBLY__84#ifndef __ASSEMBLY__
88 85
89/*86/*
arch/arm64/include/asm/debug-monitors.h+16−28
@@ -18,6 +18,12 @@ · 17 unmodified lines
18 18
19#ifdef __KERNEL__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/* Low-level stepping controls. */27/* Low-level stepping controls. */
22#define DBG_MDSCR_SS (1 << 0)28#define DBG_MDSCR_SS (1 << 0)
23#define DBG_SPSR_SS (1 << 21)29#define DBG_SPSR_SS (1 << 21)
@@ -38,12 +44,7 @@ · 14 unmodified lines
38/*44/*
39 * Break point instruction encoding45 * Break point instruction encoding
40 */46 */
41#define BREAK_INSTR_SIZE 447#define BREAK_INSTR_SIZE AARCH64_INSN_SIZE
42
43/*
44 * ESR values expected for dynamic and compile time BRK instruction
45 */
46#define DBG_ESR_VAL_BRK(x) (0xf2000000 | ((x) & 0xfffff))
47 48
48/*49/*
49 * #imm16 values used for BRK instruction generation50 * #imm16 values used for BRK instruction generation
@@ -51,10 +52,12 @@ · 1 unmodified line
51 * 0x100: for triggering a fault on purpose (reserved)52 * 0x100: for triggering a fault on purpose (reserved)
52 * 0x400: for dynamic BRK instruction53 * 0x400: for dynamic BRK instruction
53 * 0x401: for compile time BRK instruction54 * 0x401: for compile time BRK instruction
55 * 0x800: kernel-mode BUG() and WARN() traps
54 */56 */
55#define FAULT_BRK_IMM 0x10057#define FAULT_BRK_IMM 0x100
56#define KGDB_DYN_DBG_BRK_IMM 0x40058#define KGDB_DYN_DBG_BRK_IMM 0x400
57#define KGDB_COMPILED_DBG_BRK_IMM 0x40159#define KGDB_COMPILED_DBG_BRK_IMM 0x401
60#define BUG_BRK_IMM 0x800
58 61
59/*62/*
60 * BRK instruction encoding63 * BRK instruction encoding
@@ -68,25 +71,10 @@ · 7 unmodified lines
68 */71 */
69#define AARCH64_BREAK_FAULT (AARCH64_BREAK_MON | (FAULT_BRK_IMM << 5))72#define AARCH64_BREAK_FAULT (AARCH64_BREAK_MON | (FAULT_BRK_IMM << 5))
70 73
71/*74#define AARCH64_BREAK_KGDB_DYN_DBG \
72 * Extract byte from BRK instruction75 (AARCH64_BREAK_MON | (KGDB_DYN_DBG_BRK_IMM << 5))
73 */76#define KGDB_DYN_BRK_INS_BYTE(x) \
74#define KGDB_DYN_DBG_BRK_INS_BYTE(x) \77 ((AARCH64_BREAK_KGDB_DYN_DBG >> (8 * (x))) & 0xff)
75 ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff)
76
77/*
78 * Extract byte from BRK #imm16
79 */
80#define KGBD_DYN_DBG_BRK_IMM_BYTE(x) \
81 (((((KGDB_DYN_DBG_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff)
82
83#define KGDB_DYN_DBG_BRK_BYTE(x) \
84 (KGDB_DYN_DBG_BRK_INS_BYTE(x) | KGBD_DYN_DBG_BRK_IMM_BYTE(x))
85
86#define KGDB_DYN_BRK_INS_BYTE0 KGDB_DYN_DBG_BRK_BYTE(0)
87#define KGDB_DYN_BRK_INS_BYTE1 KGDB_DYN_DBG_BRK_BYTE(1)
88#define KGDB_DYN_BRK_INS_BYTE2 KGDB_DYN_DBG_BRK_BYTE(2)
89#define KGDB_DYN_BRK_INS_BYTE3 KGDB_DYN_DBG_BRK_BYTE(3)
90 78
91#define CACHE_FLUSH_IS_SAFE 179#define CACHE_FLUSH_IS_SAFE 1
92 80
@@ -127,13 +115,13 @@ void unregister_break_hook(struct break_hook *hook); · 34 unmodified lines
127 115
128u8 debug_monitors_arch(void);116u8 debug_monitors_arch(void);
129 117
130enum debug_el {118enum dbg_active_el {
131 DBG_ACTIVE_EL0 = 0,119 DBG_ACTIVE_EL0 = 0,
132 DBG_ACTIVE_EL1,120 DBG_ACTIVE_EL1,
133};121};
134 122
135void enable_debug_monitors(enum debug_el el);123void enable_debug_monitors(enum dbg_active_el el);
136void disable_debug_monitors(enum debug_el el);124void disable_debug_monitors(enum dbg_active_el el);
137 125
138void user_rewind_single_step(struct task_struct *task);126void user_rewind_single_step(struct task_struct *task);
139void user_fastforward_single_step(struct task_struct *task);127void user_fastforward_single_step(struct task_struct *task);
arch/arm64/include/asm/esr.h+9−0
@@ -18,6 +18,8 @@ · 17 unmodified lines
18#ifndef __ASM_ESR_H18#ifndef __ASM_ESR_H
19#define __ASM_ESR_H19#define __ASM_ESR_H
20 20
21#include <asm/memory.h>
22
21#define ESR_ELx_EC_UNKNOWN (0x00)23#define ESR_ELx_EC_UNKNOWN (0x00)
22#define ESR_ELx_EC_WFx (0x01)24#define ESR_ELx_EC_WFx (0x01)
23/* Unallocated EC: 0x02 */25/* Unallocated EC: 0x02 */
@@ -99,6 +101,13 @@ · 75 unmodified lines
99#define ESR_ELx_WFx_ISS_WFE (UL(1) << 0)101#define ESR_ELx_WFx_ISS_WFE (UL(1) << 0)
100#define ESR_ELx_xVC_IMM_MASK ((1UL << 16) - 1)102#define ESR_ELx_xVC_IMM_MASK ((1UL << 16) - 1)
101 103
104/* ESR value templates for specific events */
105
106/* BRK instruction trap from AArch64 state */
107#define ESR_ELx_VAL_BRK64(imm) \
108 ((ESR_ELx_EC_BRK64 << ESR_ELx_EC_SHIFT) | ESR_ELx_IL | \
109 ((imm) & 0xffff))
110
102#ifndef __ASSEMBLY__111#ifndef __ASSEMBLY__
103#include <asm/types.h>112#include <asm/types.h>
104 113
arch/arm64/include/asm/exception.h+6−0
@@ -18,7 +18,13 @@ · 17 unmodified lines
18#ifndef __ASM_EXCEPTION_H18#ifndef __ASM_EXCEPTION_H
19#define __ASM_EXCEPTION_H19#define __ASM_EXCEPTION_H
20 20
21#include <linux/ftrace.h>
22
21#define __exception __attribute__((section(".exception.text")))23#define __exception __attribute__((section(".exception.text")))
24#ifdef CONFIG_FUNCTION_GRAPH_TRACER
25#define __exception_irq_entry __irq_entry
26#else
22#define __exception_irq_entry __exception27#define __exception_irq_entry __exception
28#endif
23 29
24#endif /* __ASM_EXCEPTION_H */30#endif /* __ASM_EXCEPTION_H */
arch/arm64/include/asm/fixmap.h+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
8 * Copyright (C) 1998 Ingo Molnar8 * Copyright (C) 1998 Ingo Molnar
9 * Copyright (C) 2013 Mark Salter <msalter@redhat.com>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
arch/arm64/include/asm/futex.h+10−0
@@ -20,10 +20,17 @@ · 19 unmodified lines
20 20
21#include <linux/futex.h>21#include <linux/futex.h>
22#include <linux/uaccess.h>22#include <linux/uaccess.h>
23
24#include <asm/alternative.h>
25#include <asm/cpufeature.h>
23#include <asm/errno.h>26#include <asm/errno.h>
27#include <asm/sysreg.h>
24 28
25#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \29#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \
26 asm volatile( \30 asm volatile( \
31 ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
32 CONFIG_ARM64_PAN) \
33" prfm pstl1strm, %2\n" \
27"1: ldxr %w1, %2\n" \34"1: ldxr %w1, %2\n" \
28 insn "\n" \35 insn "\n" \
29"2: stlxr %w3, %w0, %2\n" \36"2: stlxr %w3, %w0, %2\n" \
@@ -39,6 +46,8 @@ · 9 unmodified lines
39" .align 3\n" \46" .align 3\n" \
40" .quad 1b, 4b, 2b, 4b\n" \47" .quad 1b, 4b, 2b, 4b\n" \
41" .popsection\n" \48" .popsection\n" \
49 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
50 CONFIG_ARM64_PAN) \
42 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \51 : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \
43 : "r" (oparg), "Ir" (-EFAULT) \52 : "r" (oparg), "Ir" (-EFAULT) \
44 : "memory")53 : "memory")
@@ -112,6 +121,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, · 67 unmodified lines
112 return -EFAULT;121 return -EFAULT;
113 122
114 asm volatile("// futex_atomic_cmpxchg_inatomic\n"123 asm volatile("// futex_atomic_cmpxchg_inatomic\n"
124" prfm pstl1strm, %2\n"
115"1: ldxr %w1, %2\n"125"1: ldxr %w1, %2\n"
116" sub %w3, %w1, %w4\n"126" sub %w3, %w1, %w4\n"
117" cbnz %w3, 3f\n"127" cbnz %w3, 3f\n"
arch/arm64/include/asm/hardirq.h+0−4
@@ -24,9 +24,7 @@ · 23 unmodified lines
24 24
25typedef struct {25typedef struct {
26 unsigned int __softirq_pending;26 unsigned int __softirq_pending;
27#ifdef CONFIG_SMP
28 unsigned int ipi_irqs[NR_IPI];27 unsigned int ipi_irqs[NR_IPI];
29#endif
30} ____cacheline_aligned irq_cpustat_t;28} ____cacheline_aligned irq_cpustat_t;
31 29
32#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */30#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
@@ -34,10 +32,8 @@ typedef struct { · 1 unmodified line
34#define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++32#define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++
35#define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member)33#define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member)
36 34
37#ifdef CONFIG_SMP
38u64 smp_irq_stat_cpu(unsigned int cpu);35u64 smp_irq_stat_cpu(unsigned int cpu);
39#define arch_irq_stat_cpu smp_irq_stat_cpu36#define arch_irq_stat_cpu smp_irq_stat_cpu
40#endif
41 37
42#define __ARCH_IRQ_EXIT_IRQS_DISABLED 138#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
43 39
arch/arm64/include/asm/hugetlb.h+0−4
@@ -13,10 +13,6 @@ · 12 unmodified lines
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.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#ifndef __ASM_HUGETLB_H18#ifndef __ASM_HUGETLB_H
arch/arm64/include/asm/irq_work.h+0−11
@@ -1,8 +1,6 @@
1#ifndef __ASM_IRQ_WORK_H1#ifndef __ASM_IRQ_WORK_H
2#define __ASM_IRQ_WORK_H2#define __ASM_IRQ_WORK_H
3 3
4#ifdef CONFIG_SMP
5
6#include <asm/smp.h>4#include <asm/smp.h>
7 5
8static inline bool arch_irq_work_has_interrupt(void)6static inline bool arch_irq_work_has_interrupt(void)
@@ -10,13 +8,4 @@ static inline bool arch_irq_work_has_interrupt(void) · 1 unmodified line
10 return !!__smp_cross_call;8 return !!__smp_cross_call;
11}9}
12 10
13#else
14
15static inline bool arch_irq_work_has_interrupt(void)
16{
17 return false;
18}
19
20#endif
21
22#endif /* __ASM_IRQ_WORK_H */11#endif /* __ASM_IRQ_WORK_H */
arch/arm64/include/asm/lse.h+53−0
@@ -0,0 +1,53 @@
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 */
arch/arm64/include/asm/memory.h+8−0
@@ -113,6 +113,14 @@ extern phys_addr_t memstart_addr; · 112 unmodified lines
113/* PHYS_OFFSET - the physical address of the start of memory. */113/* PHYS_OFFSET - the physical address of the start of memory. */
114#define PHYS_OFFSET ({ memstart_addr; })114#define PHYS_OFFSET ({ memstart_addr; })
115 115
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
116/*124/*
117 * PFNs are used to describe any physical page; this means125 * PFNs are used to describe any physical page; this means
118 * PFN 0 == physical address 0.126 * PFN 0 == physical address 0.
arch/arm64/include/asm/mmu.h+0−1
@@ -28,7 +28,6 @@ typedef struct { · 27 unmodified lines
28#define ASID(mm) ((mm)->context.id & 0xffff)28#define ASID(mm) ((mm)->context.id & 0xffff)
29 29
30extern void paging_init(void);30extern void paging_init(void);
31extern void setup_mm_for_reboot(void);
32extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);31extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
33extern void init_mem_pgprot(void);32extern void init_mem_pgprot(void);
34extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,33extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
arch/arm64/include/asm/percpu.h+0−8
@@ -16,8 +16,6 @@ · 15 unmodified lines
16#ifndef __ASM_PERCPU_H16#ifndef __ASM_PERCPU_H
17#define __ASM_PERCPU_H17#define __ASM_PERCPU_H
18 18
19#ifdef CONFIG_SMP
20
21static inline void set_my_cpu_offset(unsigned long off)19static inline void set_my_cpu_offset(unsigned long off)
22{20{
23 asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");21 asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
@@ -38,12 +36,6 @@ static inline unsigned long __my_cpu_offset(void) · 14 unmodified lines
38}36}
39#define __my_cpu_offset __my_cpu_offset()37#define __my_cpu_offset __my_cpu_offset()
40 38
41#else /* !CONFIG_SMP */
42
43#define set_my_cpu_offset(x) do { } while (0)
44
45#endif /* CONFIG_SMP */
46
47#define PERCPU_OP(op, asm_op) \39#define PERCPU_OP(op, asm_op) \
48static inline unsigned long __percpu_##op(void *ptr, \40static inline unsigned long __percpu_##op(void *ptr, \
49 unsigned long val, int size) \41 unsigned long val, int size) \
arch/arm64/include/asm/perf_event.h+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
17#ifndef __ASM_PERF_EVENT_H17#ifndef __ASM_PERF_EVENT_H
18#define __ASM_PERF_EVENT_H18#define __ASM_PERF_EVENT_H
19 19
20#ifdef CONFIG_HW_PERF_EVENTS20#ifdef CONFIG_PERF_EVENTS
21struct pt_regs;21struct pt_regs;
22extern unsigned long perf_instruction_pointer(struct pt_regs *regs);22extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
23extern unsigned long perf_misc_flags(struct pt_regs *regs);23extern unsigned long perf_misc_flags(struct pt_regs *regs);
arch/arm64/include/asm/pgtable-hwdef.h+3−0
@@ -104,6 +104,7 @@ · 103 unmodified lines
104#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */104#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
105#define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */105#define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */
106#define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */106#define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */
107#define PTE_DBM (_AT(pteval_t, 1) << 51) /* Dirty Bit Management */
107#define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */108#define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */
108#define PTE_UXN (_AT(pteval_t, 1) << 54) /* User XN */109#define PTE_UXN (_AT(pteval_t, 1) << 54) /* User XN */
109 110
@@ -168,5 +169,7 @@ · 58 unmodified lines
168#define TCR_TG1_64K (UL(3) << 30)169#define TCR_TG1_64K (UL(3) << 30)
169#define TCR_ASID16 (UL(1) << 36)170#define TCR_ASID16 (UL(1) << 36)
170#define TCR_TBI0 (UL(1) << 37)171#define TCR_TBI0 (UL(1) << 37)
172#define TCR_HA (UL(1) << 39)
173#define TCR_HD (UL(1) << 40)
171 174
172#endif175#endif
arch/arm64/include/asm/pgtable.h+160−7
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#ifndef __ASM_PGTABLE_H16#ifndef __ASM_PGTABLE_H
17#define __ASM_PGTABLE_H17#define __ASM_PGTABLE_H
18 18
19#include <asm/bug.h>
19#include <asm/proc-fns.h>20#include <asm/proc-fns.h>
20 21
21#include <asm/memory.h>22#include <asm/memory.h>
@@ -27,7 +28,11 @@ · 5 unmodified lines
27#define PTE_VALID (_AT(pteval_t, 1) << 0)28#define PTE_VALID (_AT(pteval_t, 1) << 0)
28#define PTE_DIRTY (_AT(pteval_t, 1) << 55)29#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
29#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)30#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
31#ifdef CONFIG_ARM64_HW_AFDBM
32#define PTE_WRITE (PTE_DBM) /* same as DBM */
33#else
30#define PTE_WRITE (_AT(pteval_t, 1) << 57)34#define PTE_WRITE (_AT(pteval_t, 1) << 57)
35#endif
31#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */36#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
32 37
33/*38/*
@@ -48,18 +53,16 @@ · 14 unmodified lines
48#define FIRST_USER_ADDRESS 0UL53#define FIRST_USER_ADDRESS 0UL
49 54
50#ifndef __ASSEMBLY__55#ifndef __ASSEMBLY__
56
57#include <linux/mmdebug.h>
58
51extern void __pte_error(const char *file, int line, unsigned long val);59extern void __pte_error(const char *file, int line, unsigned long val);
52extern void __pmd_error(const char *file, int line, unsigned long val);60extern void __pmd_error(const char *file, int line, unsigned long val);
53extern void __pud_error(const char *file, int line, unsigned long val);61extern void __pud_error(const char *file, int line, unsigned long val);
54extern void __pgd_error(const char *file, int line, unsigned long val);62extern void __pgd_error(const char *file, int line, unsigned long val);
55 63
56#ifdef CONFIG_SMP
57#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)64#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
58#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)65#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
59#else
60#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF)
61#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF)
62#endif
63 66
64#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))67#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
65#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))68#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
@@ -137,12 +140,20 @@ extern struct page *empty_zero_page; · 71 unmodified lines
137 * The following only work if pte_present(). Undefined behaviour otherwise.140 * The following only work if pte_present(). Undefined behaviour otherwise.
138 */141 */
139#define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))142#define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
140#define pte_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY))
141#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))143#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
142#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))144#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
143#define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))145#define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
144#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))146#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))
145 147
148#ifdef CONFIG_ARM64_HW_AFDBM
149#define pte_hw_dirty(pte) (!(pte_val(pte) & PTE_RDONLY))
150#else
151#define pte_hw_dirty(pte) (0)
152#endif
153#define pte_sw_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY))
154#define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte))
155
156#define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID))
146#define pte_valid_user(pte) \157#define pte_valid_user(pte) \
147 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))158 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
148#define pte_valid_not_user(pte) \159#define pte_valid_not_user(pte) \
@@ -209,20 +220,49 @@ static inline void set_pte(pte_t *ptep, pte_t pte) · 60 unmodified lines
209 }220 }
210}221}
211 222
223struct mm_struct;
224struct vm_area_struct;
225
212extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);226extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
213 227
228/*
229 * PTE bits configuration in the presence of hardware Dirty Bit Management
230 * (PTE_WRITE == PTE_DBM):
231 *
232 * Dirty Writable | PTE_RDONLY PTE_WRITE PTE_DIRTY (sw)
233 * 0 0 | 1 0 0
234 * 0 1 | 1 1 0
235 * 1 0 | 1 0 1
236 * 1 1 | 0 1 x
237 *
238 * When hardware DBM is not present, the sofware PTE_DIRTY bit is updated via
239 * the page fault mechanism. Checking the dirty status of a pte becomes:
240 *
241 * PTE_DIRTY || !PTE_RDONLY
242 */
214static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,243static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
215 pte_t *ptep, pte_t pte)244 pte_t *ptep, pte_t pte)
216{245{
217 if (pte_valid_user(pte)) {246 if (pte_valid_user(pte)) {
218 if (!pte_special(pte) && pte_exec(pte))247 if (!pte_special(pte) && pte_exec(pte))
219 __sync_icache_dcache(pte, addr);248 __sync_icache_dcache(pte, addr);
220 if (pte_dirty(pte) && pte_write(pte))249 if (pte_sw_dirty(pte) && pte_write(pte))
221 pte_val(pte) &= ~PTE_RDONLY;250 pte_val(pte) &= ~PTE_RDONLY;
222 else251 else
223 pte_val(pte) |= PTE_RDONLY;252 pte_val(pte) |= PTE_RDONLY;
224 }253 }
225 254
255 /*
256 * If the existing pte is valid, check for potential race with
257 * hardware updates of the pte (ptep_set_access_flags safely changes
258 * valid ptes without going through an invalid entry).
259 */
260 if (IS_ENABLED(CONFIG_DEBUG_VM) && IS_ENABLED(CONFIG_ARM64_HW_AFDBM) &&
261 pte_valid(*ptep)) {
262 BUG_ON(!pte_young(pte));
263 BUG_ON(pte_write(*ptep) && !pte_dirty(pte));
264 }
265
226 set_pte(ptep, pte);266 set_pte(ptep, pte);
227}267}
228 268
@@ -461,6 +501,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) · 232 unmodified lines
461{501{
462 const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |502 const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
463 PTE_PROT_NONE | PTE_WRITE | PTE_TYPE_MASK;503 PTE_PROT_NONE | PTE_WRITE | PTE_TYPE_MASK;
504 /* preserve the hardware dirty information */
505 if (pte_hw_dirty(pte))
506 newprot |= PTE_DIRTY;
464 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);507 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
465 return pte;508 return pte;
466}509}
@@ -470,6 +513,101 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) · 3 unmodified lines
470 return pte_pmd(pte_modify(pmd_pte(pmd), newprot));513 return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
471}514}
472 515
516#ifdef CONFIG_ARM64_HW_AFDBM
517/*
518 * Atomic pte/pmd modifications.
519 */
520#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
521static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
522 unsigned long address,
523 pte_t *ptep)
524{
525 pteval_t pteval;
526 unsigned int tmp, res;
527
528 asm volatile("// ptep_test_and_clear_young\n"
529 " prfm pstl1strm, %2\n"
530 "1: ldxr %0, %2\n"
531 " ubfx %w3, %w0, %5, #1 // extract PTE_AF (young)\n"
532 " and %0, %0, %4 // clear PTE_AF\n"
533 " stxr %w1, %0, %2\n"
534 " cbnz %w1, 1b\n"
535 : "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)), "=&r" (res)
536 : "L" (~PTE_AF), "I" (ilog2(PTE_AF)));
537
538 return res;
539}
540
541#ifdef CONFIG_TRANSPARENT_HUGEPAGE
542#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
543static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
544 unsigned long address,
545 pmd_t *pmdp)
546{
547 return ptep_test_and_clear_young(vma, address, (pte_t *)pmdp);
548}
549#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
550
551#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
552static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
553 unsigned long address, pte_t *ptep)
554{
555 pteval_t old_pteval;
556 unsigned int tmp;
557
558 asm volatile("// ptep_get_and_clear\n"
559 " prfm pstl1strm, %2\n"
560 "1: ldxr %0, %2\n"
561 " stxr %w1, xzr, %2\n"
562 " cbnz %w1, 1b\n"
563 : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep)));
564
565 return __pte(old_pteval);
566}
567
568#ifdef CONFIG_TRANSPARENT_HUGEPAGE
569#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
570static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
571 unsigned long address, pmd_t *pmdp)
572{
573 return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
574}
575#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
576
577/*
578 * ptep_set_wrprotect - mark read-only while trasferring potential hardware
579 * dirty status (PTE_DBM && !PTE_RDONLY) to the software PTE_DIRTY bit.
580 */
581#define __HAVE_ARCH_PTEP_SET_WRPROTECT
582static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
583{
584 pteval_t pteval;
585 unsigned long tmp;
586
587 asm volatile("// ptep_set_wrprotect\n"
588 " prfm pstl1strm, %2\n"
589 "1: ldxr %0, %2\n"
590 " tst %0, %4 // check for hw dirty (!PTE_RDONLY)\n"
591 " csel %1, %3, xzr, eq // set PTE_DIRTY|PTE_RDONLY if dirty\n"
592 " orr %0, %0, %1 // if !dirty, PTE_RDONLY is already set\n"
593 " and %0, %0, %5 // clear PTE_WRITE/PTE_DBM\n"
594 " stxr %w1, %0, %2\n"
595 " cbnz %w1, 1b\n"
596 : "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
597 : "r" (PTE_DIRTY|PTE_RDONLY), "L" (PTE_RDONLY), "L" (~PTE_WRITE)
598 : "cc");
599}
600
601#ifdef CONFIG_TRANSPARENT_HUGEPAGE
602#define __HAVE_ARCH_PMDP_SET_WRPROTECT
603static inline void pmdp_set_wrprotect(struct mm_struct *mm,
604 unsigned long address, pmd_t *pmdp)
605{
606 ptep_set_wrprotect(mm, address, (pte_t *)pmdp);
607}
608#endif
609#endif /* CONFIG_ARM64_HW_AFDBM */
610
473extern pgd_t swapper_pg_dir[PTRS_PER_PGD];611extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
474extern pgd_t idmap_pg_dir[PTRS_PER_PGD];612extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
475 613
@@ -505,6 +643,21 @@ extern int kern_addr_valid(unsigned long addr); · 29 unmodified lines
505 643
506#define pgtable_cache_init() do { } while (0)644#define pgtable_cache_init() do { } while (0)
507 645
646/*
647 * On AArch64, the cache coherency is handled via the set_pte_at() function.
648 */
649static inline void update_mmu_cache(struct vm_area_struct *vma,
650 unsigned long addr, pte_t *ptep)
651{
652 /*
653 * set_pte() does not have a DSB for user mappings, so make sure that
654 * the page table write is visible.
655 */
656 dsb(ishst);
657}
658
659#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
660
508#endif /* !__ASSEMBLY__ */661#endif /* !__ASSEMBLY__ */
509 662
510#endif /* __ASM_PGTABLE_H */663#endif /* __ASM_PGTABLE_H */
arch/arm64/include/asm/processor.h+2−0
@@ -186,4 +186,6 @@ static inline void spin_lock_prefetch(const void *x) · 185 unmodified lines
186 186
187#endif187#endif
188 188
189void cpu_enable_pan(void);
190
189#endif /* __ASM_PROCESSOR_H */191#endif /* __ASM_PROCESSOR_H */
arch/arm64/include/asm/ptrace.h+0−4
@@ -183,11 +183,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs) · 182 unmodified lines
183 183
184#define instruction_pointer(regs) ((unsigned long)(regs)->pc)184#define instruction_pointer(regs) ((unsigned long)(regs)->pc)
185 185
186#ifdef CONFIG_SMP
187extern unsigned long profile_pc(struct pt_regs *regs);186extern unsigned long profile_pc(struct pt_regs *regs);
188#else
189#define profile_pc(regs) instruction_pointer(regs)
190#endif
191 187
192#endif /* __ASSEMBLY__ */188#endif /* __ASSEMBLY__ */
193#endif189#endif
arch/arm64/include/asm/smp.h+0−4
@@ -20,10 +20,6 @@ · 19 unmodified lines
20#include <linux/cpumask.h>20#include <linux/cpumask.h>
21#include <linux/thread_info.h>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#define raw_smp_processor_id() (current_thread_info()->cpu)23#define raw_smp_processor_id() (current_thread_info()->cpu)
28 24
29struct seq_file;25struct seq_file;
arch/arm64/include/asm/smp_plat.h+0−2
@@ -56,6 +56,4 @@ static inline int get_logical_index(u64 mpidr) · 55 unmodified lines
56 return -EINVAL;56 return -EINVAL;
57}57}
58 58
59void __init do_post_cpus_up_work(void);
60
61#endif /* __ASM_SMP_PLAT_H */59#endif /* __ASM_SMP_PLAT_H */
arch/arm64/include/asm/spinlock.h+114−33
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#ifndef __ASM_SPINLOCK_H16#ifndef __ASM_SPINLOCK_H
17#define __ASM_SPINLOCK_H17#define __ASM_SPINLOCK_H
18 18
19#include <asm/lse.h>
19#include <asm/spinlock_types.h>20#include <asm/spinlock_types.h>
20#include <asm/processor.h>21#include <asm/processor.h>
21 22
@@ -38,11 +39,21 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) · 16 unmodified lines
38 39
39 asm volatile(40 asm volatile(
40 /* Atomically increment the next ticket. */41 /* Atomically increment the next ticket. */
42 ARM64_LSE_ATOMIC_INSN(
43 /* LL/SC */
41" prfm pstl1strm, %3\n"44" prfm pstl1strm, %3\n"
42"1: ldaxr %w0, %3\n"45"1: ldaxr %w0, %3\n"
43" add %w1, %w0, %w5\n"46" add %w1, %w0, %w5\n"
44" stxr %w2, %w1, %3\n"47" stxr %w2, %w1, %3\n"
45" cbnz %w2, 1b\n"48" cbnz %w2, 1b\n",
49 /* LSE atomics */
50" mov %w2, %w5\n"
51" ldadda %w2, %w0, %3\n"
52" nop\n"
53" nop\n"
54" nop\n"
55 )
56
46 /* Did we get the lock? */57 /* Did we get the lock? */
47" eor %w1, %w0, %w0, ror #16\n"58" eor %w1, %w0, %w0, ror #16\n"
48" cbz %w1, 3f\n"59" cbz %w1, 3f\n"
@@ -67,15 +78,25 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) · 18 unmodified lines
67 unsigned int tmp;78 unsigned int tmp;
68 arch_spinlock_t lockval;79 arch_spinlock_t lockval;
69 80
70 asm volatile(81 asm volatile(ARM64_LSE_ATOMIC_INSN(
71" prfm pstl1strm, %2\n"82 /* LL/SC */
72"1: ldaxr %w0, %2\n"83 " prfm pstl1strm, %2\n"
73" eor %w1, %w0, %w0, ror #16\n"84 "1: ldaxr %w0, %2\n"
74" cbnz %w1, 2f\n"85 " eor %w1, %w0, %w0, ror #16\n"
75" add %w0, %w0, %3\n"86 " cbnz %w1, 2f\n"
76" stxr %w1, %w0, %2\n"87 " add %w0, %w0, %3\n"
77" cbnz %w1, 1b\n"88 " stxr %w1, %w0, %2\n"
78"2:"89 " cbnz %w1, 1b\n"
90 "2:",
91 /* LSE atomics */
92 " ldr %w0, %2\n"
93 " eor %w1, %w0, %w0, ror #16\n"
94 " cbnz %w1, 1f\n"
95 " add %w1, %w0, %3\n"
96 " casa %w0, %w1, %2\n"
97 " and %w1, %w1, #0xffff\n"
98 " eor %w1, %w1, %w0, lsr #16\n"
99 "1:")
79 : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)100 : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
80 : "I" (1 << TICKET_SHIFT)101 : "I" (1 << TICKET_SHIFT)
81 : "memory");102 : "memory");
@@ -85,10 +106,19 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) · 3 unmodified lines
85 106
86static inline void arch_spin_unlock(arch_spinlock_t *lock)107static inline void arch_spin_unlock(arch_spinlock_t *lock)
87{108{
88 asm volatile(109 unsigned long tmp;
89" stlrh %w1, %0\n"110
90 : "=Q" (lock->owner)111 asm volatile(ARM64_LSE_ATOMIC_INSN(
91 : "r" (lock->owner + 1)112 /* LL/SC */
113 " ldrh %w1, %0\n"
114 " add %w1, %w1, #1\n"
115 " stlrh %w1, %0",
116 /* LSE atomics */
117 " mov %w1, #1\n"
118 " nop\n"
119 " staddlh %w1, %0")
120 : "=Q" (lock->owner), "=&r" (tmp)
121 :
92 : "memory");122 : "memory");
93}123}
94 124
@@ -123,13 +153,24 @@ static inline void arch_write_lock(arch_rwlock_t *rw) · 28 unmodified lines
123{153{
124 unsigned int tmp;154 unsigned int tmp;
125 155
126 asm volatile(156 asm volatile(ARM64_LSE_ATOMIC_INSN(
157 /* LL/SC */
127 " sevl\n"158 " sevl\n"
128 "1: wfe\n"159 "1: wfe\n"
129 "2: ldaxr %w0, %1\n"160 "2: ldaxr %w0, %1\n"
130 " cbnz %w0, 1b\n"161 " cbnz %w0, 1b\n"
131 " stxr %w0, %w2, %1\n"162 " stxr %w0, %w2, %1\n"
132 " cbnz %w0, 2b\n"163 " cbnz %w0, 2b\n"
164 " nop",
165 /* LSE atomics */
166 "1: mov %w0, wzr\n"
167 "2: casa %w0, %w2, %1\n"
168 " cbz %w0, 3f\n"
169 " ldxr %w0, %1\n"
170 " cbz %w0, 2b\n"
171 " wfe\n"
172 " b 1b\n"
173 "3:")
133 : "=&r" (tmp), "+Q" (rw->lock)174 : "=&r" (tmp), "+Q" (rw->lock)
134 : "r" (0x80000000)175 : "r" (0x80000000)
135 : "memory");176 : "memory");
@@ -139,11 +180,18 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) · 3 unmodified lines
139{180{
140 unsigned int tmp;181 unsigned int tmp;
141 182
142 asm volatile(183 asm volatile(ARM64_LSE_ATOMIC_INSN(
143 " ldaxr %w0, %1\n"184 /* LL/SC */
144 " cbnz %w0, 1f\n"185 "1: ldaxr %w0, %1\n"
186 " cbnz %w0, 2f\n"
145 " stxr %w0, %w2, %1\n"187 " stxr %w0, %w2, %1\n"
146 "1:\n"188 " cbnz %w0, 1b\n"
189 "2:",
190 /* LSE atomics */
191 " mov %w0, wzr\n"
192 " casa %w0, %w2, %1\n"
193 " nop\n"
194 " nop")
147 : "=&r" (tmp), "+Q" (rw->lock)195 : "=&r" (tmp), "+Q" (rw->lock)
148 : "r" (0x80000000)196 : "r" (0x80000000)
149 : "memory");197 : "memory");
@@ -153,9 +201,10 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) · 3 unmodified lines
153 201
154static inline void arch_write_unlock(arch_rwlock_t *rw)202static inline void arch_write_unlock(arch_rwlock_t *rw)
155{203{
156 asm volatile(204 asm volatile(ARM64_LSE_ATOMIC_INSN(
157 " stlr %w1, %0\n"205 " stlr wzr, %0",
158 : "=Q" (rw->lock) : "r" (0) : "memory");206 " swpl wzr, wzr, %0")
207 : "=Q" (rw->lock) :: "memory");
159}208}
160 209
161/* write_can_lock - would write_trylock() succeed? */210/* write_can_lock - would write_trylock() succeed? */
@@ -172,6 +221,10 @@ static inline void arch_write_unlock(arch_rwlock_t *rw) · 10 unmodified lines
172 *221 *
173 * The memory barriers are implicit with the load-acquire and store-release222 * The memory barriers are implicit with the load-acquire and store-release
174 * instructions.223 * instructions.
224 *
225 * Note that in UNDEFINED cases, such as unlocking a lock twice, the LL/SC
226 * and LSE implementations may exhibit different behaviour (although this
227 * will have no effect on lockdep).
175 */228 */
176static inline void arch_read_lock(arch_rwlock_t *rw)229static inline void arch_read_lock(arch_rwlock_t *rw)
177{230{
@@ -179,26 +232,43 @@ static inline void arch_read_lock(arch_rwlock_t *rw) · 1 unmodified line
179 232
180 asm volatile(233 asm volatile(
181 " sevl\n"234 " sevl\n"
235 ARM64_LSE_ATOMIC_INSN(
236 /* LL/SC */
182 "1: wfe\n"237 "1: wfe\n"
183 "2: ldaxr %w0, %2\n"238 "2: ldaxr %w0, %2\n"
184 " add %w0, %w0, #1\n"239 " add %w0, %w0, #1\n"
185 " tbnz %w0, #31, 1b\n"240 " tbnz %w0, #31, 1b\n"
186 " stxr %w1, %w0, %2\n"241 " stxr %w1, %w0, %2\n"
187 " cbnz %w1, 2b\n"242 " nop\n"
243 " cbnz %w1, 2b",
244 /* LSE atomics */
245 "1: wfe\n"
246 "2: ldxr %w0, %2\n"
247 " adds %w1, %w0, #1\n"
248 " tbnz %w1, #31, 1b\n"
249 " casa %w0, %w1, %2\n"
250 " sbc %w0, %w1, %w0\n"
251 " cbnz %w0, 2b")
188 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)252 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
189 :253 :
190 : "memory");254 : "cc", "memory");
191}255}
192 256
193static inline void arch_read_unlock(arch_rwlock_t *rw)257static inline void arch_read_unlock(arch_rwlock_t *rw)
194{258{
195 unsigned int tmp, tmp2;259 unsigned int tmp, tmp2;
196 260
197 asm volatile(261 asm volatile(ARM64_LSE_ATOMIC_INSN(
262 /* LL/SC */
198 "1: ldxr %w0, %2\n"263 "1: ldxr %w0, %2\n"
199 " sub %w0, %w0, #1\n"264 " sub %w0, %w0, #1\n"
200 " stlxr %w1, %w0, %2\n"265 " stlxr %w1, %w0, %2\n"
201 " cbnz %w1, 1b\n"266 " cbnz %w1, 1b",
267 /* LSE atomics */
268 " movn %w0, #0\n"
269 " nop\n"
270 " nop\n"
271 " staddl %w0, %2")
202 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)272 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
203 :273 :
204 : "memory");274 : "memory");
@@ -206,17 +276,28 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) · 1 unmodified line
206 276
207static inline int arch_read_trylock(arch_rwlock_t *rw)277static inline int arch_read_trylock(arch_rwlock_t *rw)
208{278{
209 unsigned int tmp, tmp2 = 1;279 unsigned int tmp, tmp2;
210 280
211 asm volatile(281 asm volatile(ARM64_LSE_ATOMIC_INSN(
212 " ldaxr %w0, %2\n"282 /* LL/SC */
283 " mov %w1, #1\n"
284 "1: ldaxr %w0, %2\n"
213 " add %w0, %w0, #1\n"285 " add %w0, %w0, #1\n"
214 " tbnz %w0, #31, 1f\n"286 " tbnz %w0, #31, 2f\n"
215 " stxr %w1, %w0, %2\n"287 " stxr %w1, %w0, %2\n"
216 "1:\n"288 " cbnz %w1, 1b\n"
217 : "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock)289 "2:",
290 /* LSE atomics */
291 " ldr %w0, %2\n"
292 " adds %w1, %w0, #1\n"
293 " tbnz %w1, #31, 1f\n"
294 " casa %w0, %w1, %2\n"
295 " sbc %w1, %w1, %w0\n"
296 " nop\n"
297 "1:")
298 : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
218 :299 :
219 : "memory");300 : "cc", "memory");
220 301
221 return !tmp2;302 return !tmp2;
222}303}
arch/arm64/include/asm/spinlock_types.h+2−0
@@ -20,6 +20,8 @@ · 19 unmodified lines
20# error "please don't include this file directly"20# error "please don't include this file directly"
21#endif21#endif
22 22
23#include <linux/types.h>
24
23#define TICKET_SHIFT 1625#define TICKET_SHIFT 16
24 26
25typedef struct {27typedef struct {
arch/arm64/include/asm/sysreg.h+35−5
@@ -20,8 +20,29 @@ · 19 unmodified lines
20#ifndef __ASM_SYSREG_H20#ifndef __ASM_SYSREG_H
21#define __ASM_SYSREG_H21#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#define sys_reg(op0, op1, crn, crm, op2) \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#ifdef __ASSEMBLY__47#ifdef __ASSEMBLY__
27 48
@@ -31,11 +52,11 @@ · 3 unmodified lines
31 .equ __reg_num_xzr, 3152 .equ __reg_num_xzr, 31
32 53
33 .macro mrs_s, rt, sreg54 .macro mrs_s, rt, sreg
34 .inst 0xd5300000|(\sreg)|(__reg_num_\rt)55 .inst 0xd5200000|(\sreg)|(__reg_num_\rt)
35 .endm56 .endm
36 57
37 .macro msr_s, sreg, rt58 .macro msr_s, sreg, rt
38 .inst 0xd5100000|(\sreg)|(__reg_num_\rt)59 .inst 0xd5000000|(\sreg)|(__reg_num_\rt)
39 .endm60 .endm
40 61
41#else62#else
@@ -47,14 +68,23 @@ asm( · 5 unmodified lines
47" .equ __reg_num_xzr, 31\n"68" .equ __reg_num_xzr, 31\n"
48"\n"69"\n"
49" .macro mrs_s, rt, sreg\n"70" .macro mrs_s, rt, sreg\n"
50" .inst 0xd5300000|(\\sreg)|(__reg_num_\\rt)\n"71" .inst 0xd5200000|(\\sreg)|(__reg_num_\\rt)\n"
51" .endm\n"72" .endm\n"
52"\n"73"\n"
53" .macro msr_s, sreg, rt\n"74" .macro msr_s, sreg, rt\n"
54" .inst 0xd5100000|(\\sreg)|(__reg_num_\\rt)\n"75" .inst 0xd5000000|(\\sreg)|(__reg_num_\\rt)\n"
55" .endm\n"76" .endm\n"
56);77);
57 78
79static inline void config_sctlr_el1(u32 clear, u32 set)
80{
81 u32 val;
82
83 asm volatile("mrs %0, sctlr_el1" : "=r" (val));
84 val &= ~clear;
85 val |= set;
86 asm volatile("msr sctlr_el1, %0" : : "r" (val));
87}
58#endif88#endif
59 89
60#endif /* __ASM_SYSREG_H */90#endif /* __ASM_SYSREG_H */
arch/arm64/include/asm/tlb.h+6−1
@@ -41,7 +41,12 @@ static inline void tlb_flush(struct mmu_gather *tlb) · 40 unmodified lines
41 flush_tlb_mm(tlb->mm);41 flush_tlb_mm(tlb->mm);
42 } else {42 } else {
43 struct vm_area_struct vma = { .vm_mm = tlb->mm, };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
arch/arm64/include/asm/tlbflush.h+34−42
@@ -87,27 +87,56 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, · 86 unmodified lines
87 ((unsigned long)ASID(vma->vm_mm) << 48);87 ((unsigned long)ASID(vma->vm_mm) << 48);
88 88
89 dsb(ishst);89 dsb(ishst);
90 asm("tlbi vae1is, %0" : : "r" (addr));90 asm("tlbi vale1is, %0" : : "r" (addr));
91 dsb(ish);91 dsb(ish);
92}92}
93 93
94/*
95 * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
96 * necessarily a performance improvement.
97 */
98#define MAX_TLB_RANGE (1024UL << PAGE_SHIFT)
99
94static inline void __flush_tlb_range(struct vm_area_struct *vma,100static inline void __flush_tlb_range(struct vm_area_struct *vma,
95 unsigned long start, unsigned long end)101 unsigned long start, unsigned long end,
102 bool last_level)
96{103{
97 unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48;104 unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48;
98 unsigned long addr;105 unsigned long addr;
106
107 if ((end - start) > MAX_TLB_RANGE) {
108 flush_tlb_mm(vma->vm_mm);
109 return;
110 }
111
99 start = asid | (start >> 12);112 start = asid | (start >> 12);
100 end = asid | (end >> 12);113 end = asid | (end >> 12);
101 114
102 dsb(ishst);115 dsb(ishst);
103 for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))116 for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) {
104 asm("tlbi vae1is, %0" : : "r"(addr));117 if (last_level)
118 asm("tlbi vale1is, %0" : : "r"(addr));
119 else
120 asm("tlbi vae1is, %0" : : "r"(addr));
121 }
105 dsb(ish);122 dsb(ish);
106}123}
107 124
108static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long end)125static inline void flush_tlb_range(struct vm_area_struct *vma,
126 unsigned long start, unsigned long end)
127{
128 __flush_tlb_range(vma, start, end, false);
129}
130
131static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
109{132{
110 unsigned long addr;133 unsigned long addr;
134
135 if ((end - start) > MAX_TLB_RANGE) {
136 flush_tlb_all();
137 return;
138 }
139
111 start >>= 12;140 start >>= 12;
112 end >>= 12;141 end >>= 12;
113 142
@@ -118,29 +147,6 @@ static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long e · 4 unmodified lines
118 isb();147 isb();
119}148}
120 149
121/*
122 * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
123 * necessarily a performance improvement.
124 */
125#define MAX_TLB_RANGE (1024UL << PAGE_SHIFT)
126
127static inline void flush_tlb_range(struct vm_area_struct *vma,
128 unsigned long start, unsigned long end)
129{
130 if ((end - start) <= MAX_TLB_RANGE)
131 __flush_tlb_range(vma, start, end);
132 else
133 flush_tlb_mm(vma->vm_mm);
134}
135
136static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
137{
138 if ((end - start) <= MAX_TLB_RANGE)
139 __flush_tlb_kernel_range(start, end);
140 else
141 flush_tlb_all();
142}
143
144/*150/*
145 * Used to invalidate the TLB (walk caches) corresponding to intermediate page151 * Used to invalidate the TLB (walk caches) corresponding to intermediate page
146 * table levels (pgd/pud/pmd).152 * table levels (pgd/pud/pmd).
@@ -154,20 +160,6 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, · 7 unmodified lines
154 asm("tlbi vae1is, %0" : : "r" (addr));160 asm("tlbi vae1is, %0" : : "r" (addr));
155 dsb(ish);161 dsb(ish);
156}162}
157/*
158 * On AArch64, the cache coherency is handled via the set_pte_at() function.
159 */
160static inline void update_mmu_cache(struct vm_area_struct *vma,
161 unsigned long addr, pte_t *ptep)
162{
163 /*
164 * set_pte() does not have a DSB for user mappings, so make sure that
165 * the page table write is visible.
166 */
167 dsb(ishst);
168}
169
170#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
171 163
172#endif164#endif
173 165
arch/arm64/include/asm/topology.h+0−9
@@ -1,8 +1,6 @@
1#ifndef __ASM_TOPOLOGY_H1#ifndef __ASM_TOPOLOGY_H
2#define __ASM_TOPOLOGY_H2#define __ASM_TOPOLOGY_H
3 3
4#ifdef CONFIG_SMP
5
6#include <linux/cpumask.h>4#include <linux/cpumask.h>
7 5
8struct cpu_topology {6struct cpu_topology {
@@ -24,13 +22,6 @@ void init_cpu_topology(void); · 15 unmodified lines
24void store_cpu_topology(unsigned int cpuid);22void store_cpu_topology(unsigned int cpuid);
25const struct cpumask *cpu_coregroup_mask(int cpu);23const struct cpumask *cpu_coregroup_mask(int cpu);
26 24
27#else
28
29static inline void init_cpu_topology(void) { }
30static inline void store_cpu_topology(unsigned int cpuid) { }
31
32#endif
33
34#include <asm-generic/topology.h>25#include <asm-generic/topology.h>
35 26
36#endif /* _ASM_ARM_TOPOLOGY_H */27#endif /* _ASM_ARM_TOPOLOGY_H */
arch/arm64/include/asm/traps.h+21−2
@@ -34,13 +34,32 @@ struct undef_hook { · 33 unmodified lines
34void register_undef_hook(struct undef_hook *hook);34void register_undef_hook(struct undef_hook *hook);
35void unregister_undef_hook(struct undef_hook *hook);35void unregister_undef_hook(struct undef_hook *hook);
36 36
37#ifdef CONFIG_FUNCTION_GRAPH_TRACER
38static 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
47static inline int __in_irqentry_text(unsigned long ptr)
48{
49 return 0;
50}
51#endif
52
37static inline int in_exception_text(unsigned long ptr)53static inline int in_exception_text(unsigned long ptr)
38{54{
39 extern char __exception_text_start[];55 extern char __exception_text_start[];
40 extern char __exception_text_end[];56 extern char __exception_text_end[];
57 int in;
58
59 in = ptr >= (unsigned long)&__exception_text_start &&
60 ptr < (unsigned long)&__exception_text_end;
41 61
42 return ptr >= (unsigned long)&__exception_text_start &&62 return in ? : __in_irqentry_text(ptr);
43 ptr < (unsigned long)&__exception_text_end;
44}63}
45 64
46#endif65#endif
arch/arm64/include/asm/uaccess.h+11−0
@@ -24,7 +24,10 @@ · 23 unmodified lines
24#include <linux/string.h>24#include <linux/string.h>
25#include <linux/thread_info.h>25#include <linux/thread_info.h>
26 26
27#include <asm/alternative.h>
28#include <asm/cpufeature.h>
27#include <asm/ptrace.h>29#include <asm/ptrace.h>
30#include <asm/sysreg.h>
28#include <asm/errno.h>31#include <asm/errno.h>
29#include <asm/memory.h>32#include <asm/memory.h>
30#include <asm/compiler.h>33#include <asm/compiler.h>
@@ -131,6 +134,8 @@ static inline void set_fs(mm_segment_t fs) · 100 unmodified lines
131do { \134do { \
132 unsigned long __gu_val; \135 unsigned long __gu_val; \
133 __chk_user_ptr(ptr); \136 __chk_user_ptr(ptr); \
137 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
138 CONFIG_ARM64_PAN)); \
134 switch (sizeof(*(ptr))) { \139 switch (sizeof(*(ptr))) { \
135 case 1: \140 case 1: \
136 __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \141 __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \
@@ -148,6 +153,8 @@ do { \ · 11 unmodified lines
148 BUILD_BUG(); \153 BUILD_BUG(); \
149 } \154 } \
150 (x) = (__force __typeof__(*(ptr)))__gu_val; \155 (x) = (__force __typeof__(*(ptr)))__gu_val; \
156 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
157 CONFIG_ARM64_PAN)); \
151} while (0)158} while (0)
152 159
153#define __get_user(x, ptr) \160#define __get_user(x, ptr) \
@@ -194,6 +201,8 @@ do { \ · 40 unmodified lines
194do { \201do { \
195 __typeof__(*(ptr)) __pu_val = (x); \202 __typeof__(*(ptr)) __pu_val = (x); \
196 __chk_user_ptr(ptr); \203 __chk_user_ptr(ptr); \
204 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
205 CONFIG_ARM64_PAN)); \
197 switch (sizeof(*(ptr))) { \206 switch (sizeof(*(ptr))) { \
198 case 1: \207 case 1: \
199 __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \208 __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \
@@ -210,6 +219,8 @@ do { \ · 10 unmodified lines
210 default: \219 default: \
211 BUILD_BUG(); \220 BUILD_BUG(); \
212 } \221 } \
222 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
223 CONFIG_ARM64_PAN)); \
213} while (0)224} while (0)
214 225
215#define __put_user(x, ptr) \226#define __put_user(x, ptr) \
arch/arm64/include/uapi/asm/hwcap.h+1−0
@@ -27,5 +27,6 @@ · 26 unmodified lines
27#define HWCAP_SHA1 (1 << 5)27#define HWCAP_SHA1 (1 << 5)
28#define HWCAP_SHA2 (1 << 6)28#define HWCAP_SHA2 (1 << 6)
29#define HWCAP_CRC32 (1 << 7)29#define HWCAP_CRC32 (1 << 7)
30#define HWCAP_ATOMICS (1 << 8)
30 31
31#endif /* _UAPI__ASM_HWCAP_H */32#endif /* _UAPI__ASM_HWCAP_H */
arch/arm64/include/uapi/asm/ptrace.h+1−0
@@ -44,6 +44,7 @@ · 43 unmodified lines
44#define PSR_I_BIT 0x0000008044#define PSR_I_BIT 0x00000080
45#define PSR_A_BIT 0x0000010045#define PSR_A_BIT 0x00000100
46#define PSR_D_BIT 0x0000020046#define PSR_D_BIT 0x00000200
47#define PSR_PAN_BIT 0x00400000
47#define PSR_Q_BIT 0x0800000048#define PSR_Q_BIT 0x08000000
48#define PSR_V_BIT 0x1000000049#define PSR_V_BIT 0x10000000
49#define PSR_C_BIT 0x2000000050#define PSR_C_BIT 0x20000000
arch/arm64/kernel/Makefile+3−3
@@ -17,15 +17,15 @@ arm64-obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ · 16 unmodified lines
17 sys.o stacktrace.o time.o traps.o io.o vdso.o \17 sys.o stacktrace.o time.o traps.o io.o vdso.o \
18 hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \18 hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \
19 return_address.o cpuinfo.o cpu_errata.o \19 return_address.o cpuinfo.o cpu_errata.o \
20 cpufeature.o alternative.o cacheinfo.o20 cpufeature.o alternative.o cacheinfo.o \
21 smp.o smp_spin_table.o topology.o
21 22
22arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \23arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
23 sys_compat.o entry32.o \24 sys_compat.o entry32.o \
24 ../../arm/kernel/opcodes.o25 ../../arm/kernel/opcodes.o
25arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o26arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
26arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o27arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
27arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o28arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
28arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
29arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o29arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
30arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o30arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
31arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o31arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
arch/arm64/kernel/alternative.c+25−5
@@ -85,7 +85,7 @@ static u32 get_alt_insn(struct alt_instr *alt, u32 *insnptr, u32 *altinsnptr) · 84 unmodified lines
85 return insn;85 return insn;
86}86}
87 87
88static int __apply_alternatives(void *alt_region)88static void __apply_alternatives(void *alt_region)
89{89{
90 struct alt_instr *alt;90 struct alt_instr *alt;
91 struct alt_region *region = alt_region;91 struct alt_region *region = alt_region;
@@ -114,19 +114,39 @@ static int __apply_alternatives(void *alt_region) · 22 unmodified lines
114 flush_icache_range((uintptr_t)origptr,114 flush_icache_range((uintptr_t)origptr,
115 (uintptr_t)(origptr + nr_inst));115 (uintptr_t)(origptr + nr_inst));
116 }116 }
117
118 return 0;
119}117}
120 118
121void 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 */
123static int __apply_alternatives_multi_stop(void *unused)
122{124{
125 static int patched = 0;
123 struct alt_region region = {126 struct alt_region region = {
124 .begin = __alt_instructions,127 .begin = __alt_instructions,
125 .end = __alt_instructions_end,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
146void __init apply_alternatives_all(void)
147{
128 /* better not try code patching on a live SMP system */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
132void apply_alternatives(void *start, size_t length)152void apply_alternatives(void *start, size_t length)
arch/arm64/kernel/armv8_deprecated.c+8−11
@@ -14,8 +14,11 @@ · 13 unmodified lines
14#include <linux/slab.h>14#include <linux/slab.h>
15#include <linux/sysctl.h>15#include <linux/sysctl.h>
16 16
17#include <asm/alternative.h>
18#include <asm/cpufeature.h>
17#include <asm/insn.h>19#include <asm/insn.h>
18#include <asm/opcodes.h>20#include <asm/opcodes.h>
21#include <asm/sysreg.h>
19#include <asm/system_misc.h>22#include <asm/system_misc.h>
20#include <asm/traps.h>23#include <asm/traps.h>
21#include <asm/uaccess.h>24#include <asm/uaccess.h>
@@ -279,6 +282,8 @@ static void register_insn_emulation_sysctl(struct ctl_table *table) · 257 unmodified lines
279 */282 */
280#define __user_swpX_asm(data, addr, res, temp, B) \283#define __user_swpX_asm(data, addr, res, temp, B) \
281 __asm__ __volatile__( \284 __asm__ __volatile__( \
285 ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
286 CONFIG_ARM64_PAN) \
282 " mov %w2, %w1\n" \287 " mov %w2, %w1\n" \
283 "0: ldxr"B" %w1, [%3]\n" \288 "0: ldxr"B" %w1, [%3]\n" \
284 "1: stxr"B" %w0, %w2, [%3]\n" \289 "1: stxr"B" %w0, %w2, [%3]\n" \
@@ -294,7 +299,9 @@ static void register_insn_emulation_sysctl(struct ctl_table *table) · 9 unmodified lines
294 " .align 3\n" \299 " .align 3\n" \
295 " .quad 0b, 3b\n" \300 " .quad 0b, 3b\n" \
296 " .quad 1b, 3b\n" \301 " .quad 1b, 3b\n" \
297 " .popsection" \302 " .popsection\n" \
303 ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
304 CONFIG_ARM64_PAN) \
298 : "=&r" (res), "+r" (data), "=&r" (temp) \305 : "=&r" (res), "+r" (data), "=&r" (temp) \
299 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \306 : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \
300 : "memory")307 : "memory")
@@ -504,16 +511,6 @@ ret: · 203 unmodified lines
504 return 0;511 return 0;
505}512}
506 513
507static inline void config_sctlr_el1(u32 clear, u32 set)
508{
509 u32 val;
510
511 asm volatile("mrs %0, sctlr_el1" : "=r" (val));
512 val &= ~clear;
513 val |= set;
514 asm volatile("msr sctlr_el1, %0" : : "r" (val));
515}
516
517static int cp15_barrier_set_hw_mode(bool enable)514static int cp15_barrier_set_hw_mode(bool enable)
518{515{
519 if (enable)516 if (enable)
arch/arm64/kernel/cpu_ops.c+0−2
@@ -30,9 +30,7 @@ extern const struct cpu_operations cpu_psci_ops; · 29 unmodified lines
30const struct cpu_operations *cpu_ops[NR_CPUS];30const struct cpu_operations *cpu_ops[NR_CPUS];
31 31
32static const struct cpu_operations *supported_cpu_ops[] __initconst = {32static const struct cpu_operations *supported_cpu_ops[] __initconst = {
33#ifdef CONFIG_SMP
34 &smp_spin_table_ops,33 &smp_spin_table_ops,
35#endif
36 &cpu_psci_ops,34 &cpu_psci_ops,
37 NULL,35 NULL,
38};36};
arch/arm64/kernel/cpufeature.c+46−7
@@ -21,24 +21,57 @@ · 20 unmodified lines
21#include <linux/types.h>21#include <linux/types.h>
22#include <asm/cpu.h>22#include <asm/cpu.h>
23#include <asm/cpufeature.h>23#include <asm/cpufeature.h>
24#include <asm/processor.h>
24 25
25static bool26static bool
26has_id_aa64pfr0_feature(const struct arm64_cpu_capabilities *entry)27feature_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->min_field_value;
31 return (val & entry->register_mask) == entry->register_value;
32}32}
33 33
34#define __ID_FEAT_CHK(reg) \
35static bool __maybe_unused \
36has_##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);
47
34static const struct arm64_cpu_capabilities arm64_features[] = {48static const struct arm64_cpu_capabilities arm64_features[] = {
35 {49 {
36 .desc = "GIC system register CPU interface",50 .desc = "GIC system register CPU interface",
37 .capability = ARM64_HAS_SYSREG_GIC_CPUIF,51 .capability = ARM64_HAS_SYSREG_GIC_CPUIF,
38 .matches = has_id_aa64pfr0_feature,52 .matches = has_id_aa64pfr0_feature,
39 .register_mask = (0xf << 24),53 .field_pos = 24,
40 .register_value = (1 << 24),54 .min_field_value = 1,
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,
41 },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
@@ -55,9 +88,15 @@ void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps, · 10 unmodified lines
55 pr_info("%s %s\n", info, caps[i].desc);88 pr_info("%s %s\n", info, caps[i].desc);
56 cpus_set_cap(caps[i].capability);89 cpus_set_cap(caps[i].capability);
57 }90 }
91
92 /* second pass allows enable() to consider interacting capabilities */
93 for (i = 0; caps[i].desc; i++) {
94 if (cpus_have_cap(caps[i].capability) && caps[i].enable)
95 caps[i].enable();
96 }
58}97}
59 98
60void check_local_cpu_features(void)99void check_local_cpu_features(void)
61{100{
62 check_cpu_capabilities(arm64_features, "detected feature");101 check_cpu_capabilities(arm64_features, "detected feature:");
63}102}
arch/arm64/kernel/debug-monitors.c+2−2
@@ -82,7 +82,7 @@ early_param("nodebugmon", early_debug_disable); · 81 unmodified lines
82static DEFINE_PER_CPU(int, mde_ref_count);82static DEFINE_PER_CPU(int, mde_ref_count);
83static DEFINE_PER_CPU(int, kde_ref_count);83static DEFINE_PER_CPU(int, kde_ref_count);
84 84
85void enable_debug_monitors(enum debug_el el)85void enable_debug_monitors(enum dbg_active_el el)
86{86{
87 u32 mdscr, enable = 0;87 u32 mdscr, enable = 0;
88 88
@@ -102,7 +102,7 @@ void enable_debug_monitors(enum debug_el el) · 13 unmodified lines
102 }102 }
103}103}
104 104
105void disable_debug_monitors(enum debug_el el)105void disable_debug_monitors(enum dbg_active_el el)
106{106{
107 u32 mdscr, disable = 0;107 u32 mdscr, disable = 0;
108 108
arch/arm64/kernel/efi-stub.c+32−9
@@ -13,7 +13,7 @@ · 12 unmodified lines
13#include <asm/efi.h>13#include <asm/efi.h>
14#include <asm/sections.h>14#include <asm/sections.h>
15 15
16efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table,16efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
17 unsigned long *image_addr,17 unsigned long *image_addr,
18 unsigned long *image_size,18 unsigned long *image_size,
19 unsigned long *reserve_addr,19 unsigned long *reserve_addr,
@@ -23,21 +23,44 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, · 3 unmodified lines
23{23{
24 efi_status_t status;24 efi_status_t status;
25 unsigned long kernel_size, kernel_memsize = 0;25 unsigned long kernel_size, kernel_memsize = 0;
26 unsigned long nr_pages;
27 void *old_image_addr = (void *)*image_addr;
26 28
27 /* Relocate the image, if required. */29 /* Relocate the image, if required. */
28 kernel_size = _edata - _text;30 kernel_size = _edata - _text;
29 if (*image_addr != (dram_base + TEXT_OFFSET)) {31 if (*image_addr != (dram_base + TEXT_OFFSET)) {
30 kernel_memsize = kernel_size + (_end - _edata);32 kernel_memsize = kernel_size + (_end - _edata);
31 status = efi_low_alloc(sys_table, kernel_memsize + TEXT_OFFSET,33
32 SZ_2M, reserve_addr);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 if (status != EFI_SUCCESS) {51 if (status != EFI_SUCCESS) {
34 pr_efi_err(sys_table, "Failed to relocate kernel\n");52 kernel_memsize += TEXT_OFFSET;
35 return status;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,62 memcpy((void *)*image_addr, old_image_addr, kernel_size);
38 kernel_size);63 *reserve_size = kernel_memsize;
39 *image_addr = *reserve_addr + TEXT_OFFSET;
40 *reserve_size = kernel_memsize + TEXT_OFFSET;
41 }64 }
42 65
43 66
arch/arm64/kernel/entry.S+19−27
@@ -116,41 +116,34 @@ · 115 unmodified lines
116 */116 */
117 .endm117 .endm
118 118
119 .macro kernel_exit, el, ret = 0119 .macro kernel_exit, el
120 ldp x21, x22, [sp, #S_PC] // load ELR, SPSR120 ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
121 .if \el == 0121 .if \el == 0
122 ct_user_enter122 ct_user_enter
123 ldr x23, [sp, #S_SP] // load return stack pointer123 ldr x23, [sp, #S_SP] // load return stack pointer
124 msr sp_el0, x23124 msr sp_el0, x23
125
126#ifdef CONFIG_ARM64_ERRATUM_845719125#ifdef CONFIG_ARM64_ERRATUM_845719
127 126alternative_if_not ARM64_WORKAROUND_845719
128#undef SEQUENCE_ORG127 nop
129#undef SEQUENCE_ALT128 nop
130
131#ifdef CONFIG_PID_IN_CONTEXTIDR129#ifdef CONFIG_PID_IN_CONTEXTIDR
132 130 nop
133#define SEQUENCE_ORG "nop ; nop ; nop"131#endif
134#define SEQUENCE_ALT "tbz x22, #4, 1f ; mrs x29, contextidr_el1; msr contextidr_el1, x29; 1:"132alternative_else
135 133 tbz x22, #4, 1f
134#ifdef CONFIG_PID_IN_CONTEXTIDR
135 mrs x29, contextidr_el1
136 msr contextidr_el1, x29
136#else137#else
137 138 msr contextidr_el1, xzr
138#define SEQUENCE_ORG "nop ; nop"
139#define SEQUENCE_ALT "tbz x22, #4, 1f ; msr contextidr_el1, xzr; 1:"
140
141#endif139#endif
142 1401:
143 alternative_insn SEQUENCE_ORG, SEQUENCE_ALT, ARM64_WORKAROUND_845719141alternative_endif
144
145#endif142#endif
146 .endif143 .endif
147 msr elr_el1, x21 // set up the return data144 msr elr_el1, x21 // set up the return data
148 msr spsr_el1, x22145 msr spsr_el1, x22
149 .if \ret
150 ldr x1, [sp, #S_X1] // preserve x0 (syscall return)
151 .else
152 ldp x0, x1, [sp, #16 * 0]146 ldp x0, x1, [sp, #16 * 0]
153 .endif
154 ldp x2, x3, [sp, #16 * 1]147 ldp x2, x3, [sp, #16 * 1]
155 ldp x4, x5, [sp, #16 * 2]148 ldp x4, x5, [sp, #16 * 2]
156 ldp x6, x7, [sp, #16 * 3]149 ldp x6, x7, [sp, #16 * 3]
@@ -613,22 +606,21 @@ ENDPROC(cpu_switch_to) · 456 unmodified lines
613 */606 */
614ret_fast_syscall:607ret_fast_syscall:
615 disable_irq // disable interrupts608 disable_irq // disable interrupts
609 str x0, [sp, #S_X0] // returned x0
616 ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing610 ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing
617 and x2, x1, #_TIF_SYSCALL_WORK611 and x2, x1, #_TIF_SYSCALL_WORK
618 cbnz x2, ret_fast_syscall_trace612 cbnz x2, ret_fast_syscall_trace
619 and x2, x1, #_TIF_WORK_MASK613 and x2, x1, #_TIF_WORK_MASK
620 cbnz x2, fast_work_pending614 cbnz x2, work_pending
621 enable_step_tsk x1, x2615 enable_step_tsk x1, x2
622 kernel_exit 0, ret = 1616 kernel_exit 0
623ret_fast_syscall_trace:617ret_fast_syscall_trace:
624 enable_irq // enable interrupts618 enable_irq // enable interrupts
625 b __sys_trace_return619 b __sys_trace_return_skipped // we already saved x0
626 620
627/*621/*
628 * Ok, we need to do extra processing, enter the slow path.622 * Ok, we need to do extra processing, enter the slow path.
629 */623 */
630fast_work_pending:
631 str x0, [sp, #S_X0] // returned x0
632work_pending:624work_pending:
633 tbnz x1, #TIF_NEED_RESCHED, work_resched625 tbnz x1, #TIF_NEED_RESCHED, work_resched
634 /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */626 /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
@@ -652,7 +644,7 @@ ret_to_user: · 17 unmodified lines
652 cbnz x2, work_pending644 cbnz x2, work_pending
653 enable_step_tsk x1, x2645 enable_step_tsk x1, x2
654no_work_pending:646no_work_pending:
655 kernel_exit 0, ret = 0647 kernel_exit 0
656ENDPROC(ret_to_user)648ENDPROC(ret_to_user)
657 649
658/*650/*
arch/arm64/kernel/fpsimd.c+1−0
@@ -158,6 +158,7 @@ void fpsimd_thread_switch(struct task_struct *next) · 157 unmodified lines
158void fpsimd_flush_thread(void)158void fpsimd_flush_thread(void)
159{159{
160 memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));160 memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
161 fpsimd_flush_task_state(current);
161 set_thread_flag(TIF_FOREIGN_FPSTATE);162 set_thread_flag(TIF_FOREIGN_FPSTATE);
162}163}
163 164
arch/arm64/kernel/head.S+8−7
@@ -62,13 +62,8 @@ · 61 unmodified lines
62/*62/*
63 * Initial memory map attributes.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#define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | PTE_SHARED65#define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | PTE_SHARED
70#define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S66#define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S
71#endif
72 67
73#ifdef CONFIG_ARM64_64K_PAGES68#ifdef CONFIG_ARM64_64K_PAGES
74#define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS69#define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS
@@ -574,7 +569,6 @@ ENTRY(__boot_cpu_mode) · 499 unmodified lines
574 .long BOOT_CPU_MODE_EL1569 .long BOOT_CPU_MODE_EL1
575 .popsection570 .popsection
576 571
577#ifdef CONFIG_SMP
578 /*572 /*
579 * This provides a "holding pen" for platforms to hold all secondary573 * This provides a "holding pen" for platforms to hold all secondary
580 * cores are held until we're ready for them to initialise.574 * cores are held until we're ready for them to initialise.
@@ -622,7 +616,6 @@ ENTRY(__secondary_switched) · 41 unmodified lines
622 mov x29, #0616 mov x29, #0
623 b secondary_start_kernel617 b secondary_start_kernel
624ENDPROC(__secondary_switched)618ENDPROC(__secondary_switched)
625#endif /* CONFIG_SMP */
626 619
627/*620/*
628 * Enable the MMU.621 * Enable the MMU.
@@ -641,5 +634,13 @@ __enable_mmu: · 12 unmodified lines
641 isb634 isb
642 msr sctlr_el1, x0635 msr sctlr_el1, x0
643 isb636 isb
637 /*
638 * Invalidate the local I-cache so that any instructions fetched
639 * speculatively from the PoC are discarded, since they may have
640 * been dynamically patched at the PoU.
641 */
642 ic iallu
643 dsb nsh
644 isb
644 br x27645 br x27
645ENDPROC(__enable_mmu)646ENDPROC(__enable_mmu)
arch/arm64/kernel/hw_breakpoint.c+3−3
@@ -156,7 +156,7 @@ static void write_wb_reg(int reg, int n, u64 val) · 155 unmodified lines
156 * Convert a breakpoint privilege level to the corresponding exception156 * Convert a breakpoint privilege level to the corresponding exception
157 * level.157 * level.
158 */158 */
159static enum debug_el debug_exception_level(int privilege)159static enum dbg_active_el debug_exception_level(int privilege)
160{160{
161 switch (privilege) {161 switch (privilege) {
162 case AARCH64_BREAKPOINT_EL0:162 case AARCH64_BREAKPOINT_EL0:
@@ -230,7 +230,7 @@ static int hw_breakpoint_control(struct perf_event *bp, · 67 unmodified lines
230 struct perf_event **slots;230 struct perf_event **slots;
231 struct debug_info *debug_info = &current->thread.debug;231 struct debug_info *debug_info = &current->thread.debug;
232 int i, max_slots, ctrl_reg, val_reg, reg_enable;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 u32 ctrl;234 u32 ctrl;
235 235
236 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {236 if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
@@ -537,7 +537,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) · 300 unmodified lines
537 * exception level at the register level.537 * exception level at the register level.
538 * This is used when single-stepping after a breakpoint exception.538 * This is used when single-stepping after a breakpoint exception.
539 */539 */
540static void toggle_bp_registers(int reg, enum debug_el el, int enable)540static void toggle_bp_registers(int reg, enum dbg_active_el el, int enable)
541{541{
542 int i, max_slots, privilege;542 int i, max_slots, privilege;
543 u32 ctrl;543 u32 ctrl;
arch/arm64/kernel/insn.c+2−3
@@ -101,9 +101,8 @@ static void __kprobes *patch_map(void *addr, int fixmap) · 100 unmodified lines
101 return addr;101 return addr;
102 102
103 BUG_ON(!page);103 BUG_ON(!page);
104 set_fixmap(fixmap, page_to_phys(page));104 return (void *)set_fixmap_offset(fixmap, page_to_phys(page) +
105 105 (uintaddr & ~PAGE_MASK));
106 return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
107}106}
108 107
109static void __kprobes patch_unmap(int fixmap)108static void __kprobes patch_unmap(int fixmap)
arch/arm64/kernel/irq.c+0−2
@@ -33,9 +33,7 @@ unsigned long irq_err_count; · 32 unmodified lines
33 33
34int arch_show_interrupts(struct seq_file *p, int prec)34int arch_show_interrupts(struct seq_file *p, int prec)
35{35{
36#ifdef CONFIG_SMP
37 show_ipi_list(p, prec);36 show_ipi_list(p, prec);
38#endif
39 seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);37 seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
40 return 0;38 return 0;
41}39}
arch/arm64/kernel/kgdb.c+6−6
@@ -235,13 +235,13 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) · 234 unmodified lines
235 235
236static struct break_hook kgdb_brkpt_hook = {236static struct break_hook kgdb_brkpt_hook = {
237 .esr_mask = 0xffffffff,237 .esr_mask = 0xffffffff,
238 .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DBG_BRK_IMM),238 .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_DYN_DBG_BRK_IMM),
239 .fn = kgdb_brk_fn239 .fn = kgdb_brk_fn
240};240};
241 241
242static struct break_hook kgdb_compiled_brkpt_hook = {242static struct break_hook kgdb_compiled_brkpt_hook = {
243 .esr_mask = 0xffffffff,243 .esr_mask = 0xffffffff,
244 .esr_val = DBG_ESR_VAL_BRK(KGDB_COMPILED_DBG_BRK_IMM),244 .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_COMPILED_DBG_BRK_IMM),
245 .fn = kgdb_compiled_brk_fn245 .fn = kgdb_compiled_brk_fn
246};246};
247 247
@@ -328,9 +328,9 @@ void kgdb_arch_exit(void) · 80 unmodified lines
328 */328 */
329struct kgdb_arch arch_kgdb_ops = {329struct kgdb_arch arch_kgdb_ops = {
330 .gdb_bpt_instr = {330 .gdb_bpt_instr = {
331 KGDB_DYN_BRK_INS_BYTE0,331 KGDB_DYN_BRK_INS_BYTE(0),
332 KGDB_DYN_BRK_INS_BYTE1,332 KGDB_DYN_BRK_INS_BYTE(1),
333 KGDB_DYN_BRK_INS_BYTE2,333 KGDB_DYN_BRK_INS_BYTE(2),
334 KGDB_DYN_BRK_INS_BYTE3,334 KGDB_DYN_BRK_INS_BYTE(3),
335 }335 }
336};336};
arch/arm64/kernel/pci.c+13−0
@@ -38,6 +38,19 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, · 37 unmodified lines
38 return res->start;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 */
46int 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 * Try to assign the IRQ number from DT when adding a new device55 * Try to assign the IRQ number from DT when adding a new device
43 */56 */
arch/arm64/kernel/perf_callchain.c+196−0
@@ -0,0 +1,196 @@
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
23struct 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 */
32static struct frame_tail __user *
33user_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 */
71struct 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
77static struct compat_frame_tail __user *
78compat_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
109void 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 */
147static 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
154void 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
171unsigned 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
179unsigned 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}
arch/arm64/kernel/perf_event.c+25−285
@@ -25,7 +25,7 @@ · 24 unmodified lines
25#include <linux/irq.h>25#include <linux/irq.h>
26#include <linux/kernel.h>26#include <linux/kernel.h>
27#include <linux/export.h>27#include <linux/export.h>
28#include <linux/of.h>28#include <linux/of_device.h>
29#include <linux/perf_event.h>29#include <linux/perf_event.h>
30#include <linux/platform_device.h>30#include <linux/platform_device.h>
31#include <linux/slab.h>31#include <linux/slab.h>
@@ -36,7 +36,6 @@ · 4 unmodified lines
36#include <asm/irq.h>36#include <asm/irq.h>
37#include <asm/irq_regs.h>37#include <asm/irq_regs.h>
38#include <asm/pmu.h>38#include <asm/pmu.h>
39#include <asm/stacktrace.h>
40 39
41/*40/*
42 * ARMv8 supports a maximum of 32 events.41 * ARMv8 supports a maximum of 32 events.
@@ -78,6 +77,16 @@ EXPORT_SYMBOL_GPL(perf_num_counters); · 35 unmodified lines
78 77
79#define CACHE_OP_UNSUPPORTED 0xFFFF78#define CACHE_OP_UNSUPPORTED 0xFFFF
80 79
80#define PERF_MAP_ALL_UNSUPPORTED \
81 [0 ... PERF_COUNT_HW_MAX - 1] = HW_OP_UNSUPPORTED
82
83#define PERF_CACHE_MAP_ALL_UNSUPPORTED \
84[0 ... C(MAX) - 1] = { \
85 [0 ... C(OP_MAX) - 1] = { \
86 [0 ... C(RESULT_MAX) - 1] = CACHE_OP_UNSUPPORTED, \
87 }, \
88}
89
81static int90static int
82armpmu_map_cache_event(const unsigned (*cache_map)91armpmu_map_cache_event(const unsigned (*cache_map)
83 [PERF_COUNT_HW_CACHE_MAX]92 [PERF_COUNT_HW_CACHE_MAX]
@@ -435,10 +444,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) · 351 unmodified lines
435 unsigned int i, irqs;444 unsigned int i, irqs;
436 struct platform_device *pmu_device = armpmu->plat_device;445 struct platform_device *pmu_device = armpmu->plat_device;
437 446
438 if (!pmu_device) {447 if (!pmu_device)
439 pr_err("no PMU device registered\n");
440 return -ENODEV;448 return -ENODEV;
441 }
442 449
443 irqs = min(pmu_device->num_resources, num_possible_cpus());450 irqs = min(pmu_device->num_resources, num_possible_cpus());
444 if (!irqs) {451 if (!irqs) {
@@ -703,118 +710,28 @@ enum armv8_pmuv3_perf_types { · 258 unmodified lines
703 710
704/* PMUv3 HW events mapping. */711/* PMUv3 HW events mapping. */
705static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {712static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
713 PERF_MAP_ALL_UNSUPPORTED,
706 [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,714 [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
707 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,715 [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
708 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,716 [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
709 [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,717 [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
710 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
711 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,718 [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
712 [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
713 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
714 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
715};719};
716 720
717static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]721static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
718 [PERF_COUNT_HW_CACHE_OP_MAX]722 [PERF_COUNT_HW_CACHE_OP_MAX]
719 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {723 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
720 [C(L1D)] = {724 PERF_CACHE_MAP_ALL_UNSUPPORTED,
721 [C(OP_READ)] = {725
722 [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,726 [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
723 [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,727 [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
724 },728 [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
725 [C(OP_WRITE)] = {729 [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
726 [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,730
727 [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,731 [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
728 },732 [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
729 [C(OP_PREFETCH)] = {733 [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
730 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,734 [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
731 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
732 },
733 },
734 [C(L1I)] = {
735 [C(OP_READ)] = {
736 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
737 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
738 },
739 [C(OP_WRITE)] = {
740 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
741 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
742 },
743 [C(OP_PREFETCH)] = {
744 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
745 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
746 },
747 },
748 [C(LL)] = {
749 [C(OP_READ)] = {
750 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
751 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
752 },
753 [C(OP_WRITE)] = {
754 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
755 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
756 },
757 [C(OP_PREFETCH)] = {
758 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
759 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
760 },
761 },
762 [C(DTLB)] = {
763 [C(OP_READ)] = {
764 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
765 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
766 },
767 [C(OP_WRITE)] = {
768 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
769 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
770 },
771 [C(OP_PREFETCH)] = {
772 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
773 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
774 },
775 },
776 [C(ITLB)] = {
777 [C(OP_READ)] = {
778 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
779 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
780 },
781 [C(OP_WRITE)] = {
782 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
783 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
784 },
785 [C(OP_PREFETCH)] = {
786 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
787 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
788 },
789 },
790 [C(BPU)] = {
791 [C(OP_READ)] = {
792 [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
793 [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
794 },
795 [C(OP_WRITE)] = {
796 [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
797 [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
798 },
799 [C(OP_PREFETCH)] = {
800 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
801 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
802 },
803 },
804 [C(NODE)] = {
805 [C(OP_READ)] = {
806 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
807 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
808 },
809 [C(OP_WRITE)] = {
810 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
811 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
812 },
813 [C(OP_PREFETCH)] = {
814 [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
815 [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
816 },
817 },
818};735};
819 736
820/*737/*
@@ -1337,7 +1254,7 @@ static int armpmu_device_probe(struct platform_device *pdev) · 516 unmodified lines
1337 }1254 }
1338 1255
1339 for_each_possible_cpu(cpu)1256 for_each_possible_cpu(cpu)
1340 if (arch_find_n_match_cpu_physical_id(dn, cpu, NULL))1257 if (dn == of_cpu_device_node_get(cpu))
1341 break;1258 break;
1342 1259
1343 if (cpu >= nr_cpu_ids) {1260 if (cpu >= nr_cpu_ids) {
@@ -1415,180 +1332,3 @@ static int __init init_hw_perf_events(void) · 71 unmodified lines
1415}1332}
1416early_initcall(init_hw_perf_events);1333early_initcall(init_hw_perf_events);
1417 1334
1418/*
1419 * Callchain handling code.
1420 */
1421struct frame_tail {
1422 struct frame_tail __user *fp;
1423 unsigned long lr;
1424} __attribute__((packed));
1425
1426/*
1427 * Get the return address for a single stackframe and return a pointer to the
1428 * next frame tail.
1429 */
1430static struct frame_tail __user *
1431user_backtrace(struct frame_tail __user *tail,
1432 struct perf_callchain_entry *entry)
1433{
1434 struct frame_tail buftail;
1435 unsigned long err;
1436
1437 /* Also check accessibility of one struct frame_tail beyond */
1438 if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
1439 return NULL;
1440
1441 pagefault_disable();
1442 err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
1443 pagefault_enable();
1444
1445 if (err)
1446 return NULL;
1447
1448 perf_callchain_store(entry, buftail.lr);
1449
1450 /*
1451 * Frame pointers should strictly progress back up the stack
1452 * (towards higher addresses).
1453 */
1454 if (tail >= buftail.fp)
1455 return NULL;
1456
1457 return buftail.fp;
1458}
1459
1460#ifdef CONFIG_COMPAT
1461/*
1462 * The registers we're interested in are at the end of the variable
1463 * length saved register structure. The fp points at the end of this
1464 * structure so the address of this struct is:
1465 * (struct compat_frame_tail *)(xxx->fp)-1
1466 *
1467 * This code has been adapted from the ARM OProfile support.
1468 */
1469struct compat_frame_tail {
1470 compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */
1471 u32 sp;
1472 u32 lr;
1473} __attribute__((packed));
1474
1475static struct compat_frame_tail __user *
1476compat_user_backtrace(struct compat_frame_tail __user *tail,
1477 struct perf_callchain_entry *entry)
1478{
1479 struct compat_frame_tail buftail;
1480 unsigned long err;
1481
1482 /* Also check accessibility of one struct frame_tail beyond */
1483 if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
1484 return NULL;
1485
1486 pagefault_disable();
1487 err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
1488 pagefault_enable();
1489
1490 if (err)
1491 return NULL;
1492
1493 perf_callchain_store(entry, buftail.lr);
1494
1495 /*
1496 * Frame pointers should strictly progress back up the stack
1497 * (towards higher addresses).
1498 */
1499 if (tail + 1 >= (struct compat_frame_tail __user *)
1500 compat_ptr(buftail.fp))
1501 return NULL;
1502
1503 return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
1504}
1505#endif /* CONFIG_COMPAT */
1506
1507void perf_callchain_user(struct perf_callchain_entry *entry,
1508 struct pt_regs *regs)
1509{
1510 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1511 /* We don't support guest os callchain now */
1512 return;
1513 }
1514
1515 perf_callchain_store(entry, regs->pc);
1516
1517 if (!compat_user_mode(regs)) {
1518 /* AARCH64 mode */
1519 struct frame_tail __user *tail;
1520
1521 tail = (struct frame_tail __user *)regs->regs[29];
1522
1523 while (entry->nr < PERF_MAX_STACK_DEPTH &&
1524 tail && !((unsigned long)tail & 0xf))
1525 tail = user_backtrace(tail, entry);
1526 } else {
1527#ifdef CONFIG_COMPAT
1528 /* AARCH32 compat mode */
1529 struct compat_frame_tail __user *tail;
1530
1531 tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
1532
1533 while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
1534 tail && !((unsigned long)tail & 0x3))
1535 tail = compat_user_backtrace(tail, entry);
1536#endif
1537 }
1538}
1539
1540/*
1541 * Gets called by walk_stackframe() for every stackframe. This will be called
1542 * whist unwinding the stackframe and is like a subroutine return so we use
1543 * the PC.
1544 */
1545static int callchain_trace(struct stackframe *frame, void *data)
1546{
1547 struct perf_callchain_entry *entry = data;
1548 perf_callchain_store(entry, frame->pc);
1549 return 0;
1550}
1551
1552void perf_callchain_kernel(struct perf_callchain_entry *entry,
1553 struct pt_regs *regs)
1554{
1555 struct stackframe frame;
1556
1557 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1558 /* We don't support guest os callchain now */
1559 return;
1560 }
1561
1562 frame.fp = regs->regs[29];
1563 frame.sp = regs->sp;
1564 frame.pc = regs->pc;
1565
1566 walk_stackframe(&frame, callchain_trace, entry);
1567}
1568
1569unsigned long perf_instruction_pointer(struct pt_regs *regs)
1570{
1571 if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
1572 return perf_guest_cbs->get_guest_ip();
1573
1574 return instruction_pointer(regs);
1575}
1576
1577unsigned long perf_misc_flags(struct pt_regs *regs)
1578{
1579 int misc = 0;
1580
1581 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
1582 if (perf_guest_cbs->is_user_mode())
1583 misc |= PERF_RECORD_MISC_GUEST_USER;
1584 else
1585 misc |= PERF_RECORD_MISC_GUEST_KERNEL;
1586 } else {
1587 if (user_mode(regs))
1588 misc |= PERF_RECORD_MISC_USER;
1589 else
1590 misc |= PERF_RECORD_MISC_KERNEL;
1591 }
1592
1593 return misc;
1594}
arch/arm64/kernel/psci.c+0−5
@@ -110,8 +110,6 @@ free_mem: · 109 unmodified lines
110 return ret;110 return ret;
111}111}
112 112
113#ifdef CONFIG_SMP
114
115static int __init cpu_psci_cpu_init(unsigned int cpu)113static int __init cpu_psci_cpu_init(unsigned int cpu)
116{114{
117 return 0;115 return 0;
@@ -193,7 +191,6 @@ static int cpu_psci_cpu_kill(unsigned int cpu) · 75 unmodified lines
193 return -ETIMEDOUT;191 return -ETIMEDOUT;
194}192}
195#endif193#endif
196#endif
197 194
198static int psci_suspend_finisher(unsigned long index)195static int psci_suspend_finisher(unsigned long index)
199{196{
@@ -228,7 +225,6 @@ const struct cpu_operations cpu_psci_ops = { · 28 unmodified lines
228 .cpu_init_idle = cpu_psci_cpu_init_idle,225 .cpu_init_idle = cpu_psci_cpu_init_idle,
229 .cpu_suspend = cpu_psci_cpu_suspend,226 .cpu_suspend = cpu_psci_cpu_suspend,
230#endif227#endif
231#ifdef CONFIG_SMP
232 .cpu_init = cpu_psci_cpu_init,228 .cpu_init = cpu_psci_cpu_init,
233 .cpu_prepare = cpu_psci_cpu_prepare,229 .cpu_prepare = cpu_psci_cpu_prepare,
234 .cpu_boot = cpu_psci_cpu_boot,230 .cpu_boot = cpu_psci_cpu_boot,
@@ -237,6 +233,5 @@ const struct cpu_operations cpu_psci_ops = { · 2 unmodified lines
237 .cpu_die = cpu_psci_cpu_die,233 .cpu_die = cpu_psci_cpu_die,
238 .cpu_kill = cpu_psci_cpu_kill,234 .cpu_kill = cpu_psci_cpu_kill,
239#endif235#endif
240#endif
241};236};
242 237
arch/arm64/kernel/ptrace.c+91−1
@@ -826,6 +826,30 @@ static int compat_vfp_set(struct task_struct *target, · 825 unmodified lines
826 return ret;826 return ret;
827}827}
828 828
829static 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
837static 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
829static const struct user_regset aarch32_regsets[] = {853static const struct user_regset aarch32_regsets[] = {
830 [REGSET_COMPAT_GPR] = {854 [REGSET_COMPAT_GPR] = {
831 .core_note_type = NT_PRSTATUS,855 .core_note_type = NT_PRSTATUS,
@@ -850,6 +874,64 @@ static const struct user_regset_view user_aarch32_view = { · 18 unmodified lines
850 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)874 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
851};875};
852 876
877static const struct user_regset aarch32_ptrace_regsets[] = {
878 [REGSET_GPR] = {
879 .core_note_type = NT_PRSTATUS,
880 .n = COMPAT_ELF_NGREG,
881 .size = sizeof(compat_elf_greg_t),
882 .align = sizeof(compat_elf_greg_t),
883 .get = compat_gpr_get,
884 .set = compat_gpr_set
885 },
886 [REGSET_FPR] = {
887 .core_note_type = NT_ARM_VFP,
888 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
889 .size = sizeof(compat_ulong_t),
890 .align = sizeof(compat_ulong_t),
891 .get = compat_vfp_get,
892 .set = compat_vfp_set
893 },
894 [REGSET_TLS] = {
895 .core_note_type = NT_ARM_TLS,
896 .n = 1,
897 .size = sizeof(compat_ulong_t),
898 .align = sizeof(compat_ulong_t),
899 .get = compat_tls_get,
900 .set = compat_tls_set,
901 },
902#ifdef CONFIG_HAVE_HW_BREAKPOINT
903 [REGSET_HW_BREAK] = {
904 .core_note_type = NT_ARM_HW_BREAK,
905 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
906 .size = sizeof(u32),
907 .align = sizeof(u32),
908 .get = hw_break_get,
909 .set = hw_break_set,
910 },
911 [REGSET_HW_WATCH] = {
912 .core_note_type = NT_ARM_HW_WATCH,
913 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
914 .size = sizeof(u32),
915 .align = sizeof(u32),
916 .get = hw_break_get,
917 .set = hw_break_set,
918 },
919#endif
920 [REGSET_SYSTEM_CALL] = {
921 .core_note_type = NT_ARM_SYSTEM_CALL,
922 .n = 1,
923 .size = sizeof(int),
924 .align = sizeof(int),
925 .get = system_call_get,
926 .set = system_call_set,
927 },
928};
929
930static const struct user_regset_view user_aarch32_ptrace_view = {
931 .name = "aarch32", .e_machine = EM_ARM,
932 .regsets = aarch32_ptrace_regsets, .n = ARRAY_SIZE(aarch32_ptrace_regsets)
933};
934
853static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,935static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
854 compat_ulong_t __user *ret)936 compat_ulong_t __user *ret)
855{937{
@@ -1109,8 +1191,16 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, · 253 unmodified lines
1109const struct user_regset_view *task_user_regset_view(struct task_struct *task)1191const struct user_regset_view *task_user_regset_view(struct task_struct *task)
1110{1192{
1111#ifdef CONFIG_COMPAT1193#ifdef CONFIG_COMPAT
1112 if (is_compat_thread(task_thread_info(task)))1194 /*
1195 * Core dumping of 32-bit tasks or compat ptrace requests must use the
1196 * user_aarch32_view compatible with arm32. Native ptrace requests on
1197 * 32-bit children use an extended user_aarch32_ptrace_view to allow
1198 * access to the TLS register.
1199 */
1200 if (is_compat_task())
1113 return &user_aarch32_view;1201 return &user_aarch32_view;
1202 else if (is_compat_thread(task_thread_info(task)))
1203 return &user_aarch32_ptrace_view;
1114#endif1204#endif
1115 return &user_aarch64_view;1205 return &user_aarch64_view;
1116}1206}
arch/arm64/kernel/setup.c+34−51
@@ -62,7 +62,6 @@ · 61 unmodified lines
62#include <asm/traps.h>62#include <asm/traps.h>
63#include <asm/memblock.h>63#include <asm/memblock.h>
64#include <asm/efi.h>64#include <asm/efi.h>
65#include <asm/virt.h>
66#include <asm/xen/hypervisor.h>65#include <asm/xen/hypervisor.h>
67 66
68unsigned long elf_hwcap __read_mostly;67unsigned long elf_hwcap __read_mostly;
@@ -130,7 +129,6 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) · 61 unmodified lines
130}129}
131 130
132struct mpidr_hash mpidr_hash;131struct mpidr_hash mpidr_hash;
133#ifdef CONFIG_SMP
134/**132/**
135 * smp_build_mpidr_hash - Pre-compute shifts required at each affinity133 * smp_build_mpidr_hash - Pre-compute shifts required at each affinity
136 * level in order to build a linear index from an134 * level in order to build a linear index from an
@@ -196,35 +194,11 @@ static void __init smp_build_mpidr_hash(void) · 59 unmodified lines
196 pr_warn("Large number of MPIDR hash buckets detected\n");194 pr_warn("Large number of MPIDR hash buckets detected\n");
197 __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash));195 __flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash));
198}196}
199#endif
200
201static void __init hyp_mode_check(void)
202{
203 if (is_hyp_mode_available())
204 pr_info("CPU: All CPU(s) started at EL2\n");
205 else if (is_hyp_mode_mismatched())
206 WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC,
207 "CPU: CPUs started in inconsistent modes");
208 else
209 pr_info("CPU: All CPU(s) started at EL1\n");
210}
211
212void __init do_post_cpus_up_work(void)
213{
214 hyp_mode_check();
215 apply_alternatives_all();
216}
217
218#ifdef CONFIG_UP_LATE_INIT
219void __init up_late_init(void)
220{
221 do_post_cpus_up_work();
222}
223#endif /* CONFIG_UP_LATE_INIT */
224 197
225static void __init setup_processor(void)198static void __init setup_processor(void)
226{199{
227 u64 features, block;200 u64 features;
201 s64 block;
228 u32 cwg;202 u32 cwg;
229 int cls;203 int cls;
230 204
@@ -254,8 +228,8 @@ static void __init setup_processor(void) · 23 unmodified lines
254 * for non-negative values. Negative values are reserved.228 * for non-negative values. Negative values are reserved.
255 */229 */
256 features = read_cpuid(ID_AA64ISAR0_EL1);230 features = read_cpuid(ID_AA64ISAR0_EL1);
257 block = (features >> 4) & 0xf;231 block = cpuid_feature_extract_field(features, 4);
258 if (!(block & 0x8)) {232 if (block > 0) {
259 switch (block) {233 switch (block) {
260 default:234 default:
261 case 2:235 case 2:
@@ -267,26 +241,36 @@ static void __init setup_processor(void) · 5 unmodified lines
267 }241 }
268 }242 }
269 243
270 block = (features >> 8) & 0xf;244 if (cpuid_feature_extract_field(features, 8) > 0)
271 if (block && !(block & 0x8))
272 elf_hwcap |= HWCAP_SHA1;245 elf_hwcap |= HWCAP_SHA1;
273 246
274 block = (features >> 12) & 0xf;247 if (cpuid_feature_extract_field(features, 12) > 0)
275 if (block && !(block & 0x8))
276 elf_hwcap |= HWCAP_SHA2;248 elf_hwcap |= HWCAP_SHA2;
277 249
278 block = (features >> 16) & 0xf;250 if (cpuid_feature_extract_field(features, 16) > 0)
279 if (block && !(block & 0x8))
280 elf_hwcap |= HWCAP_CRC32;251 elf_hwcap |= HWCAP_CRC32;
281 252
253 block = cpuid_feature_extract_field(features, 20);
254 if (block > 0) {
255 switch (block) {
256 default:
257 case 2:
258 elf_hwcap |= HWCAP_ATOMICS;
259 case 1:
260 /* RESERVED */
261 case 0:
262 break;
263 }
264 }
265
282#ifdef CONFIG_COMPAT266#ifdef CONFIG_COMPAT
283 /*267 /*
284 * ID_ISAR5_EL1 carries similar information as above, but pertaining to268 * ID_ISAR5_EL1 carries similar information as above, but pertaining to
285 * the Aarch32 32-bit execution state.269 * the AArch32 32-bit execution state.
286 */270 */
287 features = read_cpuid(ID_ISAR5_EL1);271 features = read_cpuid(ID_ISAR5_EL1);
288 block = (features >> 4) & 0xf;272 block = cpuid_feature_extract_field(features, 4);
289 if (!(block & 0x8)) {273 if (block > 0) {
290 switch (block) {274 switch (block) {
291 default:275 default:
292 case 2:276 case 2:
@@ -298,16 +282,13 @@ static void __init setup_processor(void) · 5 unmodified lines
298 }282 }
299 }283 }
300 284
301 block = (features >> 8) & 0xf;285 if (cpuid_feature_extract_field(features, 8) > 0)
302 if (block && !(block & 0x8))
303 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1;286 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1;
304 287
305 block = (features >> 12) & 0xf;288 if (cpuid_feature_extract_field(features, 12) > 0)
306 if (block && !(block & 0x8))
307 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2;289 compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2;
308 290
309 block = (features >> 16) & 0xf;291 if (cpuid_feature_extract_field(features, 16) > 0)
310 if (block && !(block & 0x8))
311 compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32;292 compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32;
312#endif293#endif
313}294}
@@ -404,10 +385,8 @@ void __init setup_arch(char **cmdline_p) · 90 unmodified lines
404 xen_early_init();385 xen_early_init();
405 386
406 cpu_read_bootcpu_ops();387 cpu_read_bootcpu_ops();
407#ifdef CONFIG_SMP
408 smp_init_cpus();388 smp_init_cpus();
409 smp_build_mpidr_hash();389 smp_build_mpidr_hash();
410#endif
411 390
412#ifdef CONFIG_VT391#ifdef CONFIG_VT
413#if defined(CONFIG_VGA_CONSOLE)392#if defined(CONFIG_VGA_CONSOLE)
@@ -426,8 +405,13 @@ void __init setup_arch(char **cmdline_p) · 12 unmodified lines
426 405
427static int __init arm64_device_init(void)406static int __init arm64_device_init(void)
428{407{
429 of_iommu_init();408 if (of_have_populated_dt()) {
430 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);409 of_iommu_init();
410 of_platform_populate(NULL, of_default_bus_match_table,
411 NULL, NULL);
412 } else if (acpi_disabled) {
413 pr_crit("Device tree not populated\n");
414 }
431 return 0;415 return 0;
432}416}
433arch_initcall_sync(arm64_device_init);417arch_initcall_sync(arm64_device_init);
@@ -455,6 +439,7 @@ static const char *hwcap_str[] = { · 21 unmodified lines
455 "sha1",439 "sha1",
456 "sha2",440 "sha2",
457 "crc32",441 "crc32",
442 "atomics",
458 NULL443 NULL
459};444};
460 445
@@ -507,9 +492,7 @@ static int c_show(struct seq_file *m, void *v) · 46 unmodified lines
507 * online processors, looking for lines beginning with492 * online processors, looking for lines beginning with
508 * "processor". Give glibc what it expects.493 * "processor". Give glibc what it expects.
509 */494 */
510#ifdef CONFIG_SMP
511 seq_printf(m, "processor\t: %d\n", i);495 seq_printf(m, "processor\t: %d\n", i);
512#endif
513 496
514 /*497 /*
515 * Dump out the common processor features in a single line.498 * Dump out the common processor features in a single line.
arch/arm64/kernel/sleep.S+8−6
@@ -82,7 +82,6 @@ ENTRY(__cpu_suspend_enter) · 81 unmodified lines
82 str x2, [x0, #CPU_CTX_SP]82 str x2, [x0, #CPU_CTX_SP]
83 ldr x1, =sleep_save_sp83 ldr x1, =sleep_save_sp
84 ldr x1, [x1, #SLEEP_SAVE_SP_VIRT]84 ldr x1, [x1, #SLEEP_SAVE_SP_VIRT]
85#ifdef CONFIG_SMP
86 mrs x7, mpidr_el185 mrs x7, mpidr_el1
87 ldr x9, =mpidr_hash86 ldr x9, =mpidr_hash
88 ldr x10, [x9, #MPIDR_HASH_MASK]87 ldr x10, [x9, #MPIDR_HASH_MASK]
@@ -94,7 +93,6 @@ ENTRY(__cpu_suspend_enter) · 5 unmodified lines
94 ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)]93 ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)]
95 compute_mpidr_hash x8, x3, x4, x5, x6, x7, x1094 compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10
96 add x1, x1, x8, lsl #395 add x1, x1, x8, lsl #3
97#endif
98 bl __cpu_suspend_save96 bl __cpu_suspend_save
99 /*97 /*
100 * Grab suspend finisher in x20 and its argument in x1998 * Grab suspend finisher in x20 and its argument in x19
@@ -135,6 +133,14 @@ ENTRY(cpu_resume_mmu) · 34 unmodified lines
135 ldr x3, =cpu_resume_after_mmu133 ldr x3, =cpu_resume_after_mmu
136 msr sctlr_el1, x0 // restore sctlr_el1134 msr sctlr_el1, x0 // restore sctlr_el1
137 isb135 isb
136 /*
137 * Invalidate the local I-cache so that any instructions fetched
138 * speculatively from the PoC are discarded, since they may have
139 * been dynamically patched at the PoU.
140 */
141 ic iallu
142 dsb nsh
143 isb
138 br x3 // global jump to virtual address144 br x3 // global jump to virtual address
139ENDPROC(cpu_resume_mmu)145ENDPROC(cpu_resume_mmu)
140 .popsection146 .popsection
@@ -151,7 +157,6 @@ ENDPROC(cpu_resume_after_mmu) · 10 unmodified lines
151 157
152ENTRY(cpu_resume)158ENTRY(cpu_resume)
153 bl el2_setup // if in EL2 drop to EL1 cleanly159 bl el2_setup // if in EL2 drop to EL1 cleanly
154#ifdef CONFIG_SMP
155 mrs x1, mpidr_el1160 mrs x1, mpidr_el1
156 adrp x8, mpidr_hash161 adrp x8, mpidr_hash
157 add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address162 add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address
@@ -161,9 +166,6 @@ ENTRY(cpu_resume) · 3 unmodified lines
161 ldp w5, w6, [x8, #(MPIDR_HASH_SHIFTS + 8)]166 ldp w5, w6, [x8, #(MPIDR_HASH_SHIFTS + 8)]
162 compute_mpidr_hash x7, x3, x4, x5, x6, x1, x2167 compute_mpidr_hash x7, x3, x4, x5, x6, x1, x2
163 /* x7 contains hash index, let's use it to grab context pointer */168 /* x7 contains hash index, let's use it to grab context pointer */
164#else
165 mov x7, xzr
166#endif
167 ldr_l x0, sleep_save_sp + SLEEP_SAVE_SP_PHYS169 ldr_l x0, sleep_save_sp + SLEEP_SAVE_SP_PHYS
168 ldr x0, [x0, x7, lsl #3]170 ldr x0, [x0, x7, lsl #3]
169 /* load sp from context */171 /* load sp from context */
arch/arm64/kernel/smp.c+14−1
@@ -52,6 +52,7 @@ · 51 unmodified lines
52#include <asm/sections.h>52#include <asm/sections.h>
53#include <asm/tlbflush.h>53#include <asm/tlbflush.h>
54#include <asm/ptrace.h>54#include <asm/ptrace.h>
55#include <asm/virt.h>
55 56
56#define CREATE_TRACE_POINTS57#define CREATE_TRACE_POINTS
57#include <trace/events/ipi.h>58#include <trace/events/ipi.h>
@@ -310,10 +311,22 @@ void cpu_die(void) · 252 unmodified lines
310}311}
311#endif312#endif
312 313
314static void __init hyp_mode_check(void)
315{
316 if (is_hyp_mode_available())
317 pr_info("CPU: All CPU(s) started at EL2\n");
318 else if (is_hyp_mode_mismatched())
319 WARN_TAINT(1, TAINT_CPU_OUT_OF_SPEC,
320 "CPU: CPUs started in inconsistent modes");
321 else
322 pr_info("CPU: All CPU(s) started at EL1\n");
323}
324
313void __init smp_cpus_done(unsigned int max_cpus)325void __init smp_cpus_done(unsigned int max_cpus)
314{326{
315 pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());327 pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
316 do_post_cpus_up_work();328 hyp_mode_check();
329 apply_alternatives_all();
317}330}
318 331
319void __init smp_prepare_boot_cpu(void)332void __init smp_prepare_boot_cpu(void)
arch/arm64/kernel/time.c+0−2
@@ -42,7 +42,6 @@ · 41 unmodified lines
42#include <asm/thread_info.h>42#include <asm/thread_info.h>
43#include <asm/stacktrace.h>43#include <asm/stacktrace.h>
44 44
45#ifdef CONFIG_SMP
46unsigned long profile_pc(struct pt_regs *regs)45unsigned long profile_pc(struct pt_regs *regs)
47{46{
48 struct stackframe frame;47 struct stackframe frame;
@@ -62,7 +61,6 @@ unsigned long profile_pc(struct pt_regs *regs) · 13 unmodified lines
62 return frame.pc;61 return frame.pc;
63}62}
64EXPORT_SYMBOL(profile_pc);63EXPORT_SYMBOL(profile_pc);
65#endif
66 64
67void __init time_init(void)65void __init time_init(void)
68{66{
arch/arm64/kernel/topology.c+1−1
@@ -300,6 +300,6 @@ void __init init_cpu_topology(void) · 299 unmodified lines
300 * Discard anything that was parsed if we hit an error so we300 * Discard anything that was parsed if we hit an error so we
301 * don't use partial information.301 * don't use partial information.
302 */302 */
303 if (parse_dt_topology())303 if (of_have_populated_dt() && parse_dt_topology())
304 reset_cpu_topology();304 reset_cpu_topology();
305}305}
arch/arm64/kernel/traps.c+80−14
@@ -17,6 +17,7 @@ · 16 unmodified lines
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */18 */
19 19
20#include <linux/bug.h>
20#include <linux/signal.h>21#include <linux/signal.h>
21#include <linux/personality.h>22#include <linux/personality.h>
22#include <linux/kallsyms.h>23#include <linux/kallsyms.h>
@@ -32,8 +33,10 @@ · 9 unmodified lines
32#include <linux/syscalls.h>33#include <linux/syscalls.h>
33 34
34#include <asm/atomic.h>35#include <asm/atomic.h>
36#include <asm/bug.h>
35#include <asm/debug-monitors.h>37#include <asm/debug-monitors.h>
36#include <asm/esr.h>38#include <asm/esr.h>
39#include <asm/insn.h>
37#include <asm/traps.h>40#include <asm/traps.h>
38#include <asm/stacktrace.h>41#include <asm/stacktrace.h>
39#include <asm/exception.h>42#include <asm/exception.h>
@@ -52,11 +55,12 @@ int show_unhandled_signals = 1; · 12 unmodified lines
52 * Dump out the contents of some memory nicely...55 * Dump out the contents of some memory nicely...
53 */56 */
54static void dump_mem(const char *lvl, const char *str, unsigned long bottom,57static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
55 unsigned long top)58 unsigned long top, bool compat)
56{59{
57 unsigned long first;60 unsigned long first;
58 mm_segment_t fs;61 mm_segment_t fs;
59 int i;62 int i;
63 unsigned int width = compat ? 4 : 8;
60 64
61 /*65 /*
62 * We need to switch to kernel mode so that we can use __get_user66 * We need to switch to kernel mode so that we can use __get_user
@@ -75,13 +79,22 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, · 12 unmodified lines
75 memset(str, ' ', sizeof(str));79 memset(str, ' ', sizeof(str));
76 str[sizeof(str) - 1] = '\0';80 str[sizeof(str) - 1] = '\0';
77 81
78 for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {82 for (p = first, i = 0; i < (32 / width)
83 && p < top; i++, p += width) {
79 if (p >= bottom && p < top) {84 if (p >= bottom && p < top) {
80 unsigned int val;85 unsigned long val;
81 if (__get_user(val, (unsigned int *)p) == 0)86
82 sprintf(str + i * 9, " %08x", val);87 if (width == 8) {
83 else88 if (__get_user(val, (unsigned long *)p) == 0)
84 sprintf(str + i * 9, " ????????");89 sprintf(str + i * 17, " %016lx", val);
90 else
91 sprintf(str + i * 17, " ????????????????");
92 } else {
93 if (__get_user(val, (unsigned int *)p) == 0)
94 sprintf(str + i * 9, " %08lx", val);
95 else
96 sprintf(str + i * 9, " ????????");
97 }
85 }98 }
86 }99 }
87 printk("%s%04lx:%s\n", lvl, first & 0xffff, str);100 printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
@@ -95,7 +108,7 @@ static void dump_backtrace_entry(unsigned long where, unsigned long stack) · 7 unmodified lines
95 print_ip_sym(where);108 print_ip_sym(where);
96 if (in_exception_text(where))109 if (in_exception_text(where))
97 dump_mem("", "Exception stack", stack,110 dump_mem("", "Exception stack", stack,
98 stack + sizeof(struct pt_regs));111 stack + sizeof(struct pt_regs), false);
99}112}
100 113
101static void dump_instr(const char *lvl, struct pt_regs *regs)114static void dump_instr(const char *lvl, struct pt_regs *regs)
@@ -179,11 +192,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) · 77 unmodified lines
179#else192#else
180#define S_PREEMPT ""193#define S_PREEMPT ""
181#endif194#endif
182#ifdef CONFIG_SMP
183#define S_SMP " SMP"195#define S_SMP " SMP"
184#else
185#define S_SMP ""
186#endif
187 196
188static int __die(const char *str, int err, struct thread_info *thread,197static int __die(const char *str, int err, struct thread_info *thread,
189 struct pt_regs *regs)198 struct pt_regs *regs)
@@ -207,7 +216,8 @@ static int __die(const char *str, int err, struct thread_info *thread, · 17 unmodified lines
207 216
208 if (!user_mode(regs) || in_interrupt()) {217 if (!user_mode(regs) || in_interrupt()) {
209 dump_mem(KERN_EMERG, "Stack: ", regs->sp,218 dump_mem(KERN_EMERG, "Stack: ", regs->sp,
210 THREAD_SIZE + (unsigned long)task_stack_page(tsk));219 THREAD_SIZE + (unsigned long)task_stack_page(tsk),
220 compat_user_mode(regs));
211 dump_backtrace(regs, tsk);221 dump_backtrace(regs, tsk);
212 dump_instr(KERN_EMERG, regs);222 dump_instr(KERN_EMERG, regs);
213 }223 }
@@ -459,7 +469,63 @@ void __pgd_error(const char *file, int line, unsigned long val) · 245 unmodified lines
459 pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);469 pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);
460}470}
461 471
472/* GENERIC_BUG traps */
473
474int is_valid_bugaddr(unsigned long addr)
475{
476 /*
477 * bug_handler() only called for BRK #BUG_BRK_IMM.
478 * So the answer is trivial -- any spurious instances with no
479 * bug table entry will be rejected by report_bug() and passed
480 * back to the debug-monitors code and handled as a fatal
481 * unexpected debug exception.
482 */
483 return 1;
484}
485
486static int bug_handler(struct pt_regs *regs, unsigned int esr)
487{
488 if (user_mode(regs))
489 return DBG_HOOK_ERROR;
490
491 switch (report_bug(regs->pc, regs)) {
492 case BUG_TRAP_TYPE_BUG:
493 die("Oops - BUG", regs, 0);
494 break;
495
496 case BUG_TRAP_TYPE_WARN:
497 /* Ideally, report_bug() should backtrace for us... but no. */
498 dump_backtrace(regs, NULL);
499 break;
500
501 default:
502 /* unknown/unrecognised bug trap type */
503 return DBG_HOOK_ERROR;
504 }
505
506 /* If thread survives, skip over the BUG instruction and continue: */
507 regs->pc += AARCH64_INSN_SIZE; /* skip BRK and resume */
508 return DBG_HOOK_HANDLED;
509}
510
511static struct break_hook bug_break_hook = {
512 .esr_val = 0xf2000000 | BUG_BRK_IMM,
513 .esr_mask = 0xffffffff,
514 .fn = bug_handler,
515};
516
517/*
518 * Initial handler for AArch64 BRK exceptions
519 * This handler only used until debug_traps_init().
520 */
521int __init early_brk64(unsigned long addr, unsigned int esr,
522 struct pt_regs *regs)
523{
524 return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
525}
526
527/* This registration must happen early, before debug_traps_init(). */
462void __init trap_init(void)528void __init trap_init(void)
463{529{
464 return;530 register_break_hook(&bug_break_hook);
465}531}
arch/arm64/kvm/hyp.S+10−2
@@ -810,7 +810,11 @@ · 809 unmodified lines
810 * Call into the vgic backend for state saving810 * Call into the vgic backend for state saving
811 */811 */
812.macro save_vgic_state812.macro save_vgic_state
813 alternative_insn "bl __save_vgic_v2_state", "bl __save_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF813alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF
814 bl __save_vgic_v2_state
815alternative_else
816 bl __save_vgic_v3_state
817alternative_endif
814 mrs x24, hcr_el2818 mrs x24, hcr_el2
815 mov x25, #HCR_INT_OVERRIDE819 mov x25, #HCR_INT_OVERRIDE
816 neg x25, x25820 neg x25, x25
@@ -827,7 +831,11 @@ · 10 unmodified lines
827 orr x24, x24, #HCR_INT_OVERRIDE831 orr x24, x24, #HCR_INT_OVERRIDE
828 orr x24, x24, x25832 orr x24, x24, x25
829 msr hcr_el2, x24833 msr hcr_el2, x24
830 alternative_insn "bl __restore_vgic_v2_state", "bl __restore_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF834alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF
835 bl __restore_vgic_v2_state
836alternative_else
837 bl __restore_vgic_v3_state
838alternative_endif
831.endm839.endm
832 840
833.macro save_timer_state841.macro save_timer_state
arch/arm64/lib/Makefile+13−0
@@ -3,3 +3,16 @@ lib-y := bitops.o clear_user.o delay.o copy_from_user.o \ · 2 unmodified lines
3 clear_page.o memchr.o memcpy.o memmove.o memset.o \3 clear_page.o memchr.o memcpy.o memmove.o memset.o \
4 memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \4 memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \
5 strchr.o strrchr.o5 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.
12lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o
13CFLAGS_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
arch/arm64/lib/atomic_ll_sc.c+3−0
@@ -0,0 +1,3 @@
1#include <asm/atomic.h>
2#define __ARM64_IN_ATOMIC_IMPL
3#include <asm/atomic_ll_sc.h>
arch/arm64/lib/bitops.S+26−19
@@ -18,52 +18,59 @@ · 17 unmodified lines
18 18
19#include <linux/linkage.h>19#include <linux/linkage.h>
20#include <asm/assembler.h>20#include <asm/assembler.h>
21#include <asm/lse.h>
21 22
22/*23/*
23 * x0: bits 5:0 bit offset24 * x0: bits 5:0 bit offset
24 * bits 31:6 word offset25 * bits 31:6 word offset
25 * x1: address26 * x1: address
26 */27 */
27 .macro bitop, name, instr28 .macro bitop, name, llsc, lse
28ENTRY( \name )29ENTRY( \name )
29 and w3, w0, #63 // Get bit offset30 and w3, w0, #63 // Get bit offset
30 eor w0, w0, w3 // Clear low bits31 eor w0, w0, w3 // Clear low bits
31 mov x2, #132 mov x2, #1
32 add x1, x1, x0, lsr #3 // Get word offset33 add x1, x1, x0, lsr #3 // Get word offset
34alt_lse " prfm pstl1strm, [x1]", "nop"
33 lsl x3, x2, x3 // Create mask35 lsl x3, x2, x3 // Create mask
341: ldxr x2, [x1]36
35 \instr x2, x2, x337alt_lse "1: ldxr x2, [x1]", "\lse x3, [x1]"
36 stxr w0, x2, [x1]38alt_lse " \llsc x2, x2, x3", "nop"
37 cbnz w0, 1b39alt_lse " stxr w0, x2, [x1]", "nop"
40alt_lse " cbnz w0, 1b", "nop"
41
38 ret42 ret
39ENDPROC(\name )43ENDPROC(\name )
40 .endm44 .endm
41 45
42 .macro testop, name, instr46 .macro testop, name, llsc, lse
43ENTRY( \name )47ENTRY( \name )
44 and w3, w0, #63 // Get bit offset48 and w3, w0, #63 // Get bit offset
45 eor w0, w0, w3 // Clear low bits49 eor w0, w0, w3 // Clear low bits
46 mov x2, #150 mov x2, #1
47 add x1, x1, x0, lsr #3 // Get word offset51 add x1, x1, x0, lsr #3 // Get word offset
52alt_lse " prfm pstl1strm, [x1]", "nop"
48 lsl x4, x2, x3 // Create mask53 lsl x4, x2, x3 // Create mask
491: ldxr x2, [x1]54
50 lsr x0, x2, x3 // Save old value of bit55alt_lse "1: ldxr x2, [x1]", "\lse x4, x2, [x1]"
51 \instr x2, x2, x4 // toggle bit56 lsr x0, x2, x3
52 stlxr w5, x2, [x1]57alt_lse " \llsc x2, x2, x4", "nop"
53 cbnz w5, 1b58alt_lse " stlxr w5, x2, [x1]", "nop"
54 dmb ish59alt_lse " cbnz w5, 1b", "nop"
60alt_lse " dmb ish", "nop"
61
55 and x0, x0, #162 and x0, x0, #1
563: ret63 ret
57ENDPROC(\name )64ENDPROC(\name )
58 .endm65 .endm
59 66
60/*67/*
61 * Atomic bit operations.68 * Atomic bit operations.
62 */69 */
63 bitop change_bit, eor70 bitop change_bit, eor, steor
64 bitop clear_bit, bic71 bitop clear_bit, bic, stclr
65 bitop set_bit, orr72 bitop set_bit, orr, stset
66 73
67 testop test_and_change_bit, eor74 testop test_and_change_bit, eor, ldeoral
68 testop test_and_clear_bit, bic75 testop test_and_clear_bit, bic, ldclral
69 testop test_and_set_bit, orr76 testop test_and_set_bit, orr, ldsetal
arch/arm64/lib/clear_user.S+8−0
@@ -16,7 +16,11 @@ · 15 unmodified lines
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
18#include <linux/linkage.h>18#include <linux/linkage.h>
19
20#include <asm/alternative.h>
19#include <asm/assembler.h>21#include <asm/assembler.h>
22#include <asm/cpufeature.h>
23#include <asm/sysreg.h>
20 24
21 .text25 .text
22 26
@@ -29,6 +33,8 @@ · 6 unmodified lines
29 * Alignment fixed up by hardware.33 * Alignment fixed up by hardware.
30 */34 */
31ENTRY(__clear_user)35ENTRY(__clear_user)
36ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
37 CONFIG_ARM64_PAN)
32 mov x2, x1 // save the size for fixup return38 mov x2, x1 // save the size for fixup return
33 subs x1, x1, #839 subs x1, x1, #8
34 b.mi 2f40 b.mi 2f
@@ -48,6 +54,8 @@ USER(9f, strh wzr, [x0], #2 ) · 13 unmodified lines
48 b.mi 5f54 b.mi 5f
49USER(9f, strb wzr, [x0] )55USER(9f, strb wzr, [x0] )
505: mov x0, #0565: mov x0, #0
57ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
58 CONFIG_ARM64_PAN)
51 ret59 ret
52ENDPROC(__clear_user)60ENDPROC(__clear_user)
53 61
arch/arm64/lib/copy_from_user.S+19−6
@@ -15,7 +15,11 @@ · 14 unmodified lines
15 */15 */
16 16
17#include <linux/linkage.h>17#include <linux/linkage.h>
18
19#include <asm/alternative.h>
18#include <asm/assembler.h>20#include <asm/assembler.h>
21#include <asm/cpufeature.h>
22#include <asm/sysreg.h>
19 23
20/*24/*
21 * Copy from user space to a kernel buffer (alignment handled by the hardware)25 * Copy from user space to a kernel buffer (alignment handled by the hardware)
@@ -28,14 +32,21 @@ · 6 unmodified lines
28 * x0 - bytes not copied32 * x0 - bytes not copied
29 */33 */
30ENTRY(__copy_from_user)34ENTRY(__copy_from_user)
31 add x4, x1, x2 // upper user buffer boundary35ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
32 subs x2, x2, #836 CONFIG_ARM64_PAN)
37 add x5, x1, x2 // upper user buffer boundary
38 subs x2, x2, #16
39 b.mi 1f
400:
41USER(9f, ldp x3, x4, [x1], #16)
42 subs x2, x2, #16
43 stp x3, x4, [x0], #16
44 b.pl 0b
451: adds x2, x2, #8
33 b.mi 2f46 b.mi 2f
341:
35USER(9f, ldr x3, [x1], #8 )47USER(9f, ldr x3, [x1], #8 )
36 subs x2, x2, #848 sub x2, x2, #8
37 str x3, [x0], #849 str x3, [x0], #8
38 b.pl 1b
392: adds x2, x2, #4502: adds x2, x2, #4
40 b.mi 3f51 b.mi 3f
41USER(9f, ldr w3, [x1], #4 )52USER(9f, ldr w3, [x1], #4 )
@@ -51,12 +62,14 @@ USER(9f, ldrh w3, [x1], #2 ) · 9 unmodified lines
51USER(9f, ldrb w3, [x1] )62USER(9f, ldrb w3, [x1] )
52 strb w3, [x0]63 strb w3, [x0]
535: mov x0, #0645: mov x0, #0
65ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
66 CONFIG_ARM64_PAN)
54 ret67 ret
55ENDPROC(__copy_from_user)68ENDPROC(__copy_from_user)
56 69
57 .section .fixup,"ax"70 .section .fixup,"ax"
58 .align 271 .align 2
599: sub x2, x4, x1729: sub x2, x5, x1
60 mov x3, x273 mov x3, x2
6110: strb wzr, [x0], #1 // zero remaining buffer space7410: strb wzr, [x0], #1 // zero remaining buffer space
62 subs x3, x3, #175 subs x3, x3, #1
arch/arm64/lib/copy_in_user.S+19−6
@@ -17,7 +17,11 @@ · 16 unmodified lines
17 */17 */
18 18
19#include <linux/linkage.h>19#include <linux/linkage.h>
20
21#include <asm/alternative.h>
20#include <asm/assembler.h>22#include <asm/assembler.h>
23#include <asm/cpufeature.h>
24#include <asm/sysreg.h>
21 25
22/*26/*
23 * Copy from user space to user space (alignment handled by the hardware)27 * Copy from user space to user space (alignment handled by the hardware)
@@ -30,14 +34,21 @@ · 6 unmodified lines
30 * x0 - bytes not copied34 * x0 - bytes not copied
31 */35 */
32ENTRY(__copy_in_user)36ENTRY(__copy_in_user)
33 add x4, x0, x2 // upper user buffer boundary37ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
34 subs x2, x2, #838 CONFIG_ARM64_PAN)
39 add x5, x0, x2 // upper user buffer boundary
40 subs x2, x2, #16
41 b.mi 1f
420:
43USER(9f, ldp x3, x4, [x1], #16)
44 subs x2, x2, #16
45USER(9f, stp x3, x4, [x0], #16)
46 b.pl 0b
471: adds x2, x2, #8
35 b.mi 2f48 b.mi 2f
361:
37USER(9f, ldr x3, [x1], #8 )49USER(9f, ldr x3, [x1], #8 )
38 subs x2, x2, #850 sub x2, x2, #8
39USER(9f, str x3, [x0], #8 )51USER(9f, str x3, [x0], #8 )
40 b.pl 1b
412: adds x2, x2, #4522: adds x2, x2, #4
42 b.mi 3f53 b.mi 3f
43USER(9f, ldr w3, [x1], #4 )54USER(9f, ldr w3, [x1], #4 )
@@ -53,11 +64,13 @@ USER(9f, strh w3, [x0], #2 ) · 9 unmodified lines
53USER(9f, ldrb w3, [x1] )64USER(9f, ldrb w3, [x1] )
54USER(9f, strb w3, [x0] )65USER(9f, strb w3, [x0] )
555: mov x0, #0665: mov x0, #0
67ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
68 CONFIG_ARM64_PAN)
56 ret69 ret
57ENDPROC(__copy_in_user)70ENDPROC(__copy_in_user)
58 71
59 .section .fixup,"ax"72 .section .fixup,"ax"
60 .align 273 .align 2
619: sub x0, x4, x0 // bytes not copied749: sub x0, x5, x0 // bytes not copied
62 ret75 ret
63 .previous76 .previous
arch/arm64/lib/copy_to_user.S+19−6
@@ -15,7 +15,11 @@ · 14 unmodified lines
15 */15 */
16 16
17#include <linux/linkage.h>17#include <linux/linkage.h>
18
19#include <asm/alternative.h>
18#include <asm/assembler.h>20#include <asm/assembler.h>
21#include <asm/cpufeature.h>
22#include <asm/sysreg.h>
19 23
20/*24/*
21 * Copy to user space from a kernel buffer (alignment handled by the hardware)25 * Copy to user space from a kernel buffer (alignment handled by the hardware)
@@ -28,14 +32,21 @@ · 6 unmodified lines
28 * x0 - bytes not copied32 * x0 - bytes not copied
29 */33 */
30ENTRY(__copy_to_user)34ENTRY(__copy_to_user)
31 add x4, x0, x2 // upper user buffer boundary35ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
32 subs x2, x2, #836 CONFIG_ARM64_PAN)
37 add x5, x0, x2 // upper user buffer boundary
38 subs x2, x2, #16
39 b.mi 1f
400:
41 ldp x3, x4, [x1], #16
42 subs x2, x2, #16
43USER(9f, stp x3, x4, [x0], #16)
44 b.pl 0b
451: adds x2, x2, #8
33 b.mi 2f46 b.mi 2f
341:
35 ldr x3, [x1], #847 ldr x3, [x1], #8
36 subs x2, x2, #848 sub x2, x2, #8
37USER(9f, str x3, [x0], #8 )49USER(9f, str x3, [x0], #8 )
38 b.pl 1b
392: adds x2, x2, #4502: adds x2, x2, #4
40 b.mi 3f51 b.mi 3f
41 ldr w3, [x1], #452 ldr w3, [x1], #4
@@ -51,11 +62,13 @@ USER(9f, strh w3, [x0], #2 ) · 9 unmodified lines
51 ldrb w3, [x1]62 ldrb w3, [x1]
52USER(9f, strb w3, [x0] )63USER(9f, strb w3, [x0] )
535: mov x0, #0645: mov x0, #0
65ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
66 CONFIG_ARM64_PAN)
54 ret67 ret
55ENDPROC(__copy_to_user)68ENDPROC(__copy_to_user)
56 69
57 .section .fixup,"ax"70 .section .fixup,"ax"
58 .align 271 .align 2
599: sub x0, x4, x0 // bytes not copied729: sub x0, x5, x0 // bytes not copied
60 ret73 ret
61 .previous74 .previous
arch/arm64/mm/cache.S+6−1
@@ -143,7 +143,12 @@ __dma_clean_range: · 142 unmodified lines
143 dcache_line_size x2, x3143 dcache_line_size x2, x3
144 sub x3, x2, #1144 sub x3, x2, #1
145 bic x0, x0, x3145 bic x0, x0, x3
1461: alternative_insn "dc cvac, x0", "dc civac, x0", ARM64_WORKAROUND_CLEAN_CACHE1461:
147alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
148 dc cvac, x0
149alternative_else
150 dc civac, x0
151alternative_endif
147 add x0, x0, x2152 add x0, x0, x2
148 cmp x0, x1153 cmp x0, x1
149 b.lo 1b154 b.lo 1b
arch/arm64/mm/context.c+0−16
@@ -53,8 +53,6 @@ static void flush_context(void) · 52 unmodified lines
53 __flush_icache_all();53 __flush_icache_all();
54}54}
55 55
56#ifdef CONFIG_SMP
57
58static void set_mm_context(struct mm_struct *mm, unsigned int asid)56static void set_mm_context(struct mm_struct *mm, unsigned int asid)
59{57{
60 unsigned long flags;58 unsigned long flags;
@@ -110,23 +108,12 @@ static void reset_context(void *info) · 49 unmodified lines
110 cpu_switch_mm(mm->pgd, mm);108 cpu_switch_mm(mm->pgd, mm);
111}109}
112 110
113#else
114
115static inline void set_mm_context(struct mm_struct *mm, unsigned int asid)
116{
117 mm->context.id = asid;
118 cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
119}
120
121#endif
122
123void __new_context(struct mm_struct *mm)111void __new_context(struct mm_struct *mm)
124{112{
125 unsigned int asid;113 unsigned int asid;
126 unsigned int bits = asid_bits();114 unsigned int bits = asid_bits();
127 115
128 raw_spin_lock(&cpu_asid_lock);116 raw_spin_lock(&cpu_asid_lock);
129#ifdef CONFIG_SMP
130 /*117 /*
131 * Check the ASID again, in case the change was broadcast from another118 * Check the ASID again, in case the change was broadcast from another
132 * CPU before we acquired the lock.119 * CPU before we acquired the lock.
@@ -136,7 +123,6 @@ void __new_context(struct mm_struct *mm) · 3 unmodified lines
136 raw_spin_unlock(&cpu_asid_lock);123 raw_spin_unlock(&cpu_asid_lock);
137 return;124 return;
138 }125 }
139#endif
140 /*126 /*
141 * At this point, it is guaranteed that the current mm (with an old127 * At this point, it is guaranteed that the current mm (with an old
142 * ASID) isn't active on any other CPU since the ASIDs are changed128 * ASID) isn't active on any other CPU since the ASIDs are changed
@@ -155,10 +141,8 @@ void __new_context(struct mm_struct *mm) · 12 unmodified lines
155 cpu_last_asid = ASID_FIRST_VERSION;141 cpu_last_asid = ASID_FIRST_VERSION;
156 asid = cpu_last_asid + smp_processor_id();142 asid = cpu_last_asid + smp_processor_id();
157 flush_context();143 flush_context();
158#ifdef CONFIG_SMP
159 smp_wmb();144 smp_wmb();
160 smp_call_function(reset_context, NULL, 1);145 smp_call_function(reset_context, NULL, 1);
161#endif
162 cpu_last_asid += NR_CPUS - 1;146 cpu_last_asid += NR_CPUS - 1;
163 }147 }
164 148
arch/arm64/mm/dma-mapping.c+20−13
@@ -144,6 +144,7 @@ static void *__dma_alloc(struct device *dev, size_t size, · 143 unmodified lines
144 struct page *page;144 struct page *page;
145 void *ptr, *coherent_ptr;145 void *ptr, *coherent_ptr;
146 bool coherent = is_device_dma_coherent(dev);146 bool coherent = is_device_dma_coherent(dev);
147 pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false);
147 148
148 size = PAGE_ALIGN(size);149 size = PAGE_ALIGN(size);
149 150
@@ -171,9 +172,7 @@ static void *__dma_alloc(struct device *dev, size_t size, · 21 unmodified lines
171 /* create a coherent mapping */172 /* create a coherent mapping */
172 page = virt_to_page(ptr);173 page = virt_to_page(ptr);
173 coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,174 coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
174 __get_dma_pgprot(attrs,175 prot, NULL);
175 __pgprot(PROT_NORMAL_NC), false),
176 NULL);
177 if (!coherent_ptr)176 if (!coherent_ptr)
178 goto no_map;177 goto no_map;
179 178
@@ -303,9 +302,10 @@ static void __swiotlb_sync_sg_for_device(struct device *dev, · 123 unmodified lines
303 sg->length, dir);302 sg->length, dir);
304}303}
305 304
306/* vma->vm_page_prot must be set appropriately before calling this function */305static int __swiotlb_mmap(struct device *dev,
307static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma,306 struct vm_area_struct *vma,
308 void *cpu_addr, dma_addr_t dma_addr, size_t size)307 void *cpu_addr, dma_addr_t dma_addr, size_t size,
308 struct dma_attrs *attrs)
309{309{
310 int ret = -ENXIO;310 int ret = -ENXIO;
311 unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>311 unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
@@ -314,6 +314,9 @@ static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, · 2 unmodified lines
314 unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;314 unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
315 unsigned long off = vma->vm_pgoff;315 unsigned long off = vma->vm_pgoff;
316 316
317 vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
318 is_device_dma_coherent(dev));
319
317 if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))320 if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
318 return ret;321 return ret;
319 322
@@ -327,20 +330,24 @@ static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, · 7 unmodified lines
327 return ret;330 return ret;
328}331}
329 332
330static int __swiotlb_mmap(struct device *dev,333static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
331 struct vm_area_struct *vma,334 void *cpu_addr, dma_addr_t handle, size_t size,
332 void *cpu_addr, dma_addr_t dma_addr, size_t size,335 struct dma_attrs *attrs)
333 struct dma_attrs *attrs)
334{336{
335 vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,337 int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
336 is_device_dma_coherent(dev));338
337 return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);339 if (!ret)
340 sg_set_page(sgt->sgl, phys_to_page(dma_to_phys(dev, handle)),
341 PAGE_ALIGN(size), 0);
342
343 return ret;
338}344}
339 345
340static struct dma_map_ops swiotlb_dma_ops = {346static struct dma_map_ops swiotlb_dma_ops = {
341 .alloc = __dma_alloc,347 .alloc = __dma_alloc,
342 .free = __dma_free,348 .free = __dma_free,
343 .mmap = __swiotlb_mmap,349 .mmap = __swiotlb_mmap,
350 .get_sgtable = __swiotlb_get_sgtable,
344 .map_page = __swiotlb_map_page,351 .map_page = __swiotlb_map_page,
345 .unmap_page = __swiotlb_unmap_page,352 .unmap_page = __swiotlb_unmap_page,
346 .map_sg = __swiotlb_map_sg_attrs,353 .map_sg = __swiotlb_map_sg_attrs,
arch/arm64/mm/fault.c+26−2
@@ -30,9 +30,11 @@ · 29 unmodified lines
30#include <linux/highmem.h>30#include <linux/highmem.h>
31#include <linux/perf_event.h>31#include <linux/perf_event.h>
32 32
33#include <asm/cpufeature.h>
33#include <asm/exception.h>34#include <asm/exception.h>
34#include <asm/debug-monitors.h>35#include <asm/debug-monitors.h>
35#include <asm/esr.h>36#include <asm/esr.h>
37#include <asm/sysreg.h>
36#include <asm/system_misc.h>38#include <asm/system_misc.h>
37#include <asm/pgtable.h>39#include <asm/pgtable.h>
38#include <asm/tlbflush.h>40#include <asm/tlbflush.h>
@@ -223,6 +225,13 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, · 184 unmodified lines
223 mm_flags |= FAULT_FLAG_WRITE;225 mm_flags |= FAULT_FLAG_WRITE;
224 }226 }
225 227
228 /*
229 * PAN bit set implies the fault happened in kernel space, but not
230 * in the arch's user access functions.
231 */
232 if (IS_ENABLED(CONFIG_ARM64_PAN) && (regs->pstate & PSR_PAN_BIT))
233 goto no_context;
234
226 /*235 /*
227 * As per x86, we may deadlock here. However, since the kernel only236 * As per x86, we may deadlock here. However, since the kernel only
228 * validly references user space from well defined areas of the code,237 * validly references user space from well defined areas of the code,
@@ -492,14 +501,22 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr, · 263 unmodified lines
492 arm64_notify_die("Oops - SP/PC alignment exception", regs, &info, esr);501 arm64_notify_die("Oops - SP/PC alignment exception", regs, &info, esr);
493}502}
494 503
495static struct fault_info debug_fault_info[] = {504int __init early_brk64(unsigned long addr, unsigned int esr,
505 struct pt_regs *regs);
506
507/*
508 * __refdata because early_brk64 is __init, but the reference to it is
509 * clobbered at arch_initcall time.
510 * See traps.c and debug-monitors.c:debug_traps_init().
511 */
512static struct fault_info __refdata debug_fault_info[] = {
496 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" },513 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" },
497 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" },514 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" },
498 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" },515 { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" },
499 { do_bad, SIGBUS, 0, "unknown 3" },516 { do_bad, SIGBUS, 0, "unknown 3" },
500 { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" },517 { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" },
501 { do_bad, SIGTRAP, 0, "aarch32 vector catch" },518 { do_bad, SIGTRAP, 0, "aarch32 vector catch" },
502 { do_bad, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" },519 { early_brk64, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" },
503 { do_bad, SIGBUS, 0, "unknown 7" },520 { do_bad, SIGBUS, 0, "unknown 7" },
504};521};
505 522
@@ -536,3 +553,10 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, · 30 unmodified lines
536 553
537 return 0;554 return 0;
538}555}
556
557#ifdef CONFIG_ARM64_PAN
558void cpu_enable_pan(void)
559{
560 config_sctlr_el1(SCTLR_EL1_SPAN, 0);
561}
562#endif /* CONFIG_ARM64_PAN */
arch/arm64/mm/flush.c+0−4
@@ -60,14 +60,10 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, · 59 unmodified lines
60 unsigned long uaddr, void *dst, const void *src,60 unsigned long uaddr, void *dst, const void *src,
61 unsigned long len)61 unsigned long len)
62{62{
63#ifdef CONFIG_SMP
64 preempt_disable();63 preempt_disable();
65#endif
66 memcpy(dst, src, len);64 memcpy(dst, src, len);
67 flush_ptrace_access(vma, page, uaddr, dst, len);65 flush_ptrace_access(vma, page, uaddr, dst, len);
68#ifdef CONFIG_SMP
69 preempt_enable();66 preempt_enable();
70#endif
71}67}
72 68
73void __sync_icache_dcache(pte_t pte, unsigned long addr)69void __sync_icache_dcache(pte_t pte, unsigned long addr)
arch/arm64/mm/hugetlbpage.c+0−4
@@ -13,10 +13,6 @@ · 12 unmodified lines
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.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#include <linux/init.h>18#include <linux/init.h>
arch/arm64/mm/init.c+2−2
@@ -358,9 +358,9 @@ void free_initmem(void) · 357 unmodified lines
358 358
359#ifdef CONFIG_BLK_DEV_INITRD359#ifdef CONFIG_BLK_DEV_INITRD
360 360
361static int keep_initrd;361static int keep_initrd __initdata;
362 362
363void free_initrd_mem(unsigned long start, unsigned long end)363void __init free_initrd_mem(unsigned long start, unsigned long end)
364{364{
365 if (!keep_initrd)365 if (!keep_initrd)
366 free_reserved_area((void *)start, (void *)end, 0, "initrd");366 free_reserved_area((void *)start, (void *)end, 0, "initrd");
arch/arm64/mm/mmu.c+1−12
@@ -267,7 +267,7 @@ static void *late_alloc(unsigned long size) · 266 unmodified lines
267 return ptr;267 return ptr;
268}268}
269 269
270static void __ref create_mapping(phys_addr_t phys, unsigned long virt,270static void __init create_mapping(phys_addr_t phys, unsigned long virt,
271 phys_addr_t size, pgprot_t prot)271 phys_addr_t size, pgprot_t prot)
272{272{
273 if (virt < VMALLOC_START) {273 if (virt < VMALLOC_START) {
@@ -460,17 +460,6 @@ void __init paging_init(void) · 186 unmodified lines
460 cpu_set_default_tcr_t0sz();460 cpu_set_default_tcr_t0sz();
461}461}
462 462
463/*
464 * Enable the identity mapping to allow the MMU disabling.
465 */
466void 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}
473
474/*463/*
475 * Check whether a kernel address is valid (derived from arch/x86/).464 * Check whether a kernel address is valid (derived from arch/x86/).
476 */465 */
arch/arm64/mm/proc.S+15−6
@@ -34,11 +34,7 @@ · 33 unmodified lines
34#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K34#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K
35#endif35#endif
36 36
37#ifdef CONFIG_SMP
38#define TCR_SMP_FLAGS TCR_SHARED37#define TCR_SMP_FLAGS TCR_SHARED
39#else
40#define TCR_SMP_FLAGS 0
41#endif
42 38
43/* PTWs cacheable, inner/outer WBWA */39/* PTWs cacheable, inner/outer WBWA */
44#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA40#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA
@@ -150,13 +146,13 @@ ENDPROC(cpu_do_switch_mm) · 105 unmodified lines
150 * value of the SCTLR_EL1 register.146 * value of the SCTLR_EL1 register.
151 */147 */
152ENTRY(__cpu_setup)148ENTRY(__cpu_setup)
153 ic iallu // I+BTB cache invalidate
154 tlbi vmalle1is // invalidate I + D TLBs149 tlbi vmalle1is // invalidate I + D TLBs
155 dsb ish150 dsb ish
156 151
157 mov x0, #3 << 20152 mov x0, #3 << 20
158 msr cpacr_el1, x0 // Enable FP/ASIMD153 msr cpacr_el1, x0 // Enable FP/ASIMD
159 msr mdscr_el1, xzr // Reset mdscr_el1154 mov x0, #1 << 12 // Reset mdscr_el1 and disable
155 msr mdscr_el1, x0 // access to the DCC from EL0
160 /*156 /*
161 * Memory region attributes for LPAE:157 * Memory region attributes for LPAE:
162 *158 *
@@ -196,6 +192,19 @@ ENTRY(__cpu_setup) · 33 unmodified lines
196 */192 */
197 mrs x9, ID_AA64MMFR0_EL1193 mrs x9, ID_AA64MMFR0_EL1
198 bfi x10, x9, #32, #3194 bfi x10, x9, #32, #3
195#ifdef CONFIG_ARM64_HW_AFDBM
196 /*
197 * Hardware update of the Access and Dirty bits.
198 */
199 mrs x9, ID_AA64MMFR1_EL1
200 and x9, x9, #0xf
201 cbz x9, 2f
202 cmp x9, #2
203 b.lt 1f
204 orr x10, x10, #TCR_HD // hardware Dirty flag update
2051: orr x10, x10, #TCR_HA // hardware Access flag update
2062:
207#endif /* CONFIG_ARM64_HW_AFDBM */
199 msr tcr_el1, x10208 msr tcr_el1, x10
200 ret // return to head.S209 ret // return to head.S
201ENDPROC(__cpu_setup)210ENDPROC(__cpu_setup)
drivers/of/fdt.c+7−5
@@ -967,7 +967,9 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, · 966 unmodified lines
967}967}
968 968
969#ifdef CONFIG_HAVE_MEMBLOCK969#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
972void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)974void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
973{975{
@@ -984,16 +986,16 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) · 10 unmodified lines
984 }986 }
985 size &= PAGE_MASK;987 size &= PAGE_MASK;
986 988
987 if (base > MAX_PHYS_ADDR) {989 if (base > MAX_MEMBLOCK_ADDR) {
988 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",990 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
989 base, base + size);991 base, base + size);
990 return;992 return;
991 }993 }
992 994
993 if (base + size - 1 > MAX_PHYS_ADDR) {995 if (base + size - 1 > MAX_MEMBLOCK_ADDR) {
994 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",996 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
995 ((u64)MAX_PHYS_ADDR) + 1, base + size);997 ((u64)MAX_MEMBLOCK_ADDR) + 1, base + size);
996 size = MAX_PHYS_ADDR - base + 1;998 size = MAX_MEMBLOCK_ADDR - base + 1;
997 }999 }
998 1000
999 if (base + size < phys_offset) {1001 if (base + size < phys_offset) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t