From: Laszlo Ersek <lersek@redhat.com>
To: Star Zeng <star.zeng@intel.com>, edk2-devel@lists.01.org
Cc: Ruiyu Ni <ruiyu.ni@intel.com>, Heyi Guo <heyi.guo@linaro.org>,
Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Brijesh Singh <brijesh.singh@amd.com>
Subject: Re: [PATCH] MdeModulePkg SerialDxe: Process timeout consistently in SerialRead
Date: Wed, 16 Aug 2017 01:30:30 +0200 [thread overview]
Message-ID: <b748580c-cb51-32c9-acf9-780841ef15da@redhat.com> (raw)
In-Reply-To: <1501835363-61956-1-git-send-email-star.zeng@intel.com>
Hi Star,
On 08/04/17 10:29, Star Zeng wrote:
> https://lists.01.org/pipermail/edk2-devel/2017-July/012385.html
> reported the timeout processing in SerialRead is not consistent.
>
> Since SerialPortPoll only checks the status of serial port and
> returns immediately, and SerialPortRead does not really implement
> a time out mechanism and will always wait for enough input,
> it will cause below results:
> 1. If there is no serial input at all, this interface will return
> timeout immediately without any waiting;
> 2. If there is A characters in serial port FIFO, and caller requires
> A+1 characters, it will wait until a new input is coming and timeout
> will not really occur.
>
> This patch is to update SerialRead() to check SerialPortPoll() and
> read data through SerialPortRead() one byte by one byte, and check
> timeout against mSerialIoMode.Timeout if no input.
>
> Cc: Heyi Guo <heyi.guo@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> ---
> MdeModulePkg/Universal/SerialDxe/SerialIo.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/MdeModulePkg/Universal/SerialDxe/SerialIo.c b/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> index d2383e56dd8f..43d33dba0c2a 100644
> --- a/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> +++ b/MdeModulePkg/Universal/SerialDxe/SerialIo.c
> @@ -465,11 +465,25 @@ SerialRead (
> )
> {
> UINTN Count;
> + UINTN TimeOut;
>
> Count = 0;
>
> - if (SerialPortPoll ()) {
> - Count = SerialPortRead (Buffer, *BufferSize);
> + while (Count < *BufferSize) {
> + TimeOut = 0;
> + while (TimeOut < mSerialIoMode.Timeout) {
> + if (SerialPortPoll ()) {
> + break;
> + }
> + gBS->Stall (10);
> + TimeOut += 10;
> + }
> + if (TimeOut >= mSerialIoMode.Timeout) {
> + break;
> + }
> + SerialPortRead (Buffer, 1);
> + Count++;
> + Buffer = (VOID *) ((UINT8 *) Buffer + 1);
> }
>
> if (Count != *BufferSize) {
>
This patch breaks the ArmVirtQemu platform's boot process -- it seems to
fall into an infinite loop. I guess the above loop(s) never complete?
If I revert this patch on top of current master (af0364f01e8c,
"Nt32/PlatformBootManagerLib: Enable STD_ERROR on all consoles",
2017-08-14), then ArmVirtQemu boots fine.
I found this commit with bisection:
> 4cf3f37c87ba1f9d58072444bd735e40e4779e70 is the first bad commit
> commit 4cf3f37c87ba1f9d58072444bd735e40e4779e70
> Author: Star Zeng <star.zeng@intel.com>
> Date: Tue Jul 18 16:32:16 2017 +0800
>
> MdeModulePkg SerialDxe: Process timeout consistently in SerialRead
>
> https://lists.01.org/pipermail/edk2-devel/2017-July/012385.html
> reported the timeout processing in SerialRead is not consistent.
>
> Since SerialPortPoll only checks the status of serial port and
> returns immediately, and SerialPortRead does not really implement
> a time out mechanism and will always wait for enough input,
> it will cause below results:
> 1. If there is no serial input at all, this interface will return
> timeout immediately without any waiting;
> 2. If there is A characters in serial port FIFO, and caller requires
> A+1 characters, it will wait until a new input is coming and timeout
> will not really occur.
>
> This patch is to update SerialRead() to check SerialPortPoll() and
> read data through SerialPortRead() one byte by one byte, and check
> timeout against mSerialIoMode.Timeout if no input.
>
> Cc: Heyi Guo <heyi.guo@linaro.org>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Star Zeng <star.zeng@intel.com>
> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
>
> :040000 040000 aaa8b75d378ec613b828db938c36a16723583906 d034044918d7f5b8d30783e0a9eccdf3cf21e5c5 M MdeModulePkg
Bisection log:
> git bisect start
> # bad: [af0364f01e8cac95afad01437f13beef90f6640b] Nt32/PlatformBootManagerLib: Enable STD_ERROR on all consoles
> git bisect bad af0364f01e8cac95afad01437f13beef90f6640b
> # good: [c325e41585e374d40fb36b434e61a1ab0fca5b1c] MdeModulePkg: Fix coding style issues
> git bisect good c325e41585e374d40fb36b434e61a1ab0fca5b1c
> # good: [636cda51903b4b28e1c9b099c4f22a84e61b09da] OvmfPkg/OvmfPkg.fdf.inc: extract VARS_LIVE_SIZE and VARS_SPARE_SIZE macros
> git bisect good 636cda51903b4b28e1c9b099c4f22a84e61b09da
> # good: [997b2c543751cb4a3473270c1a7016ade311f01b] BaseTools/GenCrc32: Fix a bug to hand empty file for decode
> git bisect good 997b2c543751cb4a3473270c1a7016ade311f01b
> # good: [f1658838c267723139711c0b15d98a74980ae4c5] OvmfPkg/IoMmuDxe: abort harder on memory encryption mask failures
> git bisect good f1658838c267723139711c0b15d98a74980ae4c5
> # bad: [9458afa33728e64049d465f052b2c5c3ca3e881c] IntelFrameworkModulePkg: Fix Xcode 9 Beta treating 32-bit left shift as undefined
> git bisect bad 9458afa33728e64049d465f052b2c5c3ca3e881c
> # good: [6e414300b5f19d3045a0d21ad90ac2fe965478a5] EmbeddedPkg/AndroidFastboot: split android boot header
> git bisect good 6e414300b5f19d3045a0d21ad90ac2fe965478a5
> # bad: [416d48f755518fd1d202b97be2e9944df6e8f0d4] ShellPkg/drivers: Show Image Name in non-SFO mode
> git bisect bad 416d48f755518fd1d202b97be2e9944df6e8f0d4
> # bad: [2913ebb2b550f50a14f105e26995dd095e627ba4] NetworkPkg/HttpBootDxe: Refine the coding style.
> git bisect bad 2913ebb2b550f50a14f105e26995dd095e627ba4
> # bad: [9e2a8e928995c3b1bb664b73fd59785055c6b5f6] OvmfPkg/AcpiPlatformDxe: short-circuit the transfer of an empty S3_CONTEXT
> git bisect bad 9e2a8e928995c3b1bb664b73fd59785055c6b5f6
> # bad: [4cf3f37c87ba1f9d58072444bd735e40e4779e70] MdeModulePkg SerialDxe: Process timeout consistently in SerialRead
> git bisect bad 4cf3f37c87ba1f9d58072444bd735e40e4779e70
> # first bad commit: [4cf3f37c87ba1f9d58072444bd735e40e4779e70] MdeModulePkg SerialDxe: Process timeout consistently in SerialRead
In retrospect, I see that you asked me for feedback in the original
discussion, at the following URL:
https://lists.01.org/pipermail/edk2-devel/2017-July/012406.html
Unfortunately, this was on July 18th, and I was on vacation then. (I
think I configured my email account to send an automated out-of-office
reply.)
Looking at the patch now, one idea I have is to keep the time running
across all bytes read; that is, use mSerialIoMode.Timeout as a global
timeout for the entire SerialRead() call.
Unfortunately, the UEFI-2.7 spec defines the "SERIAL_IO_MODE.Timeout"
field, and the Timeout parameter of
EFI_SERIAL_IO_PROTOCOL.SetAttributes(), inconsistently with each other.
First it says (about the field):
Timeout If applicable, the number of microseconds to wait before
timing out a Read or Write operation.
(This is compatible with my idea.)
But then it says (in the general description, and about the
SetAttributes() parameter):
The default attributes for all UART-style serial device interfaces
are: [...] a 1,000,000 microsecond timeout *per character* [...]
Timeout The requested time out *for a single character* in
microseconds. This timeout applies to both the transmit and
receive side of the interface. A Timeout value of 0 will use
the device's default time out value.
(Emphases mine.)
... I added some debug messages to the loops, and the first invocation
of the function seems to hang with the following parameters:
> SerialRead: BufferSize=1 mSerialIoMode.Timeout=1000000
That is, the caller wants to read a single character (which is not
arriving). The timeout is the default 1 second. However, the wait takes
much-much longer than 1 second (it appears to be infinite). It seems
that gBS->Stall(10) takes much longer than 10 microseconds. According to
the UEFI spec,
The Stall() function stalls execution on the processor for at least
the requested number of microseconds. [...]
So Stall() is allowed to wait longer (possibly a lot longer) -- I guess
it depends on some timer's resolution.
I have another idea related to this -- let me research it a bit later. I
might post some patches.
Thanks
Laszlo
next prev parent reply other threads:[~2017-08-15 23:28 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-04 8:29 [PATCH] MdeModulePkg SerialDxe: Process timeout consistently in SerialRead Star Zeng
2017-08-04 9:12 ` Ni, Ruiyu
2017-08-04 9:25 ` Zeng, Star
2017-08-04 9:53 ` Ni, Ruiyu
2017-08-15 23:30 ` Laszlo Ersek [this message]
2017-08-15 23:59 ` Kinney, Michael D
2017-08-16 2:02 ` Laszlo Ersek
2017-08-16 2:22 ` Zeng, Star
2017-08-16 10:21 ` Laszlo Ersek
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-list 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=b748580c-cb51-32c9-acf9-780841ef15da@redhat.com \
--to=devel@edk2.groups.io \
/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