From owner-svn-src-all@freebsd.org Thu Jan 11 09:42:26 2018 Return-Path: Delivered-To: svn-src-all@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 2756FE7AC44; Thu, 11 Jan 2018 09:42:26 +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 DD32063A3B; Thu, 11 Jan 2018 09:42:25 +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 0CFA213305; Thu, 11 Jan 2018 09:42:25 +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 w0B9gOUP036448; Thu, 11 Jan 2018 09:42:24 GMT (envelope-from wma@FreeBSD.org) Received: (from wma@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w0B9gOMd036447; Thu, 11 Jan 2018 09:42:24 GMT (envelope-from wma@FreeBSD.org) Message-Id: <201801110942.w0B9gOMd036447@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 09:42:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r327815 - head/sys/powerpc/powernv X-SVN-Group: head X-SVN-Commit-Author: wma X-SVN-Commit-Paths: head/sys/powerpc/powernv X-SVN-Commit-Revision: 327815 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jan 2018 09:42:26 -0000 Author: wma Date: Thu Jan 11 09:42:24 2018 New Revision: 327815 URL: https://svnweb.freebsd.org/changeset/base/327815 Log: PowerNV: add buffer for OPAL console 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. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation Modified: head/sys/powerpc/powernv/opal_console.c Modified: head/sys/powerpc/powernv/opal_console.c ============================================================================== --- head/sys/powerpc/powernv/opal_console.c Thu Jan 11 09:39:38 2018 (r327814) +++ head/sys/powerpc/powernv/opal_console.c Thu Jan 11 09:42:24 2018 (r327815) @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -72,6 +73,7 @@ struct uart_opal_softc { }; static struct uart_opal_softc *console_sc = NULL; + #if defined(KDB) static int alt_break_state; #endif @@ -127,6 +129,48 @@ static struct ttydevsw uart_opal_tty_class = { .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) { @@ -231,6 +275,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); @@ -332,25 +377,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; @@ -361,7 +401,11 @@ uart_opal_put(struct uart_opal_softc *sc, void *buffer 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;