aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm/fault.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 15:11:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 15:11:37 -0400
commitab182e67ec99ea0c8d7435a32a4a1ed9bb02559a (patch)
treefa71bef0067a61952561552c6652d922060f5530 /arch/arm64/mm/fault.c
parent7246f60068840847bdcf595be5f0b5ca632736e0 (diff)
parent92f66f84d9695d07adf9bc987bbcce4bf9b8e87c (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Catalin Marinas: - kdump support, including two necessary memblock additions: memblock_clear_nomap() and memblock_cap_memory_range() - ARMv8.3 HWCAP bits for JavaScript conversion instructions, complex numbers and weaker release consistency - arm64 ACPI platform MSI support - arm perf updates: ACPI PMU support, L3 cache PMU in some Qualcomm SoCs, Cortex-A53 L2 cache events and DTLB refills, MAINTAINERS update for DT perf bindings - architected timer errata framework (the arch/arm64 changes only) - support for DMA_ATTR_FORCE_CONTIGUOUS in the arm64 iommu DMA API - arm64 KVM refactoring to use common system register definitions - remove support for ASID-tagged VIVT I-cache (no ARMv8 implementation using it and deprecated in the architecture) together with some I-cache handling clean-up - PE/COFF EFI header clean-up/hardening - define BUG() instruction without CONFIG_BUG * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (92 commits) arm64: Fix the DMA mmap and get_sgtable API with DMA_ATTR_FORCE_CONTIGUOUS arm64: Print DT machine model in setup_machine_fdt() arm64: pmu: Wire-up Cortex A53 L2 cache events and DTLB refills arm64: module: split core and init PLT sections arm64: pmuv3: handle pmuv3+ arm64: Add CNTFRQ_EL0 trap handler arm64: Silence spurious kbuild warning on menuconfig arm64: pmuv3: use arm_pmu ACPI framework arm64: pmuv3: handle !PMUv3 when probing drivers/perf: arm_pmu: add ACPI framework arm64: add function to get a cpu's MADT GICC table drivers/perf: arm_pmu: split out platform device probe logic drivers/perf: arm_pmu: move irq request/free into probe drivers/perf: arm_pmu: split cpu-local irq request/free drivers/perf: arm_pmu: rename irq request/free functions drivers/perf: arm_pmu: handle no platform_device drivers/perf: arm_pmu: simplify cpu_pmu_request_irqs() drivers/perf: arm_pmu: factor out pmu registration drivers/perf: arm_pmu: fold init into alloc drivers/perf: arm_pmu: define armpmu_init_fn ...
Diffstat (limited to 'arch/arm64/mm/fault.c')
-rw-r--r--arch/arm64/mm/fault.c55
1 files changed, 36 insertions, 19 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 1b35b8bddbfb..37b95dff0b07 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -174,12 +174,33 @@ static bool is_el1_instruction_abort(unsigned int esr)
174 return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR; 174 return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR;
175} 175}
176 176
177static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs,
178 unsigned long addr)
179{
180 unsigned int ec = ESR_ELx_EC(esr);
181 unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
182
183 if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
184 return false;
185
186 if (fsc_type == ESR_ELx_FSC_PERM)
187 return true;
188
189 if (addr < USER_DS && system_uses_ttbr0_pan())
190 return fsc_type == ESR_ELx_FSC_FAULT &&
191 (regs->pstate & PSR_PAN_BIT);
192
193 return false;
194}
195
177/* 196/*
178 * The kernel tried to access some page that wasn't present. 197 * The kernel tried to access some page that wasn't present.
179 */ 198 */
180static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, 199static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
181 unsigned int esr, struct pt_regs *regs) 200 unsigned int esr, struct pt_regs *regs)
182{ 201{
202 const char *msg;
203
183 /* 204 /*
184 * Are we prepared to handle this kernel fault? 205 * Are we prepared to handle this kernel fault?
185 * We are almost certainly not prepared to handle instruction faults. 206 * We are almost certainly not prepared to handle instruction faults.
@@ -191,9 +212,20 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
191 * No handler, we'll have to terminate things with extreme prejudice. 212 * No handler, we'll have to terminate things with extreme prejudice.
192 */ 213 */
193 bust_spinlocks(1); 214 bust_spinlocks(1);
194 pr_alert("Unable to handle kernel %s at virtual address %08lx\n", 215
195 (addr < PAGE_SIZE) ? "NULL pointer dereference" : 216 if (is_permission_fault(esr, regs, addr)) {
196 "paging request", addr); 217 if (esr & ESR_ELx_WNR)
218 msg = "write to read-only memory";
219 else
220 msg = "read from unreadable memory";
221 } else if (addr < PAGE_SIZE) {
222 msg = "NULL pointer dereference";
223 } else {
224 msg = "paging request";
225 }
226
227 pr_alert("Unable to handle kernel %s at virtual address %08lx\n", msg,
228 addr);
197 229
198 show_pte(mm, addr); 230 show_pte(mm, addr);
199 die("Oops", regs, esr); 231 die("Oops", regs, esr);
@@ -287,21 +319,6 @@ out:
287 return fault; 319 return fault;
288} 320}
289 321
290static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs)
291{
292 unsigned int ec = ESR_ELx_EC(esr);
293 unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
294
295 if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
296 return false;
297
298 if (system_uses_ttbr0_pan())
299 return fsc_type == ESR_ELx_FSC_FAULT &&
300 (regs->pstate & PSR_PAN_BIT);
301 else
302 return fsc_type == ESR_ELx_FSC_PERM;
303}
304
305static bool is_el0_instruction_abort(unsigned int esr) 322static bool is_el0_instruction_abort(unsigned int esr)
306{ 323{
307 return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; 324 return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW;
@@ -339,7 +356,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
339 mm_flags |= FAULT_FLAG_WRITE; 356 mm_flags |= FAULT_FLAG_WRITE;
340 } 357 }
341 358
342 if (addr < USER_DS && is_permission_fault(esr, regs)) { 359 if (addr < USER_DS && is_permission_fault(esr, regs, addr)) {
343 /* regs->orig_addr_limit may be 0 if we entered from EL0 */ 360 /* regs->orig_addr_limit may be 0 if we entered from EL0 */
344 if (regs->orig_addr_limit == KERNEL_DS) 361 if (regs->orig_addr_limit == KERNEL_DS)
345 die("Accessing user space memory with fs=KERNEL_DS", regs, esr); 362 die("Accessing user space memory with fs=KERNEL_DS", regs, esr);