From: Darren Kenny <darren.kenny@oracle.com>
To: Alexander Bulekov <alxndr@bu.edu>, qemu-devel@nongnu.org
Cc: Thomas Huth <thuth@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
f4bug@amsat.org, Alexander Bulekov <alxndr@bu.edu>,
Bandan Das <bsd@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Igor Mammedov <imammedo@redhat.com>
Subject: Re: [PATCH v3 1/3] memory: add a sparse memory device for fuzzing
Date: Mon, 15 Mar 2021 14:54:02 +0000 [thread overview]
Message-ID: <m2o8fksc1h.fsf@oracle.com> (raw)
In-Reply-To: <20210315140512.8357-2-alxndr@bu.edu>
On Monday, 2021-03-15 at 10:05:10 -04, Alexander Bulekov wrote:
> For testing, it can be useful to simulate an enormous amount of memory
> (e.g. 2^64 RAM). This adds an MMIO device that acts as sparse memory.
> When something writes a nonzero value to a sparse-mem address, we
> allocate a block of memory. For now, since the only user of this device
> is the fuzzer, we do not track and free zeroed blocks. The device has a
> very low priority (so it can be mapped beneath actual RAM, and virtual
> device MMIO regions).
>
> Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
> ---
> MAINTAINERS | 1 +
> hw/mem/meson.build | 1 +
> hw/mem/sparse-mem.c | 151 ++++++++++++++++++++++++++++++++++++
> include/hw/mem/sparse-mem.h | 19 +++++
> 4 files changed, 172 insertions(+)
> create mode 100644 hw/mem/sparse-mem.c
> create mode 100644 include/hw/mem/sparse-mem.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5ca3c9f851..2d25210edf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2633,6 +2633,7 @@ R: Thomas Huth <thuth@redhat.com>
> S: Maintained
> F: tests/qtest/fuzz/
> F: scripts/oss-fuzz/
> +F: hw/mem/sparse-mem.c
> F: docs/devel/fuzzing.rst
>
> Register API
> diff --git a/hw/mem/meson.build b/hw/mem/meson.build
> index 0d22f2b572..ef79e04678 100644
> --- a/hw/mem/meson.build
> +++ b/hw/mem/meson.build
> @@ -1,5 +1,6 @@
> mem_ss = ss.source_set()
> mem_ss.add(files('memory-device.c'))
> +mem_ss.add(when: 'CONFIG_FUZZ', if_true: files('sparse-mem.c'))
> mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
> mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
> mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
> diff --git a/hw/mem/sparse-mem.c b/hw/mem/sparse-mem.c
> new file mode 100644
> index 0000000000..a13ac74dd9
> --- /dev/null
> +++ b/hw/mem/sparse-mem.c
> @@ -0,0 +1,151 @@
> +/*
> + * A sparse memory device. Useful for fuzzing
> + *
> + * Copyright Red Hat Inc., 2021
> + *
> + * Authors:
> + * Alexander Bulekov <alxndr@bu.edu>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "exec/address-spaces.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/sysbus.h"
> +#include "qapi/error.h"
> +#include "qemu/units.h"
> +#include "sysemu/qtest.h"
> +#include "hw/mem/sparse-mem.h"
> +
> +#define SPARSE_MEM(obj) OBJECT_CHECK(SparseMemState, (obj), TYPE_SPARSE_MEM)
> +#define SPARSE_BLOCK_SIZE 0x1000
> +
> +typedef struct SparseMemState {
> + SysBusDevice parent_obj;
> + MemoryRegion mmio;
> + uint64_t baseaddr;
> + uint64_t length;
> + uint64_t size_used;
> + uint64_t maxsize;
> + GHashTable *mapped;
> +} SparseMemState;
> +
> +typedef struct sparse_mem_block {
> + uint8_t data[SPARSE_BLOCK_SIZE];
> +} sparse_mem_block;
> +
> +static uint64_t sparse_mem_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> + SparseMemState *s = opaque;
> + uint64_t ret = 0;
> + size_t pfn = addr / SPARSE_BLOCK_SIZE;
> + size_t offset = addr % SPARSE_BLOCK_SIZE;
> + sparse_mem_block *block;
> +
> + block = g_hash_table_lookup(s->mapped, (void *)pfn);
> + if (block) {
> + assert(offset + size <= sizeof(block->data));
> + memcpy(&ret, block->data + offset, size);
> + }
> + return ret;
> +}
> +
> +static void sparse_mem_write(void *opaque, hwaddr addr, uint64_t v,
> + unsigned int size)
> +{
> + SparseMemState *s = opaque;
> + size_t pfn = addr / SPARSE_BLOCK_SIZE;
> + size_t offset = addr % SPARSE_BLOCK_SIZE;
> + sparse_mem_block *block;
> +
> + if (!g_hash_table_lookup(s->mapped, (void *)pfn) &&
> + s->size_used + SPARSE_BLOCK_SIZE < s->maxsize && v) {
> + g_hash_table_insert(s->mapped, (void *)pfn,
> + g_new0(sparse_mem_block, 1));
> + s->size_used += sizeof(block->data);
> + }
> + block = g_hash_table_lookup(s->mapped, (void *)pfn);
> + if (!block) {
> + return;
> + }
> +
> + assert(offset + size <= sizeof(block->data));
> +
> + memcpy(block->data + offset, &v, size);
> +
> +}
> +
> +static const MemoryRegionOps sparse_mem_ops = {
> + .read = sparse_mem_read,
> + .write = sparse_mem_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid = {
> + .min_access_size = 1,
> + .max_access_size = 8,
> + .unaligned = false,
> + },
> +};
> +
> +static Property sparse_mem_properties[] = {
> + /* The base address of the memory */
> + DEFINE_PROP_UINT64("baseaddr", SparseMemState, baseaddr, 0x0),
> + /* The length of the sparse memory region */
> + DEFINE_PROP_UINT64("length", SparseMemState, length, UINT64_MAX),
> + /* Max amount of actual memory that can be used to back the sparse memory */
> + DEFINE_PROP_UINT64("maxsize", SparseMemState, maxsize, 10 * MiB),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +MemoryRegion *sparse_mem_init(uint64_t addr, uint64_t length)
> +{
> + DeviceState *dev;
> +
> + dev = qdev_new(TYPE_SPARSE_MEM);
> + qdev_prop_set_uint64(dev, "baseaddr", addr);
> + qdev_prop_set_uint64(dev, "length", length);
> + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000);
> + return &SPARSE_MEM(dev)->mmio;
> +}
> +
> +static void sparse_mem_realize(DeviceState *dev, Error **errp)
> +{
> + SparseMemState *s = SPARSE_MEM(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> + if (!qtest_enabled()) {
> + error_setg(errp, "sparse_mem device should only be used "
> + "for testing with QTest");
> + return;
> + }
> +
> + assert(s->baseaddr + s->length > s->baseaddr);
> +
> + s->mapped = g_hash_table_new(NULL, NULL);
> + memory_region_init_io(&s->mmio, OBJECT(s), &sparse_mem_ops, s,
> + "sparse-mem", s->length);
> + sysbus_init_mmio(sbd, &s->mmio);
> +}
> +
> +static void sparse_mem_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + device_class_set_props(dc, sparse_mem_properties);
> +
> + dc->desc = "Sparse Memory Device";
> + dc->realize = sparse_mem_realize;
> +}
> +
> +static const TypeInfo sparse_mem_types[] = {
> + {
> + .name = TYPE_SPARSE_MEM,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(SparseMemState),
> + .class_init = sparse_mem_class_init,
> + },
> +};
> +DEFINE_TYPES(sparse_mem_types);
> diff --git a/include/hw/mem/sparse-mem.h b/include/hw/mem/sparse-mem.h
> new file mode 100644
> index 0000000000..f9863b154b
> --- /dev/null
> +++ b/include/hw/mem/sparse-mem.h
> @@ -0,0 +1,19 @@
> +/*
> + * A sparse memory device. Useful for fuzzing
> + *
> + * Copyright Red Hat Inc., 2021
> + *
> + * Authors:
> + * Alexander Bulekov <alxndr@bu.edu>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef SPARSE_MEM_H
> +#define SPARSE_MEM_H
> +#define TYPE_SPARSE_MEM "sparse-mem"
> +
> +MemoryRegion *sparse_mem_init(uint64_t addr, uint64_t length);
> +
> +#endif
> --
> 2.27.0
next prev parent reply other threads:[~2021-03-15 14:56 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-15 14:05 [PATCH v3 0/3] fuzz: Add a sparse-memory device to accelerate fuzzing Alexander Bulekov
2021-03-15 14:05 ` [PATCH v3 1/3] memory: add a sparse memory device for fuzzing Alexander Bulekov
2021-03-15 14:54 ` Darren Kenny [this message]
2021-03-15 14:05 ` [PATCH v3 2/3] fuzz: configure a sparse-mem device, by default Alexander Bulekov
2021-03-15 14:05 ` [PATCH v3 3/3] fuzz: move some DMA hooks Alexander Bulekov
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=m2o8fksc1h.fsf@oracle.com \
--to=darren.kenny@oracle.com \
--cc=alxndr@bu.edu \
--cc=bsd@redhat.com \
--cc=f4bug@amsat.org \
--cc=imammedo@redhat.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=thuth@redhat.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.