From 6be84779f740db4088eab4011b26f9149503a4fa Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Tue, 27 Jan 2004 05:23:19 -0800 Subject: [PATCH] ia64: Implement exception-table sorting for real. --- arch/ia64/kernel/unaligned.c | 4 +-- arch/ia64/mm/extable.c | 48 +++++++++++++++++++++++++++++++++--- arch/ia64/mm/fault.c | 2 +- include/asm-ia64/uaccess.h | 11 ++++----- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 95f77b1dfa117..6cb14f493cd9f 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1,7 +1,7 @@ /* * Architecture-specific unaligned trap handling. * - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co * Stephane Eranian * David Mosberger-Tang * @@ -1328,7 +1328,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * handler into reading an arbitrary kernel addresses... */ if (!user_mode(regs)) - eh = SEARCH_EXCEPTION_TABLE(regs); + eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); if (user_mode(regs) || eh) { if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) goto force_sigbus; diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 7f7955395173d..58ef7a7460123 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c @@ -1,7 +1,7 @@ /* * Kernel exception handling table support. Derived from arch/alpha/mm/extable.c. * - * Copyright (C) 1998, 1999, 2001-2002 Hewlett-Packard Co + * Copyright (C) 1998, 1999, 2001-2002, 2004 Hewlett-Packard Co * David Mosberger-Tang */ @@ -10,9 +10,51 @@ #include #include -void sort_extable(struct exception_table_entry *start, - struct exception_table_entry *finish) +static inline int +compare_entries (struct exception_table_entry *l, struct exception_table_entry *r) { + u64 lip = (u64) &l->addr + l->addr; + u64 rip = (u64) &r->addr + r->addr; + + if (lip < rip) + return -1; + if (lip == rip) + return 0; + else + return 1; +} + +static inline void +swap_entries (struct exception_table_entry *l, struct exception_table_entry *r) +{ + u64 delta = (u64) r - (u64) l; + struct exception_table_entry tmp; + + tmp = *l; + l->addr = r->addr + delta; + l->cont = r->cont + delta; + r->addr = tmp.addr - delta; + r->cont = tmp.cont - delta; +} + +/* + * Sort the exception table. It's usually already sorted, but there may be unordered + * entries due to multiple text sections (such as the .init text section). Note that the + * exception-table-entries contain location-relative addresses, which requires a bit of + * care during sorting to avoid overflows in the offset members (e.g., it would not be + * safe to make a temporary copy of an exception-table entry on the stack, because the + * stack may be more than 2GB away from the exception-table). + */ +void +sort_extable (struct exception_table_entry *start, struct exception_table_entry *finish) +{ + struct exception_table_entry *p, *q; + + /* insertion sort */ + for (p = start + 1; p < finish; ++p) + /* start .. p-1 is sorted; push p down to it's proper place */ + for (q = p; q > start && compare_entries(&q[0], &q[-1]) < 0; --q) + swap_entries(&q[0], &q[-1]); } const struct exception_table_entry * diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index fa66ec8b4cfb4..9584a1b2248ab 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -58,7 +58,7 @@ mapped_kernel_page_is_present (unsigned long address) if (pgd_none(*pgd) || pgd_bad(*pgd)) return 0; - pmd = pmd_offset(pgd,address); + pmd = pmd_offset(pgd, address); if (pmd_none(*pmd) || pmd_bad(*pmd)) return 0; diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h index add46cb74d48a..60e77a7807904 100644 --- a/include/asm-ia64/uaccess.h +++ b/include/asm-ia64/uaccess.h @@ -28,7 +28,7 @@ * * Based on . * - * Copyright (C) 1998, 1999, 2001-2003 Hewlett-Packard Co + * Copyright (C) 1998, 1999, 2001-2004 Hewlett-Packard Co * David Mosberger-Tang */ @@ -283,24 +283,23 @@ extern unsigned long __strnlen_user (const char *, long); __su_ret; \ }) +/* Generic code can't deal with the location-relative format that we use for compactness. */ #define ARCH_HAS_SORT_EXTABLE #define ARCH_HAS_SEARCH_EXTABLE struct exception_table_entry { - int addr; /* gp-relative address of insn this fixup is for */ - int cont; /* gp-relative continuation address; if bit 2 is set, r9 is set to 0 */ + int addr; /* location-relative address of insn this fixup is for */ + int cont; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ }; extern void handle_exception (struct pt_regs *regs, const struct exception_table_entry *e); extern const struct exception_table_entry *search_exception_tables (unsigned long addr); -# define SEARCH_EXCEPTION_TABLE(regs) search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri) - static inline int done_with_exception (struct pt_regs *regs) { const struct exception_table_entry *e; - e = SEARCH_EXCEPTION_TABLE(regs); + e = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); if (e) { handle_exception(regs, e); return 1; -- 2.53.0