From be081d9bf3e163a9ed1ca2f0f14f08424c7f9016 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jun 2015 13:14:18 -0700 Subject: ARM64: smp: Fix suspicious RCU usage with ipi tracepoints John Stultz reported an RCU splat on ARM with ipi trace events enabled. It looks like the same problem exists on ARM64. At this point in the IPI handling path we haven't called irq_enter() yet, so RCU doesn't know that we're about to exit idle and properly warns that we're using RCU from an idle CPU. Use trace_ipi_entry_rcuidle() instead of trace_ipi_entry() so that RCU is informed about our exit from idle. Cc: John Stultz Cc: Nicolas Pitre Acked-by: Steven Rostedt Reviewed-by: Paul E. McKenney Cc: # 3.17+ Fixes: 45ed695ac10a ("ARM64: add IPI tracepoints") Signed-off-by: Stephen Boyd Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 4b2121b..a1883bf 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -693,7 +693,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); if ((unsigned)ipinr < NR_IPI) { - trace_ipi_entry(ipi_types[ipinr]); + trace_ipi_entry_rcuidle(ipi_types[ipinr]); __inc_irq_stat(cpu, ipi_irqs[ipinr]); } @@ -736,7 +736,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) } if ((unsigned)ipinr < NR_IPI) - trace_ipi_exit(ipi_types[ipinr]); + trace_ipi_exit_rcuidle(ipi_types[ipinr]); set_irq_regs(old_regs); } -- cgit v0.10.2 From 8eee539ddea09bccae2426f09b0ba6a18b72b691 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 25 Jun 2015 05:47:39 -0700 Subject: arm64: bpf: fix out-of-bounds read in bpf2a64_offset() Problems occur when bpf_to or bpf_from has value prog->len - 1 (e.g., "Very long jump backwards" in test_bpf where the last instruction is a jump): since ctx->offset has length prog->len, ctx->offset[bpf_to + 1] or ctx->offset[bpf_from + 1] will cause an out-of-bounds read, leading to a bogus jump offset and kernel panic. This patch moves updating ctx->offset to after calling build_insn(), and changes indexing to use bpf_to and bpf_from without + 1. Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler") Cc: # 3.18+ Cc: Zi Shen Lim Cc: Will Deacon Acked-by: Alexei Starovoitov Signed-off-by: Xi Wang Signed-off-by: Catalin Marinas diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index dc6a484..c81ddd4 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -113,9 +113,9 @@ static inline void emit_a64_mov_i(const int is64, const int reg, static inline int bpf2a64_offset(int bpf_to, int bpf_from, const struct jit_ctx *ctx) { - int to = ctx->offset[bpf_to + 1]; + int to = ctx->offset[bpf_to]; /* -1 to account for the Branch instruction */ - int from = ctx->offset[bpf_from + 1] - 1; + int from = ctx->offset[bpf_from] - 1; return to - from; } @@ -640,10 +640,11 @@ static int build_body(struct jit_ctx *ctx) const struct bpf_insn *insn = &prog->insnsi[i]; int ret; + ret = build_insn(insn, ctx); + if (ctx->image == NULL) ctx->offset[i] = ctx->idx; - ret = build_insn(insn, ctx); if (ret > 0) { i++; continue; -- cgit v0.10.2 From d63903bbc30c7ccad040851dfdb4da12d9a17bcf Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 25 Jun 2015 18:39:15 -0700 Subject: arm64: bpf: fix endianness conversion bugs Upper bits should be zeroed in endianness conversion: - even when there's no need to change endianness (i.e., BPF_FROM_BE on big endian or BPF_FROM_LE on little endian); - after rev16. This patch fixes such bugs by emitting extra instructions to clear upper bits. Cc: Zi Shen Lim Acked-by: Alexei Starovoitov Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler") Cc: # 3.18+ Signed-off-by: Xi Wang Signed-off-by: Catalin Marinas diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h index de0a81a..98a26ce 100644 --- a/arch/arm64/net/bpf_jit.h +++ b/arch/arm64/net/bpf_jit.h @@ -110,6 +110,10 @@ /* Rd = Rn >> shift; signed */ #define A64_ASR(sf, Rd, Rn, shift) A64_SBFM(sf, Rd, Rn, shift, (sf) ? 63 : 31) +/* Zero extend */ +#define A64_UXTH(sf, Rd, Rn) A64_UBFM(sf, Rd, Rn, 0, 15) +#define A64_UXTW(sf, Rd, Rn) A64_UBFM(sf, Rd, Rn, 0, 31) + /* Move wide (immediate) */ #define A64_MOVEW(sf, Rd, imm16, shift, type) \ aarch64_insn_gen_movewide(Rd, imm16, shift, \ diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index c81ddd4..c047598 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -289,23 +289,41 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) case BPF_ALU | BPF_END | BPF_FROM_BE: #ifdef CONFIG_CPU_BIG_ENDIAN if (BPF_SRC(code) == BPF_FROM_BE) - break; + goto emit_bswap_uxt; #else /* !CONFIG_CPU_BIG_ENDIAN */ if (BPF_SRC(code) == BPF_FROM_LE) - break; + goto emit_bswap_uxt; #endif switch (imm) { case 16: emit(A64_REV16(is64, dst, dst), ctx); + /* zero-extend 16 bits into 64 bits */ + emit(A64_UXTH(is64, dst, dst), ctx); break; case 32: emit(A64_REV32(is64, dst, dst), ctx); + /* upper 32 bits already cleared */ break; case 64: emit(A64_REV64(dst, dst), ctx); break; } break; +emit_bswap_uxt: + switch (imm) { + case 16: + /* zero-extend 16 bits into 64 bits */ + emit(A64_UXTH(is64, dst, dst), ctx); + break; + case 32: + /* zero-extend 32 bits into 64 bits */ + emit(A64_UXTW(is64, dst, dst), ctx); + break; + case 64: + /* nop */ + break; + } + break; /* dst = imm */ case BPF_ALU | BPF_MOV | BPF_K: case BPF_ALU64 | BPF_MOV | BPF_K: -- cgit v0.10.2 From 2341c0234731f5a6ea0b403f3dc14d1841b8e247 Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Thu, 25 Jun 2015 10:19:50 +0530 Subject: arm64/hw_breakpoint.c: remove unnecessary header Header is not needed for arm64/hw_breakpoint.c, Removing the same. Signed-off-by: Maninder Singh Reviewed-by: Vaneet Narang Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index e7d934d..7a1a5da 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 1e43ba9cd867f05f3e85579c370b939e1ce585e9 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 30 Jun 2015 18:04:49 +0200 Subject: arm64: fix incorrect use of pgprot_t variable This fixes a build failure under STRICT_MM_TYPECHECKS, by adding a missing pgprot_val() around a pgport_t reference. Signed-off-by: Ard Biesheuvel Signed-off-by: Catalin Marinas diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 82d3435..a4ede4e 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -117,7 +117,7 @@ void split_pud(pud_t *old_pud, pmd_t *pmd) int i = 0; do { - set_pmd(pmd, __pmd(addr | prot)); + set_pmd(pmd, __pmd(addr | pgprot_val(prot))); addr += PMD_SIZE; } while (pmd++, i++, i < PTRS_PER_PMD); } -- cgit v0.10.2 From 18a11b5e79697ddc61e30181737c91ce21eaa859 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 3 Jun 2015 21:53:37 +0100 Subject: arm64: perf: Don't use of_node after putting it It's possible, albeit unlikely, that using the of_node here will reference freed memory. Call of_node_put() after printing the name to be safe. Signed-off-by: Stephen Boyd Signed-off-by: Will Deacon diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 702591f..8af7784 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -1340,12 +1340,13 @@ static int armpmu_device_probe(struct platform_device *pdev) if (arch_find_n_match_cpu_physical_id(dn, cpu, NULL)) break; - of_node_put(dn); if (cpu >= nr_cpu_ids) { pr_warn("Failed to find logical CPU for %s\n", dn->name); + of_node_put(dn); break; } + of_node_put(dn); irqs[i] = cpu; } -- cgit v0.10.2 From b265da5a45ce60bd3d7505cc0eaa6cfba50946a1 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Mon, 29 Jun 2015 09:02:40 +0100 Subject: arm64: perf: fix unassigned cpu_pmu->plat_device when probing PMU PPIs Commit d795ef9aa831 ("arm64: perf: don't warn about missing interrupt-affinity property for PPIs") added a check for PPIs so that we avoid parsing the interrupt-affinity property for these naturally affine interrupts. Unfortunately, this check can trigger an early (successful) return and we will not assign the value of cpu_pmu->plat_device. This patch fixes the issue. Signed-off-by: Shannon Zhao Signed-off-by: Will Deacon diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 8af7784..b31e9a4 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -1318,7 +1318,7 @@ static int armpmu_device_probe(struct platform_device *pdev) /* Don't bother with PPIs; they're already affine */ irq = platform_get_irq(pdev, 0); if (irq >= 0 && irq_is_percpu(irq)) - return 0; + goto out; irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL); if (!irqs) @@ -1356,6 +1356,7 @@ static int armpmu_device_probe(struct platform_device *pdev) else kfree(irqs); +out: cpu_pmu->plat_device = pdev; return 0; } -- cgit v0.10.2 From fd28f5d439fca77348c129d5b73043a56f8a0296 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Wed, 1 Jul 2015 14:08:31 +0200 Subject: arm64: Don't report clear pmds and puds as huge The current pmd_huge() and pud_huge() functions simply check if the table bit is not set and reports the entries as huge in that case. This is counter-intuitive as a clear pmd/pud cannot also be a huge pmd/pud, and it is inconsistent with at least arm and x86. To prevent others from making the same mistake as me in looking at code that calls these functions and to fix an issue with KVM on arm64 that causes memory corruption due to incorrect page reference counting resulting from this mistake, let's change the behavior. Signed-off-by: Christoffer Dall Reviewed-by: Steve Capper Acked-by: Marc Zyngier Fixes: 084bd29810a5 ("ARM64: mm: HugeTLB support.") Cc: # 3.11+ Signed-off-by: Catalin Marinas diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 2de9d2e..0eeb4f09 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -40,13 +40,13 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) int pmd_huge(pmd_t pmd) { - return !(pmd_val(pmd) & PMD_TABLE_BIT); + return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); } int pud_huge(pud_t pud) { #ifndef __PAGETABLE_PMD_FOLDED - return !(pud_val(pud) & PUD_TABLE_BIT); + return pud_val(pud) && !(pud_val(pud) & PUD_TABLE_BIT); #else return 0; #endif -- cgit v0.10.2 From ea389daa7fd91f2fed8b06c01d4460e861c27023 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 2 Jul 2015 09:33:07 +0800 Subject: arm64: cpuidle: add __init section marker to arm_cpuidle_init It is not needed after booting, this patch moves the arm_cpuidle_init() function to the __init section. Signed-off-by: Jisheng Zhang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c index 7ce589c..9047cab6 100644 --- a/arch/arm64/kernel/cpuidle.c +++ b/arch/arm64/kernel/cpuidle.c @@ -15,7 +15,7 @@ #include #include -int arm_cpuidle_init(unsigned int cpu) +int __init arm_cpuidle_init(unsigned int cpu) { int ret = -EOPNOTSUPP; -- cgit v0.10.2 From f9058929f2acbb273ec83104ebeeab0593595e15 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 3 Jul 2015 15:29:06 +0800 Subject: ARM64 / SMP: Switch pr_err() to pr_debug() for disabled GICC entry It is normal that firmware presents GICC entry or entries (processors) with disabled flag in ACPI MADT, taking a system of 16 cpus for example, ACPI firmware may present 8 ebabled first with another 8 cpus disabled in MADT, the disabled cpus can be hot-added later. Firmware may also present more cpus than the hardware actually has, but disabled the unused ones, and easily enable it when the hardware has such cpus to make the firmware code scalable. So that's not an error for disabled cpus in MADT, we can switch pr_err() to pr_debug() to make the boot a little quieter by default. Since hwid for disabled cpus often are invalid, and we check invalid hwid first in the code, for use case that hot add cpus later will be filtered out and will not be counted in possible cups, so move this check before the hwid one to prepare the code to count for disabeld cpus when cpu hot-plug is introduced. Signed-off-by: Hanjun Guo Reviewed-by: Al Stone Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a1883bf..695801a 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -396,13 +396,13 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) { u64 hwid = processor->arm_mpidr; - if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) { - pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid); + if (!(processor->flags & ACPI_MADT_ENABLED)) { + pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid); return; } - if (!(processor->flags & ACPI_MADT_ENABLED)) { - pr_err("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid); + if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) { + pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid); return; } -- cgit v0.10.2 From f871d26807078cf4cc0a64a97ee2c6bb513a4397 Mon Sep 17 00:00:00 2001 From: "Suzuki K. Poulose" Date: Fri, 3 Jul 2015 15:08:08 +0100 Subject: arm64: Fix show_unhandled_signal_ratelimited usage Commit 86dca36e6ba introduced ratelimited usage for 'unhandled_signal' messages. The commit checks the ratelimit irrespective of whether the signal is handled or not, which is wrong and leads to false reports like the below in dmesg : __do_user_fault: 127 callbacks suppressed Do the ratelimit check only if the signal is unhandled. Fixes: 86dca36e6ba0 ("arm64: use private ratelimit state along with show_unhandled_signals") Cc: Vladimir Murzin Signed-off-by: Suzuki K. Poulose Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index a12251c..566bc4c 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -335,7 +335,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) if (call_undef_hook(regs) == 0) return; - if (show_unhandled_signals_ratelimited() && unhandled_signal(current, SIGILL)) { + if (unhandled_signal(current, SIGILL) && show_unhandled_signals_ratelimited()) { pr_info("%s[%d]: undefined instruction: pc=%p\n", current->comm, task_pid_nr(current), pc); dump_instr(KERN_INFO, regs); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 66bd92a..ffa36e2 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -115,7 +115,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, { struct siginfo si; - if (show_unhandled_signals_ratelimited() && unhandled_signal(tsk, sig)) { + if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) { pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", tsk->comm, task_pid_nr(tsk), fault_name(esr), sig, addr, esr); -- cgit v0.10.2