Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 2 Jun 2011 14:12:37 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222613 - in head/sys/powerpc: aim include ofw
Message-ID:  <201106021412.p52ECbaK020881@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Thu Jun  2 14:12:37 2011
New Revision: 222613
URL: http://svn.freebsd.org/changeset/base/222613

Log:
  MFpseries:
  Renovate and improve the AIM Open Firmware support:
  - Add RTAS (Run-Time Abstraction Services) support, found on all IBM systems
    and some Apple ones
  - Improve support for 32-bit real mode Open Firmware systems
  - Pull some more OF bits over from the AIM directory
  - Fix memory detection on IBM LPARs and systems with more than one /memory
    node (by andreast@)

Added:
  head/sys/powerpc/include/rtas.h   (contents, props changed)
  head/sys/powerpc/ofw/ofwcall32.S   (contents, props changed)
  head/sys/powerpc/ofw/ofwcall64.S   (contents, props changed)
  head/sys/powerpc/ofw/ofwmagic.S
     - copied unchanged from r222507, head/sys/powerpc/aim/ofwmagic.S
  head/sys/powerpc/ofw/rtas.c   (contents, props changed)
Deleted:
  head/sys/powerpc/aim/ofwmagic.S
Modified:
  head/sys/powerpc/aim/locore32.S
  head/sys/powerpc/aim/locore64.S
  head/sys/powerpc/ofw/ofw_machdep.c
  head/sys/powerpc/ofw/ofw_real.c

Modified: head/sys/powerpc/aim/locore32.S
==============================================================================
--- head/sys/powerpc/aim/locore32.S	Thu Jun  2 14:09:30 2011	(r222612)
+++ head/sys/powerpc/aim/locore32.S	Thu Jun  2 14:12:37 2011	(r222613)
@@ -87,9 +87,6 @@ GLOBAL(tmpstk)
 GLOBAL(esym)
 	.long	0			/* end of symbol table */
 
-GLOBAL(ofmsr)
-	.long	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
-
 #define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
 GLOBAL(intrnames)
 	.space	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -99,16 +96,6 @@ GLOBAL(intrcnt)
 	.space	INTRCNT_COUNT * 4 * 2
 GLOBAL(eintrcnt)
 
-/*
- * File-scope for locore.S
- */
-idle_u:
-	.long	0			/* fake uarea during idle after exit */
-openfirmware_entry:
-	.long	0			/* Open Firmware entry point */
-srsave:
-	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
 	.text
 	.globl	btext
 btext:

Modified: head/sys/powerpc/aim/locore64.S
==============================================================================
--- head/sys/powerpc/aim/locore64.S	Thu Jun  2 14:09:30 2011	(r222612)
+++ head/sys/powerpc/aim/locore64.S	Thu Jun  2 14:12:37 2011	(r222613)
@@ -76,7 +76,6 @@
         .set    kernbase, KERNBASE
 
 #define	TMPSTKSZ	8192		/* 8K temporary stack */
-#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
 
 /*
  * Globals
@@ -85,14 +84,9 @@
 	.align	4
 GLOBAL(tmpstk)
 	.space	TMPSTKSZ
-GLOBAL(ofwstk)
-	.space	OFWSTKSZ
 GLOBAL(esym)
 	.llong	0			/* end of symbol table */
 
-GLOBAL(ofmsr)
-	.llong	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
-
 #define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
 GLOBAL(intrnames)
 	.space	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -102,16 +96,6 @@ GLOBAL(intrcnt)
 	.space	INTRCNT_COUNT * 4 * 2
 GLOBAL(eintrcnt)
 
-/*
- * File-scope for locore.S
- */
-idle_u:
-	.llong	0			/* fake uarea during idle after exit */
-openfirmware_entry:
-	.llong	0			/* Open Firmware entry point */
-srsave:
-	.llong	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
 	.text
 	.globl	btext
 btext:
@@ -208,122 +192,6 @@ tocbase:
         .llong  .TOC.@tocbase
 
 /*
- * Open Firmware Real-mode Entry Point. This is a huge pain.
- */
-
-ASENTRY(ofw_32bit_mode_entry)
-	mflr	%r0
-	std	%r0,16(%r1)
-	stdu	%r1,-208(%r1)
-
-	/*
-	 * We need to save the following, because OF's register save/
-	 * restore code assumes that the contents of registers are
-	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
-	 * get placed in that order in the stack.
-	 */
-
-	mfcr	%r4
-	std	%r4,48(%r1)
-	std	%r13,56(%r1)
-	std	%r14,64(%r1)
-	std	%r15,72(%r1)
-	std	%r16,80(%r1)
-	std	%r17,88(%r1)
-	std	%r18,96(%r1)
-	std	%r19,104(%r1)
-	std	%r20,112(%r1)
-	std	%r21,120(%r1)
-	std	%r22,128(%r1)
-	std	%r23,136(%r1)
-	std	%r24,144(%r1)
-	std	%r25,152(%r1)
-	std	%r26,160(%r1)
-	std	%r27,168(%r1)
-	std	%r28,176(%r1)
-	std	%r29,184(%r1)
-	std	%r30,192(%r1)
-	std	%r31,200(%r1)
-
-	/* Record the old MSR */
-	mfmsr	%r6
-
-	/* read client interface handler */
-	lis	%r4,openfirmware_entry@ha
-	ld	%r4,openfirmware_entry@l(%r4)
-
-	/*
-	 * Set the MSR to the OF value. This has the side effect of disabling
-	 * exceptions, which is important for the next few steps.
-	 */
-
-	lis	%r5,ofmsr@ha
-	ld	%r5,ofmsr@l(%r5)
-	mtmsrd	%r5
-	isync
-
-	/*
-	 * Set up OF stack. This needs to be accessible in real mode and
-	 * use the 32-bit ABI stack frame format. The pointer to the current
-	 * kernel stack is placed at the very top of the stack along with
-	 * the old MSR so we can get them back later.
-	 */
-	mr	%r5,%r1
-	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
-	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
-	std	%r5,8(%r1)	/* Save real stack pointer */
-	std	%r2,16(%r1)	/* Save old TOC */
-	std	%r6,24(%r1)	/* Save old MSR */
-	li	%r5,0
-	stw	%r5,4(%r1)
-	stw	%r5,0(%r1)
-
-	/* Finally, branch to OF */
-	mtctr	%r4
-	bctrl
-
-	/* Reload stack pointer and MSR from the OFW stack */
-	ld	%r6,24(%r1)
-	ld	%r2,16(%r1)
-	ld	%r1,8(%r1)
-
-	/* Now set the real MSR */
-	mtmsrd	%r6
-	isync
-
-	/* Sign-extend the return value from OF */
-	extsw	%r3,%r3
-
-	/* Restore all the non-volatile registers */
-	ld	%r5,48(%r1)
-	mtcr	%r5
-	ld	%r13,56(%r1)
-	ld	%r14,64(%r1)
-	ld	%r15,72(%r1)
-	ld	%r16,80(%r1)
-	ld	%r17,88(%r1)
-	ld	%r18,96(%r1)
-	ld	%r19,104(%r1)
-	ld	%r20,112(%r1)
-	ld	%r21,120(%r1)
-	ld	%r22,128(%r1)
-	ld	%r23,136(%r1)
-	ld	%r24,144(%r1)
-	ld	%r25,152(%r1)
-	ld	%r26,160(%r1)
-	ld	%r27,168(%r1)
-	ld	%r28,176(%r1)
-	ld	%r29,184(%r1)
-	ld	%r30,192(%r1)
-	ld	%r31,200(%r1)
-
-	/* Restore the stack and link register */
-	ld	%r1,0(%r1)
-	ld	%r0,16(%r1)
-	mtlr 	%r0
-	blr
-
-/*
  * int setfault()
  *
  * Similar to setjmp to setup for handling faults on accesses to user memory.

Added: head/sys/powerpc/include/rtas.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/include/rtas.h	Thu Jun  2 14:12:37 2011	(r222613)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_RTAS_H_
+#define _MACHINE_RTAS_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <dev/ofw/openfirm.h>
+
+/*
+ * RTAS functions are defined by 32-bit integer tokens. These vary from
+ * system to system, and can be looked up from their standardized names
+ * using rtas_token_lookup(). If RTAS is not available, rtas_token_lookup()
+ * and rtas_call_method() return -1; this can be checked in advance using
+ * rtas_exists(). Otherwise, rtas_call_method() returns one of the RTAS
+ * status codes from the bottom of this file.
+ */
+
+int rtas_exists(void);
+int rtas_call_method(cell_t token, int nargs, int nreturns, ...);
+cell_t rtas_token_lookup(const char *method);
+
+/* RTAS Status Codes: see CHRP or PAPR specification */
+#define	RTAS_OK				0
+#define	RTAS_HW_ERROR			-1
+#define	RTAS_BUSY			-2
+#define	RTAS_PARAM_ERROR		-3
+#define	RTAS_STATE_CHANGE		-7
+#define	RTAS_VENDOR_BEGIN		9000
+#define	RTAS_EXTENDED_DELAY		9900
+#define	RTAS_ISOLATION_ERROR		-9000
+#define	RTAS_VENDOR_ERROR_BEGIN		-9004
+
+#endif /* _MACHINE_RTAS_H_ */
+

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c	Thu Jun  2 14:09:30 2011	(r222612)
+++ head/sys/powerpc/ofw/ofw_machdep.c	Thu Jun  2 14:12:37 2011	(r222613)
@@ -60,17 +60,15 @@ __FBSDID("$FreeBSD$");
 #include <machine/platform.h>
 #include <machine/ofw_machdep.h>
 
-#define	OFMEM_REGIONS	32
-static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
-static struct mem_region OFfree[OFMEM_REGIONS + 3];
-static int nOFmem;
+static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
+static struct mem_region OFfree[PHYS_AVAIL_SZ];
 
 extern register_t ofmsr[5];
-static int	(*ofwcall)(void *);
+extern void	*openfirmware_entry;
 static void	*fdt;
 int		ofw_real_mode;
 
-int		ofw_32bit_mode_entry(void *);
+int		ofwcall(void *);
 static void	ofw_quiesce(void);
 static int	openfirmware(void *args);
 
@@ -134,11 +132,32 @@ memr_merge(struct mem_region *from, stru
 	to->mr_size = end - to->mr_start;
 }
 
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int	mr_cmp(const void *a, const void *b);
+
+static int
+mr_cmp(const void *a, const void *b)
+{
+	const struct	mem_region *regiona;
+	const struct	mem_region *regionb;
+
+	regiona = a;
+	regionb = b;
+	if (regiona->mr_start < regionb->mr_start)
+		return (-1);
+	else if (regiona->mr_start > regionb->mr_start)
+		return (1);
+	else
+		return (0);
+}
+
 static int
 parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
 {
 	cell_t address_cells, size_cells;
-	cell_t OFmem[4*(OFMEM_REGIONS + 1)];
+	cell_t OFmem[4 * PHYS_AVAIL_SZ];
 	int sz, i, j;
 	int apple_hack_mode;
 	phandle_t phandle;
@@ -175,7 +194,7 @@ parse_ofw_memory(phandle_t node, const c
 	 * Get memory.
 	 */
 	if ((node == -1) || (sz = OF_getprop(node, prop,
-	    OFmem, sizeof(OFmem[0]) * 4 * OFMEM_REGIONS)) <= 0)
+	    OFmem, sizeof(OFmem[0]) * 4 * PHYS_AVAIL_SZ)) <= 0)
 		panic("Physical memory map not found");
 
 	i = 0;
@@ -225,7 +244,7 @@ parse_ofw_memory(phandle_t node, const c
 	#ifdef __powerpc64__
 	if (apple_hack_mode) {
 		/* Add in regions above 4 GB to the available list */
-		struct mem_region himem[OFMEM_REGIONS];
+		struct mem_region himem[PHYS_AVAIL_SZ];
 		int hisz;
 
 		hisz = parse_ofw_memory(node, "reg", himem);
@@ -243,6 +262,81 @@ parse_ofw_memory(phandle_t node, const c
 	return (sz);
 }
 
+static int
+parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
+		    struct mem_region *ofavail)
+{
+	phandle_t phandle;
+	vm_offset_t base;
+	int i, idx, len, lasz, lmsz, res;
+	uint32_t lmb_size[2];
+	unsigned long *dmem, flags;
+
+	lmsz = *msz;
+	lasz = *asz;
+
+	phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
+	if (phandle == -1)
+		/* No drconf node, return. */
+		return (0);
+
+	res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
+	if (res == -1)
+		return (0);
+
+	/* Parse the /ibm,dynamic-memory.
+	   The first position gives the # of entries. The next two words
+ 	   reflect the address of the memory block. The next four words are
+	   the DRC index, reserved, list index and flags.
+	   (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
+	   
+	    #el  Addr   DRC-idx  res   list-idx  flags
+	   -------------------------------------------------
+	   | 4 |   8   |   4   |   4   |   4   |   4   |....
+	   -------------------------------------------------
+	*/
+
+	len = OF_getproplen(phandle, "ibm,dynamic-memory");
+	if (len > 0) {
+
+		/* We have to use a variable length array on the stack
+		   since we have very limited stack space.
+		*/
+		cell_t arr[len/sizeof(cell_t)];
+
+		res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
+				 sizeof(arr));
+		if (res == -1)
+			return (0);
+
+		/* Number of elements */
+		idx = arr[0];
+
+		/* First address. */
+		dmem = (void*)&arr[1];
+	
+		for (i = 0; i < idx; i++) {
+			base = *dmem;
+			dmem += 2;
+			flags = *dmem;
+			/* Use region only if available and not reserved. */
+			if ((flags & 0x8) && !(flags & 0x80)) {
+				ofmem[lmsz].mr_start = base;
+				ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
+				ofavail[lasz].mr_start = base;
+				ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
+				lmsz++;
+				lasz++;
+			}
+			dmem++;
+		}
+	}
+
+	*msz = lmsz;
+	*asz = lasz;
+
+	return (1);
+}
 /*
  * This is called during powerpc_init, before the system is really initialized.
  * It shall provide the total and the available regions of RAM.
@@ -255,31 +349,62 @@ ofw_mem_regions(struct mem_region **memp
 		struct mem_region **availp, int *availsz)
 {
 	phandle_t phandle;
+	vm_offset_t maxphysaddr;
 	int asz, msz, fsz;
-	int i, j;
+	int i, j, res;
 	int still_merging;
+	char name[31];
 
 	asz = msz = 0;
 
 	/*
-	 * Get memory.
+	 * Get memory from all the /memory nodes.
 	 */
-	phandle = OF_finddevice("/memory");
-	if (phandle == -1)
-		phandle = OF_finddevice("/memory@0");
+	for (phandle = OF_child(OF_peer(0)); phandle != 0;
+	    phandle = OF_peer(phandle)) {
+		if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
+			continue;
+		if (strncmp(name, "memory", sizeof(name)) != 0)
+			continue;
+
+		res = parse_ofw_memory(phandle, "reg", &OFmem[msz]);
+		msz += res/sizeof(struct mem_region);
+		if (OF_getproplen(phandle, "available") >= 0)
+			res = parse_ofw_memory(phandle, "available",
+			    &OFavail[asz]);
+		else
+			res = parse_ofw_memory(phandle, "reg", &OFavail[asz]);
+		asz += res/sizeof(struct mem_region);
+	}
 
-	msz = parse_ofw_memory(phandle, "reg", OFmem);
-	nOFmem = msz / sizeof(struct mem_region);
-	asz = parse_ofw_memory(phandle, "available", OFavail);
+	/* Check for memory in ibm,dynamic-reconfiguration-memory */
+	parse_drconf_memory(&msz, &asz, OFmem, OFavail);
+
+	qsort(OFmem, msz, sizeof(*OFmem), mr_cmp);
+	qsort(OFavail, asz, sizeof(*OFavail), mr_cmp);
 
 	*memp = OFmem;
-	*memsz = nOFmem;
-	
+	*memsz = msz;
+
+	/*
+	 * On some firmwares (SLOF), some memory may be marked available that
+	 * doesn't actually exist. This manifests as an extension of the last
+	 * available segment past the end of physical memory, so truncate that
+	 * one.
+	 */
+	maxphysaddr = 0;
+	for (i = 0; i < msz; i++)
+		if (OFmem[i].mr_start + OFmem[i].mr_size > maxphysaddr)
+			maxphysaddr = OFmem[i].mr_start + OFmem[i].mr_size;
+
+	if (OFavail[asz - 1].mr_start + OFavail[asz - 1].mr_size > maxphysaddr)
+		OFavail[asz - 1].mr_size = maxphysaddr -
+		    OFavail[asz - 1].mr_start;
+
 	/*
 	 * OFavail may have overlapping regions - collapse these
 	 * and copy out remaining regions to OFfree
 	 */
-	asz /= sizeof(struct mem_region);
 	do {
 		still_merging = FALSE;
 		for (i = 0; i < asz; i++) {
@@ -318,19 +443,6 @@ OF_initial_setup(void *fdt_ptr, void *ju
 	else
 		ofw_real_mode = 1;
 
-	ofwcall = NULL;
-
-	#ifdef __powerpc64__
-		/*
-		 * For PPC64, we need to use some hand-written
-		 * asm trampolines to get to OF.
-		 */
-		if (openfirm != NULL)
-			ofwcall = ofw_32bit_mode_entry;
-	#else
-		ofwcall = openfirm;
-	#endif
-
 	fdt = fdt_ptr;
 
 	#ifdef FDT_DTB_STATIC
@@ -345,7 +457,7 @@ OF_bootstrap()
 {
 	boolean_t status = FALSE;
 
-	if (ofwcall != NULL) {
+	if (openfirmware_entry != NULL) {
 		if (ofw_real_mode) {
 			status = OF_install(OFW_STD_REAL, 0);
 		} else {
@@ -481,12 +593,7 @@ openfirmware(void *args)
 	int result;
 	#ifdef SMP
 	struct ofw_rv_args rv_args;
-	#endif
-
-	if (pmap_bootstrapped && ofw_real_mode)
-		args = (void *)pmap_kextract((vm_offset_t)args);
 
-	#ifdef SMP
 	rv_args.args = args;
 	rv_args.in_progress = 1;
 	smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,

Modified: head/sys/powerpc/ofw/ofw_real.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_real.c	Thu Jun  2 14:09:30 2011	(r222612)
+++ head/sys/powerpc/ofw/ofw_real.c	Thu Jun  2 14:12:37 2011	(r222613)
@@ -205,13 +205,14 @@ ofw_real_bounce_alloc(void *junk)
 
 	/*
 	 * Allocate a page of contiguous, wired physical memory that can
-	 * fit into a 32-bit address space.
+	 * fit into a 32-bit address space and accessed from real mode.
 	 */
 
 	mtx_lock(&of_bounce_mtx);
 
-	of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
-			     0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
+	of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0,
+	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
+	    PAGE_SIZE);
 
 	of_bounce_phys = vtophys(of_bounce_virt);
 	of_bounce_size = PAGE_SIZE;

Added: head/sys/powerpc/ofw/ofwcall32.S
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/ofw/ofwcall32.S	Thu Jun  2 14:12:37 2011	(r222613)
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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 ``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 TOOLS GMBH 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+	.data
+GLOBAL(ofmsr)
+	.long	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+	.long	0
+GLOBAL(openfirmware_entry)
+	.long	0			/* Open Firmware entry point */
+GLOBAL(rtas_entry)
+	.long	0			/* RTAS entry point */
+
+	.align	4
+ofwstk:
+	.space	OFWSTKSZ
+rtas_regsave:
+	.space	4
+
+/*
+ * Open Firmware Entry Point. May need to enter real mode.
+ *
+ * C prototype: int ofwcall(void *callbuffer);
+ */
+
+ASENTRY(ofwcall)
+	mflr	%r0
+	stw	%r0,4(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r4,openfirmware_entry@ha
+	lwz	%r4,openfirmware_entry@l(%r4)
+
+	/*
+	 * Set the MSR to the OF value. This has the side effect of disabling
+	 * exceptions, which prevents preemption later.
+	 */
+
+	lis	%r5,ofmsr@ha
+	lwz	%r5,ofmsr@l(%r5)
+	mtmsr	%r5
+	isync
+
+	/*
+	 * Set up OF stack. This needs to be potentially accessible in real mode
+	 * The pointer to the current kernel stack is placed at the very
+	 * top of the stack along with the old MSR so we can get them back
+	 * later.
+	 */
+	mr	%r5,%r1
+	lis	%r1,(ofwstk+OFWSTKSZ-16)@ha
+	addi	%r1,%r1,(ofwstk+OFWSTKSZ-16)@l
+	stw	%r5,8(%r1)	/* Save real stack pointer */
+	stw	%r6,12(%r1)	/* Save old MSR */
+	li	%r5,0
+	stw	%r5,4(%r1)
+	stw	%r5,0(%r1)
+
+	/* Finally, branch to OF */
+	mtctr	%r4
+	bctrl
+
+	/* Reload stack pointer and MSR from the OFW stack */
+	lwz	%r6,12(%r1)
+	lwz	%r1,8(%r1)
+
+	/* Now set the real MSR */
+	mtmsr	%r6
+	isync
+
+	/* Return */
+	lwz	%r0,4(%r1)
+	mtlr 	%r0
+	blr
+
+/*
+ * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+	mflr	%r0
+	stw	%r0,4(%r1)
+
+	/* Record the old MSR to real-mode-accessible area */
+	mfmsr	%r0
+	lis	%r5,rtas_regsave@ha
+	stw	%r0,rtas_regsave@l(%r5)
+
+	/* read client interface handler */
+	lis	%r5,rtas_entry@ha
+	lwz	%r5,rtas_entry@l(%r5)
+
+	/* Set the MSR to the RTAS value */
+	lis	%r6,rtasmsr@ha
+	lwz	%r6,rtasmsr@l(%r6)
+	mtmsr	%r6
+	isync
+
+	/* Branch to RTAS */
+	mtctr	%r5
+	bctrl
+
+	/* Now set the MSR back */
+	lis	%r6,rtas_regsave@ha
+	lwz	%r6,rtas_regsave@l(%r6)
+	mtmsr	%r6
+	isync
+
+	/* And return */
+	lwz	%r0,4(%r1)
+	mtlr 	%r0
+	blr
+

Added: head/sys/powerpc/ofw/ofwcall64.S
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/ofw/ofwcall64.S	Thu Jun  2 14:12:37 2011	(r222613)
@@ -0,0 +1,290 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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 ``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 TOOLS GMBH 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+	.data
+	.align	4
+ofwstk:
+	.space	OFWSTKSZ
+rtas_regsave:
+	.space	24 /* 3 * sizeof(register_t) */
+GLOBAL(ofmsr)
+	.llong  0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+	.llong	0
+GLOBAL(openfirmware_entry)
+	.llong	0			/* Open Firmware entry point */
+GLOBAL(rtas_entry)
+	.llong	0			/* RTAS entry point */
+
+/*
+ * Open Firmware Real-mode Entry Point. This is a huge pain.
+ */
+
+ASENTRY(ofwcall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-208(%r1)
+
+	/*
+	 * We need to save the following, because OF's register save/
+	 * restore code assumes that the contents of registers are
+	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+	 * get placed in that order in the stack.
+	 */
+
+	mfcr	%r4
+	std	%r4,48(%r1)
+	std	%r13,56(%r1)
+	std	%r14,64(%r1)
+	std	%r15,72(%r1)
+	std	%r16,80(%r1)
+	std	%r17,88(%r1)
+	std	%r18,96(%r1)
+	std	%r19,104(%r1)
+	std	%r20,112(%r1)
+	std	%r21,120(%r1)
+	std	%r22,128(%r1)
+	std	%r23,136(%r1)
+	std	%r24,144(%r1)
+	std	%r25,152(%r1)
+	std	%r26,160(%r1)
+	std	%r27,168(%r1)
+	std	%r28,176(%r1)
+	std	%r29,184(%r1)
+	std	%r30,192(%r1)
+	std	%r31,200(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r4,openfirmware_entry@ha
+	ld	%r4,openfirmware_entry@l(%r4)
+
+	/*
+	 * Set the MSR to the OF value. This has the side effect of disabling
+	 * exceptions, which is important for the next few steps.
+	 */
+
+	lis	%r5,ofmsr@ha
+	ld	%r5,ofmsr@l(%r5)
+	mtmsrd	%r5
+	isync
+
+	/*
+	 * Set up OF stack. This needs to be accessible in real mode and
+	 * use the 32-bit ABI stack frame format. The pointer to the current
+	 * kernel stack is placed at the very top of the stack along with
+	 * the old MSR so we can get them back later.
+	 */
+	mr	%r5,%r1
+	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
+	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
+	std	%r5,8(%r1)	/* Save real stack pointer */
+	std	%r2,16(%r1)	/* Save old TOC */
+	std	%r6,24(%r1)	/* Save old MSR */
+	li	%r5,0
+	stw	%r5,4(%r1)
+	stw	%r5,0(%r1)
+
+	/* Finally, branch to OF */
+	mtctr	%r4
+	bctrl
+
+	/* Reload stack pointer and MSR from the OFW stack */
+	ld	%r6,24(%r1)
+	ld	%r2,16(%r1)
+	ld	%r1,8(%r1)
+
+	/* Now set the real MSR */
+	mtmsrd	%r6
+	isync
+
+	/* Sign-extend the return value from OF */
+	extsw	%r3,%r3
+
+	/* Restore all the non-volatile registers */
+	ld	%r5,48(%r1)
+	mtcr	%r5
+	ld	%r13,56(%r1)
+	ld	%r14,64(%r1)
+	ld	%r15,72(%r1)
+	ld	%r16,80(%r1)
+	ld	%r17,88(%r1)
+	ld	%r18,96(%r1)
+	ld	%r19,104(%r1)
+	ld	%r20,112(%r1)
+	ld	%r21,120(%r1)
+	ld	%r22,128(%r1)
+	ld	%r23,136(%r1)
+	ld	%r24,144(%r1)
+	ld	%r25,152(%r1)
+	ld	%r26,160(%r1)
+	ld	%r27,168(%r1)
+	ld	%r28,176(%r1)
+	ld	%r29,184(%r1)
+	ld	%r30,192(%r1)
+	ld	%r31,200(%r1)
+
+	/* Restore the stack and link register */
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr 	%r0
+	blr
+
+/*
+ * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
+ * stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-208(%r1)
+
+	/*
+	 * We need to save the following, because RTAS's register save/
+	 * restore code assumes that the contents of registers are
+	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+	 * get placed in that order in the stack.
+	 */
+
+	mfcr	%r5
+	std	%r5,48(%r1)
+	std	%r13,56(%r1)
+	std	%r14,64(%r1)
+	std	%r15,72(%r1)
+	std	%r16,80(%r1)
+	std	%r17,88(%r1)
+	std	%r18,96(%r1)
+	std	%r19,104(%r1)
+	std	%r20,112(%r1)
+	std	%r21,120(%r1)
+	std	%r22,128(%r1)
+	std	%r23,136(%r1)
+	std	%r24,144(%r1)
+	std	%r25,152(%r1)
+	std	%r26,160(%r1)
+	std	%r27,168(%r1)
+	std	%r28,176(%r1)
+	std	%r29,184(%r1)
+	std	%r30,192(%r1)
+	std	%r31,200(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r5,rtas_entry@ha
+	ld	%r5,rtas_entry@l(%r5)
+
+	/*
+	 * Set the MSR to the RTAS value. This has the side effect of disabling
+	 * exceptions, which is important for the next few steps.
+	 */
+
+	lis	%r7,rtasmsr@ha
+	ld	%r7,rtasmsr@l(%r7)
+	mtmsrd	%r7
+	isync
+
+	/*
+	 * Set up RTAS register save area, so that we can get back all of
+	 * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
+	 * Put this in r1, since RTAS is obliged to save it. Kernel globals
+	 * are below 4 GB, so this is safe.
+	 */
+	mr	%r7,%r1
+	lis	%r1,rtas_regsave@ha
+	addi	%r1,%r1,rtas_regsave@l
+	std	%r7,0(%r1)	/* Save 64-bit stack pointer */
+	std	%r2,8(%r1)	/* Save TOC */
+	std	%r6,16(%r1)	/* Save MSR */
+
+	/* Finally, branch to RTAS */
+	mtctr	%r5
+	bctrl
+
+	/* 
+	 * Reload stack pointer and MSR from the reg save area in r1. We are
+	 * running in 32-bit mode at this point, so it doesn't matter if r1
+	 * has become sign-extended.
+	 */
+	ld	%r6,16(%r1)
+	ld	%r2,8(%r1)
+	ld	%r1,0(%r1)
+
+	/* Now set the real MSR */
+	mtmsrd	%r6
+	isync
+
+	/* Sign-extend the return value from RTAS */
+	extsw	%r3,%r3
+
+	/* Restore all the non-volatile registers */
+	ld	%r5,48(%r1)
+	mtcr	%r5
+	ld	%r13,56(%r1)
+	ld	%r14,64(%r1)
+	ld	%r15,72(%r1)
+	ld	%r16,80(%r1)
+	ld	%r17,88(%r1)
+	ld	%r18,96(%r1)
+	ld	%r19,104(%r1)
+	ld	%r20,112(%r1)
+	ld	%r21,120(%r1)
+	ld	%r22,128(%r1)
+	ld	%r23,136(%r1)
+	ld	%r24,144(%r1)
+	ld	%r25,152(%r1)
+	ld	%r26,160(%r1)
+	ld	%r27,168(%r1)
+	ld	%r28,176(%r1)
+	ld	%r29,184(%r1)
+	ld	%r30,192(%r1)
+	ld	%r31,200(%r1)
+
+	/* Restore the stack and link register */
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr 	%r0

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106021412.p52ECbaK020881>