diff mbox

Bug#539378: [hppa]: fails to load nfs module: Global Offset Table

Message ID 20090801190715.0929A500B@hiauly1.hia.nrc.ca (mailing list archive)
State Accepted
Headers show

Commit Message

John David Anglin Aug. 1, 2009, 7:07 p.m. UTC
> >  	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.

Since I complained about not using format 5 for small displacements,
here's an updated patch for review.  Seems to work:

dave@mx3210:/usr/src/D$ lsmod
Module                  Size  Used by
dm_snapshot            45680  0 
dm_mirror              27480  0 
dm_region_hash         17408  1 dm_mirror
dm_log                 18968  2 dm_mirror,dm_region_hash
dm_mod                111200  3 dm_snapshot,dm_mirror,dm_log
ext2                   99648  2 
sd_mod                 63792  4 
crc_t10dif              2368  1 sd_mod
tg3                   196428  0 
sym53c8xx             127568  3 
libphy                 39280  1 tg3
scsi_transport_spi     43528  1 sym53c8xx
scsi_mod              261104  3 sd_mod,sym53c8xx,scsi_transport_spi

Dave

Comments

Carlos O'Donell Aug. 1, 2009, 8:02 p.m. UTC | #1
On Sat, Aug 1, 2009 at 3:07 PM, John David
Anglin<dave@hiauly1.hia.nrc.ca> wrote:
> Signed-off-by: John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
>

Frans,

I suggest you use Dave's patch please, it is IMO the most correct patch.

Helge, Kyle, thanks also for the initial patches!

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
Frans Pop Aug. 1, 2009, 9:17 p.m. UTC | #2
On Saturday 01 August 2009, Carlos O'Donell wrote:
> I suggest you use Dave's patch please, it is IMO the most correct
> patch.

Right. I think the original patch is probably responsible for endless
errors on shutdown/reboot:

Bad Address (null pointer deref?): Code=15 regs=00000000bea7cf70 (Addr=c00007ffbea7c)

     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00001000000001001111111100001110 Not tainted
r00-03  000000ff0804ff0e 00000000405ead40 000000006fc00000 00000000bea7ca18
r04-07  0000000037de0000 ffffffffffe00008 00000000bea7ca18 00000000405ea540
r08-11  000000000fc212c1 000000006bc23fd9 000000000000000f 00000000faf59048
r12-15  00000000be784b28 0000000000000025 00000000faf5932d 0000000000000000
r16-19  00000000bea7bfa0 0000000000000014 000000004074b134 00000000bea7cda0
r20-23  00000000ffffe000 000000004011d2b4 0000000040479004 0000000000000010
r24-27  0000000000000000 000000004011d1e0 000000004011d838 00000000405dcd40
r28-31  ffffffffbea7cd90 0000000000000350 00000000bea7cf70 ffffffffbea7cda0
sr00-03  000000000607b000 0000000000000000 0000000000000000 000000000607b000
sr04-07  0000000000000000 0000000000000000 0000000000000000 0000000000000000

IASQ: 0000000000000000 0000000000000000 IAOQ: 0000000040127a10 0000000040127a14
 IIR: 0f8010dc    ISR: 000000003ffff800  IOR: c00007ffbea7cd90
 CPU:        1   CR30: 00000000bea60000 CR31: 0000000011111111
 ORIG_R28: 0000000000000000
 IAOQ[0]: unwind_once+0x370/0x3d0
 IAOQ[1]: unwind_once+0x374/0x3d0
 RP(r2): 0x6fc00000


John's version works too for me and the system now shuts down cleanly.

Cheers,
FJP

P.S. If anybody ever wants access to my box, just ask:
- model: 9000/785/J5600
- cpu: 2 x PA8600 (PCX-W+) at 552.000000 MHz
- memory: 2048 MB
- 3 x 9.1 GB SCSI harddisks
--
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
diff mbox

Patch

diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index ecd1c50..88989cb 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 */
@@ -145,12 +149,40 @@  struct stub_entry {
 /* The reassemble_* functions prepare an immediate value for
    insertion into an opcode. pa-risc uses all sorts of weird bitfields
    in the instruction to hold the value.  */
+static inline int sign_unext (int x, int len)
+{
+	int len_ones;
+
+	len_ones = (1 << len) - 1;
+	return x & len_ones;
+}
+
+static inline int low_sign_unext(int x, int len)
+{
+	int sign, temp;
+
+	sign = (x >> (len-1)) & 1;
+	temp = sign_unext (x, len-1);
+	return (temp << 1) | sign;
+}
+
 static inline int reassemble_14(int as14)
 {
 	return (((as14 & 0x1fff) << 1) |
 		((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) |
@@ -409,6 +441,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) {
@@ -462,12 +495,19 @@  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	*/
+		d = get_got(me, value, addend);
+		if (d <= 15) {
+			/* Format 5 */
+			stub->insns[0] = 0x0f6010db; /* ldd 0(%dp),%dp	*/
+			stub->insns[0] |= low_sign_unext(d, 5) << 16;
+		} else {
+			/* Format 3 */
+			stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp	*/
+			stub->insns[0] |= reassemble_16a(d);
+		}
 		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);
 		break;
 	case ELF_STUB_MILLI:
 		stub->insns[0] = 0x20200000;	/* ldil 0,%r1		*/