*/
 #define EX_TABLE(_fault, _target)              \
        stringify_in_c(.section __ex_table,"a";)\
-       PPC_LONG_ALIGN stringify_in_c(;)        \
-       PPC_LONG stringify_in_c(_fault;)        \
-       PPC_LONG stringify_in_c(_target;)       \
+       stringify_in_c(.balign 4;)              \
+       stringify_in_c(.long (_fault) - . ;)    \
+       stringify_in_c(.long (_target) - . ;)   \
        stringify_in_c(.previous)
 
 #endif /* _ASM_POWERPC_PPC_ASM_H */
 
         __access_ok((__force unsigned long)(addr), (size), get_fs()))
 
 /*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
+ * The exception table consists of pairs of relative addresses: the first is
+ * the address of an instruction that is allowed to fault, and the second is
  * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * modified, so it is entirely up to the continuation code to figure out what
+ * to do.
  *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
+ * All the routines below use bits of fixup code that are out of line with the
+ * main instruction path.  This means when everything is well, we don't even
+ * have to jump over them.  Further, they do not intrude on our cache or tlb
+ * entries.
  */
 
+#define ARCH_HAS_RELATIVE_EXTABLE
+
 struct exception_table_entry {
-       unsigned long insn;
-       unsigned long fixup;
+       int insn;
+       int fixup;
 };
 
+static inline unsigned long extable_fixup(const struct exception_table_entry *x)
+{
+       return (unsigned long)&x->fixup + x->fixup;
+}
+
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
 
                 * zero, try to fix up.
                 */
                if ((entry = search_exception_tables(regs->nip)) != NULL) {
-                       regs->nip = entry->fixup;
+                       regs->nip = extable_fixup(entry);
                        return 1;
                }
 
 
                               (*nip & 0x100)? "OUT to": "IN from",
                               regs->gpr[rb] - _IO_BASE, nip);
                        regs->msr |= MSR_RI;
-                       regs->nip = entry->fixup;
+                       regs->nip = extable_fixup(entry);
                        return 1;
                }
        }
 
 
        /* Are we prepared to handle this fault?  */
        if ((entry = search_exception_tables(regs->nip)) != NULL) {
-               regs->nip = entry->fixup;
+               regs->nip = extable_fixup(entry);
                return;
        }
 
 
        if ((entry = search_exception_tables(regs->nip)) != NULL) {
                tsi108_clear_pci_cfg_error();
                regs->msr |= MSR_RI;
-               regs->nip = entry->fixup;
+               regs->nip = extable_fixup(entry);
                return 1;
        }
        return 0;
 
        if ((entry = search_exception_tables(regs->nip)) != NULL) {
                tsi108_clear_pci_cfg_error();
                regs->msr |= MSR_RI;
-               regs->nip = entry->fixup;
+               regs->nip = extable_fixup(entry);
                return 1;
        }
        return 0;
 
                        out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
                                 0);
                        regs->msr |= MSR_RI;
-                       regs->nip = entry->fixup;
+                       regs->nip = extable_fixup(entry);
                        return 1;
                }
        }
 
 #error implement UCONTEXT_NIA
 #endif
 
+struct extbl_entry {
+       int insn;
+       int fixup;
+};
 
 static void segv_handler(int signr, siginfo_t *info, void *ptr)
 {
        ucontext_t *uc = (ucontext_t *)ptr;
        unsigned long addr = (unsigned long)info->si_addr;
        unsigned long *ip = &UCONTEXT_NIA(uc);
-       unsigned long *ex_p = (unsigned long *)__start___ex_table;
+       struct extbl_entry *entry = (struct extbl_entry *)__start___ex_table;
 
-       while (ex_p < (unsigned long *)__stop___ex_table) {
+       while (entry < (struct extbl_entry *)__stop___ex_table) {
                unsigned long insn, fixup;
 
-               insn = *ex_p++;
-               fixup = *ex_p++;
+               insn  = (unsigned long)&entry->insn + entry->insn;
+               fixup = (unsigned long)&entry->fixup + entry->fixup;
 
                if (insn == *ip) {
                        *ip = fixup;