[PATCH] 2.5.50 on ppc64
Anton Blanchard
anton at samba.org
Wed Dec 4 19:24:56 EST 2002
Hi,
I have attached the patches required to boot 2.5.50-BK on ppc64. You
can get the latest tree from the following BK location:
bk://ppc.bkbits.net/for-linus-ppc64
Otherwise you can grab Linus' tree via BK or the daily snapshots. It is
currently missing one changeset - as a workaround just enable PROFILING
support when building out of Linus' tree.
You will need a recent toolchain. A binutils bug was triggered by the
new initramfs stuff (it was trying to look for endianess in binary
blobs). Alan found and fixed it, but it does mean you need to upgrade
your toolchain if you get a bug when linking in the initramfs objects.
There should be instructions on linuxppc64.org on how to do this.
There are two patches here. The first one just adds the compiler path,
allows pci resources to start at 0 (Linus wont take this patch so far)
and works around what appears to be a compiler bug (the =g constraint
fails but the =r one works).
The second patch is Peter Bergner's patch for 64 bit dynamic executable
support.
Anton
patch1:
===== Makefile 1.352 vs edited =====
--- 1.352/Makefile Thu Nov 28 09:33:55 2002
+++ edited/Makefile Tue Dec 3 18:09:59 2002
@@ -50,7 +50,7 @@
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTCXXFLAGS = -O2
-CROSS_COMPILE =
+CROSS_COMPILE = /usr/local/ppc64/bin/powerpc64-linux-
# That's our default target when none is given on the command line
===== drivers/pci/probe.c 1.19 vs edited =====
--- 1.19/drivers/pci/probe.c Thu Nov 7 05:16:52 2002
+++ edited/drivers/pci/probe.c Tue Dec 3 18:09:59 2002
@@ -152,7 +152,7 @@
limit |= (io_limit_hi << 16);
}
- if (base && base <= limit) {
+ if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
res->start = base;
res->end = limit + 0xfff;
===== include/linux/compiler.h 1.6 vs edited =====
--- 1.6/include/linux/compiler.h Sun Sep 1 12:52:31 2002
+++ edited/include/linux/compiler.h Tue Dec 3 18:09:59 2002
@@ -17,6 +17,6 @@
shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
- __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \
+ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })
#endif /* __LINUX_COMPILER_H */
patch2:
===== arch/ppc64/kernel/process.c 1.23 vs edited =====
--- 1.23/arch/ppc64/kernel/process.c Wed Nov 27 16:32:04 2002
+++ edited/arch/ppc64/kernel/process.c Tue Dec 3 18:11:32 2002
@@ -225,22 +225,30 @@
/*
* Set up a thread for executing a new program
*/
-void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
+void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp)
{
- /* NIP is *really* a pointer to the function descriptor for
+ unsigned long entry, toc, load_addr = regs->gpr[2];
+
+ /* fdptr is a relocated pointer to the function descriptor for
* the elf _start routine. The first entry in the function
* descriptor is the entry address of _start and the second
* entry is the TOC value we need to use.
*/
- unsigned long *entry = (unsigned long *)nip;
- unsigned long *toc = entry + 1;
-
set_fs(USER_DS);
- memset(regs->gpr, 0, sizeof(regs->gpr));
- memset(®s->ctr, 0, 4 * sizeof(regs->ctr));
- __get_user(regs->nip, entry);
+ __get_user(entry, (unsigned long *)fdptr);
+ __get_user(toc, (unsigned long *)fdptr+1);
+
+ /* Check whether the e_entry function descriptor entries
+ * need to be relocated before we can use them.
+ */
+ if ( load_addr != 0 ) {
+ entry += load_addr;
+ toc += load_addr;
+ }
+
+ regs->nip = entry;
regs->gpr[1] = sp;
- __get_user(regs->gpr[2], toc);
+ regs->gpr[2] = toc;
regs->msr = MSR_USER64;
if (last_task_used_math == current)
last_task_used_math = 0;
===== fs/binfmt_elf.c 1.34 vs edited =====
--- 1.34/fs/binfmt_elf.c Mon Nov 25 19:59:02 2002
+++ edited/fs/binfmt_elf.c Tue Dec 3 18:12:27 2002
@@ -457,6 +457,7 @@
unsigned int size;
unsigned long elf_entry, interp_load_addr = 0;
unsigned long start_code, end_code, start_data, end_data;
+ unsigned long reloc_func_desc = 0;
struct elfhdr elf_ex;
struct elfhdr interp_elf_ex;
struct exec interp_ex;
@@ -681,6 +682,7 @@
load_bias += error -
ELF_PAGESTART(load_bias + vaddr);
load_addr += load_bias;
+ reloc_func_desc = load_addr;
}
}
k = elf_ppnt->p_vaddr;
@@ -727,6 +729,7 @@
send_sig(SIGSEGV, current, 0);
return 0;
}
+ reloc_func_desc = interp_load_addr;
} else {
elf_entry = elf_ex.e_entry;
}
@@ -774,10 +777,14 @@
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
- * example. This macro performs whatever initialization to
- * the regs structure is required.
+ * example. In addition, it may also specify (eg, PowerPC64 ELF)
+ * that the e_entry field is the address of the function descriptor
+ * for the startup routine, rather than the address of the startup
+ * routine itself. This macro performs whatever initialization to
+ * the regs structure is required as well as any relocations to the
+ * function descriptor entries when executing dynamically links apps.
*/
- ELF_PLAT_INIT(regs);
+ ELF_PLAT_INIT(regs, reloc_func_desc);
#endif
start_thread(regs, elf_entry, bprm->p);
===== include/asm-ppc64/elf.h 1.4 vs edited =====
--- 1.4/include/asm-ppc64/elf.h Fri Nov 8 00:06:17 2002
+++ edited/include/asm-ppc64/elf.h Tue Dec 3 18:12:08 2002
@@ -84,6 +84,15 @@
#define ELF_PLATFORM (NULL)
+
+#define ELF_PLAT_INIT(_r, load_addr) do { \
+ memset(_r->gpr, 0, sizeof(_r->gpr)); \
+ _r->ctr = _r->link = _r->xer = _r->ccr = 0; \
+ _r->gpr[2] = load_addr; \
+} while (0)
+
+
+
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) \
do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list