From: Peter Xu <peterx@redhat.com>
To: "Philippe Mathieu-Daudé" <philmd@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>,
Fabiano Rosas <farosas@suse.de>,
Gerd Hoffmann <kraxel@redhat.com>,
qemu-devel@nongnu.org, qemu-block@nongnu.org,
Hanna Reitz <hreitz@redhat.com>, Kevin Wolf <kwolf@redhat.com>
Subject: Re: [PATCH v2 2/2] hw/pflash: implement update buffer for block writes
Date: Wed, 17 Jan 2024 15:52:24 +0800 [thread overview]
Message-ID: <ZaeHOCHTs0-ivm4j@x1n> (raw)
In-Reply-To: <4b7fe91d-9e96-4de4-af6f-c9be81c43ab1@linaro.org>
On Tue, Jan 16, 2024 at 05:08:28PM +0100, Philippe Mathieu-Daudé wrote:
> On 12/1/24 17:54, Peter Maydell wrote:
> > On Mon, 8 Jan 2024 at 13:06, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> > >
> > > Hi Gerd,
> > >
> > > On 8/1/24 13:53, Philippe Mathieu-Daudé wrote:
> > > > From: Gerd Hoffmann <kraxel@redhat.com>
> > > >
> > > > Add an update buffer where all block updates are staged.
> > > > Flush or discard updates properly, so we should never see
> > > > half-completed block writes in pflash storage.
> > > >
> > > > Drop a bunch of FIXME comments ;)
> > > >
> > > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > > > Message-ID: <20240105135855.268064-3-kraxel@redhat.com>
> > > > Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> > > > ---
> > > > hw/block/pflash_cfi01.c | 106 ++++++++++++++++++++++++++++++----------
> > > > 1 file changed, 80 insertions(+), 26 deletions(-)
>
>
> > > > +static const VMStateDescription vmstate_pflash_blk_write = {
> > > > + .name = "pflash_cfi01_blk_write",
> > > > + .version_id = 1,
> > > > + .minimum_version_id = 1,
> > > > + .needed = pflash_blk_write_state_needed,
> > > > + .fields = (const VMStateField[]) {
> > > > + VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
> > >
> > > I don't get the difference with VMSTATE_VBUFFER_ALLOC_UINT32() which
> > > sets VMS_ALLOC. In this case pflash_cfi01_realize() does the alloc so
> > > we don't need VMS_ALLOC?
> >
> > Yes, that's the idea. A VMS_ALLOC vmstate type means "this
> > block of memory is dynamically sized at runtime, so when the
> > migration code is doing inbound migration it needs to
> > allocate a buffer of the right size first (based on some
> > state struct field we've already migrated) and then put the
> > incoming data into it". VMS_VBUFFER means "the size of the buffer
> > isn't a compile-time constant, so we need to fish it out of
> > some other state struct field". So:
> >
> > VMSTATE_VBUFFER_UINT32: we need to migrate (a pointer to) an array
> > of uint32_t; the size of that is in some other struct field,
> > but it's a runtime constant and we can assume the memory has
> > already been allocated
> >
> > VMSTATE_VBUFFER_ALLOC_UINT32: we need to migrate an array
> > of uint32_t of variable size dependent on the inbound migration
> > data, and so the migration code must allocate it
>
> Thanks Peter!
>
> Do you mind if we commit your explanation as is? As:
Any attempt to provide more documents there for the macros would be nice if
anyone would like to post a patch. Though some comments below for this
specific one.
>
> -- >8 --
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 294d2d8486..5c6f6c5c32 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -573,4 +573,6 @@ extern const VMStateInfo vmstate_info_qlist;
>
> -/* a variable length array (i.e. _type *_field) but we know the
> - * length
> +/**
> + * VMSTATE_STRUCT_VARRAY_POINTER_KNOWN:
> + *
> + * A variable length array (i.e. _type *_field) but we know the length.
> */
> @@ -678,2 +680,10 @@ extern const VMStateInfo vmstate_info_qlist;
>
> +/**
> + * VMSTATE_VBUFFER_UINT32:
> + *
> + * We need to migrate (a pointer to) an array of uint32_t; the size of
IIUC it's not an array of uint32_t, but a buffer with dynamic size. the
"uint32_t" is trying to describe the type of the size field, afaict. Same
issue for below one.
For example, comparing VMSTATE_VBUFFER_UINT32 vs VMSTATE_VBUFFER, we should
see the only difference is:
.size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
vs:
.size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
I think it checks the size field to match that type.
Interestingly, when I look at the code to use the size, it looks like a bug
to me, where we always parse the size field to be int32_t..
static int vmstate_size(void *opaque, const VMStateField *field)
{
int size = field->size;
if (field->flags & VMS_VBUFFER) {
size = *(int32_t *)(opaque + field->size_offset); <----------- see here..
if (field->flags & VMS_MULTIPLY) {
size *= field->size;
}
}
return size;
}
I think it'll start to crash things when bit32 start to be used. And I had
a feeling that this is overlooked in the commit a19cbfb346 ("spice: add qxl
device") where VMSTATE_VBUFFER_UINT32 is introduced.
I don't have a good way to trivially fix it because we don't remember that
type of size in vmsd. However a simple solution could be that we convert
all existing VMSTATE_VBUFFER() (potentially, VMSTATE_PARTIAL_VBUFFER users;
there seems to have only 1 caller..) to always use uint32_t. I don't think
it's wise to try using a signed for size anyway, and it should be
compatible change as we doubled the size.
I'll hold a bit to see whether there's some comment, then I can try to post
a patch.
> + * that is in some other struct field, but it's a runtime constant and
> + * we can assume the memory has already been allocated.
> +*/
> +
> #define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test,
> _field_size) { \
> @@ -688,2 +698,9 @@ extern const VMStateInfo vmstate_info_qlist;
>
> +/**
> + * VMSTATE_VBUFFER_ALLOC_UINT32:
> + *
> + * We need to migrate an array of uint32_t of variable size dependent
> + * on the inbound migration data, and so the migration code must
> + * allocate it.
> +*/
> #define VMSTATE_VBUFFER_ALLOC_UINT32(_field, _state, _version, \
> ---
>
--
Peter Xu
next prev parent reply other threads:[~2024-01-17 7:52 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-08 12:53 [PATCH v2 0/2] hw/pflash: implement update buffer for block writes Philippe Mathieu-Daudé
2024-01-08 12:53 ` [PATCH v2 1/2] hw/block/pflash_cfi01: Use the LD/ST API in pflash_data_read/write Philippe Mathieu-Daudé
2024-01-08 12:53 ` [PATCH v2 2/2] hw/pflash: implement update buffer for block writes Philippe Mathieu-Daudé
2024-01-08 13:05 ` Philippe Mathieu-Daudé
2024-01-12 16:54 ` Peter Maydell
2024-01-16 16:08 ` Philippe Mathieu-Daudé
2024-01-16 16:09 ` Peter Maydell
2024-01-17 7:52 ` Peter Xu [this message]
2024-01-09 21:40 ` Richard Henderson
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=ZaeHOCHTs0-ivm4j@x1n \
--to=peterx@redhat.com \
--cc=farosas@suse.de \
--cc=hreitz@redhat.com \
--cc=kraxel@redhat.com \
--cc=kwolf@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-block@nongnu.org \
--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 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.