summaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm
diff options
context:
space:
mode:
authorLinus Torvalds2018-04-05 01:01:43 +0200
committerLinus Torvalds2018-04-05 01:01:43 +0200
commit23221d997b3d28cb80c4d4d1b4bd36610f8e12fc (patch)
tree2abbdfd8f44c4d61440f780bad2f584ef301e6a3 /arch/arm64/mm
parentMerge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kerne... (diff)
parentarm64: uaccess: Fix omissions from usercopy whitelist (diff)
downloadkernel-qcow2-linux-23221d997b3d28cb80c4d4d1b4bd36610f8e12fc.tar.gz
kernel-qcow2-linux-23221d997b3d28cb80c4d4d1b4bd36610f8e12fc.tar.xz
kernel-qcow2-linux-23221d997b3d28cb80c4d4d1b4bd36610f8e12fc.zip
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Will Deacon: "Nothing particularly stands out here, probably because people were tied up with spectre/meltdown stuff last time around. Still, the main pieces are: - Rework of our CPU features framework so that we can whitelist CPUs that don't require kpti even in a heterogeneous system - Support for the IDC/DIC architecture extensions, which allow us to elide instruction and data cache maintenance when writing out instructions - Removal of the large memory model which resulted in suboptimal codegen by the compiler and increased the use of literal pools, which could potentially be used as ROP gadgets since they are mapped as executable - Rework of forced signal delivery so that the siginfo_t is well-formed and handling of show_unhandled_signals is consolidated and made consistent between different fault types - More siginfo cleanup based on the initial patches from Eric Biederman - Workaround for Cortex-A55 erratum #1024718 - Some small ACPI IORT updates and cleanups from Lorenzo Pieralisi - Misc cleanups and non-critical fixes" * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (70 commits) arm64: uaccess: Fix omissions from usercopy whitelist arm64: fpsimd: Split cpu field out from struct fpsimd_state arm64: tlbflush: avoid writing RES0 bits arm64: cmpxchg: Include linux/compiler.h in asm/cmpxchg.h arm64: move percpu cmpxchg implementation from cmpxchg.h to percpu.h arm64: cmpxchg: Include build_bug.h instead of bug.h for BUILD_BUG arm64: lse: Include compiler_types.h and export.h for out-of-line LL/SC arm64: fpsimd: include <linux/init.h> in fpsimd.h drivers/perf: arm_pmu_platform: do not warn about affinity on uniprocessor perf: arm_spe: include linux/vmalloc.h for vmap() Revert "arm64: Revert L1_CACHE_SHIFT back to 6 (64-byte cache line size)" arm64: cpufeature: Avoid warnings due to unused symbols arm64: Add work around for Arm Cortex-A55 Erratum 1024718 arm64: Delay enabling hardware DBM feature arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35 arm64: capabilities: Handle shared entries arm64: capabilities: Add support for checks based on a list of MIDRs arm64: Add helpers for checking CPU MIDR against a range arm64: capabilities: Clean up midr range helpers arm64: capabilities: Change scope of VHE to Boot CPU feature ...
Diffstat (limited to 'arch/arm64/mm')
-rw-r--r--arch/arm64/mm/cache.S21
-rw-r--r--arch/arm64/mm/fault.c236
-rw-r--r--arch/arm64/mm/proc.S22
3 files changed, 137 insertions, 142 deletions
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 758bde7e2fa6..30334d81b021 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -50,6 +50,10 @@ ENTRY(flush_icache_range)
*/
ENTRY(__flush_cache_user_range)
uaccess_ttbr0_enable x2, x3, x4
+alternative_if ARM64_HAS_CACHE_IDC
+ dsb ishst
+ b 7f
+alternative_else_nop_endif
dcache_line_size x2, x3
sub x3, x2, #1
bic x4, x0, x3
@@ -60,8 +64,13 @@ user_alt 9f, "dc cvau, x4", "dc civac, x4", ARM64_WORKAROUND_CLEAN_CACHE
b.lo 1b
dsb ish
+7:
+alternative_if ARM64_HAS_CACHE_DIC
+ isb
+ b 8f
+alternative_else_nop_endif
invalidate_icache_by_line x0, x1, x2, x3, 9f
- mov x0, #0
+8: mov x0, #0
1:
uaccess_ttbr0_disable x1, x2
ret
@@ -80,6 +89,12 @@ ENDPROC(__flush_cache_user_range)
* - end - virtual end address of region
*/
ENTRY(invalidate_icache_range)
+alternative_if ARM64_HAS_CACHE_DIC
+ mov x0, xzr
+ isb
+ ret
+alternative_else_nop_endif
+
uaccess_ttbr0_enable x2, x3, x4
invalidate_icache_by_line x0, x1, x2, x3, 2f
@@ -116,6 +131,10 @@ ENDPIPROC(__flush_dcache_area)
* - size - size in question
*/
ENTRY(__clean_dcache_area_pou)
+alternative_if ARM64_HAS_CACHE_IDC
+ dsb ishst
+ ret
+alternative_else_nop_endif
dcache_by_line_op cvau, ish, x0, x1, x2, x3
ret
ENDPROC(__clean_dcache_area_pou)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index bff11553eb05..4165485e8b6e 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -43,6 +43,7 @@
#include <asm/system_misc.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+#include <asm/traps.h>
#include <acpi/ghes.h>
@@ -289,58 +290,31 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
do_exit(SIGKILL);
}
-static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
- unsigned int esr, unsigned int sig, int code,
- struct pt_regs *regs, int fault)
+static void __do_user_fault(struct siginfo *info, unsigned int esr)
{
- struct siginfo si;
- const struct fault_info *inf;
- unsigned int lsb = 0;
-
- if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) {
- inf = esr_to_fault_info(esr);
- pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x",
- tsk->comm, task_pid_nr(tsk), inf->name, sig,
- addr, esr);
- print_vma_addr(KERN_CONT ", in ", regs->pc);
- pr_cont("\n");
- __show_regs(regs);
- }
-
- tsk->thread.fault_address = addr;
- tsk->thread.fault_code = esr;
- si.si_signo = sig;
- si.si_errno = 0;
- si.si_code = code;
- si.si_addr = (void __user *)addr;
- /*
- * Either small page or large page may be poisoned.
- * In other words, VM_FAULT_HWPOISON_LARGE and
- * VM_FAULT_HWPOISON are mutually exclusive.
- */
- if (fault & VM_FAULT_HWPOISON_LARGE)
- lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
- else if (fault & VM_FAULT_HWPOISON)
- lsb = PAGE_SHIFT;
- si.si_addr_lsb = lsb;
-
- force_sig_info(sig, &si, tsk);
+ current->thread.fault_address = (unsigned long)info->si_addr;
+ current->thread.fault_code = esr;
+ arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current);
}
static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
{
- struct task_struct *tsk = current;
- const struct fault_info *inf;
-
/*
* If we are in kernel mode at this point, we have no context to
* handle this fault with.
*/
if (user_mode(regs)) {
- inf = esr_to_fault_info(esr);
- __do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs, 0);
- } else
+ const struct fault_info *inf = esr_to_fault_info(esr);
+ struct siginfo si = {
+ .si_signo = inf->sig,
+ .si_code = inf->code,
+ .si_addr = (void __user *)addr,
+ };
+
+ __do_user_fault(&si, esr);
+ } else {
__do_kernel_fault(addr, esr, regs);
+ }
}
#define VM_FAULT_BADMAP 0x010000
@@ -393,7 +367,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
{
struct task_struct *tsk;
struct mm_struct *mm;
- int fault, sig, code, major = 0;
+ struct siginfo si;
+ int fault, major = 0;
unsigned long vm_flags = VM_READ | VM_WRITE;
unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -525,27 +500,37 @@ retry:
return 0;
}
+ clear_siginfo(&si);
+ si.si_addr = (void __user *)addr;
+
if (fault & VM_FAULT_SIGBUS) {
/*
* We had some memory, but were unable to successfully fix up
* this page fault.
*/
- sig = SIGBUS;
- code = BUS_ADRERR;
- } else if (fault & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) {
- sig = SIGBUS;
- code = BUS_MCEERR_AR;
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_ADRERR;
+ } else if (fault & VM_FAULT_HWPOISON_LARGE) {
+ unsigned int hindex = VM_FAULT_GET_HINDEX(fault);
+
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_MCEERR_AR;
+ si.si_addr_lsb = hstate_index_to_shift(hindex);
+ } else if (fault & VM_FAULT_HWPOISON) {
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_MCEERR_AR;
+ si.si_addr_lsb = PAGE_SHIFT;
} else {
/*
* Something tried to access memory that isn't in our memory
* map.
*/
- sig = SIGSEGV;
- code = fault == VM_FAULT_BADACCESS ?
- SEGV_ACCERR : SEGV_MAPERR;
+ si.si_signo = SIGSEGV;
+ si.si_code = fault == VM_FAULT_BADACCESS ?
+ SEGV_ACCERR : SEGV_MAPERR;
}
- __do_user_fault(tsk, addr, esr, sig, code, regs, fault);
+ __do_user_fault(&si, esr);
return 0;
no_context:
@@ -582,8 +567,6 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
const struct fault_info *inf;
inf = esr_to_fault_info(esr);
- pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
- inf->name, esr, addr);
/*
* Synchronous aborts may interrupt code which had interrupts masked.
@@ -600,83 +583,83 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
nmi_exit();
}
- info.si_signo = SIGBUS;
+ info.si_signo = inf->sig;
info.si_errno = 0;
- info.si_code = BUS_FIXME;
+ info.si_code = inf->code;
if (esr & ESR_ELx_FnV)
info.si_addr = NULL;
else
info.si_addr = (void __user *)addr;
- arm64_notify_die("", regs, &info, esr);
+ arm64_notify_die(inf->name, regs, &info, esr);
return 0;
}
static const struct fault_info fault_info[] = {
- { do_bad, SIGBUS, BUS_FIXME, "ttbr address size fault" },
- { do_bad, SIGBUS, BUS_FIXME, "level 1 address size fault" },
- { do_bad, SIGBUS, BUS_FIXME, "level 2 address size fault" },
- { do_bad, SIGBUS, BUS_FIXME, "level 3 address size fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "level 2 address size fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "level 3 address size fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 0 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 8" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 8" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 12" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 12" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
- { do_sea, SIGBUS, BUS_FIXME, "synchronous external abort" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 17" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 18" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 19" },
- { do_sea, SIGBUS, BUS_FIXME, "level 0 (translation table walk)" },
- { do_sea, SIGBUS, BUS_FIXME, "level 1 (translation table walk)" },
- { do_sea, SIGBUS, BUS_FIXME, "level 2 (translation table walk)" },
- { do_sea, SIGBUS, BUS_FIXME, "level 3 (translation table walk)" },
- { do_sea, SIGBUS, BUS_FIXME, "synchronous parity or ECC error" }, // Reserved when RAS is implemented
- { do_bad, SIGBUS, BUS_FIXME, "unknown 25" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 26" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 27" },
- { do_sea, SIGBUS, BUS_FIXME, "level 0 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
- { do_sea, SIGBUS, BUS_FIXME, "level 1 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
- { do_sea, SIGBUS, BUS_FIXME, "level 2 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
- { do_sea, SIGBUS, BUS_FIXME, "level 3 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
- { do_bad, SIGBUS, BUS_FIXME, "unknown 32" },
+ { do_sea, SIGBUS, BUS_OBJERR, "synchronous external abort" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 17" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 18" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 19" },
+ { do_sea, SIGKILL, SI_KERNEL, "level 0 (translation table walk)" },
+ { do_sea, SIGKILL, SI_KERNEL, "level 1 (translation table walk)" },
+ { do_sea, SIGKILL, SI_KERNEL, "level 2 (translation table walk)" },
+ { do_sea, SIGKILL, SI_KERNEL, "level 3 (translation table walk)" },
+ { do_sea, SIGBUS, BUS_OBJERR, "synchronous parity or ECC error" }, // Reserved when RAS is implemented
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 25" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 26" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 27" },
+ { do_sea, SIGKILL, SI_KERNEL, "level 0 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
+ { do_sea, SIGKILL, SI_KERNEL, "level 1 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
+ { do_sea, SIGKILL, SI_KERNEL, "level 2 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
+ { do_sea, SIGKILL, SI_KERNEL, "level 3 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 32" },
{ do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 34" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 35" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 36" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 37" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 38" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 39" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 40" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 41" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 42" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 43" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 44" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 45" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 46" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 47" },
- { do_bad, SIGBUS, BUS_FIXME, "TLB conflict abort" },
- { do_bad, SIGBUS, BUS_FIXME, "Unsupported atomic hardware update fault" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 50" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 51" },
- { do_bad, SIGBUS, BUS_FIXME, "implementation fault (lockdown abort)" },
- { do_bad, SIGBUS, BUS_FIXME, "implementation fault (unsupported exclusive)" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 54" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 55" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 56" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 57" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 58" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 59" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 60" },
- { do_bad, SIGBUS, BUS_FIXME, "section domain fault" },
- { do_bad, SIGBUS, BUS_FIXME, "page domain fault" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 63" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 34" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 35" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 36" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 37" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 38" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 39" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 40" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 41" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 42" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 43" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 44" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 45" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 46" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 47" },
+ { do_bad, SIGKILL, SI_KERNEL, "TLB conflict abort" },
+ { do_bad, SIGKILL, SI_KERNEL, "Unsupported atomic hardware update fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 50" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 51" },
+ { do_bad, SIGKILL, SI_KERNEL, "implementation fault (lockdown abort)" },
+ { do_bad, SIGBUS, BUS_OBJERR, "implementation fault (unsupported exclusive)" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 54" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 55" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 56" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 57" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 58" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 59" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 60" },
+ { do_bad, SIGKILL, SI_KERNEL, "section domain fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "page domain fault" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 63" },
};
int handle_guest_sea(phys_addr_t addr, unsigned int esr)
@@ -698,19 +681,17 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
if (!inf->fn(addr, esr, regs))
return;
- pr_alert("Unhandled fault: %s at 0x%016lx\n",
- inf->name, addr);
-
- mem_abort_decode(esr);
-
- if (!user_mode(regs))
+ if (!user_mode(regs)) {
+ pr_alert("Unhandled fault at 0x%016lx\n", addr);
+ mem_abort_decode(esr);
show_pte(addr);
+ }
info.si_signo = inf->sig;
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
- arm64_notify_die("", regs, &info, esr);
+ arm64_notify_die(inf->name, regs, &info, esr);
}
asmlinkage void __exception do_el0_irq_bp_hardening(void)
@@ -741,7 +722,6 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
struct pt_regs *regs)
{
struct siginfo info;
- struct task_struct *tsk = current;
if (user_mode(regs)) {
if (instruction_pointer(regs) > TASK_SIZE)
@@ -749,17 +729,11 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
local_irq_enable();
}
- if (show_unhandled_signals && unhandled_signal(tsk, SIGBUS))
- pr_info_ratelimited("%s[%d]: %s exception: pc=%p sp=%p\n",
- tsk->comm, task_pid_nr(tsk),
- esr_get_class_string(esr), (void *)regs->pc,
- (void *)regs->sp);
-
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
info.si_addr = (void __user *)addr;
- arm64_notify_die("Oops - SP/PC alignment exception", regs, &info, esr);
+ arm64_notify_die("SP/PC alignment exception", regs, &info, esr);
}
int __init early_brk64(unsigned long addr, unsigned int esr,
@@ -774,11 +748,11 @@ static struct fault_info __refdata debug_fault_info[] = {
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" },
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" },
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 3" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 3" },
{ do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" },
- { do_bad, SIGTRAP, TRAP_FIXME, "aarch32 vector catch" },
+ { do_bad, SIGKILL, SI_KERNEL, "aarch32 vector catch" },
{ early_brk64, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" },
- { do_bad, SIGBUS, BUS_FIXME, "unknown 7" },
+ { do_bad, SIGKILL, SI_KERNEL, "unknown 7" },
};
void __init hook_debug_fault_code(int nr,
@@ -814,14 +788,11 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
if (!inf->fn(addr, esr, regs)) {
rv = 1;
} else {
- pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n",
- inf->name, esr, addr);
-
info.si_signo = inf->sig;
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
- arm64_notify_die("", regs, &info, 0);
+ arm64_notify_die(inf->name, regs, &info, esr);
rv = 0;
}
@@ -833,7 +804,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
NOKPROBE_SYMBOL(do_debug_exception);
#ifdef CONFIG_ARM64_PAN
-int cpu_enable_pan(void *__unused)
+void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
{
/*
* We modify PSTATE. This won't work from irq context as the PSTATE
@@ -843,6 +814,5 @@ int cpu_enable_pan(void *__unused)
config_sctlr_el1(SCTLR_EL1_SPAN, 0);
asm(SET_PSTATE_PAN(1));
- return 0;
}
#endif /* CONFIG_ARM64_PAN */
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index c0af47617299..5f9a73a4452c 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -36,6 +36,12 @@
#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K
#endif
+#ifdef CONFIG_RANDOMIZE_BASE
+#define TCR_KASLR_FLAGS TCR_NFD1
+#else
+#define TCR_KASLR_FLAGS 0
+#endif
+
#define TCR_SMP_FLAGS TCR_SHARED
/* PTWs cacheable, inner/outer WBWA */
@@ -432,7 +438,8 @@ ENTRY(__cpu_setup)
* both user and kernel.
*/
ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
- TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 | TCR_A1
+ TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
+ TCR_TBI0 | TCR_A1
tcr_set_idmap_t0sz x10, x9
/*
@@ -441,16 +448,15 @@ ENTRY(__cpu_setup)
tcr_compute_pa_size x10, #TCR_IPS_SHIFT, x5, x6
#ifdef CONFIG_ARM64_HW_AFDBM
/*
- * Hardware update of the Access and Dirty bits.
+ * Enable hardware update of the Access Flags bit.
+ * Hardware dirty bit management is enabled later,
+ * via capabilities.
*/
mrs x9, ID_AA64MMFR1_EL1
and x9, x9, #0xf
- cbz x9, 2f
- cmp x9, #2
- b.lt 1f
- orr x10, x10, #TCR_HD // hardware Dirty flag update
-1: orr x10, x10, #TCR_HA // hardware Access flag update
-2:
+ cbz x9, 1f
+ orr x10, x10, #TCR_HA // hardware Access flag update
+1:
#endif /* CONFIG_ARM64_HW_AFDBM */
msr tcr_el1, x10
ret // return to head.S