From owner-svn-src-head@freebsd.org Thu Jan 11 07:40:08 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A56F7E749EF; Thu, 11 Jan 2018 07:40:08 +0000 (UTC) (envelope-from wma@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 6D62A836CC; Thu, 11 Jan 2018 07:40:08 +0000 (UTC) (envelope-from wma@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id AABBC11DF5; Thu, 11 Jan 2018 07:40:07 +0000 (UTC) (envelope-from wma@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w0B7e7Sw082466; Thu, 11 Jan 2018 07:40:07 GMT (envelope-from wma@FreeBSD.org) Received: (from wma@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w0B7e6hN082458; Thu, 11 Jan 2018 07:40:06 GMT (envelope-from wma@FreeBSD.org) Message-Id: <201801110740.w0B7e6hN082458@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: wma set sender to wma@FreeBSD.org using -f From: Wojciech Macek Date: Thu, 11 Jan 2018 07:40:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r327810 - in head/sys: conf powerpc/conf powerpc/powernv X-SVN-Group: head X-SVN-Commit-Author: wma X-SVN-Commit-Paths: in head/sys: conf powerpc/conf powerpc/powernv X-SVN-Commit-Revision: 327810 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jan 2018 07:40:08 -0000 Author: wma Date: Thu Jan 11 07:40:06 2018 New Revision: 327810 URL: https://svnweb.freebsd.org/changeset/base/327810 Log: PowerNV: initial support for OPAL OPAL is a dedicated firmware acting as a hypervisor. Add generic functions to provide all access. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Added: head/sys/powerpc/powernv/ head/sys/powerpc/powernv/opal.c (contents, props changed) head/sys/powerpc/powernv/opal.h (contents, props changed) head/sys/powerpc/powernv/opal_console.c (contents, props changed) head/sys/powerpc/powernv/opalcall.S (contents, props changed) head/sys/powerpc/powernv/platform_powernv.c (contents, props changed) Modified: head/sys/conf/files.powerpc head/sys/conf/options.powerpc head/sys/powerpc/conf/GENERIC64 Modified: head/sys/conf/files.powerpc ============================================================================== --- head/sys/conf/files.powerpc Thu Jan 11 07:35:14 2018 (r327809) +++ head/sys/conf/files.powerpc Thu Jan 11 07:40:06 2018 (r327810) @@ -183,6 +183,10 @@ powerpc/powermac/smusat.c optional powermac smu 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 optional powerpc | powerpc64 powerpc/powerpc/autoconf.c standard powerpc/powerpc/bcopy.c standard Modified: head/sys/conf/options.powerpc ============================================================================== --- head/sys/conf/options.powerpc Thu Jan 11 07:35:14 2018 (r327809) +++ head/sys/conf/options.powerpc Thu Jan 11 07:40:06 2018 (r327810) @@ -23,6 +23,7 @@ MPC85XX opt_platform.h POWERMAC opt_platform.h PS3 opt_platform.h MAMBO +POWERNV PSERIES PSIM Modified: head/sys/powerpc/conf/GENERIC64 ============================================================================== --- head/sys/powerpc/conf/GENERIC64 Thu Jan 11 07:35:14 2018 (r327809) +++ head/sys/powerpc/conf/GENERIC64 Thu Jan 11 07:40:06 2018 (r327810) @@ -31,6 +31,7 @@ options POWERMAC #NewWorld Apple PowerMacs 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: head/sys/powerpc/powernv/opal.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/opal.c Thu Jan 11 07:40:06 2018 (r327810) @@ -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 + +#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: head/sys/powerpc/powernv/opal.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/opal.h Thu Jan 11 07:40:06 2018 (r327810) @@ -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 +#include + +/* 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 Added: head/sys/powerpc/powernv/opal_console.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/opal_console.c Thu Jan 11 07:40:06 2018 (r327810) @@ -0,0 +1,441 @@ +/*- + * 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 + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "opal.h" +#include "uart_if.h" + +struct uart_opal_softc { + device_t dev; + phandle_t node; + int vtermid; + + struct tty *tp; + struct resource *irqres; + int irqrid; + struct callout callout; + void *sc_icookie; + int polltime; + + struct mtx sc_mtx; + int protocol; + + char opal_inbuf[16]; + uint64_t inbuflen; + uint8_t outseqno; +}; + +static struct uart_opal_softc *console_sc = NULL; +#if defined(KDB) +static int alt_break_state; +#endif + +enum { + OPAL_RAW, OPAL_HVSI +}; + +#define VS_DATA_PACKET_HEADER 0xff +#define VS_CONTROL_PACKET_HEADER 0xfe +#define VSV_SET_MODEM_CTL 0x01 +#define VSV_MODEM_CTL_UPDATE 0x02 +#define VSV_RENEGOTIATE_CONNECTION 0x03 +#define VS_QUERY_PACKET_HEADER 0xfd +#define VSV_SEND_VERSION_NUMBER 0x01 +#define VSV_SEND_MODEM_CTL_STATUS 0x02 +#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc + +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_opal_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_opal_probe), + DEVMETHOD(device_attach, uart_opal_attach), + + DEVMETHOD_END +}; + +static driver_t uart_opal_driver = { + "uart", + uart_opal_methods, + sizeof(struct uart_opal_softc), +}; + +DRIVER_MODULE(uart_opal, opalcons, uart_opal_driver, uart_devclass, 0, 0); + +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_opal); + +static void uart_opal_ttyoutwakeup(struct tty *tp); + +static struct ttydevsw uart_opal_tty_class = { + .tsw_flags = TF_INITLOCK|TF_CALLOUT, + .tsw_outwakeup = uart_opal_ttyoutwakeup, +}; + +static int +uart_opal_probe_node(struct uart_opal_softc *sc) +{ + phandle_t node = sc->node; + uint32_t reg; + char buf[64]; + + sc->inbuflen = 0; + sc->outseqno = 0; + + if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) + return (ENXIO); + if (strcmp(buf, "serial") != 0) + return (ENXIO); + + reg = -1; + OF_getprop(node, "reg", ®, sizeof(reg)); + if (reg == -1) + return (ENXIO); + sc->vtermid = reg; + sc->node = node; + + if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) + return (ENXIO); + if (strcmp(buf, "ibm,opal-console-raw") == 0) { + sc->protocol = OPAL_RAW; + return (0); + } else if (strcmp(buf, "ibm,opal-console-hvsi") == 0) { + sc->protocol = OPAL_HVSI; + return (0); + } + + return (ENXIO); +} + +static int +uart_opal_probe(device_t dev) +{ + struct uart_opal_softc sc; + int err; + + sc.node = ofw_bus_get_node(dev); + err = uart_opal_probe_node(&sc); + if (err != 0) + return (err); + + device_set_desc(dev, "OPAL Serial Port"); + + return (err); +} + +static void +uart_opal_cnprobe(struct consdev *cp) +{ + char buf[64]; + phandle_t input, chosen; + static struct uart_opal_softc sc; + + if (opal_check() != 0) + goto fail; + + if ((chosen = OF_finddevice("/chosen")) == -1) + goto fail; + + /* Check if OF has an active stdin/stdout */ + if (OF_getprop(chosen, "linux,stdout-path", buf, sizeof(buf)) <= 0) + goto fail; + + input = OF_finddevice(buf); + if (input == -1) + goto fail; + + sc.node = input; + if (uart_opal_probe_node(&sc) != 0) + goto fail; + mtx_init(&sc.sc_mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | + MTX_NOWITNESS); + + cp->cn_pri = CN_NORMAL; + console_sc = ≻ + return; + +fail: + cp->cn_pri = CN_DEAD; + return; +} + +static int +uart_opal_attach(device_t dev) +{ + struct uart_opal_softc *sc; + int unit; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->node = ofw_bus_get_node(dev); + uart_opal_probe_node(sc); + + unit = device_get_unit(dev); + 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_opal_consdev.cn_name, "ttyu%r", unit); + tty_init_console(sc->tp, 0); + } + + sc->irqrid = 0; + sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, + RF_ACTIVE | RF_SHAREABLE); + if (sc->irqres != NULL) { + bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, + 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_opal_intr, sc); + } + + tty_makedev(sc->tp, NULL, "u%r", unit); + + return (0); +} + +static void +uart_opal_cninit(struct consdev *cp) +{ + + strcpy(cp->cn_name, "opalcons"); +} + +static void +uart_opal_cnterm(struct consdev *cp) +{ +} + +static int +uart_opal_get(struct uart_opal_softc *sc, void *buffer, size_t bufsize) +{ + int err; + int hdr = 0; + + 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; + } + + if (sc->inbuflen == 0) { + uart_unlock(&sc->sc_mtx); + return (0); + } + + if (bufsize > sc->inbuflen) + bufsize = 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->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); + } + + return (bufsize); +} + +static int +uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) +{ + uint16_t seqno; + 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); + + 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[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; + err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_unlock(&sc->sc_mtx); + + len -= 4; + } + +#if 0 + if (err != OPAL_SUCCESS) + len = 0; +#endif + + return (len); +} + +static int +uart_opal_cngetc(struct consdev *cp) +{ + unsigned char c; + int retval; + + retval = uart_opal_get(console_sc, &c, 1); + if (retval != 1) + return (-1); +#if defined(KDB) + kdb_alt_break(c, &alt_break_state); +#endif + + return (c); +} + +static void +uart_opal_cnputc(struct consdev *cp, int c) +{ + unsigned char ch = c; + uart_opal_put(console_sc, &ch, 1); +} + +static void +uart_opal_cngrab(struct consdev *cp) +{ +} + +static void +uart_opal_cnungrab(struct consdev *cp) +{ +} + +static void +uart_opal_ttyoutwakeup(struct tty *tp) +{ + struct uart_opal_softc *sc; + char buffer[8]; + int len; + + sc = tty_softc(tp); + + while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) + uart_opal_put(sc, buffer, len); +} + +static void +uart_opal_intr(void *v) +{ + struct uart_opal_softc *sc = v; + struct tty *tp = sc->tp; + unsigned char c; + int len; + + tty_lock(tp); + 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_opal_intr, sc); +} + Added: head/sys/powerpc/powernv/opalcall.S ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/opalcall.S Thu Jan 11 07:40:06 2018 (r327810) @@ -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 + +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: head/sys/powerpc/powernv/platform_powernv.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/powerpc/powernv/platform_powernv.c Thu Jan 11 07:40:06 2018 (r327810) @@ -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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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); + } + } + } + + /* Next CPU core/package */ + cpu = OF_peer(cpuref->cr_hwref); + 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_get_bsp(platform_t plat, struct cpuref *cpuref) +{ + phandle_t chosen; + int cpuid, res; + struct cpuref i; + + chosen = OF_finddevice("/chosen"); + if (chosen == 0) + return (ENOENT); + + res = OF_getencprop(chosen, "fdtbootcpu", &cpuid, sizeof(cpuid)); + if (res < 0) + return (ENOENT); + + cpuref->cr_cpuid = cpuid; + + if (powernv_smp_first_cpu(plat, &i) != 0) + return (ENOENT); + cpuref->cr_hwref = i.cr_hwref; + + do { + if (i.cr_cpuid == cpuid) { + cpuref->cr_hwref = i.cr_hwref; + break; + } + } while (powernv_smp_next_cpu(plat, &i) == 0); + + return (0); +} + +#ifdef SMP +static int +powernv_smp_start_cpu(platform_t plat, struct pcpu *pc) +{ + int result, err, timeout; + + ap_pcpu = pc; + powerpc_sync(); + + result = opal_call(OPAL_START_CPU, pc->pc_cpuid, EXC_RST); + if (result < 0 || err != 0) { + printf("OPAL error (%d/%d): unable to start AP %d\n", + result, err, pc->pc_cpuid); + return (ENXIO); + } + + timeout = 10000; + while (!pc->pc_awake && timeout--) + DELAY(100); + + return ((pc->pc_awake) ? 0 : EBUSY); +} + +static struct cpu_group * +powernv_smp_topo(platform_t plat) +{ + struct pcpu *pc, *last_pc; + int i, ncores, ncpus; + + ncores = ncpus = 0; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***