svn commit: r196951 - in projects/ppc64/sys: boot boot/common boot/ofw/libofw boot/powerpc boot/powerpc/ofw boot/powerpc/uboot powerpc/aim powerpc/aim64 powerpc/include

Nathan Whitehorn nwhitehorn at FreeBSD.org
Mon Sep 7 20:39:04 UTC 2009


Author: nwhitehorn
Date: Mon Sep  7 20:39:04 2009
New Revision: 196951
URL: http://svn.freebsd.org/changeset/base/196951

Log:
  Fix up some bugs in virtual mode Open Firmware and add support to the
  PowerPC loader to load 64-bit executables. This provides the first
  64-bit PowerPC boot on real hardware, which then crashes bringing up
  the VM due to remaining missing features.

Added:
  projects/ppc64/sys/boot/ofw/libofw/ppc64_elf_freebsd.c   (contents, props changed)
Modified:
  projects/ppc64/sys/boot/Makefile
  projects/ppc64/sys/boot/common/Makefile.inc
  projects/ppc64/sys/boot/ofw/libofw/Makefile
  projects/ppc64/sys/boot/ofw/libofw/libofw.h
  projects/ppc64/sys/boot/powerpc/Makefile.inc
  projects/ppc64/sys/boot/powerpc/ofw/Makefile
  projects/ppc64/sys/boot/powerpc/ofw/conf.c
  projects/ppc64/sys/boot/powerpc/uboot/Makefile
  projects/ppc64/sys/powerpc/aim/ofw_machdep.c
  projects/ppc64/sys/powerpc/aim64/locore.S
  projects/ppc64/sys/powerpc/include/elf.h

Modified: projects/ppc64/sys/boot/Makefile
==============================================================================
--- projects/ppc64/sys/boot/Makefile	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/Makefile	Mon Sep  7 20:39:04 2009	(r196951)
@@ -13,12 +13,12 @@ SUBDIR+=		efi
 .endif
 
 # Build Open Firmware library.
-.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "sparc64"
+.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "sparc64"
 SUBDIR+=		ofw
 .endif
 
 # Build U-Boot library.
-.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "arm"
+.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "arm"
 SUBDIR+=		uboot
 .endif
 

Modified: projects/ppc64/sys/boot/common/Makefile.inc
==============================================================================
--- projects/ppc64/sys/boot/common/Makefile.inc	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/common/Makefile.inc	Mon Sep  7 20:39:04 2009	(r196951)
@@ -9,8 +9,11 @@ SRCS+=	load_elf32.c load_elf32_obj.c rel
 SRCS+=	load_elf64.c load_elf64_obj.c reloc_elf64.c
 .elif ${MACHINE} == "pc98"
 SRCS+=	load_elf32.c load_elf32_obj.c reloc_elf32.c
-.elif ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "arm"
+.elif ${MACHINE_ARCH} == "arm"
 SRCS+=	load_elf32.c reloc_elf32.c
+.elif ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64"
+SRCS+=	load_elf32.c reloc_elf32.c
+SRCS+=	load_elf64.c reloc_elf64.c
 .elif ${MACHINE_ARCH} == "sparc64" || ${MACHINE_ARCH} == "ia64"
 SRCS+=	load_elf64.c reloc_elf64.c
 .endif

Modified: projects/ppc64/sys/boot/ofw/libofw/Makefile
==============================================================================
--- projects/ppc64/sys/boot/ofw/libofw/Makefile	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/ofw/libofw/Makefile	Mon Sep  7 20:39:04 2009	(r196951)
@@ -13,8 +13,9 @@ CFLAGS+=	-I${.CURDIR}/../../../../lib/li
 CFLAGS+=	-I${.CURDIR}/../../common -I${.CURDIR}/../../.. -I.
 
 CFLAGS+=	-ffreestanding
-.if ${MACHINE_ARCH} == "powerpc"
+.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64"
 CFLAGS+=	-msoft-float
+SRCS+=		ppc64_elf_freebsd.c
 .endif
 
 .ifdef(BOOT_DISK_DEBUG)

Modified: projects/ppc64/sys/boot/ofw/libofw/libofw.h
==============================================================================
--- projects/ppc64/sys/boot/ofw/libofw/libofw.h	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/ofw/libofw/libofw.h	Mon Sep  7 20:39:04 2009	(r196951)
@@ -62,6 +62,9 @@ int	ofw_elf_loadfile(char *, vm_offset_t
 int	ofw_elf_exec(struct preloaded_file *);
 
 extern struct file_format	ofw_elf;
+#ifdef __powerpc__
+extern struct file_format	ofw_elf64;
+#endif
 
 extern void	reboot(void);
 

Added: projects/ppc64/sys/boot/ofw/libofw/ppc64_elf_freebsd.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/ppc64/sys/boot/ofw/libofw/ppc64_elf_freebsd.c	Mon Sep  7 20:39:04 2009	(r196951)
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2001 Benno Rice <benno at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define __ELF_WORD_SIZE 64
+
+#include <sys/param.h>
+#include <sys/linker.h>
+
+#include <machine/metadata.h>
+#include <machine/elf.h>
+
+#include <stand.h>
+
+#include "bootstrap.h"
+#include "libofw.h"
+#include "openfirm.h"
+
+extern char		end[];
+extern vm_offset_t	reloc;	/* From <arch>/conf.c */
+
+int
+ppc64_ofw_elf_loadfile(char *filename, u_int64_t dest,
+    struct preloaded_file **result)
+{
+	int	r;
+
+	r = __elfN(loadfile)(filename, dest, result);
+	if (r != 0)
+		return (r);
+
+	/*
+	 * No need to sync the icache for modules: this will
+	 * be done by the kernel after relocation.
+	 */
+	if (!strcmp((*result)->f_type, "elf kernel"))
+		__syncicache((void *) (*result)->f_addr, (*result)->f_size);
+	return (0);
+}
+
+int
+ppc64_ofw_elf_exec(struct preloaded_file *fp)
+{
+	struct file_metadata	*fmp;
+	vm_offset_t		mdp;
+	Elf_Ehdr		*e;
+	int			error;
+	intptr_t		entry;
+
+	if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
+		return(EFTYPE);
+	}
+	e = (Elf_Ehdr *)&fmp->md_data;
+	
+	/* Handle function descriptor */
+	entry = *(uint64_t *)e->e_entry;
+
+	if ((error = md_load(fp->f_args, &mdp)) != 0)
+		return (error);
+
+	printf("Kernel entry at 0x%lx ...\n", entry);
+
+	dev_cleanup();
+	ofw_release_heap();
+
+	OF_chain((void *)reloc, end - (char *)reloc, (void *)entry,
+	    (void *)mdp, sizeof(mdp));
+
+	panic("exec returned");
+}
+
+struct file_format	ofw_elf64 =
+{
+	ppc64_ofw_elf_loadfile,
+	ppc64_ofw_elf_exec
+};

Modified: projects/ppc64/sys/boot/powerpc/Makefile.inc
==============================================================================
--- projects/ppc64/sys/boot/powerpc/Makefile.inc	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/powerpc/Makefile.inc	Mon Sep  7 20:39:04 2009	(r196951)
@@ -1,3 +1,9 @@
 # $FreeBSD$
 
+.if ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+=	-m32 -mcpu=powerpc
+LDFLAGS+=	-m elf32-powerpc
+AFLAGS+=	--32
+.endif
+
 .include "../Makefile.inc"

Modified: projects/ppc64/sys/boot/powerpc/ofw/Makefile
==============================================================================
--- projects/ppc64/sys/boot/powerpc/ofw/Makefile	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/powerpc/ofw/Makefile	Mon Sep  7 20:39:04 2009	(r196951)
@@ -10,6 +10,7 @@ INSTALLFLAGS=	-b
 
 # Architecture-specific loader code
 SRCS=		conf.c metadata.c vers.c start.c
+SRCS+=		ucmpdi2.c
 
 LOADER_DISK_SUPPORT?=	yes
 LOADER_UFS_SUPPORT?=	yes
@@ -57,9 +58,9 @@ LIBFICL=	${.OBJDIR}/../../ficl/libficl.a
 .endif
 
 # Always add MI sources
-.PATH:		${.CURDIR}/../../common
+.PATH:		${.CURDIR}/../../common ${.CURDIR}/../../../libkern
 .include	"${.CURDIR}/../../common/Makefile.inc"
-CFLAGS+=	-I${.CURDIR}/../../common
+CFLAGS+=	-I${.CURDIR}/../../common -I${.CURDIR}/../../..
 CFLAGS+=	-I.
 
 CLEANFILES+=	vers.c loader.help

Modified: projects/ppc64/sys/boot/powerpc/ofw/conf.c
==============================================================================
--- projects/ppc64/sys/boot/powerpc/ofw/conf.c	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/powerpc/ofw/conf.c	Mon Sep  7 20:39:04 2009	(r196951)
@@ -96,6 +96,7 @@ struct netif_driver *netif_drivers[] = {
 
 struct file_format *file_formats[] = {
     &ofw_elf,
+    &ofw_elf64,
     NULL
 };
 

Modified: projects/ppc64/sys/boot/powerpc/uboot/Makefile
==============================================================================
--- projects/ppc64/sys/boot/powerpc/uboot/Makefile	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/boot/powerpc/uboot/Makefile	Mon Sep  7 20:39:04 2009	(r196951)
@@ -8,6 +8,7 @@ NO_MAN=
 
 # Architecture-specific loader code
 SRCS=		start.S conf.c vers.c
+SRCS+=		ucmpdi2.c
 
 LOADER_DISK_SUPPORT?=	no
 LOADER_UFS_SUPPORT?=	no
@@ -55,9 +56,9 @@ LIBFICL=	${.OBJDIR}/../../ficl/libficl.a
 .endif
 
 # Always add MI sources
-.PATH:		${.CURDIR}/../../common
+.PATH:		${.CURDIR}/../../common ${.CURDIR}/../../../libkern
 .include	"${.CURDIR}/../../common/Makefile.inc"
-CFLAGS+=	-I${.CURDIR}/../../common
+CFLAGS+=	-I${.CURDIR}/../../common -I${.CURDIR}/../../..
 CFLAGS+=	-I.
 
 CLEANFILES+=	vers.c ${PROG}.help

Modified: projects/ppc64/sys/powerpc/aim/ofw_machdep.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Mon Sep  7 20:39:04 2009	(r196951)
@@ -68,16 +68,8 @@ static int	(*ofwcall)(void *);
 static void	*fdt;
 int		ofw_real_mode;
 
-#ifdef __powerpc64__
-/* Handle PPC64 ABI brain damage */
-struct {
-	int		(*funcptr)(void *);
-	uintptr_t	toc;
-	uintptr_t	env;
-} ofwcall_funcdesc;
-#endif
-	
 int		ofw_real_mode_entry(void *);
+int		ofw_32bit_mode_entry(void *);
 static int	openfirmware(void *args);
 
 /*
@@ -329,22 +321,21 @@ OF_initial_setup(void *fdt_ptr, void *ju
 	else
 		ofw_real_mode = 1;
 
+	ofwcall = NULL;
+
 	#ifdef __powerpc64__
 		/*
-		 * For PPC64, we need to hack up a function descriptor object
-		 * to be able to call a memory address.
+		 * For PPC64, we need to use some hand-written
+		 * asm trampolines to get to OF.
 		 */
-		if (ofw_real_mode) {
+		if (ofw_real_mode && openfirm != NULL)
 			ofwcall = ofw_real_mode_entry;
-		} else {
-			ofwcall_funcdesc.funcptr = openfirm;
-			ofwcall_funcdesc.toc = 0;
-			ofwcall_funcdesc.env = 0;
-			ofwcall = (int (*)(void *))&ofwcall_funcdesc;
-		}
+		else
+			ofwcall = ofw_32bit_mode_entry;
 	#else
 		ofwcall = openfirm;
 	#endif
+
 	fdt = fdt_ptr;
 }
 

Modified: projects/ppc64/sys/powerpc/aim64/locore.S
==============================================================================
--- projects/ppc64/sys/powerpc/aim64/locore.S	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/powerpc/aim64/locore.S	Mon Sep  7 20:39:04 2009	(r196951)
@@ -87,10 +87,10 @@
 GLOBAL(tmpstk)
 	.space	TMPSTKSZ
 GLOBAL(esym)
-	.long	0			/* end of symbol table */
+	.llong	0			/* end of symbol table */
 
 GLOBAL(ofmsr)
-	.long	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
+	.llong	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
 
 #define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
 GLOBAL(intrnames)
@@ -105,11 +105,11 @@ GLOBAL(eintrcnt)
  * File-scope for locore.S
  */
 idle_u:
-	.long	0			/* fake uarea during idle after exit */
+	.llong	0			/* fake uarea during idle after exit */
 openfirmware_entry:
-	.long	0			/* Open Firmware entry point */
+	.llong	0			/* Open Firmware entry point */
 srsave:
-	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+	.llong	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
 	.text
 	.globl	btext
@@ -146,21 +146,32 @@ ASENTRY(__start)
 	lis	8,openfirmware_entry at ha
 	std	5,openfirmware_entry at l(8) /* save client interface handler */
 
+	/* Set up the stack pointer */
 	lis	1,(tmpstk+TMPSTKSZ-16)@ha
 	addi	1,1,(tmpstk+TMPSTKSZ-16)@l
 
+	/* Set up the TOC pointer */
+	lis	2,tocbase at ha
+	ld	2,tocbase at l(2)
+
+	/* Switch to 64-bit mode */
+	mfmsr	9
+	li	8,1
+	insrdi	9,8,1,0
+	mtmsrd	9
+
 	mfmsr	0
 	lis	9,ofmsr at ha
-	stwu	0,ofmsr at l(9)
+	stdu	0,ofmsr at l(9)
 
 	mfsprg0	0			/* save SPRG0-3 */
-	stw	0,4(9)			/* ofmsr[1] = sprg0 */
+	std	0,8(9)			/* ofmsr[1] = sprg0 */
 	mfsprg1 0
-	stw	0,8(9)			/* ofmsr[2] = sprg1 */
+	std	0,16(9)			/* ofmsr[2] = sprg1 */
 	mfsprg2 0
-	stw	0,12(9)			/* ofmsr[3] = sprg2 */
+	std	0,24(9)			/* ofmsr[3] = sprg2 */
 	mfsprg3 0
-	stw	0,16(9)			/* ofmsr[4] = sprg3 */
+	std	0,32(9)			/* ofmsr[4] = sprg3 */
 	
 	bl	.OF_initial_setup
 	nop
@@ -217,6 +228,31 @@ ASENTRY(ofw_real_mode_entry)
 	mtlr 	0
 	blr
 
+ASENTRY(ofw_32bit_mode_entry)
+	mflr	4
+	mtsprg1 4
+
+	lis	4,openfirmware_entry at ha
+	ld	4,openfirmware_entry at l(4) /* read client interface handler */
+
+	/* Set up a 32-bit MSR in r5 */
+	mfmsr	5
+	mtsprg2	5
+	clrldi	5,5,1
+
+	/* Set MSR, branch to OF, and come back */
+	mtmsrd	5
+	isync
+	mtctr	4
+	bctrl
+	mfsprg2	5
+	mtmsrd	5
+	isync
+
+	mfsprg1	4
+	mtlr 	4
+	blr
+
 /*
  * int setfault()
  *

Modified: projects/ppc64/sys/powerpc/include/elf.h
==============================================================================
--- projects/ppc64/sys/powerpc/include/elf.h	Mon Sep  7 20:10:33 2009	(r196950)
+++ projects/ppc64/sys/powerpc/include/elf.h	Mon Sep  7 20:39:04 2009	(r196951)
@@ -36,17 +36,19 @@
  * [ppc-eabi-1995-01.pdf] for details.
  */
 
+#ifndef __ELF_WORD_SIZE
 #ifdef __powerpc64__
 #define	__ELF_WORD_SIZE	64	/* Used by <sys/elf_generic.h> */
 #else
 #define	__ELF_WORD_SIZE	32	/* Used by <sys/elf_generic.h> */
 #endif
+#endif
 
 #include <sys/elf32.h>	/* Definitions common to all 32 bit architectures. */
 #include <sys/elf64.h>	/* Definitions common to all 64 bit architectures. */
 #include <sys/elf_generic.h>
 
-#ifdef __powerpc64__
+#if __ELF_WORD_SIZE == 64
 #define	ELF_ARCH	EM_PPC64
 #define	ELF_MACHINE_OK(x) ((x) == EM_PPC64)
 #else
@@ -70,7 +72,6 @@ typedef struct {	/* Auxiliary vector ent
 	} a_un;
 } Elf32_Auxinfo;
 
-#ifdef __powerpc64__
 /* XXX: check ABI */
 typedef struct {	/* Auxiliary vector entry on initial stack */
 	int	a_type;			/* Entry type. */
@@ -80,7 +81,6 @@ typedef struct {	/* Auxiliary vector ent
 		void	(*a_fcn)(void);	/* Function pointer (not used). */
 	} a_un;
 } Elf64_Auxinfo;
-#endif
 
 __ElfType(Auxinfo);
 
@@ -112,7 +112,7 @@ __ElfType(Auxinfo);
 #define	R_PPC_EMB_COUNT		(R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1)
 
 /* Define "machine" characteristics */
-#ifdef __powerpc64__
+#if __ELF_WORD_SIZE == 64
 #define	ELF_TARG_CLASS	ELFCLASS64
 #define	ELF_TARG_DATA	ELFDATA2MSB
 #define	ELF_TARG_MACH	EM_PPC64


More information about the svn-src-projects mailing list