From: David Miller <[EMAIL PROTECTED]>
Date: Thu, 15 Nov 2007 22:23:13 -0800 (PST)

> There has to be a nicer way to do this.  In fact I think I
> just figured out one such technique.
> 
> The whole reason we need these .fixup sections is to encode
> a move of -EFAULT into some register, and a control transfer.
> 
> Every kernel text address, even for modules, is in the low 32-bits on
> sparc64.  So we can encode this more simply, perhaps even with one
> 32-bit word for each entry.
> 
> I can probably encode it all in the __ex_table entries in fact,
> and I'll give that a shot.

Ok, here's what I came up with:

/*
 * The exception table consists 3 32-bit words, the encoding takes
 * advantage of the fact that all kernel text addresses on sparc64 are
 * in the low 4GB of the 64-bit address space so any location can be
 * encoded in 32-bits.
 *
 * The first word is the address of an instruction that is allowed to
 * fault.  This is the search key used by search_exception_tables().
 *
 * The second word is a continuation address in the kernel text.
 *
 * The third word is an instruction to execute before transferring
 * control to the location specified by the second word.  Most of
 * these instructions are of the form:
 *
 *      mov     -EFAULT, %reg
 *
 * Effectively the trap return TPC is set to the address of the third
 * word, and the trap return TNPC is set to the value contained in the
 * second word.
 */
struct exception_table_entry {
        unsigned int insn, fixup_addr, fixup_insn;
};

And then __put_user_asm() now looks like:

#define __put_user_asm(x,size,addr,ret)         \
__asm__ __volatile__(                           \
        "/* Put user asm, inline. */\n"         \
"1:\t"  "st"#size "a %1, [%2] %%asi\n\t"        \
        "clr    %0\n"                           \
"2:\n\n\t"                                      \
        ".section __ex_table\n\t"               \
        ".word  1b, 2b; mov %3, %0\n\t"         \
        ".previous\n\n\t"                       \
       : "=r" (ret) : "r" (x), "r" (__m(addr)), \
         "i" (-EFAULT))

The .fixup section is completely eliminated, and the exception
dispatch goes:

        regs->tpc = (unsigned long) &entry->fixup_insn;
        regs->tnpc = entry->fixup_addr;

I have a full patch implementing this and it passes a
allyesconfig build and link.
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to