From patchwork Sat May 2 11:36:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 1281668 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49DqBD3jwZz9sRf for ; Sat, 2 May 2020 23:06:12 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=BjJ6kTHX; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 49DqBD1znKzDrQg for ; Sat, 2 May 2020 23:06:12 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::542; helo=mail-pg1-x542.google.com; envelope-from=npiggin@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=BjJ6kTHX; dkim-atps=neutral Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 49DnD813JlzDr4d for ; Sat, 2 May 2020 21:37:44 +1000 (AEST) Received: by mail-pg1-x542.google.com with SMTP id d17so5897035pgo.0 for ; Sat, 02 May 2020 04:37:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AQ7LH06q27s36eZ3/yedRcPqvQ7td1+GTSbYDGqi3jA=; b=BjJ6kTHX47ijJlhrVHWi3UsUwgYTl4Ad1QfvKE9HZab+IM+ibk9bntpRwLzwuFnIPm PLNZ15RwaLxq3OHMbXvirt9XXiY42Zzar8kW9ZK7hbXXSNT+VUyI8oBPtY5JmV8fXSwG R41jMLV07WCSUu/9hLfcv+Nv6N0ELEsN3xXEaK3QpWTbkXKIL/vr+EwYW5+xru0nIJLU myyVJIgo3DRszD5TKUHsUNqGvLhq06dJyl3hjIhfUw0E2nTmJ7vh2e6l7M1roELraD5I gEYN1+D8fi661yBmYEdKJ+kVxFuhzJjW8IMtNRwH6tpWP0xUC+o+kiQuYWsYYwJYyqvj SGRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AQ7LH06q27s36eZ3/yedRcPqvQ7td1+GTSbYDGqi3jA=; b=nnBe0ClFyfpk0YI7ni61odQZuS5P1nAsayE8fRCJqKPc8UIbzLl4sFvy6laN0bAZqg O7MUI4TcvoBuFVZueaZCn2EAUeKUaZ486m4X7K4+BmKxdQCNgJBt2oPQmctWOhI7ODzG 1AXgXU8KO9lbzrlyGL7Y0u2ic4WMaixWGTG77VdPSQOKv4H7YFKKUIykOpbanu/WLjEZ Nu0jCzPCpDoWqKzS7mFTeoX74BGzpe1lxwQ/MRumEeZ8dunyB/Dab8VFw39UNEWARVLv 3d/RL6K77AZpG7lY6V4BF6/8ARhvbqcHrXwEndiqa0OTUf3JF7nOY7Dei2kFQMNoZCJh iCkQ== X-Gm-Message-State: AGi0PubQ56k0p0kGKk/liQGavSMYSuXEm36hcOIGuEJeWZvysbgMDplv s4Petibke23/KHIeC+EP7m08iq1K X-Google-Smtp-Source: APiQypKEAWcFABnwVKwqqhNUcLva93ep/AXXXoOrjjM0pcW2KCxgja0/LwwTTW5vAr7Bc2JF0DTT+g== X-Received: by 2002:a62:15d8:: with SMTP id 207mr8090274pfv.140.1588419460878; Sat, 02 May 2020 04:37:40 -0700 (PDT) Received: from bobo.ozlabs.ibm.com ([203.220.177.17]) by smtp.gmail.com with ESMTPSA id e135sm4367513pfh.37.2020.05.02.04.37.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 04:37:40 -0700 (PDT) From: Nicholas Piggin To: skiboot@lists.ozlabs.org Date: Sat, 2 May 2020 21:36:44 +1000 Message-Id: <20200502113649.176329-5-npiggin@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20200502113649.176329-1-npiggin@gmail.com> References: <20200502113649.176329-1-npiggin@gmail.com> MIME-Version: 1.0 Subject: [Skiboot] [RFC PATCH 4/9] opal: provide a "raw" console mode X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This allows the console drivers to be switched to a "raw" mode (maybe OS mode is a better name) which exposes the console hardware driver directly via the OPAL APIs, and does not allow OPAL to use it. This is not used until a subsequent patch, but it allows the OS to own the console rather than be arbitrated via the OPAL console layer. The OS then provides console services to OPAL. This can not really be achieved by advertising the UART to the OS in the DT at boot, because there is no way to coordinate the switch to the OS owning the console. Signed-off-by: Nicholas Piggin --- core/console.c | 83 +++++++++++++++++++++++++++++++++------ hw/lpc-uart.c | 83 +++++++++++++++++++++++++++++++++++++++ include/console.h | 3 ++ platforms/mambo/console.c | 60 ++++++++++++++++++++++++++++ 4 files changed, 217 insertions(+), 12 deletions(-) diff --git a/core/console.c b/core/console.c index 2a1509025..336dda7a1 100644 --- a/core/console.c +++ b/core/console.c @@ -19,12 +19,15 @@ static char *con_buf = (char *)INMEM_CON_START; static size_t con_in; static size_t con_out; static bool con_wrapped; +static bool con_raw; /* Internal console driver ops */ static struct con_ops *con_driver; /* External (OPAL) console driver ops */ static struct opal_con_ops *opal_con_driver = &dummy_opal_con; +static struct opal_con_ops *opal_raw_con_driver = NULL; +static struct opal_con_ops *opal_cooked_con_driver = &dummy_opal_con; static struct lock con_lock = LOCK_UNLOCKED; @@ -167,6 +170,9 @@ bool flush_console(void) { bool ret; + if (!con_driver) + return false; + lock(&con_lock); ret = __flush_console(true, true); unlock(&con_lock); @@ -232,9 +238,12 @@ ssize_t console_write(bool flush_to_drivers, const void *buf, size_t count) /* We use recursive locking here as we can get called * from fairly deep debug path */ - bool need_unlock = lock_recursive(&con_lock); + bool need_unlock; const char *cbuf = buf; + assert(!con_raw); + need_unlock = lock_recursive(&con_lock); + while(count--) { char c = *(cbuf++); if (c == '\n') @@ -260,6 +269,8 @@ ssize_t read(int fd __unused, void *buf, size_t req_count) bool need_unlock = lock_recursive(&con_lock); size_t count = 0; + assert(!con_raw); + if (con_driver && con_driver->read) count = con_driver->read(buf, req_count); if (!count) @@ -272,17 +283,22 @@ ssize_t read(int fd __unused, void *buf, size_t req_count) /* Helper function to perform a full synchronous flush */ void console_complete_flush(void) { - /* - * Using term 0 here is a dumb hack that works because the UART - * only has term 0 and the FSP doesn't have an explicit flush method. - */ - int64_t ret = opal_con_driver->flush(0); - - if (ret == OPAL_UNSUPPORTED || ret == OPAL_PARAMETER) - return; - - while (ret != OPAL_SUCCESS) { - ret = opal_con_driver->flush(0); + if (con_raw) { + opal_raw_con_driver->flush(0); + } else { + /* + * Using term 0 here is a dumb hack that works because the UART + * only has term 0 and the FSP doesn't have an explicit flush + * method. + */ + int64_t ret = opal_con_driver->flush(0); + + if (ret == OPAL_UNSUPPORTED || ret == OPAL_PARAMETER) + return; + + while (ret != OPAL_SUCCESS) { + ret = opal_con_driver->flush(0); + } } } @@ -311,9 +327,51 @@ static bool opal_cons_init = false; void set_opal_console(struct opal_con_ops *driver) { assert(!opal_cons_init); + opal_cooked_con_driver = driver; opal_con_driver = driver; } +void set_opal_raw_console(struct opal_con_ops *driver) +{ + assert(!opal_cons_init); + opal_raw_con_driver = driver; +} + +void set_opal_console_to_raw(void) +{ + if (!opal_raw_con_driver) + return; + + console_complete_flush(); + + opal_con_driver = opal_raw_con_driver; + if (opal_cons_init) { + opal_register(OPAL_CONSOLE_READ, opal_con_driver->read, 3); + opal_register(OPAL_CONSOLE_WRITE, opal_con_driver->write, 3); + opal_register(OPAL_CONSOLE_FLUSH, opal_con_driver->flush, 1); + opal_register(OPAL_CONSOLE_WRITE_BUFFER_SPACE, + opal_con_driver->space, 2); + } + + opal_con_driver = NULL; + con_raw = true; +} + +void set_opal_console_to_cooked(void) +{ + console_complete_flush(); + + opal_con_driver = opal_cooked_con_driver; + if (opal_cons_init) { + opal_register(OPAL_CONSOLE_READ, opal_con_driver->read, 3); + opal_register(OPAL_CONSOLE_WRITE, opal_con_driver->write, 3); + opal_register(OPAL_CONSOLE_FLUSH, opal_con_driver->flush, 1); + opal_register(OPAL_CONSOLE_WRITE_BUFFER_SPACE, + opal_con_driver->space, 2); + } + con_raw = false; +} + void init_opal_console(void) { assert(!opal_cons_init); @@ -324,6 +382,7 @@ void init_opal_console(void) opal_con_driver->name); opal_con_driver = &dummy_opal_con; + opal_cooked_con_driver = &dummy_opal_con; } prlog(PR_INFO, "OPAL: Using %s\n", opal_con_driver->name); diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index 898fc4b1c..549aad49f 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -183,6 +183,89 @@ static struct con_ops uart_con_driver = { * OPAL console driver */ +static int64_t uart_opal_raw_write(int64_t term_number, __be64 *__length, + const uint8_t *buffer) +{ + size_t written = 0, len = be64_to_cpu(*__length); + + if (term_number != 0) + return OPAL_PARAMETER; + + if (!lpc_ok() && !mmio_uart_base) + return OPAL_HARDWARE; + + while (written < len) { + if (tx_room == 0) { + uart_check_tx_room(); + if (tx_room == 0) + break; + } + uart_write(REG_THR, buffer[written++]); + tx_room--; + } + + *__length = cpu_to_be64(written); + + return OPAL_SUCCESS; +} + +static int64_t uart_opal_raw_write_buffer_space(int64_t term_number, + __be64 *__length) +{ + if (term_number != 0) + return OPAL_PARAMETER; + + uart_check_tx_room(); + *__length = cpu_to_be64(tx_room); + + return OPAL_SUCCESS; +} + +static int64_t uart_opal_raw_read(int64_t term_number, __be64 *__length, + uint8_t *buffer) +{ + size_t req_count = be64_to_cpu(*__length), read_cnt = 0; + uint8_t lsr = 0; + + if (term_number != 0) + return OPAL_PARAMETER; + + while (req_count) { + lsr = uart_read(REG_LSR); + if ((lsr & LSR_DR) == 0) + break; + buffer[read_cnt++] = uart_read(REG_RBR); + req_count--; + } + + *__length = cpu_to_be64(read_cnt); + return OPAL_SUCCESS; +} + +static int64_t uart_opal_raw_flush(int64_t term_number) +{ + if (term_number != 0) + return OPAL_PARAMETER; + + while (tx_room != 16) + uart_check_tx_room(); + + return OPAL_SUCCESS; +} + +static void uart_init_opal_raw_console(void) +{ +} + +struct opal_con_ops uart_opal_raw_con = { + .name = "OPAL UART raw console", + .init = uart_init_opal_raw_console, + .read = uart_opal_raw_read, + .write = uart_opal_raw_write, + .space = uart_opal_raw_write_buffer_space, + .flush = uart_opal_raw_flush, +}; + /* * We implement a simple buffer to buffer input data as some bugs in * Linux make it fail to read fast enough after we get an interrupt. diff --git a/include/console.h b/include/console.h index 02fc7a4b6..54ddd6718 100644 --- a/include/console.h +++ b/include/console.h @@ -65,6 +65,9 @@ extern bool flush_console(void); extern void set_console(struct con_ops *driver); extern void set_opal_console(struct opal_con_ops *driver); +extern void set_opal_raw_console(struct opal_con_ops *driver); +extern void set_opal_console_to_raw(void); +extern void set_opal_console_to_cooked(void); extern void init_opal_console(void); extern void console_complete_flush(void); diff --git a/platforms/mambo/console.c b/platforms/mambo/console.c index 6d5b20b56..f2a0ad675 100644 --- a/platforms/mambo/console.c +++ b/platforms/mambo/console.c @@ -3,6 +3,7 @@ #include #include +#include #include "mambo.h" @@ -48,10 +49,69 @@ static struct con_ops mambo_con_driver = { .write = mambo_console_write, }; +static int64_t mambo_opal_raw_write(int64_t term_number, __be64 *__length, + const uint8_t *buffer) +{ + size_t len = be64_to_cpu(*__length); + + if (term_number != 0) + return OPAL_PARAMETER; + + mambo_console_write(buffer, len); + + return OPAL_SUCCESS; +} + +static int64_t mambo_opal_raw_write_buffer_space(int64_t term_number, + __be64 *__length) +{ + if (term_number != 0) + return OPAL_PARAMETER; + + *__length = cpu_to_be64(256); + + return OPAL_SUCCESS; +} + +static int64_t mambo_opal_raw_read(int64_t term_number, __be64 *__length, + uint8_t *buffer) +{ + size_t req_count = be64_to_cpu(*__length), read_cnt = 0; + + if (term_number != 0) + return OPAL_PARAMETER; + + read_cnt = mambo_console_read(buffer, req_count); + *__length = cpu_to_be64(read_cnt); + + return OPAL_SUCCESS; +} + +static int64_t mambo_opal_raw_flush(int64_t term_number) +{ + if (term_number != 0) + return OPAL_PARAMETER; + return OPAL_SUCCESS; +} + +static void mambo_init_opal_raw_console(void) +{ +} + +struct opal_con_ops mambo_opal_raw_con = { + .name = "OPAL Mambo raw console", + .init = mambo_init_opal_raw_console, + .read = mambo_opal_raw_read, + .write = mambo_opal_raw_write, + .space = mambo_opal_raw_write_buffer_space, + .flush = mambo_opal_raw_flush, +}; + void enable_mambo_console(void) { prlog(PR_NOTICE, "Enabling Mambo console\n"); set_console(&mambo_con_driver); + set_opal_raw_console(&mambo_opal_raw_con); } /*