diff options
Diffstat (limited to 'arch/arm64/mm/fault.c')
| -rw-r--r-- | arch/arm64/mm/fault.c | 54 | 
1 files changed, 41 insertions, 13 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 1a7e92ab69eb..a30818ed9c60 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -148,7 +148,7 @@ static inline bool is_ttbr1_addr(unsigned long addr)  /*   * Dump out the page tables associated with 'addr' in the currently active mm.   */ -void show_pte(unsigned long addr) +static void show_pte(unsigned long addr)  {  	struct mm_struct *mm;  	pgd_t *pgdp; @@ -171,9 +171,10 @@ void show_pte(unsigned long addr)  		return;  	} -	pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp = %p\n", +	pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp=%016lx\n",  		 mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, -		 mm == &init_mm ? VA_BITS : (int) vabits_user, mm->pgd); +		 mm == &init_mm ? VA_BITS : (int)vabits_user, +		 (unsigned long)virt_to_phys(mm->pgd));  	pgdp = pgd_offset(mm, addr);  	pgd = READ_ONCE(*pgdp);  	pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd)); @@ -810,13 +811,45 @@ void __init hook_debug_fault_code(int nr,  	debug_fault_info[nr].name	= name;  } -asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint, -					      unsigned int esr, -					      struct pt_regs *regs) +#ifdef CONFIG_ARM64_ERRATUM_1463225 +DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); + +static int __exception +cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) +{ +	if (user_mode(regs)) +		return 0; + +	if (!__this_cpu_read(__in_cortex_a76_erratum_1463225_wa)) +		return 0; + +	/* +	 * We've taken a dummy step exception from the kernel to ensure +	 * that interrupts are re-enabled on the syscall path. Return back +	 * to cortex_a76_erratum_1463225_svc_handler() with debug exceptions +	 * masked so that we can safely restore the mdscr and get on with +	 * handling the syscall. +	 */ +	regs->pstate |= PSR_D_BIT; +	return 1; +} +#else +static int __exception +cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) +{ +	return 0; +} +#endif /* CONFIG_ARM64_ERRATUM_1463225 */ + +asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint, +					       unsigned int esr, +					       struct pt_regs *regs)  {  	const struct fault_info *inf = esr_to_debug_fault_info(esr);  	unsigned long pc = instruction_pointer(regs); -	int rv; + +	if (cortex_a76_erratum_1463225_debug_handler(regs)) +		return;  	/*  	 * Tell lockdep we disabled irqs in entry.S. Do nothing if they were @@ -828,17 +861,12 @@ asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint,  	if (user_mode(regs) && !is_ttbr0_addr(pc))  		arm64_apply_bp_hardening(); -	if (!inf->fn(addr_if_watchpoint, esr, regs)) { -		rv = 1; -	} else { +	if (inf->fn(addr_if_watchpoint, esr, regs)) {  		arm64_notify_die(inf->name, regs,  				 inf->sig, inf->code, (void __user *)pc, esr); -		rv = 0;  	}  	if (interrupts_enabled(regs))  		trace_hardirqs_on(); - -	return rv;  }  NOKPROBE_SYMBOL(do_debug_exception);  |