qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Jean-Christophe DUBOIS <jcd@tribudubois.net>
Cc: Peter Chubb <peter.chubb@nicta.com.au>,
	qemu-devel@nongnu.org, qemu-stable@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 for-2.4] i.MX: Fix UART driver to work with unitialized "chardev" device
Date: Mon, 03 Aug 2015 08:59:31 +0200	[thread overview]
Message-ID: <87fv40luwc.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <55BCF27F.50901@tribudubois.net> (Jean-Christophe DUBOIS's message of "Sat, 01 Aug 2015 18:23:27 +0200")

Jean-Christophe DUBOIS <jcd@tribudubois.net> writes:

> Le 01/08/2015 09:57, Markus Armbruster a écrit :
>> Jean-Christophe Dubois <jcd@tribudubois.net> writes:
>>
>>> The "chardev" property initialization might have failed (for example because
>>> there are not enough chardevs provided by QEMU).
>>>
>>> The serial device emulator need to be able to work with an uninitialized
>>> (NULL) chardev device pointer.
>>>
>>> This patch add some missing tests on the chr pointer value before
>>> using it.
>>>
>>> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
>>> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>>> ---
>>>
>>> Changes since V1:
>>>   * Grammar sweep on patch description
>>>   * Added Peter's "Reviewed-by"
>>>
>>>   hw/char/imx_serial.c | 8 ++++++--
>>>   1 file changed, 6 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
>>> index f3fbc77..383e50c 100644
>>> --- a/hw/char/imx_serial.c
>>> +++ b/hw/char/imx_serial.c
>>> @@ -203,7 +203,9 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
>>>               s->usr2 &= ~USR2_RDR;
>>>               s->uts1 |= UTS1_RXEMPTY;
>>>               imx_update(s);
>>> -            qemu_chr_accept_input(s->chr);
>>> +            if (s->chr) {
>>> +                qemu_chr_accept_input(s->chr);
>>> +            }
>>>           }
>>>           return c;
>>>   @@ -290,7 +292,9 @@ static void imx_serial_write(void *opaque,
>>> hwaddr offset,
>>>           }
>>>           if (value & UCR2_RXEN) {
>>>               if (!(s->ucr2 & UCR2_RXEN)) {
>>> -                qemu_chr_accept_input(s->chr);
>>> +                if (s->chr) {
>>> +                    qemu_chr_accept_input(s->chr);
>>> +                }
>>>               }
>>>           }
>>>           s->ucr2 = value & 0xffff;
>> I'm afraid this approach is inconsistent with existing practice, namely
>> that if a device requires a backend, and the backend is missing, the
>> realize() method fails.
>>
>> Example: serial_realize_core() in hw/char/serial.c, used by
>> serial_pci_realize() for device "pci-serial", multi_serial_pci_realize()
>> for devices "pci-serial-2x" and "pci-serial-4x", serial_isa_realizefn()
>> for device "isa-serial".  The latter has a bug: when the backend is
>> missing, realize fails, but the actual device is created anyway.
>>
>> Example: virtio_blk_device_realize() in hw/block/virtio-blk.c.
>>
>> Note that NICs don't require a backend.  I guess they behave like "no
>> carrier" then.  net_check_clients() warns "has no peer", however.
>>
>> Character devices without a backend could be changed not to require a
>> backend, and behave as if they had a null backend then.  Whether that's
>> a good user interface needs some thought.  Regardless, it should be
>> consistent: either all character devices do, or none.
>>
>> If you can quote another character device that already does it like your
>> patch, then your patch doesn't create a new inconsistency, it merely
>> adds to an existing one.  Acceptable.
>>
>> If you can't, you should either make your device behave like all the
>> others, or make all the others behave like yours.
> As of today it seems to me that most serial emulators (pl011.c,
> cadence_uart.c, digic-uart.c, milkymist-uart.c, ...) are calling
> qemu_char_get_next_serial() (which is a crude method that should be
> replaced with chardev prop)

Yes.

>                             to retreive their backend device. If this
> call fails (returning NULL because MAX_SERIAL_PORTS serial devices are
> already initialized/used),

Actually, it fails when serial_hds[] has no more backends.  By default,
it has one, and with -nodefaults, it has none.  You can add more with
-serial, up to MAX_SERIAL_PORTS.

>                            then qemu_chr_add_handlers() is not called
> but the realize function does not fail as very few serial drivers are
> calling error_setg(). So in effect the serial devices are running
> without backend.

Okay, the devices still using qemu_char_get_next_serial() appear to do
it like your patch.  Therefore, your patch doesn't create a new
inconsistency.

> This is the case for the existing i.MX serial driver. So without this
> patch qemu would crash (on a NULL pointer) when the 5th ( >
> MAX_SERIAL_PORT) serial device is initialized by the guest operating
> system.

I guess it crashes for the other serial devices as well when the backend
is missing.

> if the i.MX serial driver was using error_setg() then qemu would fail
> to initialize (which certainly prevent the future crash initiated by
> the guest OS). For now the i.MX serial driver does like most other
> serial drivers and just ignore the fact that there is no backend in
> the realize() call. But it does not protect itself everywhere when the
> backend is used as a NULL pointer.
>
> Now some SOCs (like i.MX25) have more than MAX_SERIAL_PORTS (which for
> now is set to 4). For example, the linux "device tree" file is
> advertising the 5 serial devices of the i.MX25 SOC.
>
> So what is the solution:
>  * Make sure that no more than MAX_SERIAL_PORTS serial devices are
> realized() and expect that the guest OS will cope with the missing
> devices (that should be present on the SOC)
>  * Realize all devices (> MAX_SERIAL_PORTS) but allow some to have no
> backend.

* Fix the devices to use device properties instead of serial_hd[], with
  backward-compatibility code to create devices for serial_hd[], like
  serial_hds_init() does.  MAX_SERIAL_PORTS is pretty much irrelevant
  then.

Regarding the question what a character device model can do when it
misses a backend:

* It can behave like a null backend.  Unlike the real null backend, this
  one is done by sprinking device model code with if (!s->chr)
  conditionals.  Ugh.

* It can fail realize().  Something (user or system) must configure
  backends for all mandatory onboard serial devices, or else QEMU won't
  start.

  Example: PC boards have four optional onboard devices.
  pc_basic_device_init() calls serial_hds_init(), which creates the i-th
  device iff serial_hds[i].  No device is created without a backend.

  Example: A hypothetical board with five mandatory devices.  Board code
  should set the backend to serial_hds[i] when that's non-null, or else
  set it to a null character device.  Again, no device is created
  without a backend.

I'm not objecting to either solution (I dislike the extra conditionals,
though).  I'm objecting to inconsistency, i.e. having *both* solutions.

Since the inconsistency already exists, my objection does *not* extend
to your patch.

  reply	other threads:[~2015-08-03  6:59 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-31 11:34 [Qemu-devel] [PATCH v2 for-2.4] i.MX: Fix UART driver to work with unitialized "chardev" device Jean-Christophe Dubois
2015-08-01  7:57 ` Markus Armbruster
2015-08-01 16:23   ` Jean-Christophe DUBOIS
2015-08-03  6:59     ` Markus Armbruster [this message]
2015-08-11 11:00 ` Peter Maydell

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=87fv40luwc.fsf@blackfin.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=jcd@tribudubois.net \
    --cc=peter.chubb@nicta.com.au \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@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).