qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: David Edmondson <david.edmondson@oracle.com>,
	qemu-devel@nongnu.org, Tom Lendacky <thomas.lendacky@amd.com>,
	James Bottomley <jejb@linux.ibm.com>
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	qemu-block@nongnu.org, "Michael S. Tsirkin" <mst@redhat.com>,
	"Xu Yandong" <xuyandong2@huawei.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Shannon Zhao" <shannon.zhaosl@gmail.com>,
	"Zheng Xiang" <zhengxiang9@huawei.com>,
	qemu-arm@nongnu.org, "haibinzhang(张海斌)" <haibinzhang@tencent.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"John Snow" <jsnow@redhat.com>,
	"Stefano Garzarella" <sgarzare@redhat.com>
Subject: Re: [PATCH v4 1/1] hw/pflash_cfi01: Allow backing devices to be smaller than memory region
Date: Thu, 9 Sep 2021 11:27:56 +0200	[thread overview]
Message-ID: <384a5d1d-de25-78d7-d8b0-226ebca44a6d@redhat.com> (raw)
In-Reply-To: <20210810134050.396747-2-david.edmondson@oracle.com>

Hi David,

On 8/10/21 3:40 PM, David Edmondson wrote:
> Allow the backing device to be smaller than the extent of the flash
> device by mapping it as a subregion of the flash device region.
> 
> Return zeroes for all reads of the flash device beyond the extent of
> the backing device.
> 
> For writes beyond the extent of the underlying device, fail on
> read-only devices and discard them for writable devices.
> 
> Signed-off-by: David Edmondson <david.edmondson@oracle.com>
> ---
>  hw/block/pflash_cfi01.c | 105 ++++++++++++++++++++++++++++++++--------
>  hw/block/trace-events   |   3 ++
>  2 files changed, 87 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
> index 81f9f971d8..f3289b6a2f 100644
> --- a/hw/block/pflash_cfi01.c
> +++ b/hw/block/pflash_cfi01.c
> @@ -83,6 +83,8 @@ struct PFlashCFI01 {
>      uint64_t counter;
>      unsigned int writeblock_size;
>      MemoryRegion mem;
> +    MemoryRegion mem_outer;
> +    char outer_name[64];
>      char *name;
>      void *storage;
>      VMChangeStateEntry *vmstate;
> @@ -434,7 +436,6 @@ static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
>          }
>          break;
>      }
> -
>  }
>  
>  static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
> @@ -656,8 +657,44 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
>  }
>  
>  
> -static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
> -                                              unsigned len, MemTxAttrs attrs)
> +static MemTxResult pflash_outer_read_with_attrs(void *opaque, hwaddr addr,
> +                                                uint64_t *value, unsigned len,
> +                                                MemTxAttrs attrs)
> +{
> +    PFlashCFI01 *pfl = opaque;
> +
> +    trace_pflash_outer_read(pfl->name, addr, len);
> +    *value = 0;

This seems to break the "width" and "old-multiple-chip-handling"
parameters ("emulating a number of flash devices wired up in parallel").

Also this breaks booting with SEV enabled on X86... See commits
9617cddb726 ("pc: add parser for OVMF reset block") and b2f73a0784b
("sev/i386: Allow AP booting under SEV-ES").

> +    return MEMTX_OK;
> +}
> +
> +static MemTxResult pflash_outer_write_with_attrs(void *opaque, hwaddr addr,
> +                                                 uint64_t value, unsigned len,
> +                                                 MemTxAttrs attrs)
> +{
> +    PFlashCFI01 *pfl = opaque;
> +
> +    trace_pflash_outer_write(pfl->name, addr, len);
> +    if (pfl->ro) {
> +        return MEMTX_ERROR;
> +    } else {
> +        warn_report_once("%s: "
> +                         "attempt to write outside of the backing block device "
> +                         "(offset " TARGET_FMT_plx ") ignored",
> +                         pfl->name, addr);

This doesn't seem acceptable on mainstream, see:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg607292.html

> +        return MEMTX_OK;
> +    }
> +}
> +
> +static const MemoryRegionOps pflash_cfi01_outer_ops = {
> +    .read_with_attrs = pflash_outer_read_with_attrs,
> +    .write_with_attrs = pflash_outer_write_with_attrs,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr,
> +                                              uint64_t *value, unsigned len,
> +                                              MemTxAttrs attrs)
>  {
>      PFlashCFI01 *pfl = opaque;
>      bool be = !!(pfl->features & (1 << PFLASH_BE));
> @@ -670,8 +707,9 @@ static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_
>      return MEMTX_OK;
>  }
>  
> -static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
> -                                               unsigned len, MemTxAttrs attrs)
> +static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr,
> +                                               uint64_t value, unsigned len,
> +                                               MemTxAttrs attrs)
>  {
>      PFlashCFI01 *pfl = opaque;
>      bool be = !!(pfl->features & (1 << PFLASH_BE));
> @@ -800,7 +838,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
>  {
>      ERRP_GUARD();
>      PFlashCFI01 *pfl = PFLASH_CFI01(dev);
> -    uint64_t total_len;
> +    uint64_t outer_len, inner_len;
>      int ret;
>  
>      if (pfl->sector_len == 0) {
> @@ -816,35 +854,60 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> -    total_len = pfl->sector_len * pfl->nb_blocs;
> -
> -    memory_region_init_rom_device(
> -        &pfl->mem, OBJECT(dev),
> -        &pflash_cfi01_ops,
> -        pfl,
> -        pfl->name, total_len, errp);
> -    if (*errp) {
> -        return;
> -    }
> -
> -    pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
> -    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
> +    outer_len = pfl->sector_len * pfl->nb_blocs;
>  
>      if (pfl->blk) {
>          uint64_t perm;
> +
>          pfl->ro = !blk_supports_write_perm(pfl->blk);
>          perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
>          ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
>          if (ret < 0) {
>              return;
>          }
> +
> +        inner_len = blk_getlength(pfl->blk);
> +
> +        if (inner_len > outer_len) {
> +            error_setg(errp, "%s: "
> +                       "block backend provides %" PRIu64 " bytes, "
> +                       "device limited to %" PRIu64 " bytes",
> +                       pfl->name, inner_len, outer_len);
> +            return;
> +        }
>      } else {
>          pfl->ro = false;
> +        inner_len = outer_len;
>      }
>  
> +    trace_pflash_realize(pfl->name, pfl->ro, inner_len, outer_len);
> +
> +    snprintf(pfl->outer_name, sizeof(pfl->outer_name),
> +             "%s container", pfl->name);
> +    memory_region_init_io(&pfl->mem_outer, OBJECT(dev),
> +                          &pflash_cfi01_outer_ops,
> +                          pfl, pfl->outer_name, outer_len);

Here you create an I/O region but name it "container" ...

> +
> +    memory_region_init_rom_device(&pfl->mem, OBJECT(dev),
> +                                  &pflash_cfi01_ops,
> +                                  pfl, pfl->name, inner_len, errp);
> +    if (*errp) {
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&pfl->mem_outer, 0, &pfl->mem);

... then add it inside the previous region, so &pfl->mem is used
as container (containing &pfl->mem_outer named "container"...).
This is confusing. Anyhow we shouldn't add subregions to I/O
regions but use real containers instead, creating the container
with memory_region_init(), then adding subregions inside.

> +
> +    pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem_outer);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);


Have you audited no code uses:

  mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash), 0);

Because we'd need to change 0 -> 1.

See also the problem with pflash_cfi01_get_memory():
https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg01988.html
https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02026.html

>      if (pfl->blk) {
> -        if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, total_len,
> -                                         errp)) {
> +        int ret = blk_pread(pfl->blk, 0, pfl->storage, inner_len);
> +
> +        if (ret < 0) {
> +            error_setg_errno(errp, -ret,
> +                             "cannot read %" PRIu64 " "
> +                             "bytes from block backend", inner_len);
>              vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
>              return;
>          }



  reply	other threads:[~2021-09-09  9:29 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-10 13:40 [PATCH v4 0/1] hw/pflash_cfi01: Allow an administrator to reduce the memory consumption of flash devices David Edmondson
2021-08-10 13:40 ` [PATCH v4 1/1] hw/pflash_cfi01: Allow backing devices to be smaller than memory region David Edmondson
2021-09-09  9:27   ` Philippe Mathieu-Daudé [this message]
2021-09-14 14:01     ` David Edmondson
2021-08-20 18:19 ` [PATCH v4 0/1] hw/pflash_cfi01: Allow an administrator to reduce the memory consumption of flash devices Philippe Mathieu-Daudé

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=384a5d1d-de25-78d7-d8b0-226ebca44a6d@redhat.com \
    --to=philmd@redhat.com \
    --cc=alex.bennee@linaro.org \
    --cc=armbru@redhat.com \
    --cc=david.edmondson@oracle.com \
    --cc=haibinzhang@tencent.com \
    --cc=imammedo@redhat.com \
    --cc=jejb@linux.ibm.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sgarzare@redhat.com \
    --cc=shannon.zhaosl@gmail.com \
    --cc=stefanha@redhat.com \
    --cc=thomas.lendacky@amd.com \
    --cc=xuyandong2@huawei.com \
    --cc=zhengxiang9@huawei.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 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).