diff options
| -rw-r--r-- | arch/arm64/mm/fault.c | 42 | ||||
| -rw-r--r-- | arch/arm64/mm/hugetlbpage.c | 14 |
2 files changed, 24 insertions, 32 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 4bf899fb451b..1b35b8bddbfb 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
| @@ -42,7 +42,20 @@ | |||
| 42 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 43 | #include <asm/tlbflush.h> | 43 | #include <asm/tlbflush.h> |
| 44 | 44 | ||
| 45 | static const char *fault_name(unsigned int esr); | 45 | struct fault_info { |
| 46 | int (*fn)(unsigned long addr, unsigned int esr, | ||
| 47 | struct pt_regs *regs); | ||
| 48 | int sig; | ||
| 49 | int code; | ||
| 50 | const char *name; | ||
| 51 | }; | ||
| 52 | |||
| 53 | static const struct fault_info fault_info[]; | ||
| 54 | |||
| 55 | static inline const struct fault_info *esr_to_fault_info(unsigned int esr) | ||
| 56 | { | ||
| 57 | return fault_info + (esr & 63); | ||
| 58 | } | ||
| 46 | 59 | ||
| 47 | #ifdef CONFIG_KPROBES | 60 | #ifdef CONFIG_KPROBES |
| 48 | static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr) | 61 | static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr) |
| @@ -197,10 +210,12 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, | |||
| 197 | struct pt_regs *regs) | 210 | struct pt_regs *regs) |
| 198 | { | 211 | { |
| 199 | struct siginfo si; | 212 | struct siginfo si; |
| 213 | const struct fault_info *inf; | ||
| 200 | 214 | ||
| 201 | if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) { | 215 | if (unhandled_signal(tsk, sig) && show_unhandled_signals_ratelimited()) { |
| 216 | inf = esr_to_fault_info(esr); | ||
| 202 | pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", | 217 | pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", |
| 203 | tsk->comm, task_pid_nr(tsk), fault_name(esr), sig, | 218 | tsk->comm, task_pid_nr(tsk), inf->name, sig, |
| 204 | addr, esr); | 219 | addr, esr); |
| 205 | show_pte(tsk->mm, addr); | 220 | show_pte(tsk->mm, addr); |
| 206 | show_regs(regs); | 221 | show_regs(regs); |
| @@ -219,14 +234,16 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re | |||
| 219 | { | 234 | { |
| 220 | struct task_struct *tsk = current; | 235 | struct task_struct *tsk = current; |
| 221 | struct mm_struct *mm = tsk->active_mm; | 236 | struct mm_struct *mm = tsk->active_mm; |
| 237 | const struct fault_info *inf; | ||
| 222 | 238 | ||
| 223 | /* | 239 | /* |
| 224 | * If we are in kernel mode at this point, we have no context to | 240 | * If we are in kernel mode at this point, we have no context to |
| 225 | * handle this fault with. | 241 | * handle this fault with. |
| 226 | */ | 242 | */ |
| 227 | if (user_mode(regs)) | 243 | if (user_mode(regs)) { |
| 228 | __do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs); | 244 | inf = esr_to_fault_info(esr); |
| 229 | else | 245 | __do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs); |
| 246 | } else | ||
| 230 | __do_kernel_fault(mm, addr, esr, regs); | 247 | __do_kernel_fault(mm, addr, esr, regs); |
| 231 | } | 248 | } |
| 232 | 249 | ||
| @@ -488,12 +505,7 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) | |||
| 488 | return 1; | 505 | return 1; |
| 489 | } | 506 | } |
| 490 | 507 | ||
| 491 | static const struct fault_info { | 508 | static const struct fault_info fault_info[] = { |
| 492 | int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); | ||
| 493 | int sig; | ||
| 494 | int code; | ||
| 495 | const char *name; | ||
| 496 | } fault_info[] = { | ||
| 497 | { do_bad, SIGBUS, 0, "ttbr address size fault" }, | 509 | { do_bad, SIGBUS, 0, "ttbr address size fault" }, |
| 498 | { do_bad, SIGBUS, 0, "level 1 address size fault" }, | 510 | { do_bad, SIGBUS, 0, "level 1 address size fault" }, |
| 499 | { do_bad, SIGBUS, 0, "level 2 address size fault" }, | 511 | { do_bad, SIGBUS, 0, "level 2 address size fault" }, |
| @@ -560,19 +572,13 @@ static const struct fault_info { | |||
| 560 | { do_bad, SIGBUS, 0, "unknown 63" }, | 572 | { do_bad, SIGBUS, 0, "unknown 63" }, |
| 561 | }; | 573 | }; |
| 562 | 574 | ||
| 563 | static const char *fault_name(unsigned int esr) | ||
| 564 | { | ||
| 565 | const struct fault_info *inf = fault_info + (esr & 63); | ||
| 566 | return inf->name; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* | 575 | /* |
| 570 | * Dispatch a data abort to the relevant handler. | 576 | * Dispatch a data abort to the relevant handler. |
| 571 | */ | 577 | */ |
| 572 | asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, | 578 | asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, |
| 573 | struct pt_regs *regs) | 579 | struct pt_regs *regs) |
| 574 | { | 580 | { |
| 575 | const struct fault_info *inf = fault_info + (esr & 63); | 581 | const struct fault_info *inf = esr_to_fault_info(esr); |
| 576 | struct siginfo info; | 582 | struct siginfo info; |
| 577 | 583 | ||
| 578 | if (!inf->fn(addr, esr, regs)) | 584 | if (!inf->fn(addr, esr, regs)) |
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index e25584d72396..7514a000e361 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c | |||
| @@ -294,10 +294,6 @@ static __init int setup_hugepagesz(char *opt) | |||
| 294 | hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); | 294 | hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); |
| 295 | } else if (ps == PUD_SIZE) { | 295 | } else if (ps == PUD_SIZE) { |
| 296 | hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); | 296 | hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); |
| 297 | } else if (ps == (PAGE_SIZE * CONT_PTES)) { | ||
| 298 | hugetlb_add_hstate(CONT_PTE_SHIFT); | ||
| 299 | } else if (ps == (PMD_SIZE * CONT_PMDS)) { | ||
| 300 | hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT); | ||
| 301 | } else { | 297 | } else { |
| 302 | hugetlb_bad_size(); | 298 | hugetlb_bad_size(); |
| 303 | pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10); | 299 | pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10); |
| @@ -306,13 +302,3 @@ static __init int setup_hugepagesz(char *opt) | |||
| 306 | return 1; | 302 | return 1; |
| 307 | } | 303 | } |
| 308 | __setup("hugepagesz=", setup_hugepagesz); | 304 | __setup("hugepagesz=", setup_hugepagesz); |
| 309 | |||
| 310 | #ifdef CONFIG_ARM64_64K_PAGES | ||
| 311 | static __init int add_default_hugepagesz(void) | ||
| 312 | { | ||
| 313 | if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL) | ||
| 314 | hugetlb_add_hstate(CONT_PTE_SHIFT); | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | arch_initcall(add_default_hugepagesz); | ||
| 318 | #endif | ||
