From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Calvin Lee <cyrus296@gmail.com>
Cc: qemu-devel@nongnu.org, mst@redhat.com, pbonzini@redhat.com
Subject: Re: [Qemu-devel] [PATCH RFC v2 2/2] PC Chipset: Send serial bytes at correct rate
Date: Mon, 14 May 2018 20:13:07 +0100 [thread overview]
Message-ID: <20180514191306.GG2497@work-vm> (raw)
In-Reply-To: <20180512000545.966-3-cyrus296@gmail.com>
* Calvin Lee (cyrus296@gmail.com) wrote:
> 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 <cyrus296@gmail.com>
Hi Calvin,
I'll leave the details of the serial to Paolo, but for the migration
some comments below.
> ---
> 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),
So the question is, why move it? If I understand what you've got, then
it's the same flag with the same semantics - but moving it you break
migration compatibility - so unless you need to, just leave it where it
is.
I think it's probably better if you leave the version_id = 1, and
actually keep serial_tsr_thr_exists just for compatibility.
You just need to fill in a sane value so that if you migrate to
an older version it doesn't confuse the old one.
> 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);
> +}
> +
If you add a property/flag on the device, and check the property in that
_needed function, then we can make it so that we don't save that section
for older machine types.
Dave
> +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;
> --
> 2.17.0
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
next prev parent reply other threads:[~2018-05-14 19:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-12 0:05 [Qemu-devel] [PATCH RFC v2 0/2] Fix UART serial implementation Calvin Lee
2018-05-12 0:05 ` [Qemu-devel] [PATCH RFC v2 1/2] PC Chipset: Improve serial divisor calculation Calvin Lee
2018-05-12 0:05 ` [Qemu-devel] [PATCH RFC v2 2/2] PC Chipset: Send serial bytes at correct rate Calvin Lee
2018-05-14 19:13 ` Dr. David Alan Gilbert [this message]
2018-05-14 19:39 ` Calvin Lee
2018-07-15 15:57 ` [Qemu-devel] [PATCH RFC v2 0/2] Fix UART serial implementation Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180514191306.GG2497@work-vm \
--to=dgilbert@redhat.com \
--cc=cyrus296@gmail.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).