aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-11-14 17:24:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-11-14 17:24:33 -0500
commit0861fd1c25a8ce79ae7647e384cb6555c46e1690 (patch)
tree37cb316d5c8efd0cbb764c9080f10ff902b3c11c
parent5ae93760cbedda64eab0a7012cc3785c32399641 (diff)
parent5fd6690c8fb2c3012012979dd8ce7492c69c5d86 (diff)
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Catalin Marinas: - fix EFI stub cache maintenance causing aborts during boot on certain platforms - handle byte stores in __clear_user without panicking - fix race condition in aarch64_insn_patch_text_sync() (instruction patching) - Couple of type fixes * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: ARCH_PFN_OFFSET should be unsigned long Correct the race condition in aarch64_insn_patch_text_sync() arm64: __clear_user: handle exceptions on strb arm64: Fix data type for physical address arm64: efi: Fix stub cache maintenance
-rw-r--r--arch/arm64/include/asm/memory.h2
-rw-r--r--arch/arm64/kernel/efi-entry.S27
-rw-r--r--arch/arm64/kernel/insn.c5
-rw-r--r--arch/arm64/lib/clear_user.S2
-rw-r--r--arch/arm64/mm/mmu.c2
5 files changed, 27 insertions, 11 deletions
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index ccc7087d3c4e..a62cd077457b 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -142,7 +142,7 @@ static inline void *phys_to_virt(phys_addr_t x)
142 * virt_to_page(k) convert a _valid_ virtual address to struct page * 142 * virt_to_page(k) convert a _valid_ virtual address to struct page *
143 * virt_addr_valid(k) indicates whether a virtual address is valid 143 * virt_addr_valid(k) indicates whether a virtual address is valid
144 */ 144 */
145#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET 145#define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET)
146 146
147#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) 147#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
148#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) 148#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index 619b1dd7bcde..d18a44940968 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -54,18 +54,17 @@ ENTRY(efi_stub_entry)
54 b.eq efi_load_fail 54 b.eq efi_load_fail
55 55
56 /* 56 /*
57 * efi_entry() will have relocated the kernel image if necessary 57 * efi_entry() will have copied the kernel image if necessary and we
58 * and we return here with device tree address in x0 and the kernel 58 * return here with device tree address in x0 and the kernel entry
59 * entry point stored at *image_addr. Save those values in registers 59 * point stored at *image_addr. Save those values in registers which
60 * which are callee preserved. 60 * are callee preserved.
61 */ 61 */
62 mov x20, x0 // DTB address 62 mov x20, x0 // DTB address
63 ldr x0, [sp, #16] // relocated _text address 63 ldr x0, [sp, #16] // relocated _text address
64 mov x21, x0 64 mov x21, x0
65 65
66 /* 66 /*
67 * Flush dcache covering current runtime addresses 67 * Calculate size of the kernel Image (same for original and copy).
68 * of kernel text/data. Then flush all of icache.
69 */ 68 */
70 adrp x1, _text 69 adrp x1, _text
71 add x1, x1, #:lo12:_text 70 add x1, x1, #:lo12:_text
@@ -73,9 +72,24 @@ ENTRY(efi_stub_entry)
73 add x2, x2, #:lo12:_edata 72 add x2, x2, #:lo12:_edata
74 sub x1, x2, x1 73 sub x1, x2, x1
75 74
75 /*
76 * Flush the copied Image to the PoC, and ensure it is not shadowed by
77 * stale icache entries from before relocation.
78 */
76 bl __flush_dcache_area 79 bl __flush_dcache_area
77 ic ialluis 80 ic ialluis
78 81
82 /*
83 * Ensure that the rest of this function (in the original Image) is
84 * visible when the caches are disabled. The I-cache can't have stale
85 * entries for the VA range of the current image, so no maintenance is
86 * necessary.
87 */
88 adr x0, efi_stub_entry
89 adr x1, efi_stub_entry_end
90 sub x1, x1, x0
91 bl __flush_dcache_area
92
79 /* Turn off Dcache and MMU */ 93 /* Turn off Dcache and MMU */
80 mrs x0, CurrentEL 94 mrs x0, CurrentEL
81 cmp x0, #CurrentEL_EL2 95 cmp x0, #CurrentEL_EL2
@@ -105,4 +119,5 @@ efi_load_fail:
105 ldp x29, x30, [sp], #32 119 ldp x29, x30, [sp], #32
106 ret 120 ret
107 121
122efi_stub_entry_end:
108ENDPROC(efi_stub_entry) 123ENDPROC(efi_stub_entry)
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index e007714ded04..8cd27fedc8b6 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -163,9 +163,10 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg)
163 * which ends with "dsb; isb" pair guaranteeing global 163 * which ends with "dsb; isb" pair guaranteeing global
164 * visibility. 164 * visibility.
165 */ 165 */
166 atomic_set(&pp->cpu_count, -1); 166 /* Notify other processors with an additional increment. */
167 atomic_inc(&pp->cpu_count);
167 } else { 168 } else {
168 while (atomic_read(&pp->cpu_count) != -1) 169 while (atomic_read(&pp->cpu_count) <= num_online_cpus())
169 cpu_relax(); 170 cpu_relax();
170 isb(); 171 isb();
171 } 172 }
diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S
index 6e0ed93d51fe..c17967fdf5f6 100644
--- a/arch/arm64/lib/clear_user.S
+++ b/arch/arm64/lib/clear_user.S
@@ -46,7 +46,7 @@ USER(9f, strh wzr, [x0], #2 )
46 sub x1, x1, #2 46 sub x1, x1, #2
474: adds x1, x1, #1 474: adds x1, x1, #1
48 b.mi 5f 48 b.mi 5f
49 strb wzr, [x0] 49USER(9f, strb wzr, [x0] )
505: mov x0, #0 505: mov x0, #0
51 ret 51 ret
52ENDPROC(__clear_user) 52ENDPROC(__clear_user)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 0bf90d26e745..f4f8b500f74c 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -202,7 +202,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
202} 202}
203 203
204static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, 204static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
205 unsigned long end, unsigned long phys, 205 unsigned long end, phys_addr_t phys,
206 int map_io) 206 int map_io)
207{ 207{
208 pud_t *pud; 208 pud_t *pud;