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 --]
next prev 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.