From patchwork Sat May 12 00:05:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Calvin Lee X-Patchwork-Id: 912282 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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.b="kId/4EJb"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40jS3W3ltxz9s15 for ; Sat, 12 May 2018 10:08:23 +1000 (AEST) Received: from localhost ([::1]:56904 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fHI5F-00055s-6P for incoming@patchwork.ozlabs.org; Fri, 11 May 2018 20:08:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55977) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fHI2v-0007QT-UH for qemu-devel@nongnu.org; Fri, 11 May 2018 20:05:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fHI2u-0007bS-Kz for qemu-devel@nongnu.org; Fri, 11 May 2018 20:05:57 -0400 Received: from mail-it0-x244.google.com ([2607:f8b0:4001:c0b::244]:38242) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fHI2u-0007bI-F5 for qemu-devel@nongnu.org; Fri, 11 May 2018 20:05:56 -0400 Received: by mail-it0-x244.google.com with SMTP id q4-v6so4223298ite.3 for ; Fri, 11 May 2018 17:05:56 -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; bh=mgSfp7uLwA4Q7oGRUayIeqkqgKkFjPIkFv/FqtNlC5U=; b=kId/4EJbaDafrvT19WGqN94I+WAMvu8/6X9YlJR+k1yeAWgkgfUPrq5vNKfmybFM0l RJ39vu3t7hzZZWcFDs4aICKjUvWoJsYVxl0Gr89KNMti8YH0e7nD+uGbskjtCzCn54uM 6K/fQRKwZ7+Fq9gd6vQ+7vaMJYjGZ2nQ4SuW7FDn5E3fCm1acfGPdNMu8NMECg9jfIYI cpMZyeJrNp+p4q7soXGdSmxO/0vOtFf0gaiYn/jbGJ3We06RmExby4iCz+8Tv8Z9y6Y6 qCmx2BNv9boxAH4hTC3nrI3YWnvVIiG0sK+u18QY17ioP5fKgBUh2R/VjqqpyMqYppvS W7cg== 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; bh=mgSfp7uLwA4Q7oGRUayIeqkqgKkFjPIkFv/FqtNlC5U=; b=MpPv5Q7euWGfyn/L2ex4oDocQncz0iHDdi2jP1Ozp0F0+6u0Qr6CtaArnLL30k/MI/ VC2mNPnBuVSbHHbZnsX7nz8H3B7VCphZh+cfiW2N8LWVr52vYn+zZPrfRJknEpl3z004 MMhvAfid+hJ1Iis7/ChyyHAAIcucUzO/ejKGjvVURYzrfuEDrOviW/ksKqgzMf0ANEzW joB/Aro88Zc4sYfCimA1NjFCsW2CDfyJFsEtMyqsOAAdddDSzSWraXvC7upFJQDNsuFz 6LO34MY02DDbBYZ0G3mddb2u0kJYkpTB7aF6ViJBsjOTuoAZVFL53hwQfeMcXrUreBAx ol+g== X-Gm-Message-State: ALKqPwfbzqjI3R3Z4p3cQQYS0KRPhEvh+oJl2eEd97JBwg0dG40a2Nmk eOY7cPTD/0mq7Rj6H4hLqTIxfjXS X-Google-Smtp-Source: AB8JxZrDIQ9U696ITc0+piZvahG/nOawiSzR3Cj3UsDjhzPn3LDaPVPKwF8P3pOAJlxSRgzBW2YeCg== X-Received: by 2002:a24:9d95:: with SMTP id f143-v6mr5879951itd.150.1526083555705; Fri, 11 May 2018 17:05:55 -0700 (PDT) Received: from localhost.localdomain (c-24-11-27-195.hsd1.ut.comcast.net. [24.11.27.195]) by smtp.gmail.com with ESMTPSA id v20-v6sm1965098iog.59.2018.05.11.17.05.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 11 May 2018 17:05:55 -0700 (PDT) From: Calvin Lee To: qemu-devel@nongnu.org Date: Fri, 11 May 2018 18:05:45 -0600 Message-Id: <20180512000545.966-3-cyrus296@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180512000545.966-1-cyrus296@gmail.com> References: <20180512000545.966-1-cyrus296@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4001:c0b::244 Subject: [Qemu-devel] [PATCH RFC v2 2/2] PC Chipset: Send serial bytes at correct rate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Calvin Lee , pbonzini@redhat.com, dgilbert@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This fixes bug in QEMU such that UART bytes would be sent immediatly after being put in the THR regardless of the UART frequency (and divisor). Now they will be sent at the appropriate rate. Signed-off-by: Calvin Lee --- I am not sure about VM migration here. I want to move a struct field from one VMStateDescription to a new one. I did this by bumping the version number on the old VMStateDescription, and kept the field as `_TEST`. If this is incorrect please let me know. hw/char/serial.c | 51 +++++++++++++++++++++++++++++++++++----- include/hw/char/serial.h | 2 ++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/hw/char/serial.c b/hw/char/serial.c index 4159a46a2f..542d949ccd 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -359,9 +359,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->lsr &= ~UART_LSR_THRE; s->lsr &= ~UART_LSR_TEMT; serial_update_irq(s); - if (s->tsr_retry == 0) { - serial_xmit(s); - } + timer_mod(s->xmit_timeout_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time); } break; case 1: @@ -586,6 +585,15 @@ static void serial_receive_break(SerialState *s) serial_update_irq(s); } +/* There is data to be sent in xmit_fifo or the thr */ +static void xmit_timeout_int(void *opaque) +{ + SerialState *s = opaque; + if (s->tsr_retry == 0) { + serial_xmit(s); + } +} + /* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */ static void fifo_timeout_int (void *opaque) { SerialState *s = opaque; @@ -723,15 +731,20 @@ static bool serial_tsr_needed(void *opaque) SerialState *s = (SerialState *)opaque; return s->tsr_retry != 0; } +static bool serial_tsr_thr_exists(void *opaque, int version_id) +{ + return version_id < 2; +} static const VMStateDescription vmstate_serial_tsr = { .name = "serial/tsr", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .needed = serial_tsr_needed, .fields = (VMStateField[]) { VMSTATE_UINT32(tsr_retry, SerialState), - VMSTATE_UINT8(thr, SerialState), + /* Moved to `xmit_timeout_timer` */ + VMSTATE_UINT8_TEST(thr, SerialState, serial_tsr_thr_exists), VMSTATE_UINT8(tsr, SerialState), VMSTATE_END_OF_LIST() } @@ -772,6 +785,24 @@ static const VMStateDescription vmstate_serial_xmit_fifo = { } }; +static bool serial_xmit_timeout_timer_needed(void *opaque) +{ + SerialState *s = (SerialState *)opaque; + return timer_pending(s->xmit_timeout_timer); +} + +static const VMStateDescription vmstate_serial_xmit_timeout_timer = { + .name = "serial/xmit_timeout_timer", + .version_id = 1, + .minimum_version_id = 1, + .needed = serial_xmit_timeout_timer_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8(thr, SerialState), + VMSTATE_TIMER_PTR(xmit_timeout_timer, SerialState), + VMSTATE_END_OF_LIST() + } +}; + static bool serial_fifo_timeout_timer_needed(void *opaque) { SerialState *s = (SerialState *)opaque; @@ -849,6 +880,7 @@ const VMStateDescription vmstate_serial = { &vmstate_serial_tsr, &vmstate_serial_recv_fifo, &vmstate_serial_xmit_fifo, + &vmstate_serial_xmit_timeout_timer, &vmstate_serial_fifo_timeout_timer, &vmstate_serial_timeout_ipending, &vmstate_serial_poll, @@ -880,6 +912,7 @@ static void serial_reset(void *opaque) s->poll_msl = 0; s->timeout_ipending = 0; + timer_del(s->xmit_timeout_timer); timer_del(s->fifo_timeout_timer); timer_del(s->modem_status_poll); @@ -928,7 +961,10 @@ void serial_realize_core(SerialState *s, Error **errp) { s->modem_status_poll = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) serial_update_msl, s); - s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s); + s->xmit_timeout_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) xmit_timeout_int, s); + s->fifo_timeout_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s); qemu_register_reset(serial_reset, s); qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1, @@ -945,6 +981,9 @@ void serial_exit_core(SerialState *s) timer_del(s->modem_status_poll); timer_free(s->modem_status_poll); + timer_del(s->xmit_timeout_timer); + timer_free(s->xmit_timeout_timer); + timer_del(s->fifo_timeout_timer); timer_free(s->fifo_timeout_timer); diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 0acfbbc382..09aece90fb 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -65,6 +65,8 @@ struct SerialState { /* Time when the last byte was successfully sent out of the tsr */ uint64_t last_xmit_ts; Fifo8 recv_fifo; + /* Time to read the next byte from the thr */ + QEMUTimer *xmit_timeout_timer; Fifo8 xmit_fifo; /* Interrupt trigger level for recv_fifo */ uint8_t recv_fifo_itl;