Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Jan 2015 23:54:56 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r277623 - in projects/powernv: conf powerpc/conf powerpc/powernv
Message-ID:  <201501232354.t0NNsuEI086763@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Fri Jan 23 23:54:55 2015
New Revision: 277623
URL: https://svnweb.freebsd.org/changeset/base/277623

Log:
  First round of PowerNV support: platform module, OPAL firmware abstraction
  layer interface, and console driver.
  
  The next set of interesting things is interrupt controller and PCI host
  bridge drivers.
  
  Sponsored by:	FreeBSD Foundation

Added:
  projects/powernv/powerpc/powernv/
  projects/powernv/powerpc/powernv/opal.c   (contents, props changed)
  projects/powernv/powerpc/powernv/opal.h   (contents, props changed)
  projects/powernv/powerpc/powernv/opal_console.c
     - copied, changed from r277539, head/sys/powerpc/pseries/phyp_console.c
  projects/powernv/powerpc/powernv/opalcall.S   (contents, props changed)
  projects/powernv/powerpc/powernv/platform_powernv.c   (contents, props changed)
Modified:
  projects/powernv/conf/files.powerpc
  projects/powernv/conf/options.powerpc
  projects/powernv/powerpc/conf/GENERIC64

Modified: projects/powernv/conf/files.powerpc
==============================================================================
--- projects/powernv/conf/files.powerpc	Fri Jan 23 23:53:56 2015	(r277622)
+++ projects/powernv/conf/files.powerpc	Fri Jan 23 23:54:55 2015	(r277623)
@@ -170,6 +170,10 @@ powerpc/powermac/smusat.c	optional	power
 powerpc/powermac/uninorth.c	optional	powermac
 powerpc/powermac/uninorthpci.c	optional	powermac pci
 powerpc/powermac/vcoregpio.c	optional	powermac 
+powerpc/powernv/opal.c		optional	powernv
+powerpc/powernv/opal_console.c	optional	powernv
+powerpc/powernv/opalcall.S	optional	powernv
+powerpc/powernv/platform_powernv.c optional	powernv
 powerpc/powerpc/altivec.c	standard
 powerpc/powerpc/autoconf.c	standard
 powerpc/powerpc/bcopy.c		standard

Modified: projects/powernv/conf/options.powerpc
==============================================================================
--- projects/powernv/conf/options.powerpc	Fri Jan 23 23:53:56 2015	(r277622)
+++ projects/powernv/conf/options.powerpc	Fri Jan 23 23:54:55 2015	(r277623)
@@ -22,6 +22,7 @@ MPC85XX			opt_platform.h
 POWERMAC		opt_platform.h
 PS3			opt_platform.h
 MAMBO
+POWERNV
 PSERIES
 PSIM
 WII			opt_platform.h

Modified: projects/powernv/powerpc/conf/GENERIC64
==============================================================================
--- projects/powernv/powerpc/conf/GENERIC64	Fri Jan 23 23:53:56 2015	(r277622)
+++ projects/powernv/powerpc/conf/GENERIC64	Fri Jan 23 23:54:55 2015	(r277623)
@@ -31,6 +31,7 @@ options 	POWERMAC		#NewWorld Apple Power
 options 	PS3			#Sony Playstation 3
 options 	MAMBO			#IBM Mambo Full System Simulator
 options 	PSERIES			#PAPR-compliant systems (e.g. IBM p)
+options		POWERNV			#Non-virtualized OpenPOWER systems
 
 options		FDT			#Flattened Device Tree
 options 	SCHED_ULE		#ULE scheduler

Added: projects/powernv/powerpc/powernv/opal.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/powernv/powerpc/powernv/opal.c	Fri Jan 23 23:54:55 2015	(r277623)
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (C) 2015 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 <dev/ofw/openfirm.h>
+
+#include "opal.h"
+
+extern uint64_t opal_entrypoint;
+extern uint64_t opal_data;
+extern uint64_t opal_msr;
+
+static int opal_initialized = 0;
+
+int
+opal_check(void)
+{
+	phandle_t opal;
+	cell_t val[2];
+
+	if (opal_initialized)
+		return (0);
+
+	opal = OF_finddevice("/ibm,opal");
+	if (opal == -1)
+		return (ENOENT);
+
+	if (!OF_hasprop(opal, "opal-base-address") ||
+	    !OF_hasprop(opal, "opal-entry-address"))
+		return (ENOENT);
+	
+	OF_getencprop(opal, "opal-base-address", val, sizeof(val));
+	opal_data = ((uint64_t)val[0] << 32) | val[1];
+	OF_getencprop(opal, "opal-entry-address", val, sizeof(val));
+	opal_entrypoint = ((uint64_t)val[0] << 32) | val[1];
+
+	opal_msr = mfmsr() & ~(PSL_EE | PSL_IR | PSL_DR | PSL_SE);
+
+	opal_initialized = 1;
+
+	return (0);
+}
+

Added: projects/powernv/powerpc/powernv/opal.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/powernv/powerpc/powernv/opal.h	Fri Jan 23 23:54:55 2015	(r277623)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2015 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 _POWERNV_OPAL_H
+#define _POWERNV_OPAL_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/* Check if OPAL is correctly instantiated. Will try to instantiate it. */
+int opal_check(void);
+
+/* Call an OPAL method. Any pointers passed must be real-mode accessible! */
+int opal_call(uint64_t token, ...);
+
+#define OPAL_CONSOLE_WRITE	1
+#define OPAL_CONSOLE_READ	2
+#define OPAL_START_CPU		41
+
+#define OPAL_SUCCESS		0
+#define	OPAL_BUSY_EVENT		-12
+
+#endif

Copied and modified: projects/powernv/powerpc/powernv/opal_console.c (from r277539, head/sys/powerpc/pseries/phyp_console.c)
==============================================================================
--- head/sys/powerpc/pseries/phyp_console.c	Thu Jan 22 22:04:43 2015	(r277539, copy source)
+++ projects/powernv/powerpc/powernv/opal_console.c	Fri Jan 23 23:54:55 2015	(r277623)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved.
+ * Copyright (C) 2011,2015 by Nathan Whitehorn. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,7 +35,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/conf.h>
 #include <sys/cons.h>
 #include <sys/tty.h>
-#include <machine/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_bus.h>
@@ -44,10 +46,10 @@ __FBSDID("$FreeBSD$");
 #include <dev/uart/uart_cpu.h>
 #include <dev/uart/uart_bus.h>
 
-#include "phyp-hvcall.h"
+#include "opal.h"
 #include "uart_if.h"
 
-struct uart_phyp_softc {
+struct uart_opal_softc {
 	device_t dev;
 	phandle_t node;
 	int vtermid;
@@ -62,21 +64,18 @@ struct uart_phyp_softc {
 	struct mtx sc_mtx;
 	int protocol;
 
-	union {
-		uint64_t u64[2];
-		char str[16];
-	} phyp_inbuf;
+	char opal_inbuf[16];
 	uint64_t inbuflen;
 	uint8_t outseqno;
 };
 
-static struct uart_phyp_softc	*console_sc = NULL;
+static struct uart_opal_softc	*console_sc = NULL;
 #if defined(KDB)
 static int			alt_break_state;
 #endif
 
 enum {
-	HVTERM1, HVTERMPROT
+	OPAL_RAW, OPAL_HVSI
 };
 
 #define VS_DATA_PACKET_HEADER		0xff
@@ -89,45 +88,45 @@ enum {
 #define  VSV_SEND_MODEM_CTL_STATUS	0x02
 #define VS_QUERY_RESPONSE_PACKET_HEADER	0xfc
 
-static int uart_phyp_probe(device_t dev);
-static int uart_phyp_attach(device_t dev);
-static void uart_phyp_intr(void *v);
+static int uart_opal_probe(device_t dev);
+static int uart_opal_attach(device_t dev);
+static void uart_opal_intr(void *v);
 
-static device_method_t uart_phyp_methods[] = {
+static device_method_t uart_opal_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe,		uart_phyp_probe),
-	DEVMETHOD(device_attach,	uart_phyp_attach),
+	DEVMETHOD(device_probe,		uart_opal_probe),
+	DEVMETHOD(device_attach,	uart_opal_attach),
 
 	DEVMETHOD_END
 };
 
-static driver_t uart_phyp_driver = {
+static driver_t uart_opal_driver = {
 	"uart",
-	uart_phyp_methods,
-	sizeof(struct uart_phyp_softc),
+	uart_opal_methods,
+	sizeof(struct uart_opal_softc),
 };
  
-DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
+DRIVER_MODULE(uart_opal, opalcons, uart_opal_driver, uart_devclass, 0, 0);
 
-static cn_probe_t uart_phyp_cnprobe;
-static cn_init_t uart_phyp_cninit;
-static cn_term_t uart_phyp_cnterm;
-static cn_getc_t uart_phyp_cngetc;
-static cn_putc_t uart_phyp_cnputc;
-static cn_grab_t uart_phyp_cngrab;
-static cn_ungrab_t uart_phyp_cnungrab;
+static cn_probe_t uart_opal_cnprobe;
+static cn_init_t uart_opal_cninit;
+static cn_term_t uart_opal_cnterm;
+static cn_getc_t uart_opal_cngetc;
+static cn_putc_t uart_opal_cnputc;
+static cn_grab_t uart_opal_cngrab;
+static cn_ungrab_t uart_opal_cnungrab;
 
-CONSOLE_DRIVER(uart_phyp);
+CONSOLE_DRIVER(uart_opal);
 
-static void uart_phyp_ttyoutwakeup(struct tty *tp);
+static void uart_opal_ttyoutwakeup(struct tty *tp);
 
-static struct ttydevsw uart_phyp_tty_class = {
+static struct ttydevsw uart_opal_tty_class = {
 	.tsw_flags	= TF_INITLOCK|TF_CALLOUT,
-	.tsw_outwakeup	= uart_phyp_ttyoutwakeup,
+	.tsw_outwakeup	= uart_opal_ttyoutwakeup,
 };
 
 static int
-uart_phyp_probe_node(struct uart_phyp_softc *sc)
+uart_opal_probe_node(struct uart_opal_softc *sc)
 {
 	phandle_t node = sc->node;
 	uint32_t reg;
@@ -136,11 +135,6 @@ uart_phyp_probe_node(struct uart_phyp_so
 	sc->inbuflen = 0;
 	sc->outseqno = 0;
 
-	if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
-		return (ENXIO);
-	if (strcmp(buf, "vty") != 0)
-		return (ENXIO);
-
 	if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0)
 		return (ENXIO);
 	if (strcmp(buf, "serial") != 0)
@@ -155,11 +149,11 @@ uart_phyp_probe_node(struct uart_phyp_so
 
 	if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0)
 		return (ENXIO);
-	if (strcmp(buf, "hvterm1") == 0) {
-		sc->protocol = HVTERM1;
+	if (strcmp(buf, "ibm,opal-console-raw") == 0) {
+		sc->protocol = OPAL_RAW;
 		return (0);
-	} else if (strcmp(buf, "hvterm-protocol") == 0) {
-		sc->protocol = HVTERMPROT;
+	} else if (strcmp(buf, "ibm,opal-console-hvsi") == 0) {
+		sc->protocol = OPAL_HVSI;
 		return (0);
 	}
 
@@ -167,54 +161,46 @@ uart_phyp_probe_node(struct uart_phyp_so
 }
 
 static int
-uart_phyp_probe(device_t dev)
+uart_opal_probe(device_t dev)
 {
-	const char *name;
-	struct uart_phyp_softc sc;
+	struct uart_opal_softc sc;
 	int err;
 
-	name = ofw_bus_get_name(dev);
-	if (name == NULL || strcmp(name, "vty") != 0)
-		return (ENXIO);
-
 	sc.node = ofw_bus_get_node(dev);
-	err = uart_phyp_probe_node(&sc);
+	err = uart_opal_probe_node(&sc);
 	if (err != 0)
 		return (err);
 
-	device_set_desc(dev, "POWER Hypervisor Virtual Serial Port");
+	device_set_desc(dev, "OPAL Serial Port");
 
 	return (err);
 }
 
 static void
-uart_phyp_cnprobe(struct consdev *cp)
+uart_opal_cnprobe(struct consdev *cp)
 {
 	char buf[64];
-	ihandle_t stdout;
 	phandle_t input, chosen;
-	static struct uart_phyp_softc sc;
+	static struct uart_opal_softc sc;
 
-	if ((chosen = OF_finddevice("/chosen")) == -1)
+	if (opal_check() != 0)
 		goto fail;
 
-	/* Check if OF has an active stdin/stdout */
-	input = -1;
-	if (OF_getprop(chosen, "stdout", &stdout,
-	    sizeof(stdout)) == sizeof(stdout) && stdout != 0)
-		input = OF_instance_to_package(stdout);
-	if (input == -1)
+	if ((chosen = OF_finddevice("/chosen")) == -1)
 		goto fail;
 
-	if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
+	/* Check if OF has an active stdin/stdout */
+	if (OF_getprop(chosen, "linux,stdout-path", buf, sizeof(buf)) <= 0)
 		goto fail;
-	if (strcmp(buf, "serial") != 0)
+	
+	input = OF_finddevice(buf);
+	if (input == -1)
 		goto fail;
 
 	sc.node = input;
-	if (uart_phyp_probe_node(&sc) != 0)
+	if (uart_opal_probe_node(&sc) != 0)
 		goto fail;
-	mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET |
+	mtx_init(&sc.sc_mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET |
 	    MTX_NOWITNESS);
 
 	cp->cn_pri = CN_NORMAL;
@@ -227,25 +213,25 @@ fail:
 }
 
 static int
-uart_phyp_attach(device_t dev)
+uart_opal_attach(device_t dev)
 {
-	struct uart_phyp_softc *sc;
+	struct uart_opal_softc *sc;
 	int unit;
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
 	sc->node = ofw_bus_get_node(dev);
-	uart_phyp_probe_node(sc);
+	uart_opal_probe_node(sc);
 
 	unit = device_get_unit(dev);
-	sc->tp = tty_alloc(&uart_phyp_tty_class, sc);
+	sc->tp = tty_alloc(&uart_opal_tty_class, sc);
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL,
 	    MTX_SPIN | MTX_QUIET | MTX_NOWITNESS);
 
 	if (console_sc != NULL && console_sc->vtermid == sc->vtermid) {
 		sc->outseqno = console_sc->outseqno;
 		console_sc = sc;
-		sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit);
+		sprintf(uart_opal_consdev.cn_name, "ttyu%r", unit);
 		tty_init_console(sc->tp, 0);
 	}
 
@@ -254,13 +240,13 @@ uart_phyp_attach(device_t dev)
 	    RF_ACTIVE | RF_SHAREABLE);
 	if (sc->irqres != NULL) {
 		bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE,
-		    NULL, uart_phyp_intr, sc, &sc->sc_icookie);
+		    NULL, uart_opal_intr, sc, &sc->sc_icookie);
 	} else {
 		callout_init(&sc->callout, CALLOUT_MPSAFE);
 		sc->polltime = hz / 20;
 		if (sc->polltime < 1)
 			sc->polltime = 1;
-		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
+		callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc);
 	}
 
 	tty_makedev(sc->tp, NULL, "u%r", unit);
@@ -269,111 +255,131 @@ uart_phyp_attach(device_t dev)
 }
 
 static void
-uart_phyp_cninit(struct consdev *cp)
+uart_opal_cninit(struct consdev *cp)
 {
 
-	strcpy(cp->cn_name, "phypcons");
+	strcpy(cp->cn_name, "opalcons");
 }
 
 static void
-uart_phyp_cnterm(struct consdev *cp)
+uart_opal_cnterm(struct consdev *cp)
 {
 }
 
 static int
-uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
+uart_opal_get(struct uart_opal_softc *sc, void *buffer, size_t bufsize)
 {
 	int err;
 	int hdr = 0;
 
-	uart_lock(&sc->sc_mtx);
-	if (sc->inbuflen == 0) {
-		err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
-		    0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
-		    &sc->phyp_inbuf.u64[1]);
-		if (err != H_SUCCESS) {
-			uart_unlock(&sc->sc_mtx);
+	if (sc->protocol == OPAL_RAW) {
+		uint64_t len = bufsize;
+		uint64_t olen = (uint64_t)&len;
+		uint64_t obuf = (uint64_t)buffer;
+
+		if (pmap_bootstrapped) {
+			olen = vtophys(&len);
+			obuf = vtophys(buffer);
+		}
+
+		err = opal_call(OPAL_CONSOLE_READ, sc->vtermid, olen, obuf);
+		if (err != OPAL_SUCCESS)
 			return (-1);
+
+		bufsize = len;
+	} else {
+		uart_lock(&sc->sc_mtx);
+		if (sc->inbuflen == 0) {
+			err = opal_call(OPAL_CONSOLE_READ, sc->vtermid,
+			    &sc->inbuflen, sc->opal_inbuf);
+			if (err != OPAL_SUCCESS) {
+				uart_unlock(&sc->sc_mtx);
+				return (-1);
+			}
+			hdr = 1; 
 		}
-		hdr = 1; 
-	}
 
-	if (sc->inbuflen == 0) {
-		uart_unlock(&sc->sc_mtx);
-		return (0);
-	}
+		if (sc->inbuflen == 0) {
+			uart_unlock(&sc->sc_mtx);
+			return (0);
+		}
 
-	if (bufsize > sc->inbuflen)
-		bufsize = sc->inbuflen;
+		if (bufsize > sc->inbuflen)
+			bufsize = sc->inbuflen;
 
-	if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
-		sc->inbuflen = sc->inbuflen - 4;
-		/* The VTERM protocol has a 4 byte header, skip it here. */
-		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4],
-		    sc->inbuflen);
-	}
+		if (hdr == 1) {
+			sc->inbuflen = sc->inbuflen - 4;
+			/* The HVSI protocol has a 4 byte header, skip it */
+			memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[4],
+			    sc->inbuflen);
+		}
 
-	memcpy(buffer, sc->phyp_inbuf.str, bufsize);
-	sc->inbuflen -= bufsize;
-	if (sc->inbuflen > 0)
-		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
-		    sc->inbuflen);
+		memcpy(buffer, sc->opal_inbuf, bufsize);
+		sc->inbuflen -= bufsize;
+		if (sc->inbuflen > 0)
+			memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[bufsize],
+			    sc->inbuflen);
+
+		uart_unlock(&sc->sc_mtx);
+	}
 
-	uart_unlock(&sc->sc_mtx);
 	return (bufsize);
 }
 
 static int
-uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
+uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize)
 {
 	uint16_t seqno;
-	uint64_t len = 0;
+	uint64_t len = bufsize;
+	char	cbuf[16];
 	int	err;
+	uint64_t olen = (uint64_t)&len;
+	uint64_t obuf = (uint64_t)cbuf;
+
+	if (pmap_bootstrapped)
+		olen = vtophys(&len);
+
+	if (sc->protocol == OPAL_RAW) {
+		if (pmap_bootstrapped)
+			obuf = vtophys(buffer);
+		else
+			obuf = (uint64_t)(buffer);
 
-	union {
-		uint64_t u64[2];
-		char bytes[16];
-	} cbuf;
-
-	uart_lock(&sc->sc_mtx);
-	switch (sc->protocol) {
-	case HVTERM1:
-		if (bufsize > 16)
-			bufsize = 16;
-		memcpy(&cbuf, buffer, bufsize);
-		len = bufsize;
-		break;
-	case HVTERMPROT:
+		err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf);
+	} else {
+		if (pmap_bootstrapped)
+			obuf = vtophys(cbuf);
+		uart_lock(&sc->sc_mtx);
 		if (bufsize > 12)
 			bufsize = 12;
 		seqno = sc->outseqno++;
-		cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
-		cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */
-		cbuf.bytes[2] = (seqno >> 8) & 0xff;
-		cbuf.bytes[3] = seqno & 0xff;
-		memcpy(&cbuf.bytes[4], buffer, bufsize);
+		cbuf[0] = VS_DATA_PACKET_HEADER;
+		cbuf[1] = 4 + bufsize; /* total length */
+		cbuf[2] = (seqno >> 8) & 0xff;
+		cbuf[3] = seqno & 0xff;
+		memcpy(&cbuf[4], buffer, bufsize);
 		len = 4 + bufsize;
-		break;
-	}
+		err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf);
+		uart_unlock(&sc->sc_mtx);
 
-	do {
-	    err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0],
-			    cbuf.u64[1]);
-		DELAY(100);
-	} while (err == H_BUSY);
+		len -= 4;
+	}
 
-	uart_unlock(&sc->sc_mtx);
+#if 0
+	if (err != OPAL_SUCCESS)
+		len = 0;
+#endif
 
-	return (bufsize);
+	return (len);
 }
 
 static int
-uart_phyp_cngetc(struct consdev *cp)
+uart_opal_cngetc(struct consdev *cp)
 {
 	unsigned char c;
 	int retval;
 
-	retval = uart_phyp_get(console_sc, &c, 1);
+	retval = uart_opal_get(console_sc, &c, 1);
 	if (retval != 1)
 		return (-1);
 #if defined(KDB)
@@ -384,50 +390,50 @@ uart_phyp_cngetc(struct consdev *cp)
 }
 
 static void
-uart_phyp_cnputc(struct consdev *cp, int c)
+uart_opal_cnputc(struct consdev *cp, int c)
 {
 	unsigned char ch = c;
-	uart_phyp_put(console_sc, &ch, 1);
+	uart_opal_put(console_sc, &ch, 1);
 }
 
 static void
-uart_phyp_cngrab(struct consdev *cp)
+uart_opal_cngrab(struct consdev *cp)
 {
 }
 
 static void
-uart_phyp_cnungrab(struct consdev *cp)
+uart_opal_cnungrab(struct consdev *cp)
 {
 }
 
 static void
-uart_phyp_ttyoutwakeup(struct tty *tp)
+uart_opal_ttyoutwakeup(struct tty *tp)
 {
-	struct uart_phyp_softc *sc;
+	struct uart_opal_softc *sc;
 	char buffer[8];
 	int len;
 
 	sc = tty_softc(tp);
 	
 	while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
-		uart_phyp_put(sc, buffer, len);
+		uart_opal_put(sc, buffer, len);
 }
 
 static void
-uart_phyp_intr(void *v)
+uart_opal_intr(void *v)
 {
-	struct uart_phyp_softc *sc = v;
+	struct uart_opal_softc *sc = v;
 	struct tty *tp = sc->tp;
 	unsigned char c;
 	int len;
 
 	tty_lock(tp);
-	while ((len = uart_phyp_get(sc, &c, 1)) > 0)
+	while ((len = uart_opal_get(sc, &c, 1)) > 0)
 		ttydisc_rint(tp, c, 0);
 	ttydisc_rint_done(tp);
 	tty_unlock(tp);
 
 	if (sc->irqres == NULL)
-		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
+		callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc);
 }
 

Added: projects/powernv/powerpc/powernv/opalcall.S
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/powernv/powerpc/powernv/opalcall.S	Fri Jan 23 23:54:55 2015	(r277623)
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (C) 2015 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 <machine/asm.h>
+
+GLOBAL(opal_entrypoint)
+	.llong	0
+GLOBAL(opal_data)
+	.llong	0
+GLOBAL(opal_msr)
+	.llong	0
+
+TOC_ENTRY(opal_entrypoint)
+TOC_ENTRY(opal_data)
+TOC_ENTRY(opal_msr)
+
+ASENTRY(opal_call)
+	/* Args:
+	 * r3: opal token
+	 * r4-r10 opal arguments
+	 */
+
+	/* Save call stuff on stack */
+	mflr	%r0
+	std	%r0,16(%r1)
+	std	%r2,-16(%r1)
+	mfcr	%r0
+	std	%r0,8(%r1)
+
+	/* Load OPAL entry information */
+	mr	%r0,%r3
+	ld	%r3,TOC_REF(opal_entrypoint)(%r2)
+	ld	%r3,0(%r3)
+	mtctr	%r3
+
+	/* Save MSR in non-volatile scratch register and turn off translation */
+	std	%r31,-8(%r1)
+	mfmsr	%r31
+
+	/* Load last bits from the TOC */
+	ld	%r3,TOC_REF(opal_msr)(%r2)
+	ld	%r3,0(%r3)
+	ld	%r2,TOC_REF(opal_data)(%r2)
+	ld	%r2,0(%r2)
+
+	mtmsrd	%r3
+	isync
+
+	/* Shift registers over */
+	mr	%r3,%r4
+	mr	%r4,%r5
+	mr	%r5,%r6
+	mr	%r6,%r7
+	mr	%r7,%r8
+	mr	%r8,%r9
+	mr	%r9,%r10
+
+	/* Call OPAL */
+	bctrl
+
+	/* Restore MSR */
+	mtmsrd	%r31
+	isync
+	ld	%r31,-8(%r1)
+	
+	/* Restore call stuff from stack */
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	ld	%r2,-16(%r1)
+	ld	%r0,8(%r1)
+	mtcr	%r0
+
+	/* And return */
+	blr
+

Added: projects/powernv/powerpc/powernv/platform_powernv.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/powernv/powerpc/powernv/platform_powernv.c	Fri Jan 23 23:54:55 2015	(r277623)
@@ -0,0 +1,333 @@
+/*-
+ * Copyright (c) 2015 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 THE AUTHOR 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$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/rtas.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/trap.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+#include "platform_if.h"
+#include "opal.h"
+
+#ifdef SMP
+extern void *ap_pcpu;
+#endif
+
+static int powernv_probe(platform_t);
+static int powernv_attach(platform_t);
+void powernv_mem_regions(platform_t, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz);
+static u_long powernv_timebase_freq(platform_t, struct cpuref *cpuref);
+static int powernv_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int powernv_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int powernv_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static void powernv_smp_ap_init(platform_t);
+#ifdef SMP
+static int powernv_smp_start_cpu(platform_t, struct pcpu *cpu);
+static struct cpu_group *powernv_smp_topo(platform_t plat);
+#endif
+static void powernv_reset(platform_t);
+
+static platform_method_t powernv_methods[] = {
+	PLATFORMMETHOD(platform_probe, 		powernv_probe),
+	PLATFORMMETHOD(platform_attach,		powernv_attach),
+	PLATFORMMETHOD(platform_mem_regions,	powernv_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	powernv_timebase_freq),
+	
+	PLATFORMMETHOD(platform_smp_ap_init,	powernv_smp_ap_init),
+	PLATFORMMETHOD(platform_smp_first_cpu,	powernv_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	powernv_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	powernv_smp_get_bsp),
+#ifdef SMP
+	PLATFORMMETHOD(platform_smp_start_cpu,	powernv_smp_start_cpu),
+	PLATFORMMETHOD(platform_smp_topo,	powernv_smp_topo),
+#endif
+
+	PLATFORMMETHOD(platform_reset,		powernv_reset),
+
+	{ 0, 0 }
+};
+
+static platform_def_t powernv_platform = {
+	"powernv",
+	powernv_methods,
+	0
+};
+
+PLATFORM_DEF(powernv_platform);
+
+static int
+powernv_probe(platform_t plat)
+{
+	if (opal_check() == 0)
+		return (BUS_PROBE_SPECIFIC);
+
+	return (ENXIO);
+}
+
+static int
+powernv_attach(platform_t plat)
+{
+	/* Ping OPAL again just to make sure */
+	opal_check();
+
+	return (0);
+}
+
+void
+powernv_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+
+	ofw_mem_regions(phys, physsz, avail, availsz);
+}
+
+static u_long
+powernv_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	phandle_t phandle;
+	int32_t ticks = -1;
+
+	phandle = cpuref->cr_hwref;
+
+	OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+static int
+powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res, cpuid;
+
+	root = OF_peer(0);
+
+	dev = OF_child(root);
+	while (dev != 0) {
+		res = OF_getprop(dev, "name", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpus") == 0)
+			break;
+		dev = OF_peer(dev);
+	}
+	if (dev == 0) {
+		/*
+		 * psim doesn't have a name property on the /cpus node,
+		 * but it can be found directly
+		 */
+		dev = OF_finddevice("/cpus");
+		if (dev == 0)
+			return (ENOENT);
+	}
+
+	cpu = OF_child(dev);
+
+	while (cpu != 0) {
+		res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpu") == 0)
+			break;
+		cpu = OF_peer(cpu);
+	}
+	if (cpu == 0)
+		return (ENOENT);
+
+	cpuref->cr_hwref = cpu;
+	res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+	    sizeof(cpuid));
+	if (res <= 0)
+		res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+	if (res <= 0)
+		cpuid = 0;
+	cpuref->cr_cpuid = cpuid;
+
+	return (0);
+}
+
+static int
+powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu;
+	int i, res, cpuid;
+
+	/* Check for whether it should be the next thread */
+	res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
+	if (res > 0) {
+		cell_t interrupt_servers[res/sizeof(cell_t)];
+		OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
+		    interrupt_servers, res);
+		for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
+			if (interrupt_servers[i] == cpuref->cr_cpuid) {
+				cpuref->cr_cpuid = interrupt_servers[i+1];
+				return (0);
+			}
+		}
+	}
+

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



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