diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-20 13:17:13 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-20 13:17:13 -0400 |
| commit | f4814e61836f5571d2b89169ba2e9ea59e2bc8c8 (patch) | |
| tree | bef84dfb86c1207af9136322437200f2a34b1e9a /arch/arm64/kernel | |
| parent | bdcff41597e823a4b5117698fb3ad0cf833e10ac (diff) | |
| parent | f7881bd644474a4a62d7bd1ec801176f635f59ae (diff) | |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"Most of these are CC'd for stable, but there are a few fixing issues
introduced during the recent merge window too.
There's also a fix for the xgene PMU driver, but it seemed daft to
send as a separate pull request, so I've included it here with the
rest of the fixes.
- Fix ACPI boot due to recent broken NUMA changes
- Fix remote enabling of CPU features requiring PSTATE bit manipulation
- Add address range check when emulating user cache maintenance
- Fix LL/SC loops that allow compiler to introduce memory accesses
- Fix recently added write_sysreg_s macro
- Ensure MDCR_EL2 is initialised on qemu targets without a PMU
- Avoid kaslr breakage due to MODVERSIONs and DYNAMIC_FTRACE
- Correctly drive recent ld when building relocatable Image
- Remove junk IS_ERR check from xgene PMU driver added during merge window
- pr_cont fixes after core changes in the merge window"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: remove pr_cont abuse from mem_init
arm64: fix show_regs fallout from KERN_CONT changes
arm64: kernel: force ET_DYN ELF type for CONFIG_RELOCATABLE=y
arm64: suspend: Reconfigure PSTATE after resume from idle
arm64: mm: Set PSTATE.PAN from the cpu_enable_pan() call
arm64: cpufeature: Schedule enable() calls instead of calling them via IPI
arm64: Cortex-A53 errata workaround: check for kernel addresses
arm64: percpu: rewrite ll/sc loops in assembly
arm64: swp emulation: bound LL/SC retries before rescheduling
arm64: sysreg: Fix use of XZR in write_sysreg_s
arm64: kaslr: keep modules close to the kernel when DYNAMIC_FTRACE=y
arm64: kernel: Init MDCR_EL2 even in the absence of a PMU
perf: xgene: Remove bogus IS_ERR() check
arm64: kernel: numa: fix ACPI boot cpu numa node mapping
arm64: kaslr: fix breakage with CONFIG_MODVERSIONS=y
Diffstat (limited to 'arch/arm64/kernel')
| -rw-r--r-- | arch/arm64/kernel/armv8_deprecated.c | 36 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 3 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpufeature.c | 10 | ||||
| -rw-r--r-- | arch/arm64/kernel/head.S | 3 | ||||
| -rw-r--r-- | arch/arm64/kernel/process.c | 18 | ||||
| -rw-r--r-- | arch/arm64/kernel/smp.c | 1 | ||||
| -rw-r--r-- | arch/arm64/kernel/suspend.c | 11 | ||||
| -rw-r--r-- | arch/arm64/kernel/traps.c | 30 |
8 files changed, 78 insertions, 34 deletions
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 42ffdb54e162..b0988bb1bf64 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c | |||
| @@ -280,35 +280,43 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table) | |||
| 280 | /* | 280 | /* |
| 281 | * Error-checking SWP macros implemented using ldxr{b}/stxr{b} | 281 | * Error-checking SWP macros implemented using ldxr{b}/stxr{b} |
| 282 | */ | 282 | */ |
| 283 | #define __user_swpX_asm(data, addr, res, temp, B) \ | 283 | |
| 284 | /* Arbitrary constant to ensure forward-progress of the LL/SC loop */ | ||
| 285 | #define __SWP_LL_SC_LOOPS 4 | ||
| 286 | |||
| 287 | #define __user_swpX_asm(data, addr, res, temp, temp2, B) \ | ||
| 284 | __asm__ __volatile__( \ | 288 | __asm__ __volatile__( \ |
| 289 | " mov %w3, %w7\n" \ | ||
| 285 | ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ | 290 | ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ |
| 286 | CONFIG_ARM64_PAN) \ | 291 | CONFIG_ARM64_PAN) \ |
| 287 | "0: ldxr"B" %w2, [%3]\n" \ | 292 | "0: ldxr"B" %w2, [%4]\n" \ |
| 288 | "1: stxr"B" %w0, %w1, [%3]\n" \ | 293 | "1: stxr"B" %w0, %w1, [%4]\n" \ |
| 289 | " cbz %w0, 2f\n" \ | 294 | " cbz %w0, 2f\n" \ |
| 290 | " mov %w0, %w4\n" \ | 295 | " sub %w3, %w3, #1\n" \ |
| 296 | " cbnz %w3, 0b\n" \ | ||
| 297 | " mov %w0, %w5\n" \ | ||
| 291 | " b 3f\n" \ | 298 | " b 3f\n" \ |
| 292 | "2:\n" \ | 299 | "2:\n" \ |
| 293 | " mov %w1, %w2\n" \ | 300 | " mov %w1, %w2\n" \ |
| 294 | "3:\n" \ | 301 | "3:\n" \ |
| 295 | " .pushsection .fixup,\"ax\"\n" \ | 302 | " .pushsection .fixup,\"ax\"\n" \ |
| 296 | " .align 2\n" \ | 303 | " .align 2\n" \ |
| 297 | "4: mov %w0, %w5\n" \ | 304 | "4: mov %w0, %w6\n" \ |
| 298 | " b 3b\n" \ | 305 | " b 3b\n" \ |
| 299 | " .popsection" \ | 306 | " .popsection" \ |
| 300 | _ASM_EXTABLE(0b, 4b) \ | 307 | _ASM_EXTABLE(0b, 4b) \ |
| 301 | _ASM_EXTABLE(1b, 4b) \ | 308 | _ASM_EXTABLE(1b, 4b) \ |
| 302 | ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ | 309 | ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ |
| 303 | CONFIG_ARM64_PAN) \ | 310 | CONFIG_ARM64_PAN) \ |
| 304 | : "=&r" (res), "+r" (data), "=&r" (temp) \ | 311 | : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ |
| 305 | : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ | 312 | : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ |
| 313 | "i" (__SWP_LL_SC_LOOPS) \ | ||
| 306 | : "memory") | 314 | : "memory") |
| 307 | 315 | ||
| 308 | #define __user_swp_asm(data, addr, res, temp) \ | 316 | #define __user_swp_asm(data, addr, res, temp, temp2) \ |
| 309 | __user_swpX_asm(data, addr, res, temp, "") | 317 | __user_swpX_asm(data, addr, res, temp, temp2, "") |
| 310 | #define __user_swpb_asm(data, addr, res, temp) \ | 318 | #define __user_swpb_asm(data, addr, res, temp, temp2) \ |
| 311 | __user_swpX_asm(data, addr, res, temp, "b") | 319 | __user_swpX_asm(data, addr, res, temp, temp2, "b") |
| 312 | 320 | ||
| 313 | /* | 321 | /* |
| 314 | * Bit 22 of the instruction encoding distinguishes between | 322 | * Bit 22 of the instruction encoding distinguishes between |
| @@ -328,12 +336,12 @@ static int emulate_swpX(unsigned int address, unsigned int *data, | |||
| 328 | } | 336 | } |
| 329 | 337 | ||
| 330 | while (1) { | 338 | while (1) { |
| 331 | unsigned long temp; | 339 | unsigned long temp, temp2; |
| 332 | 340 | ||
| 333 | if (type == TYPE_SWPB) | 341 | if (type == TYPE_SWPB) |
| 334 | __user_swpb_asm(*data, address, res, temp); | 342 | __user_swpb_asm(*data, address, res, temp, temp2); |
| 335 | else | 343 | else |
| 336 | __user_swp_asm(*data, address, res, temp); | 344 | __user_swp_asm(*data, address, res, temp, temp2); |
| 337 | 345 | ||
| 338 | if (likely(res != -EAGAIN) || signal_pending(current)) | 346 | if (likely(res != -EAGAIN) || signal_pending(current)) |
| 339 | break; | 347 | break; |
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 0150394f4cab..b75e917aac46 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
| @@ -39,10 +39,11 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry, | |||
| 39 | (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask); | 39 | (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | static void cpu_enable_trap_ctr_access(void *__unused) | 42 | static int cpu_enable_trap_ctr_access(void *__unused) |
| 43 | { | 43 | { |
| 44 | /* Clear SCTLR_EL1.UCT */ | 44 | /* Clear SCTLR_EL1.UCT */ |
| 45 | config_sctlr_el1(SCTLR_EL1_UCT, 0); | 45 | config_sctlr_el1(SCTLR_EL1_UCT, 0); |
| 46 | return 0; | ||
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | #define MIDR_RANGE(model, min, max) \ | 49 | #define MIDR_RANGE(model, min, max) \ |
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index d577f263cc4a..c02504ea304b 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
| @@ -19,7 +19,9 @@ | |||
| 19 | #define pr_fmt(fmt) "CPU features: " fmt | 19 | #define pr_fmt(fmt) "CPU features: " fmt |
| 20 | 20 | ||
| 21 | #include <linux/bsearch.h> | 21 | #include <linux/bsearch.h> |
| 22 | #include <linux/cpumask.h> | ||
| 22 | #include <linux/sort.h> | 23 | #include <linux/sort.h> |
| 24 | #include <linux/stop_machine.h> | ||
| 23 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 24 | #include <asm/cpu.h> | 26 | #include <asm/cpu.h> |
| 25 | #include <asm/cpufeature.h> | 27 | #include <asm/cpufeature.h> |
| @@ -941,7 +943,13 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) | |||
| 941 | { | 943 | { |
| 942 | for (; caps->matches; caps++) | 944 | for (; caps->matches; caps++) |
| 943 | if (caps->enable && cpus_have_cap(caps->capability)) | 945 | if (caps->enable && cpus_have_cap(caps->capability)) |
| 944 | on_each_cpu(caps->enable, NULL, true); | 946 | /* |
| 947 | * Use stop_machine() as it schedules the work allowing | ||
| 948 | * us to modify PSTATE, instead of on_each_cpu() which | ||
| 949 | * uses an IPI, giving us a PSTATE that disappears when | ||
| 950 | * we return. | ||
| 951 | */ | ||
| 952 | stop_machine(caps->enable, NULL, cpu_online_mask); | ||
| 945 | } | 953 | } |
| 946 | 954 | ||
| 947 | /* | 955 | /* |
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 427f6d3f084c..332e33193ccf 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
| @@ -586,8 +586,9 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems | |||
| 586 | b.lt 4f // Skip if no PMU present | 586 | b.lt 4f // Skip if no PMU present |
| 587 | mrs x0, pmcr_el0 // Disable debug access traps | 587 | mrs x0, pmcr_el0 // Disable debug access traps |
| 588 | ubfx x0, x0, #11, #5 // to EL2 and allow access to | 588 | ubfx x0, x0, #11, #5 // to EL2 and allow access to |
| 589 | msr mdcr_el2, x0 // all PMU counters from EL1 | ||
| 590 | 4: | 589 | 4: |
| 590 | csel x0, xzr, x0, lt // all PMU counters from EL1 | ||
| 591 | msr mdcr_el2, x0 // (if they exist) | ||
| 591 | 592 | ||
| 592 | /* Stage-2 translation */ | 593 | /* Stage-2 translation */ |
| 593 | msr vttbr_el2, xzr | 594 | msr vttbr_el2, xzr |
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 27b2f1387df4..01753cd7d3f0 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <asm/alternative.h> | 49 | #include <asm/alternative.h> |
| 50 | #include <asm/compat.h> | 50 | #include <asm/compat.h> |
| 51 | #include <asm/cacheflush.h> | 51 | #include <asm/cacheflush.h> |
| 52 | #include <asm/exec.h> | ||
| 52 | #include <asm/fpsimd.h> | 53 | #include <asm/fpsimd.h> |
| 53 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
| 54 | #include <asm/processor.h> | 55 | #include <asm/processor.h> |
| @@ -186,10 +187,19 @@ void __show_regs(struct pt_regs *regs) | |||
| 186 | printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", | 187 | printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", |
| 187 | regs->pc, lr, regs->pstate); | 188 | regs->pc, lr, regs->pstate); |
| 188 | printk("sp : %016llx\n", sp); | 189 | printk("sp : %016llx\n", sp); |
| 189 | for (i = top_reg; i >= 0; i--) { | 190 | |
| 191 | i = top_reg; | ||
| 192 | |||
| 193 | while (i >= 0) { | ||
| 190 | printk("x%-2d: %016llx ", i, regs->regs[i]); | 194 | printk("x%-2d: %016llx ", i, regs->regs[i]); |
| 191 | if (i % 2 == 0) | 195 | i--; |
| 192 | printk("\n"); | 196 | |
| 197 | if (i % 2 == 0) { | ||
| 198 | pr_cont("x%-2d: %016llx ", i, regs->regs[i]); | ||
| 199 | i--; | ||
| 200 | } | ||
| 201 | |||
| 202 | pr_cont("\n"); | ||
| 193 | } | 203 | } |
| 194 | printk("\n"); | 204 | printk("\n"); |
| 195 | } | 205 | } |
| @@ -301,7 +311,7 @@ static void tls_thread_switch(struct task_struct *next) | |||
| 301 | } | 311 | } |
| 302 | 312 | ||
| 303 | /* Restore the UAO state depending on next's addr_limit */ | 313 | /* Restore the UAO state depending on next's addr_limit */ |
| 304 | static void uao_thread_switch(struct task_struct *next) | 314 | void uao_thread_switch(struct task_struct *next) |
| 305 | { | 315 | { |
| 306 | if (IS_ENABLED(CONFIG_ARM64_UAO)) { | 316 | if (IS_ENABLED(CONFIG_ARM64_UAO)) { |
| 307 | if (task_thread_info(next)->addr_limit == KERNEL_DS) | 317 | if (task_thread_info(next)->addr_limit == KERNEL_DS) |
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index d3f151cfd4a1..8507703dabe4 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c | |||
| @@ -544,6 +544,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) | |||
| 544 | return; | 544 | return; |
| 545 | } | 545 | } |
| 546 | bootcpu_valid = true; | 546 | bootcpu_valid = true; |
| 547 | early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid)); | ||
| 547 | return; | 548 | return; |
| 548 | } | 549 | } |
| 549 | 550 | ||
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index ad734142070d..bb0cd787a9d3 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | #include <linux/ftrace.h> | 1 | #include <linux/ftrace.h> |
| 2 | #include <linux/percpu.h> | 2 | #include <linux/percpu.h> |
| 3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
| 4 | #include <asm/alternative.h> | ||
| 4 | #include <asm/cacheflush.h> | 5 | #include <asm/cacheflush.h> |
| 6 | #include <asm/cpufeature.h> | ||
| 5 | #include <asm/debug-monitors.h> | 7 | #include <asm/debug-monitors.h> |
| 8 | #include <asm/exec.h> | ||
| 6 | #include <asm/pgtable.h> | 9 | #include <asm/pgtable.h> |
| 7 | #include <asm/memory.h> | 10 | #include <asm/memory.h> |
| 8 | #include <asm/mmu_context.h> | 11 | #include <asm/mmu_context.h> |
| @@ -50,6 +53,14 @@ void notrace __cpu_suspend_exit(void) | |||
| 50 | set_my_cpu_offset(per_cpu_offset(cpu)); | 53 | set_my_cpu_offset(per_cpu_offset(cpu)); |
| 51 | 54 | ||
| 52 | /* | 55 | /* |
| 56 | * PSTATE was not saved over suspend/resume, re-enable any detected | ||
| 57 | * features that might not have been set correctly. | ||
| 58 | */ | ||
| 59 | asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, | ||
| 60 | CONFIG_ARM64_PAN)); | ||
| 61 | uao_thread_switch(current); | ||
| 62 | |||
| 63 | /* | ||
| 53 | * Restore HW breakpoint registers to sane values | 64 | * Restore HW breakpoint registers to sane values |
| 54 | * before debug exceptions are possibly reenabled | 65 | * before debug exceptions are possibly reenabled |
| 55 | * through local_dbg_restore. | 66 | * through local_dbg_restore. |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 5ff020f8fb7f..c9986b3e0a96 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
| @@ -428,24 +428,28 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
| 428 | force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); | 428 | force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | void cpu_enable_cache_maint_trap(void *__unused) | 431 | int cpu_enable_cache_maint_trap(void *__unused) |
| 432 | { | 432 | { |
| 433 | config_sctlr_el1(SCTLR_EL1_UCI, 0); | 433 | config_sctlr_el1(SCTLR_EL1_UCI, 0); |
| 434 | return 0; | ||
| 434 | } | 435 | } |
| 435 | 436 | ||
| 436 | #define __user_cache_maint(insn, address, res) \ | 437 | #define __user_cache_maint(insn, address, res) \ |
| 437 | asm volatile ( \ | 438 | if (untagged_addr(address) >= user_addr_max()) \ |
| 438 | "1: " insn ", %1\n" \ | 439 | res = -EFAULT; \ |
| 439 | " mov %w0, #0\n" \ | 440 | else \ |
| 440 | "2:\n" \ | 441 | asm volatile ( \ |
| 441 | " .pushsection .fixup,\"ax\"\n" \ | 442 | "1: " insn ", %1\n" \ |
| 442 | " .align 2\n" \ | 443 | " mov %w0, #0\n" \ |
| 443 | "3: mov %w0, %w2\n" \ | 444 | "2:\n" \ |
| 444 | " b 2b\n" \ | 445 | " .pushsection .fixup,\"ax\"\n" \ |
| 445 | " .popsection\n" \ | 446 | " .align 2\n" \ |
| 446 | _ASM_EXTABLE(1b, 3b) \ | 447 | "3: mov %w0, %w2\n" \ |
| 447 | : "=r" (res) \ | 448 | " b 2b\n" \ |
| 448 | : "r" (address), "i" (-EFAULT) ) | 449 | " .popsection\n" \ |
| 450 | _ASM_EXTABLE(1b, 3b) \ | ||
| 451 | : "=r" (res) \ | ||
| 452 | : "r" (address), "i" (-EFAULT) ) | ||
| 449 | 453 | ||
| 450 | static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) | 454 | static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) |
| 451 | { | 455 | { |
