grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: grub-devel@gnu.org
Subject: Re: [PATCH] Fix module relocation errors on PowerPC
Date: Thu, 03 Nov 2011 19:03:09 +0100	[thread overview]
Message-ID: <4EB2D75D.3020706@gmail.com> (raw)
In-Reply-To: <20111018154817.752a92f6@kryten>


[-- Attachment #1.1: Type: text/plain, Size: 789 bytes --]

Please try the attached patch
On 18.10.2011 06:48, Anton Blanchard wrote:
> Hi,
>
> I tried grub2 on a POWER6 box and got:
>
>
> Welcome to GRUB!
>
> error: relocation overflow.
> Entering rescue mode...
>
>
> Modules (and therefore the heap) need to be close to the executable to
> avoid requiring more complicated relocations. This patch uses the same
> method sparc does and puts the heap directly above the executable.
>
> We use the OF stack so we don't need to reserve any memory for it. Is
> it time to create GRUB_MACHINE_POWERPC?
>
> Anton
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: ppc_tramp.diff --]
[-- Type: text/x-diff; name="ppc_tramp.diff", Size: 6033 bytes --]

=== modified file 'grub-core/kern/dl.c'
--- grub-core/kern/dl.c	2011-07-06 15:40:36 +0000
+++ grub-core/kern/dl.c	2011-11-03 17:54:44 +0000
@@ -233,7 +233,7 @@
   unsigned i;
   Elf_Shdr *s;
   grub_size_t tsize = 0, talign = 1;
-#ifdef __ia64__
+#if defined (__ia64__) || defined (__powerpc__)
   grub_size_t tramp;
   grub_size_t got;
 #endif
@@ -248,9 +248,9 @@
 	talign = s->sh_addralign;
     }
 
-#ifdef __ia64__
+#if defined (__ia64__) || defined (__powerpc__)
   grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
-  tramp *= GRUB_IA64_DL_TRAMP_SIZE;
+  tramp *= GRUB_ARCH_DL_TRAMP_SIZE;
   got *= sizeof (grub_uint64_t);
   tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
   if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
@@ -316,7 +316,7 @@
 	  mod->segment = seg;
 	}
     }
-#ifdef __ia64__
+#if defined (__ia64__) || defined (__powerpc__)
   ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
   mod->tramp = ptr;
   ptr += tramp;
@@ -575,15 +575,9 @@
 static void
 grub_dl_flush_cache (grub_dl_t mod)
 {
-  grub_dl_segment_t seg;
-
-  for (seg = mod->segment; seg; seg = seg->next) {
-    if (seg->size) {
-      grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
-		    (unsigned long) seg->size, seg->addr);
-      grub_arch_sync_caches (seg->addr, seg->size);
-    }
-  }
+  grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
+		(unsigned long) mod->sz, mod->base);
+  grub_arch_sync_caches (mod->base, mod->sz);
 }
 
 /* Load a module from core memory.  */

=== modified file 'grub-core/kern/ia64/dl.c'
--- grub-core/kern/ia64/dl.c	2011-05-08 15:07:40 +0000
+++ grub-core/kern/ia64/dl.c	2011-11-03 17:52:40 +0000
@@ -104,13 +104,13 @@
     }
 }
 
-static grub_uint8_t nopm[5] =
+static const grub_uint8_t nopm[5] =
   {
     /* [MLX]       nop.m 0x0 */
     0x05, 0x00, 0x00, 0x00, 0x01
   };
 
-static grub_uint8_t jump[0x20] =
+static const grub_uint8_t jump[0x20] =
   {
     /* ld8 r16=[r15],8 */
     0x02, 0x80, 0x20, 0x1e, 0x18, 0x14,

=== modified file 'grub-core/kern/powerpc/dl.c'
--- grub-core/kern/powerpc/dl.c	2010-01-03 22:05:07 +0000
+++ grub-core/kern/powerpc/dl.c	2011-11-03 17:52:01 +0000
@@ -37,6 +37,65 @@
   return GRUB_ERR_NONE;
 }
 
+void
+grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+				 grub_size_t *got)
+{
+  const Elf_Ehdr *e = ehdr;
+  const Elf_Shdr *s;
+  Elf_Word entsize;
+  unsigned i;
+
+  *tramp = 0;
+  *got = 0;
+
+  /* Find a symbol table.  */
+  for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return;
+
+  entsize = s->sh_entsize;
+
+  for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_RELA)
+      {
+	const Elf_Rela *rel, *max;
+	
+	for (rel = (const Elf_Rela *) ((const char *) e + s->sh_offset),
+	       max = rel + s->sh_size / s->sh_entsize;
+	     rel < max;
+	     rel++)
+	  if (ELF_R_TYPE (rel->r_info) == R_PPC_REL24)
+	    (*tramp)++;
+	
+      }
+
+  return;
+}
+
+/* For low-endian reverse lis and addr_high as well as ori and addr_low. */
+struct trampoline
+{
+  grub_uint32_t lis;
+  grub_uint32_t ori;
+  grub_uint32_t mtctr;
+  grub_uint32_t bctr;
+};
+
+static const struct trampoline trampoline_template = 
+  {
+    0x3c000000,
+    0x60000000,
+    0x7c0903a6,
+    0x4e800420,
+  };
 
 /* Relocate symbols.  */
 grub_err_t
@@ -46,6 +105,7 @@
   Elf_Shdr *s;
   Elf_Word entsize;
   unsigned i;
+  struct trampoline *tptr = mod->tramp;
 
   /* Find a symbol table.  */
   for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
@@ -105,6 +165,18 @@
 		    {
 		      Elf_Sword delta = value - (Elf_Word) addr;
 
+		      //if (delta << 6 >> 6 != delta)
+		      {
+			COMPILE_TIME_ASSERT (sizeof (struct trampoline)
+					     == GRUB_ARCH_DL_TRAMP_SIZE);
+			grub_memcpy (tptr, &trampoline_template,
+				     sizeof (*tptr));
+			delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr;
+			tptr->lis |= (((value) >> 16) & 0xffff);
+			tptr->ori |= ((value) & 0xffff);
+			tptr++;
+		      }
+			
 		      if (delta << 6 >> 6 != delta)
 			return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow");
 		      *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);

=== modified file 'include/grub/dl.h'
--- include/grub/dl.h	2011-06-23 22:29:21 +0000
+++ include/grub/dl.h	2011-11-03 17:54:10 +0000
@@ -136,11 +136,12 @@
   Elf_Sym *symtab;
   void (*init) (struct grub_dl *mod);
   void (*fini) (void);
-#ifdef __ia64__
+#if defined (__ia64__) || defined (__powerpc__)
   void *got;
   void *tramp;
 #endif
   void *base;
+  grub_size_t sz;
   struct grub_dl *next;
 };
 typedef struct grub_dl *grub_dl_t;
@@ -176,10 +177,20 @@
 grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 				 grub_size_t *got);
 
-#ifdef __ia64__
+#if defined (__ia64__)
 #define GRUB_ARCH_DL_TRAMP_ALIGN 16
 #define GRUB_ARCH_DL_GOT_ALIGN 16
 #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size
+#else
+void
+grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+				 grub_size_t *got);
+#endif
+
+#ifdef __powerpc__
+#define GRUB_ARCH_DL_TRAMP_SIZE 16
+#define GRUB_ARCH_DL_TRAMP_ALIGN 4
+#define GRUB_ARCH_DL_GOT_ALIGN 4
 #endif
 
 #endif

=== modified file 'include/grub/kernel.h'
--- include/grub/kernel.h	2011-10-18 13:21:51 +0000
+++ include/grub/kernel.h	2011-11-03 17:27:25 +0000
@@ -34,7 +34,7 @@
 struct grub_module_header
 {
   /* The type of object.  */
-  grub_uint8_t type;
+  grub_uint32_t type;
   /* The size of object (including this header).  */
   grub_uint32_t size;
 };


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

  parent reply	other threads:[~2011-11-03 18:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-18  4:48 [PATCH] Fix module relocation errors on PowerPC Anton Blanchard
2011-10-18  5:49 ` Anton Blanchard
2011-10-29  9:39   ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-11-03 18:03 ` Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2011-11-08  8:57   ` Anton Blanchard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4EB2D75D.3020706@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).