From owner-svn-src-projects@FreeBSD.ORG Mon Jan 26 19:01:07 2015 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id A6BBE969; Mon, 26 Jan 2015 19:01:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 93540D26; Mon, 26 Jan 2015 19:01:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0QJ17QV007635; Mon, 26 Jan 2015 19:01:07 GMT (envelope-from nwhitehorn@FreeBSD.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0QJ17rB007634; Mon, 26 Jan 2015 19:01:07 GMT (envelope-from nwhitehorn@FreeBSD.org) Message-Id: <201501261901.t0QJ17rB007634@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: nwhitehorn set sender to nwhitehorn@FreeBSD.org using -f From: Nathan Whitehorn Date: Mon, 26 Jan 2015 19:01:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r277766 - projects/powernv/powerpc/powernv X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Jan 2015 19:01:07 -0000 Author: nwhitehorn Date: Mon Jan 26 19:01:06 2015 New Revision: 277766 URL: https://svnweb.freebsd.org/changeset/base/277766 Log: Avoid the lock in vtophys() by providing a static direct-mapped spinlock- protected output buffer to use when the console driver cannot acquire locks for some reason. This allows the idle thread to use printf() (e.g. the SMP startup messages) without crashing the kernel. Modified: projects/powernv/powerpc/powernv/opal_console.c Modified: projects/powernv/powerpc/powernv/opal_console.c ============================================================================== --- projects/powernv/powerpc/powernv/opal_console.c Mon Jan 26 18:48:27 2015 (r277765) +++ projects/powernv/powerpc/powernv/opal_console.c Mon Jan 26 19:01:06 2015 (r277766) @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -70,6 +71,7 @@ struct uart_opal_softc { }; static struct uart_opal_softc *console_sc = NULL; + #if defined(KDB) static int alt_break_state; #endif @@ -125,6 +127,48 @@ static struct ttydevsw uart_opal_tty_cla .tsw_outwakeup = uart_opal_ttyoutwakeup, }; +static struct { + char tmpbuf[16]; + uint64_t size; + struct mtx mtx; +} escapehatch; + +static void +uart_opal_real_map_outbuffer(uint64_t *bufferp, uint64_t *lenp) +{ + + if (!mtx_initialized(&escapehatch.mtx)) + mtx_init(&escapehatch.mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | + MTX_NOWITNESS); + + if (!pmap_bootstrapped) + return; + + if (TD_IS_IDLETHREAD(curthread)) { + escapehatch.size = *(uint64_t *)(*lenp) = + min(sizeof(escapehatch.tmpbuf), *(uint64_t *)(*lenp)); + mtx_lock_spin(&escapehatch.mtx); + memcpy(escapehatch.tmpbuf, (void *)(*bufferp), *(uint64_t *)(*lenp)); + *bufferp = (uint64_t)escapehatch.tmpbuf; + *lenp = (uint64_t)&escapehatch.size; + } + + *bufferp = vtophys(*bufferp); + *lenp = vtophys(*lenp); +} + +static void +uart_opal_real_unmap_outbuffer(uint64_t lenp, uint64_t *origlen) +{ + + if (!pmap_bootstrapped || !TD_IS_IDLETHREAD(curthread)) + return; + + mtx_assert(&escapehatch.mtx, MA_OWNED); + *origlen = escapehatch.size; + mtx_unlock_spin(&escapehatch.mtx); +} + static int uart_opal_probe_node(struct uart_opal_softc *sc) { @@ -229,6 +273,7 @@ uart_opal_attach(device_t dev) MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { + device_printf(dev, "console\n"); sc->outseqno = console_sc->outseqno; console_sc = sc; sprintf(uart_opal_consdev.cn_name, "ttyu%r", unit); @@ -330,25 +375,20 @@ static int uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) { uint16_t seqno; - uint64_t len = bufsize; + uint64_t len; 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); + obuf = (uint64_t)buffer; + len = bufsize; + uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_opal_real_unmap_outbuffer(olen, &len); } else { - if (pmap_bootstrapped) - obuf = vtophys(cbuf); uart_lock(&sc->sc_mtx); if (bufsize > 12) bufsize = 12; @@ -359,7 +399,11 @@ uart_opal_put(struct uart_opal_softc *sc cbuf[3] = seqno & 0xff; memcpy(&cbuf[4], buffer, bufsize); len = 4 + bufsize; + + uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_opal_real_unmap_outbuffer(olen, &len); + uart_unlock(&sc->sc_mtx); len -= 4;