Message ID | 4A73821A.4020506@gmx.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
On Thu, Jul 30, 2009 at 8:37 PM, John David Anglin<dave@hiauly1.hia.nrc.ca> wrote: >>    case ELF_STUB_GOT: >> -       stub->insns[0] = 0x537b0000;   /* ldd 0(%dp),%dp    */ >> +       stub->insns[0] = 0x537b0000;   /* ldd 0(%dp),%dp    */ >>        stub->insns[1] = 0x53610020;   /* ldd 10(%dp),%r1    */ >>        stub->insns[2] = 0xe820d000;   /* bve (%r1)       */ >>        stub->insns[3] = 0x537b0030;   /* ldd 18(%dp),%dp    */ >> >> -       stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); >> +       d = get_got(me, value, addend); >> +       if (d <= 15) >> +           stub->insns[0] |= reassemble_14(d); > > reassemble_14 is wrong for ldd format 3.  Need format 5 and im5 insertion. This is using reassemble_14 for ldd format 5, which is correct. Cheers, Carlos. -- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 31 Jul 2009, Carlos O'Donell wrote: > >> + Â Â Â Â Â Â if (d <= 15) > >> + Â Â Â Â Â Â Â Â Â Â stub->insns[0] |= reassemble_14(d); > > > > reassemble_14 is wrong for ldd format 3. Â Need format 5 and im5 insertion. > > This is using reassemble_14 for ldd format 5, which is correct. Huh? Format 5 has a five bit immediate and it's not compatible with reassemble_14. The value is actually being stuffed into a format 3 ldd pattern (i.e., format 3 is being used for displacements 0 and 8). If format 3 is going to be used for short displacements, then use reassemble_16a as it is the inverse to the assemble_16a operation described in the arch. Using reassemble_14 with ldd is confusing. As you pointed out, the arch shows using format 5 for short displacements. It's unclear whether there is a performance or functional difference aside from the behavior of space selection. There may be no requirement for hardware to implement short displacements using format 3. Dave
parisc: module.c - fix GOT table overflow with large kernel modules on 64 bit kernels Signed-off-by: Helge Deller <deller@gmx.de> diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index ef5caf2..d280219 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -86,8 +86,12 @@ * the bottom of the table, which has a maximum signed displacement of * 0x3fff; however, since we're only going forward, this becomes * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have - * at most 1023 entries */ -#define MAX_GOTS 1023 + * at most 1023 entries. + * To overcome this 14bit displacement with some kernel modules, we'll + * use instead the unusal 16bit displacement method (see reassemble_16a) + * which gives us a maximum positive displacement of 0x7fff, and as such + * allows us to allocate up to 4095 GOT entries. */ +#define MAX_GOTS 4095 /* three functions to determine where in the module core * or init pieces the location is */ @@ -151,6 +155,17 @@ static inline int reassemble_14(int as14) ((as14 & 0x2000) >> 13)); } +static inline int reassemble_16a(int as16) +{ + int s, t; + + /* Unusual 16-bit encoding, for wide mode only. */ + t = (as16 << 1) & 0xffff; + s = (as16 & 0x8000); + return (t ^ s ^ (s >> 1)) | (s >> 15); +} + + static inline int reassemble_17(int as17) { return (((as17 & 0x10000) >> 16) | @@ -407,6 +422,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec) { struct stub_entry *stub; + int d; /* initialize stub_offset to point in front of the section */ if (!me->arch.section[targetsec].stub_offset) { @@ -460,12 +476,17 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, */ switch (stub_type) { case ELF_STUB_GOT: - stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ + stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ stub->insns[2] = 0xe820d000; /* bve (%r1) */ stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ - stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); + d = get_got(me, value, addend); + if (d <= 15) + stub->insns[0] |= reassemble_14(d); + else + stub->insns[0] |= reassemble_16a(d); + break; case ELF_STUB_MILLI: stub->insns[0] = 0x20200000; /* ldil 0,%r1 */