diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-12 06:17:30 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-12 06:17:36 -0400 |
commit | 6cda3eb62ef42aa5acd649bf99c8db544e0f4051 (patch) | |
tree | 93f74ca002f5756c8e157611174f9540b5cf41c0 /arch/alpha | |
parent | b9c61b70075c87a8612624736faf4a2de5b1ed30 (diff) | |
parent | cec6be6d1069d697beb490bbb40a290d5ff554a2 (diff) |
Merge branch 'x86/apic' into irq/numa
Merge reason: both topics modify the APIC code but were able to do it in
parallel so far. An upcoming patch generates a conflict so
merge them to avoid the conflict.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/alpha')
-rw-r--r-- | arch/alpha/include/asm/barrier.h | 2 | ||||
-rw-r--r-- | arch/alpha/include/asm/futex.h | 118 | ||||
-rw-r--r-- | arch/alpha/include/asm/uaccess.h | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/Makefile | 6 | ||||
-rw-r--r-- | arch/alpha/kernel/binfmt_loader.c | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/err_ev6.c | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/err_ev7.c | 4 | ||||
-rw-r--r-- | arch/alpha/kernel/err_impl.h | 10 | ||||
-rw-r--r-- | arch/alpha/kernel/err_marvel.c | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/err_titan.c | 4 | ||||
-rw-r--r-- | arch/alpha/kernel/proto.h | 5 | ||||
-rw-r--r-- | arch/alpha/mm/extable.c | 40 |
12 files changed, 176 insertions, 21 deletions
diff --git a/arch/alpha/include/asm/barrier.h b/arch/alpha/include/asm/barrier.h index ac78eba909b..ce8860a0b32 100644 --- a/arch/alpha/include/asm/barrier.h +++ b/arch/alpha/include/asm/barrier.h | |||
@@ -16,11 +16,13 @@ __asm__ __volatile__("wmb": : :"memory") | |||
16 | __asm__ __volatile__("mb": : :"memory") | 16 | __asm__ __volatile__("mb": : :"memory") |
17 | 17 | ||
18 | #ifdef CONFIG_SMP | 18 | #ifdef CONFIG_SMP |
19 | #define __ASM_SMP_MB "\tmb\n" | ||
19 | #define smp_mb() mb() | 20 | #define smp_mb() mb() |
20 | #define smp_rmb() rmb() | 21 | #define smp_rmb() rmb() |
21 | #define smp_wmb() wmb() | 22 | #define smp_wmb() wmb() |
22 | #define smp_read_barrier_depends() read_barrier_depends() | 23 | #define smp_read_barrier_depends() read_barrier_depends() |
23 | #else | 24 | #else |
25 | #define __ASM_SMP_MB | ||
24 | #define smp_mb() barrier() | 26 | #define smp_mb() barrier() |
25 | #define smp_rmb() barrier() | 27 | #define smp_rmb() barrier() |
26 | #define smp_wmb() barrier() | 28 | #define smp_wmb() barrier() |
diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h index 6a332a9f099..945de222ab9 100644 --- a/arch/alpha/include/asm/futex.h +++ b/arch/alpha/include/asm/futex.h | |||
@@ -1,6 +1,116 @@ | |||
1 | #ifndef _ASM_FUTEX_H | 1 | #ifndef _ASM_ALPHA_FUTEX_H |
2 | #define _ASM_FUTEX_H | 2 | #define _ASM_ALPHA_FUTEX_H |
3 | 3 | ||
4 | #include <asm-generic/futex.h> | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #endif | 6 | #include <linux/futex.h> |
7 | #include <linux/uaccess.h> | ||
8 | #include <asm/errno.h> | ||
9 | #include <asm/barrier.h> | ||
10 | |||
11 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | ||
12 | __asm__ __volatile__( \ | ||
13 | __ASM_SMP_MB \ | ||
14 | "1: ldl_l %0,0(%2)\n" \ | ||
15 | insn \ | ||
16 | "2: stl_c %1,0(%2)\n" \ | ||
17 | " beq %1,4f\n" \ | ||
18 | " mov $31,%1\n" \ | ||
19 | "3: .subsection 2\n" \ | ||
20 | "4: br 1b\n" \ | ||
21 | " .previous\n" \ | ||
22 | " .section __ex_table,\"a\"\n" \ | ||
23 | " .long 1b-.\n" \ | ||
24 | " lda $31,3b-1b(%1)\n" \ | ||
25 | " .long 2b-.\n" \ | ||
26 | " lda $31,3b-2b(%1)\n" \ | ||
27 | " .previous\n" \ | ||
28 | : "=&r" (oldval), "=&r"(ret) \ | ||
29 | : "r" (uaddr), "r"(oparg) \ | ||
30 | : "memory") | ||
31 | |||
32 | static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | ||
33 | { | ||
34 | int op = (encoded_op >> 28) & 7; | ||
35 | int cmp = (encoded_op >> 24) & 15; | ||
36 | int oparg = (encoded_op << 8) >> 20; | ||
37 | int cmparg = (encoded_op << 20) >> 20; | ||
38 | int oldval = 0, ret; | ||
39 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
40 | oparg = 1 << oparg; | ||
41 | |||
42 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
43 | return -EFAULT; | ||
44 | |||
45 | pagefault_disable(); | ||
46 | |||
47 | switch (op) { | ||
48 | case FUTEX_OP_SET: | ||
49 | __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg); | ||
50 | break; | ||
51 | case FUTEX_OP_ADD: | ||
52 | __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg); | ||
53 | break; | ||
54 | case FUTEX_OP_OR: | ||
55 | __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg); | ||
56 | break; | ||
57 | case FUTEX_OP_ANDN: | ||
58 | __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg); | ||
59 | break; | ||
60 | case FUTEX_OP_XOR: | ||
61 | __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg); | ||
62 | break; | ||
63 | default: | ||
64 | ret = -ENOSYS; | ||
65 | } | ||
66 | |||
67 | pagefault_enable(); | ||
68 | |||
69 | if (!ret) { | ||
70 | switch (cmp) { | ||
71 | case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; | ||
72 | case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; | ||
73 | case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; | ||
74 | case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; | ||
75 | case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; | ||
76 | case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; | ||
77 | default: ret = -ENOSYS; | ||
78 | } | ||
79 | } | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | static inline int | ||
84 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
85 | { | ||
86 | int prev, cmp; | ||
87 | |||
88 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
89 | return -EFAULT; | ||
90 | |||
91 | __asm__ __volatile__ ( | ||
92 | __ASM_SMP_MB | ||
93 | "1: ldl_l %0,0(%2)\n" | ||
94 | " cmpeq %0,%3,%1\n" | ||
95 | " beq %1,3f\n" | ||
96 | " mov %4,%1\n" | ||
97 | "2: stl_c %1,0(%2)\n" | ||
98 | " beq %1,4f\n" | ||
99 | "3: .subsection 2\n" | ||
100 | "4: br 1b\n" | ||
101 | " .previous\n" | ||
102 | " .section __ex_table,\"a\"\n" | ||
103 | " .long 1b-.\n" | ||
104 | " lda $31,3b-1b(%0)\n" | ||
105 | " .long 2b-.\n" | ||
106 | " lda $31,3b-2b(%0)\n" | ||
107 | " .previous\n" | ||
108 | : "=&r"(prev), "=&r"(cmp) | ||
109 | : "r"(uaddr), "r"((long)oldval), "r"(newval) | ||
110 | : "memory"); | ||
111 | |||
112 | return prev; | ||
113 | } | ||
114 | |||
115 | #endif /* __KERNEL__ */ | ||
116 | #endif /* _ASM_ALPHA_FUTEX_H */ | ||
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 163f3053001..b49ec2f8d6e 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h | |||
@@ -507,5 +507,7 @@ struct exception_table_entry | |||
507 | (pc) + (_fixup)->fixup.bits.nextinsn; \ | 507 | (pc) + (_fixup)->fixup.bits.nextinsn; \ |
508 | }) | 508 | }) |
509 | 509 | ||
510 | #define ARCH_HAS_SORT_EXTABLE | ||
511 | #define ARCH_HAS_SEARCH_EXTABLE | ||
510 | 512 | ||
511 | #endif /* __ALPHA_UACCESS_H */ | 513 | #endif /* __ALPHA_UACCESS_H */ |
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index a427538252f..7739a62440a 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile | |||
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror -Wno-sign-compare | |||
8 | 8 | ||
9 | obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ | 9 | obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ |
10 | irq_alpha.o signal.o setup.o ptrace.o time.o \ | 10 | irq_alpha.o signal.o setup.o ptrace.o time.o \ |
11 | alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o | 11 | alpha_ksyms.o systbls.o err_common.o io.o |
12 | 12 | ||
13 | obj-$(CONFIG_VGA_HOSE) += console.o | 13 | obj-$(CONFIG_VGA_HOSE) += console.o |
14 | obj-$(CONFIG_SMP) += smp.o | 14 | obj-$(CONFIG_SMP) += smp.o |
@@ -43,6 +43,10 @@ else | |||
43 | # Misc support | 43 | # Misc support |
44 | obj-$(CONFIG_ALPHA_SRM) += srmcons.o | 44 | obj-$(CONFIG_ALPHA_SRM) += srmcons.o |
45 | 45 | ||
46 | ifdef CONFIG_BINFMT_AOUT | ||
47 | obj-y += binfmt_loader.o | ||
48 | endif | ||
49 | |||
46 | # Core logic support | 50 | # Core logic support |
47 | obj-$(CONFIG_ALPHA_APECS) += core_apecs.o | 51 | obj-$(CONFIG_ALPHA_APECS) += core_apecs.o |
48 | obj-$(CONFIG_ALPHA_CIA) += core_cia.o | 52 | obj-$(CONFIG_ALPHA_CIA) += core_cia.o |
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c index 4a0af906b00..3fcfad41013 100644 --- a/arch/alpha/kernel/binfmt_loader.c +++ b/arch/alpha/kernel/binfmt_loader.c | |||
@@ -46,6 +46,6 @@ static struct linux_binfmt loader_format = { | |||
46 | 46 | ||
47 | static int __init init_loader_binfmt(void) | 47 | static int __init init_loader_binfmt(void) |
48 | { | 48 | { |
49 | return register_binfmt(&loader_format); | 49 | return insert_binfmt(&loader_format); |
50 | } | 50 | } |
51 | arch_initcall(init_loader_binfmt); | 51 | arch_initcall(init_loader_binfmt); |
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 985e5c1681a..8ca6345bf13 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c | |||
@@ -229,7 +229,7 @@ ev6_process_logout_frame(struct el_common *mchk_header, int print) | |||
229 | } | 229 | } |
230 | 230 | ||
231 | void | 231 | void |
232 | ev6_machine_check(u64 vector, u64 la_ptr) | 232 | ev6_machine_check(unsigned long vector, unsigned long la_ptr) |
233 | { | 233 | { |
234 | struct el_common *mchk_header = (struct el_common *)la_ptr; | 234 | struct el_common *mchk_header = (struct el_common *)la_ptr; |
235 | 235 | ||
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c index 73770c6ca01..d738a67112d 100644 --- a/arch/alpha/kernel/err_ev7.c +++ b/arch/alpha/kernel/err_ev7.c | |||
@@ -117,7 +117,7 @@ ev7_collect_logout_frame_subpackets(struct el_subpacket *el_ptr, | |||
117 | } | 117 | } |
118 | 118 | ||
119 | void | 119 | void |
120 | ev7_machine_check(u64 vector, u64 la_ptr) | 120 | ev7_machine_check(unsigned long vector, unsigned long la_ptr) |
121 | { | 121 | { |
122 | struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; | 122 | struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; |
123 | char *saved_err_prefix = err_print_prefix; | 123 | char *saved_err_prefix = err_print_prefix; |
@@ -246,7 +246,7 @@ ev7_process_pal_subpacket(struct el_subpacket *header) | |||
246 | 246 | ||
247 | switch(header->type) { | 247 | switch(header->type) { |
248 | case EL_TYPE__PAL__LOGOUT_FRAME: | 248 | case EL_TYPE__PAL__LOGOUT_FRAME: |
249 | printk("%s*** MCHK occurred on LPID %ld (RBOX %llx)\n", | 249 | printk("%s*** MCHK occurred on LPID %lld (RBOX %llx)\n", |
250 | err_print_prefix, | 250 | err_print_prefix, |
251 | packet->by_type.logout.whami, | 251 | packet->by_type.logout.whami, |
252 | packet->by_type.logout.rbox_whami); | 252 | packet->by_type.logout.rbox_whami); |
diff --git a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h index 3c12258158e..0c010ca4611 100644 --- a/arch/alpha/kernel/err_impl.h +++ b/arch/alpha/kernel/err_impl.h | |||
@@ -60,26 +60,26 @@ extern struct ev7_lf_subpackets * | |||
60 | ev7_collect_logout_frame_subpackets(struct el_subpacket *, | 60 | ev7_collect_logout_frame_subpackets(struct el_subpacket *, |
61 | struct ev7_lf_subpackets *); | 61 | struct ev7_lf_subpackets *); |
62 | extern void ev7_register_error_handlers(void); | 62 | extern void ev7_register_error_handlers(void); |
63 | extern void ev7_machine_check(u64, u64); | 63 | extern void ev7_machine_check(unsigned long, unsigned long); |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * err_ev6.c | 66 | * err_ev6.c |
67 | */ | 67 | */ |
68 | extern void ev6_register_error_handlers(void); | 68 | extern void ev6_register_error_handlers(void); |
69 | extern int ev6_process_logout_frame(struct el_common *, int); | 69 | extern int ev6_process_logout_frame(struct el_common *, int); |
70 | extern void ev6_machine_check(u64, u64); | 70 | extern void ev6_machine_check(unsigned long, unsigned long); |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * err_marvel.c | 73 | * err_marvel.c |
74 | */ | 74 | */ |
75 | extern void marvel_machine_check(u64, u64); | 75 | extern void marvel_machine_check(unsigned long, unsigned long); |
76 | extern void marvel_register_error_handlers(void); | 76 | extern void marvel_register_error_handlers(void); |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * err_titan.c | 79 | * err_titan.c |
80 | */ | 80 | */ |
81 | extern int titan_process_logout_frame(struct el_common *, int); | 81 | extern int titan_process_logout_frame(struct el_common *, int); |
82 | extern void titan_machine_check(u64, u64); | 82 | extern void titan_machine_check(unsigned long, unsigned long); |
83 | extern void titan_register_error_handlers(void); | 83 | extern void titan_register_error_handlers(void); |
84 | extern int privateer_process_logout_frame(struct el_common *, int); | 84 | extern int privateer_process_logout_frame(struct el_common *, int); |
85 | extern void privateer_machine_check(u64, u64); | 85 | extern void privateer_machine_check(unsigned long, unsigned long); |
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 6bfd243efba..52a79dfc13c 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c | |||
@@ -1042,7 +1042,7 @@ marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print) | |||
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | void | 1044 | void |
1045 | marvel_machine_check(u64 vector, u64 la_ptr) | 1045 | marvel_machine_check(unsigned long vector, unsigned long la_ptr) |
1046 | { | 1046 | { |
1047 | struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; | 1047 | struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; |
1048 | int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL; | 1048 | int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL; |
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index c7e28a88d6e..f7ed97ce0df 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c | |||
@@ -380,7 +380,7 @@ titan_process_logout_frame(struct el_common *mchk_header, int print) | |||
380 | } | 380 | } |
381 | 381 | ||
382 | void | 382 | void |
383 | titan_machine_check(u64 vector, u64 la_ptr) | 383 | titan_machine_check(unsigned long vector, unsigned long la_ptr) |
384 | { | 384 | { |
385 | struct el_common *mchk_header = (struct el_common *)la_ptr; | 385 | struct el_common *mchk_header = (struct el_common *)la_ptr; |
386 | struct el_TITAN_sysdata_mcheck *tmchk = | 386 | struct el_TITAN_sysdata_mcheck *tmchk = |
@@ -702,7 +702,7 @@ privateer_process_logout_frame(struct el_common *mchk_header, int print) | |||
702 | } | 702 | } |
703 | 703 | ||
704 | void | 704 | void |
705 | privateer_machine_check(u64 vector, u64 la_ptr) | 705 | privateer_machine_check(unsigned long vector, unsigned long la_ptr) |
706 | { | 706 | { |
707 | struct el_common *mchk_header = (struct el_common *)la_ptr; | 707 | struct el_common *mchk_header = (struct el_common *)la_ptr; |
708 | struct el_TITAN_sysdata_mcheck *tmchk = | 708 | struct el_TITAN_sysdata_mcheck *tmchk = |
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 567f2598d09..3d2627ec986 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h | |||
@@ -36,7 +36,6 @@ extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | |||
36 | extern struct pci_ops irongate_pci_ops; | 36 | extern struct pci_ops irongate_pci_ops; |
37 | extern int irongate_pci_clr_err(void); | 37 | extern int irongate_pci_clr_err(void); |
38 | extern void irongate_init_arch(void); | 38 | extern void irongate_init_arch(void); |
39 | extern void irongate_machine_check(u64, u64); | ||
40 | #define irongate_pci_tbi ((void *)0) | 39 | #define irongate_pci_tbi ((void *)0) |
41 | 40 | ||
42 | /* core_lca.c */ | 41 | /* core_lca.c */ |
@@ -49,7 +48,7 @@ extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | |||
49 | extern struct pci_ops marvel_pci_ops; | 48 | extern struct pci_ops marvel_pci_ops; |
50 | extern void marvel_init_arch(void); | 49 | extern void marvel_init_arch(void); |
51 | extern void marvel_kill_arch(int); | 50 | extern void marvel_kill_arch(int); |
52 | extern void marvel_machine_check(u64, u64); | 51 | extern void marvel_machine_check(unsigned long, unsigned long); |
53 | extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 52 | extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
54 | extern int marvel_pa_to_nid(unsigned long); | 53 | extern int marvel_pa_to_nid(unsigned long); |
55 | extern int marvel_cpuid_to_nid(int); | 54 | extern int marvel_cpuid_to_nid(int); |
@@ -86,7 +85,7 @@ extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | |||
86 | extern struct pci_ops titan_pci_ops; | 85 | extern struct pci_ops titan_pci_ops; |
87 | extern void titan_init_arch(void); | 86 | extern void titan_init_arch(void); |
88 | extern void titan_kill_arch(int); | 87 | extern void titan_kill_arch(int); |
89 | extern void titan_machine_check(u64, u64); | 88 | extern void titan_machine_check(unsigned long, unsigned long); |
90 | extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 89 | extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
91 | extern struct _alpha_agp_info *titan_agp_info(void); | 90 | extern struct _alpha_agp_info *titan_agp_info(void); |
92 | 91 | ||
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index dc7aeda1577..62dc379d301 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c | |||
@@ -3,11 +3,49 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/sort.h> | ||
6 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
7 | 8 | ||
9 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
10 | { | ||
11 | return (unsigned long)&x->insn + x->insn; | ||
12 | } | ||
13 | |||
14 | static void swap_ex(void *a, void *b, int size) | ||
15 | { | ||
16 | struct exception_table_entry *ex_a = a, *ex_b = b; | ||
17 | unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b); | ||
18 | unsigned int t = ex_a->fixup.unit; | ||
19 | |||
20 | ex_a->fixup.unit = ex_b->fixup.unit; | ||
21 | ex_b->fixup.unit = t; | ||
22 | ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn); | ||
23 | ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn); | ||
24 | } | ||
25 | |||
26 | /* | ||
27 | * The exception table needs to be sorted so that the binary | ||
28 | * search that we use to find entries in it works properly. | ||
29 | * This is used both for the kernel exception table and for | ||
30 | * the exception tables of modules that get loaded. | ||
31 | */ | ||
32 | static int cmp_ex(const void *a, const void *b) | ||
33 | { | ||
34 | const struct exception_table_entry *x = a, *y = b; | ||
35 | |||
36 | /* avoid overflow */ | ||
37 | if (ex_to_addr(x) > ex_to_addr(y)) | ||
38 | return 1; | ||
39 | if (ex_to_addr(x) < ex_to_addr(y)) | ||
40 | return -1; | ||
41 | return 0; | ||
42 | } | ||
43 | |||
8 | void sort_extable(struct exception_table_entry *start, | 44 | void sort_extable(struct exception_table_entry *start, |
9 | struct exception_table_entry *finish) | 45 | struct exception_table_entry *finish) |
10 | { | 46 | { |
47 | sort(start, finish - start, sizeof(struct exception_table_entry), | ||
48 | cmp_ex, swap_ex); | ||
11 | } | 49 | } |
12 | 50 | ||
13 | const struct exception_table_entry * | 51 | const struct exception_table_entry * |
@@ -20,7 +58,7 @@ search_extable(const struct exception_table_entry *first, | |||
20 | unsigned long mid_value; | 58 | unsigned long mid_value; |
21 | 59 | ||
22 | mid = (last - first) / 2 + first; | 60 | mid = (last - first) / 2 + first; |
23 | mid_value = (unsigned long)&mid->insn + mid->insn; | 61 | mid_value = ex_to_addr(mid); |
24 | if (mid_value == value) | 62 | if (mid_value == value) |
25 | return mid; | 63 | return mid; |
26 | else if (mid_value < value) | 64 | else if (mid_value < value) |