diff options
Diffstat (limited to 'arch/arm64/mm/fault.c')
| -rw-r--r-- | arch/arm64/mm/fault.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 0cb0e09995e1..a30818ed9c60 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
| @@ -171,9 +171,10 @@ static void show_pte(unsigned long addr) | |||
| 171 | return; | 171 | return; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp = %p\n", | 174 | pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp=%016lx\n", |
| 175 | mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, | 175 | mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, |
| 176 | mm == &init_mm ? VA_BITS : (int) vabits_user, mm->pgd); | 176 | mm == &init_mm ? VA_BITS : (int)vabits_user, |
| 177 | (unsigned long)virt_to_phys(mm->pgd)); | ||
| 177 | pgdp = pgd_offset(mm, addr); | 178 | pgdp = pgd_offset(mm, addr); |
| 178 | pgd = READ_ONCE(*pgdp); | 179 | pgd = READ_ONCE(*pgdp); |
| 179 | pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd)); | 180 | pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd)); |
| @@ -810,6 +811,36 @@ void __init hook_debug_fault_code(int nr, | |||
| 810 | debug_fault_info[nr].name = name; | 811 | debug_fault_info[nr].name = name; |
| 811 | } | 812 | } |
| 812 | 813 | ||
| 814 | #ifdef CONFIG_ARM64_ERRATUM_1463225 | ||
| 815 | DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); | ||
| 816 | |||
| 817 | static int __exception | ||
| 818 | cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) | ||
| 819 | { | ||
| 820 | if (user_mode(regs)) | ||
| 821 | return 0; | ||
| 822 | |||
| 823 | if (!__this_cpu_read(__in_cortex_a76_erratum_1463225_wa)) | ||
| 824 | return 0; | ||
| 825 | |||
| 826 | /* | ||
| 827 | * We've taken a dummy step exception from the kernel to ensure | ||
| 828 | * that interrupts are re-enabled on the syscall path. Return back | ||
| 829 | * to cortex_a76_erratum_1463225_svc_handler() with debug exceptions | ||
| 830 | * masked so that we can safely restore the mdscr and get on with | ||
| 831 | * handling the syscall. | ||
| 832 | */ | ||
| 833 | regs->pstate |= PSR_D_BIT; | ||
| 834 | return 1; | ||
| 835 | } | ||
| 836 | #else | ||
| 837 | static int __exception | ||
| 838 | cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) | ||
| 839 | { | ||
| 840 | return 0; | ||
| 841 | } | ||
| 842 | #endif /* CONFIG_ARM64_ERRATUM_1463225 */ | ||
| 843 | |||
| 813 | asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint, | 844 | asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint, |
| 814 | unsigned int esr, | 845 | unsigned int esr, |
| 815 | struct pt_regs *regs) | 846 | struct pt_regs *regs) |
| @@ -817,6 +848,9 @@ asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint, | |||
| 817 | const struct fault_info *inf = esr_to_debug_fault_info(esr); | 848 | const struct fault_info *inf = esr_to_debug_fault_info(esr); |
| 818 | unsigned long pc = instruction_pointer(regs); | 849 | unsigned long pc = instruction_pointer(regs); |
| 819 | 850 | ||
| 851 | if (cortex_a76_erratum_1463225_debug_handler(regs)) | ||
| 852 | return; | ||
| 853 | |||
| 820 | /* | 854 | /* |
| 821 | * Tell lockdep we disabled irqs in entry.S. Do nothing if they were | 855 | * Tell lockdep we disabled irqs in entry.S. Do nothing if they were |
| 822 | * already disabled to preserve the last enabled/disabled addresses. | 856 | * already disabled to preserve the last enabled/disabled addresses. |
