From: "Michael S. Tsirkin" <mst@redhat.com>
To: Vladimir Murzin <vladimir.murzin@arm.com>
Cc: Laurent Vivier <lvivier@redhat.com>,
linux-kernel@vger.kernel.org, amit@kernel.org,
Herbert Xu <herbert@gondor.apana.org.au>,
Matt Mackall <mpm@selenic.com>,
virtualization@lists.linux-foundation.org,
Dmitriy Vyukov <dvyukov@google.com>,
rusty@rustcorp.com.au, akong@redhat.com,
Alexander Potapenko <glider@google.com>,
linux-crypto@vger.kernel.org,
Mauricio De Carvalho <Mauricio.DeCarvalho@arm.com>,
Kevin Brodsky <Kevin.Brodsky@arm.com>
Subject: Re: [PATCH v2 4/4] hwrng: virtio - always add a pending request
Date: Wed, 3 Aug 2022 07:39:57 -0400 [thread overview]
Message-ID: <20220803073243-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <2c1198c4-77aa-5cb8-6bb4-b974850651be@arm.com>
On Wed, Aug 03, 2022 at 09:57:35AM +0100, Vladimir Murzin wrote:
> On 8/2/22 13:49, Vladimir Murzin wrote:
> > Hi Laurent,
> >
> > On 10/28/21 11:11, Laurent Vivier wrote:
> >> If we ensure we have already some data available by enqueuing
> >> again the buffer once data are exhausted, we can return what we
> >> have without waiting for the device answer.
> >>
> >> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> >> ---
> >> drivers/char/hw_random/virtio-rng.c | 26 ++++++++++++--------------
> >> 1 file changed, 12 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
> >> index 8ba97cf4ca8f..0a7dde135db1 100644
> >> --- a/drivers/char/hw_random/virtio-rng.c
> >> +++ b/drivers/char/hw_random/virtio-rng.c
> >> @@ -20,7 +20,6 @@ struct virtrng_info {
> >> struct virtqueue *vq;
> >> char name[25];
> >> int index;
> >> - bool busy;
> >> bool hwrng_register_done;
> >> bool hwrng_removed;
> >> /* data transfer */
> >> @@ -44,16 +43,18 @@ static void random_recv_done(struct virtqueue *vq)
> >> return;
> >>
> >> vi->data_idx = 0;
> >> - vi->busy = false;
> >>
> >> complete(&vi->have_data);
> >> }
> >>
> >> -/* The host will fill any buffer we give it with sweet, sweet randomness. */
> >> -static void register_buffer(struct virtrng_info *vi)
> >> +static void request_entropy(struct virtrng_info *vi)
> >> {
> >> struct scatterlist sg;
> >>
> >> + reinit_completion(&vi->have_data);
> >> + vi->data_avail = 0;
> >> + vi->data_idx = 0;
> >> +
> >> sg_init_one(&sg, vi->data, sizeof(vi->data));
> >>
> >> /* There should always be room for one buffer. */
> >> @@ -69,6 +70,8 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf,
> >> memcpy(buf, vi->data + vi->data_idx, size);
> >> vi->data_idx += size;
> >> vi->data_avail -= size;
> >> + if (vi->data_avail == 0)
> >> + request_entropy(vi);
> >> return size;
> >> }
> >>
> >> @@ -98,13 +101,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
> >> * so either size is 0 or data_avail is 0
> >> */
> >> while (size != 0) {
> >> - /* data_avail is 0 */
> >> - if (!vi->busy) {
> >> - /* no pending request, ask for more */
> >> - vi->busy = true;
> >> - reinit_completion(&vi->have_data);
> >> - register_buffer(vi);
> >> - }
> >> + /* data_avail is 0 but a request is pending */
> >> ret = wait_for_completion_killable(&vi->have_data);
> >> if (ret < 0)
> >> return ret;
> >> @@ -126,8 +123,7 @@ static void virtio_cleanup(struct hwrng *rng)
> >> {
> >> struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
> >>
> >> - if (vi->busy)
> >> - complete(&vi->have_data);
> >> + complete(&vi->have_data);
> >> }
> >>
> >> static int probe_common(struct virtio_device *vdev)
> >> @@ -163,6 +159,9 @@ static int probe_common(struct virtio_device *vdev)
> >> goto err_find;
> >> }
> >>
> >> + /* we always have a pending entropy request */
> >> + request_entropy(vi);
> >> +
> >> return 0;
> >>
> >> err_find:
> >> @@ -181,7 +180,6 @@ static void remove_common(struct virtio_device *vdev)
> >> vi->data_idx = 0;
> >> complete(&vi->have_data);
> >> vdev->config->reset(vdev);
> >> - vi->busy = false;
> >> if (vi->hwrng_register_done)
> >> hwrng_unregister(&vi->hwrng);
> >> vdev->config->del_vqs(vdev);
> >
> > We observed that after this commit virtio-rng implementation in FVP doesn't
> > work
> >
> > INFO: bp.virtio_rng: Selected Random Generator Device: XORSHIFT DEVICE
> > INFO: bp.virtio_rng: Using seed value: 0x5674bba8
> > Error: FVP_Base_AEMvA: bp.virtio_rng: <vq0-requestq> Found invalid descriptor index
> > In file: (unknown):0
> > In process: FVP_Base_AEMvA.thread_p_12 @ 935500020 ns
> > Info: FVP_Base_AEMvA: bp.virtio_rng: Could not extract buffer
> >
> > while basic baremetal test works as expected
> >
> > INFO: bp.virtio_rng: Selected Random Generator Device: XORSHIFT DEVICE
> > INFO: bp.virtio_rng: Using seed value: 0x541c142e
> > Info: FVP_Base_AEMv8A: bp.virtio_rng: Generated Number: 0x4b098991ceb377e6
> > Info: FVP_Base_AEMv8A: bp.virtio_rng: Generated Number: 0xbdcbe3f765ba62f7
> >
> > We are trying to get an idea what is missing and where, yet none of us familiar
> > with the driver :(
> >
> > I'm looping Kevin who originally reported that and Mauricio who is looking form
> > the FVP side.
>
> With the following diff FVP works agin
>
> diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
> index a6f3a8a2ac..042503ad6c 100644
> --- a/drivers/char/hw_random/virtio-rng.c
> +++ b/drivers/char/hw_random/virtio-rng.c
> @@ -54,6 +54,7 @@ static void request_entropy(struct virtrng_info *vi)
> reinit_completion(&vi->have_data);
> vi->data_avail = 0;
> vi->data_idx = 0;
> + smp_mb();
>
> sg_init_one(&sg, vi->data, sizeof(vi->data));
>
>
> What do you reckon?
>
> Cheers
> Vladimir
Thanks for debugging this!
OK, interesting.
data_idx and data_avail are accessed from virtio_read.
Which as far as I can tell is invoked just with reading_mutex.
But, request_entropy is called from probe when device is registered
this time without locks
so it can trigger while another thread is calling virtio_read.
Second request_entropy is called from a callback random_recv_done
also without locks.
So it's great that smp_mb helped here but I suspect in fact we
need locking. Laurent?
--
MST
WARNING: multiple messages have this Message-ID (diff)
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Vladimir Murzin <vladimir.murzin@arm.com>
Cc: Laurent Vivier <lvivier@redhat.com>,
Mauricio De Carvalho <Mauricio.DeCarvalho@arm.com>,
Kevin Brodsky <Kevin.Brodsky@arm.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
amit@kernel.org, rusty@rustcorp.com.au,
linux-kernel@vger.kernel.org,
virtualization@lists.linux-foundation.org,
Alexander Potapenko <glider@google.com>,
linux-crypto@vger.kernel.org, Matt Mackall <mpm@selenic.com>,
akong@redhat.com, Dmitriy Vyukov <dvyukov@google.com>
Subject: Re: [PATCH v2 4/4] hwrng: virtio - always add a pending request
Date: Wed, 3 Aug 2022 07:39:57 -0400 [thread overview]
Message-ID: <20220803073243-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <2c1198c4-77aa-5cb8-6bb4-b974850651be@arm.com>
On Wed, Aug 03, 2022 at 09:57:35AM +0100, Vladimir Murzin wrote:
> On 8/2/22 13:49, Vladimir Murzin wrote:
> > Hi Laurent,
> >
> > On 10/28/21 11:11, Laurent Vivier wrote:
> >> If we ensure we have already some data available by enqueuing
> >> again the buffer once data are exhausted, we can return what we
> >> have without waiting for the device answer.
> >>
> >> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> >> ---
> >> drivers/char/hw_random/virtio-rng.c | 26 ++++++++++++--------------
> >> 1 file changed, 12 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
> >> index 8ba97cf4ca8f..0a7dde135db1 100644
> >> --- a/drivers/char/hw_random/virtio-rng.c
> >> +++ b/drivers/char/hw_random/virtio-rng.c
> >> @@ -20,7 +20,6 @@ struct virtrng_info {
> >> struct virtqueue *vq;
> >> char name[25];
> >> int index;
> >> - bool busy;
> >> bool hwrng_register_done;
> >> bool hwrng_removed;
> >> /* data transfer */
> >> @@ -44,16 +43,18 @@ static void random_recv_done(struct virtqueue *vq)
> >> return;
> >>
> >> vi->data_idx = 0;
> >> - vi->busy = false;
> >>
> >> complete(&vi->have_data);
> >> }
> >>
> >> -/* The host will fill any buffer we give it with sweet, sweet randomness. */
> >> -static void register_buffer(struct virtrng_info *vi)
> >> +static void request_entropy(struct virtrng_info *vi)
> >> {
> >> struct scatterlist sg;
> >>
> >> + reinit_completion(&vi->have_data);
> >> + vi->data_avail = 0;
> >> + vi->data_idx = 0;
> >> +
> >> sg_init_one(&sg, vi->data, sizeof(vi->data));
> >>
> >> /* There should always be room for one buffer. */
> >> @@ -69,6 +70,8 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf,
> >> memcpy(buf, vi->data + vi->data_idx, size);
> >> vi->data_idx += size;
> >> vi->data_avail -= size;
> >> + if (vi->data_avail == 0)
> >> + request_entropy(vi);
> >> return size;
> >> }
> >>
> >> @@ -98,13 +101,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
> >> * so either size is 0 or data_avail is 0
> >> */
> >> while (size != 0) {
> >> - /* data_avail is 0 */
> >> - if (!vi->busy) {
> >> - /* no pending request, ask for more */
> >> - vi->busy = true;
> >> - reinit_completion(&vi->have_data);
> >> - register_buffer(vi);
> >> - }
> >> + /* data_avail is 0 but a request is pending */
> >> ret = wait_for_completion_killable(&vi->have_data);
> >> if (ret < 0)
> >> return ret;
> >> @@ -126,8 +123,7 @@ static void virtio_cleanup(struct hwrng *rng)
> >> {
> >> struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
> >>
> >> - if (vi->busy)
> >> - complete(&vi->have_data);
> >> + complete(&vi->have_data);
> >> }
> >>
> >> static int probe_common(struct virtio_device *vdev)
> >> @@ -163,6 +159,9 @@ static int probe_common(struct virtio_device *vdev)
> >> goto err_find;
> >> }
> >>
> >> + /* we always have a pending entropy request */
> >> + request_entropy(vi);
> >> +
> >> return 0;
> >>
> >> err_find:
> >> @@ -181,7 +180,6 @@ static void remove_common(struct virtio_device *vdev)
> >> vi->data_idx = 0;
> >> complete(&vi->have_data);
> >> vdev->config->reset(vdev);
> >> - vi->busy = false;
> >> if (vi->hwrng_register_done)
> >> hwrng_unregister(&vi->hwrng);
> >> vdev->config->del_vqs(vdev);
> >
> > We observed that after this commit virtio-rng implementation in FVP doesn't
> > work
> >
> > INFO: bp.virtio_rng: Selected Random Generator Device: XORSHIFT DEVICE
> > INFO: bp.virtio_rng: Using seed value: 0x5674bba8
> > Error: FVP_Base_AEMvA: bp.virtio_rng: <vq0-requestq> Found invalid descriptor index
> > In file: (unknown):0
> > In process: FVP_Base_AEMvA.thread_p_12 @ 935500020 ns
> > Info: FVP_Base_AEMvA: bp.virtio_rng: Could not extract buffer
> >
> > while basic baremetal test works as expected
> >
> > INFO: bp.virtio_rng: Selected Random Generator Device: XORSHIFT DEVICE
> > INFO: bp.virtio_rng: Using seed value: 0x541c142e
> > Info: FVP_Base_AEMv8A: bp.virtio_rng: Generated Number: 0x4b098991ceb377e6
> > Info: FVP_Base_AEMv8A: bp.virtio_rng: Generated Number: 0xbdcbe3f765ba62f7
> >
> > We are trying to get an idea what is missing and where, yet none of us familiar
> > with the driver :(
> >
> > I'm looping Kevin who originally reported that and Mauricio who is looking form
> > the FVP side.
>
> With the following diff FVP works agin
>
> diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
> index a6f3a8a2ac..042503ad6c 100644
> --- a/drivers/char/hw_random/virtio-rng.c
> +++ b/drivers/char/hw_random/virtio-rng.c
> @@ -54,6 +54,7 @@ static void request_entropy(struct virtrng_info *vi)
> reinit_completion(&vi->have_data);
> vi->data_avail = 0;
> vi->data_idx = 0;
> + smp_mb();
>
> sg_init_one(&sg, vi->data, sizeof(vi->data));
>
>
> What do you reckon?
>
> Cheers
> Vladimir
Thanks for debugging this!
OK, interesting.
data_idx and data_avail are accessed from virtio_read.
Which as far as I can tell is invoked just with reading_mutex.
But, request_entropy is called from probe when device is registered
this time without locks
so it can trigger while another thread is calling virtio_read.
Second request_entropy is called from a callback random_recv_done
also without locks.
So it's great that smp_mb helped here but I suspect in fact we
need locking. Laurent?
--
MST
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
next prev parent reply other threads:[~2022-08-03 11:40 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-28 10:11 [PATCH v2 0/4] hwrng: virtio - add an internal buffer Laurent Vivier
2021-10-28 10:11 ` Laurent Vivier
2021-10-28 10:11 ` [PATCH v2 1/4] " Laurent Vivier
2021-10-28 10:11 ` Laurent Vivier
2021-10-28 10:11 ` [PATCH v2 2/4] hwrng: virtio - don't wait on cleanup Laurent Vivier
2021-10-28 10:11 ` Laurent Vivier
2021-10-28 10:11 ` [PATCH v2 3/4] hwrng: virtio - don't waste entropy Laurent Vivier
2021-10-28 10:11 ` Laurent Vivier
2021-10-28 10:11 ` [PATCH v2 4/4] hwrng: virtio - always add a pending request Laurent Vivier
2021-10-28 10:11 ` Laurent Vivier
2022-08-02 12:49 ` Vladimir Murzin
2022-08-03 8:57 ` Vladimir Murzin
2022-08-03 11:39 ` Michael S. Tsirkin [this message]
2022-08-03 11:39 ` Michael S. Tsirkin
2022-08-03 12:25 ` Vladimir Murzin
2022-08-03 12:55 ` Michael S. Tsirkin
2022-08-03 12:55 ` Michael S. Tsirkin
2022-08-03 13:12 ` Vladimir Murzin
2022-08-09 20:16 ` Michael S. Tsirkin
2022-08-09 20:16 ` Michael S. Tsirkin
2022-08-10 7:54 ` Vladimir Murzin
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=20220803073243-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=Kevin.Brodsky@arm.com \
--cc=Mauricio.DeCarvalho@arm.com \
--cc=akong@redhat.com \
--cc=amit@kernel.org \
--cc=dvyukov@google.com \
--cc=glider@google.com \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lvivier@redhat.com \
--cc=mpm@selenic.com \
--cc=rusty@rustcorp.com.au \
--cc=virtualization@lists.linux-foundation.org \
--cc=vladimir.murzin@arm.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.