diff mbox series

[RFC,4/8] ioregionfd: Introduce IORegionDFObject type

Message ID fa5bc2e2773966fd209a2c866eb95ac8ac60a928.1644302411.git.elena.ufimtseva@oracle.com (mailing list archive)
State New, archived
Headers show
Series ioregionfd introduction | expand

Commit Message

Elena Ufimtseva Feb. 8, 2022, 7:22 a.m. UTC
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
---
 meson.build                    |  15 ++-
 qapi/qom.json                  |  32 +++++-
 include/hw/remote/ioregionfd.h |  40 +++++++
 hw/remote/ioregionfd.c         | 196 +++++++++++++++++++++++++++++++++
 Kconfig.host                   |   3 +
 MAINTAINERS                    |   2 +
 hw/remote/Kconfig              |   4 +
 hw/remote/meson.build          |   1 +
 meson_options.txt              |   2 +
 scripts/meson-buildoptions.sh  |   3 +
 10 files changed, 294 insertions(+), 4 deletions(-)
 create mode 100644 include/hw/remote/ioregionfd.h
 create mode 100644 hw/remote/ioregionfd.c

Comments

Markus Armbruster Feb. 11, 2022, 1:46 p.m. UTC | #1
Elena Ufimtseva <elena.ufimtseva@oracle.com> writes:

> Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>

[...]

> diff --git a/qapi/qom.json b/qapi/qom.json
> index eeb5395ff3..439fb94c93 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -689,6 +689,29 @@
>          'data': { 'chardev': 'str',
>                    '*log': 'str' } }
>  
> +##
> +# @IORegionFDObjectProperties:
> +#
> +# Describes ioregionfd for the device
> +#
> +# @devid: the id of the device to be associated with the ioregionfd
> +#
> +# @iofd: File descriptor
> +#
> +# @bar: BAR number to use with ioregionfd
> +#
> +# @start: offset from the BAR start address of ioregionfd
> +#
> +# @size: size of the ioregionfd
> +##
> +# Since: 2.9
> +{ 'struct': 'IORegionFDObjectProperties',
> +  'data': { 'devid': 'str',
> +            'iofd': 'str',
> +            'bar': 'int',
> +            '*start': 'int',
> +            '*size':'int' } }

Should these three be 'uint32' to match struct IORegionFD?

> +
>  ##
>  # @RemoteObjectProperties:
>  #
> @@ -842,8 +865,10 @@
>      'tls-creds-psk',
>      'tls-creds-x509',
>      'tls-cipher-suites',
> -    { 'name': 'x-remote-object', 'features': [ 'unstable' ] }
> -  ] }
> +    { 'name': 'x-remote-object', 'features': [ 'unstable' ] },
> +    { 'name' :'ioregionfd-object',
> +      'if': 'CONFIG_IOREGIONFD' }
> + ] }
>  
>  ##
>  # @ObjectOptions:
> @@ -905,7 +930,8 @@
>        'tls-creds-psk':              'TlsCredsPskProperties',
>        'tls-creds-x509':             'TlsCredsX509Properties',
>        'tls-cipher-suites':          'TlsCredsProperties',
> -      'x-remote-object':            'RemoteObjectProperties'
> +      'x-remote-object':            'RemoteObjectProperties',
> +      'ioregionfd-object':          'IORegionFDObjectProperties'
>    } }
>  
>  ##
> diff --git a/include/hw/remote/ioregionfd.h b/include/hw/remote/ioregionfd.h
> new file mode 100644
> index 0000000000..c8a8b32ee0
> --- /dev/null
> +++ b/include/hw/remote/ioregionfd.h
> @@ -0,0 +1,40 @@
> +/*
> + * Ioregionfd headers
> + *
> + * Copyright © 2018, 2022 Oracle and/or its affiliates.
> + *
> + * 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 IOREGIONFD_H
> +#define IOREGIONFD_H
> +
> +#define PCI_BARS_NR 6
> +
> +typedef struct {
> +    uint64_t val;
> +    bool memory;
> +} IORegionFDOp;
> +
> +typedef struct {
> +    int fd;
> +    char *devid;
> +    uint32_t bar;
> +    uint32_t start;
> +    uint32_t size;
> +    bool memory;
> +} IORegionFD;
> +
> +struct IORegionFDObject {
> +    /* private */
> +    Object parent;
> +
> +    IORegionFD ioregfd;
> +    QTAILQ_ENTRY(IORegionFDObject) next;
> +};
> +
> +typedef struct IORegionFDObject IORegionFDObject;
> +
> +#endif /* IOREGIONFD_H */

[...]
Stefan Hajnoczi Feb. 14, 2022, 2:37 p.m. UTC | #2
On Mon, Feb 07, 2022 at 11:22:18PM -0800, Elena Ufimtseva wrote:
> Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
> ---
>  meson.build                    |  15 ++-
>  qapi/qom.json                  |  32 +++++-
>  include/hw/remote/ioregionfd.h |  40 +++++++
>  hw/remote/ioregionfd.c         | 196 +++++++++++++++++++++++++++++++++
>  Kconfig.host                   |   3 +
>  MAINTAINERS                    |   2 +
>  hw/remote/Kconfig              |   4 +
>  hw/remote/meson.build          |   1 +
>  meson_options.txt              |   2 +
>  scripts/meson-buildoptions.sh  |   3 +
>  10 files changed, 294 insertions(+), 4 deletions(-)
>  create mode 100644 include/hw/remote/ioregionfd.h
>  create mode 100644 hw/remote/ioregionfd.c
> 
> diff --git a/meson.build b/meson.build
> index 96de1a6ef9..6483e754bd 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -258,6 +258,17 @@ if targetos != 'linux' and get_option('multiprocess').enabled()
>  endif
>  multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
>  
> +# TODO: drop this limitation

What is the reason for the limitation?

> +if not multiprocess_allowed and not get_option('ioregionfd').disabled()
> +  error('To enable ioregiofd support, enable mutliprocess option.')

s/ioregiofd/ioregionfd/
Elena Ufimtseva Feb. 15, 2022, 6:18 p.m. UTC | #3
On Mon, Feb 14, 2022 at 02:37:21PM +0000, Stefan Hajnoczi wrote:
> On Mon, Feb 07, 2022 at 11:22:18PM -0800, Elena Ufimtseva wrote:
> > Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
> > ---
> >  meson.build                    |  15 ++-
> >  qapi/qom.json                  |  32 +++++-
> >  include/hw/remote/ioregionfd.h |  40 +++++++
> >  hw/remote/ioregionfd.c         | 196 +++++++++++++++++++++++++++++++++
> >  Kconfig.host                   |   3 +
> >  MAINTAINERS                    |   2 +
> >  hw/remote/Kconfig              |   4 +
> >  hw/remote/meson.build          |   1 +
> >  meson_options.txt              |   2 +
> >  scripts/meson-buildoptions.sh  |   3 +
> >  10 files changed, 294 insertions(+), 4 deletions(-)
> >  create mode 100644 include/hw/remote/ioregionfd.h
> >  create mode 100644 hw/remote/ioregionfd.c
> > 
> > diff --git a/meson.build b/meson.build
> > index 96de1a6ef9..6483e754bd 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -258,6 +258,17 @@ if targetos != 'linux' and get_option('multiprocess').enabled()
> >  endif
> >  multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
> >  
> > +# TODO: drop this limitation
> 
> What is the reason for the limitation?
>

The idea is to limit use of this acceleration until the API is more
generic and does not need mutliprocess.

> > +if not multiprocess_allowed and not get_option('ioregionfd').disabled()
> > +  error('To enable ioregiofd support, enable mutliprocess option.')
> 
> s/ioregiofd/ioregionfd/
!

Thanks Stefan!
Elena Ufimtseva Feb. 15, 2022, 6:19 p.m. UTC | #4
On Fri, Feb 11, 2022 at 02:46:47PM +0100, Markus Armbruster wrote:
> Elena Ufimtseva <elena.ufimtseva@oracle.com> writes:
> 
> > Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
> 
> [...]
> 
> > diff --git a/qapi/qom.json b/qapi/qom.json
> > index eeb5395ff3..439fb94c93 100644
> > --- a/qapi/qom.json
> > +++ b/qapi/qom.json
> > @@ -689,6 +689,29 @@
> >          'data': { 'chardev': 'str',
> >                    '*log': 'str' } }
> >  
> > +##
> > +# @IORegionFDObjectProperties:
> > +#
> > +# Describes ioregionfd for the device
> > +#
> > +# @devid: the id of the device to be associated with the ioregionfd
> > +#
> > +# @iofd: File descriptor
> > +#
> > +# @bar: BAR number to use with ioregionfd
> > +#
> > +# @start: offset from the BAR start address of ioregionfd
> > +#
> > +# @size: size of the ioregionfd
> > +##
> > +# Since: 2.9
> > +{ 'struct': 'IORegionFDObjectProperties',
> > +  'data': { 'devid': 'str',
> > +            'iofd': 'str',
> > +            'bar': 'int',
> > +            '*start': 'int',
> > +            '*size':'int' } }
> 
> Should these three be 'uint32' to match struct IORegionFD?
>

That is right, I will fix this.

Thank you Markus.
> > +
> >  ##
> >  # @RemoteObjectProperties:
> >  #
> > @@ -842,8 +865,10 @@
> >      'tls-creds-psk',
> >      'tls-creds-x509',
> >      'tls-cipher-suites',
> > -    { 'name': 'x-remote-object', 'features': [ 'unstable' ] }
> > -  ] }
> > +    { 'name': 'x-remote-object', 'features': [ 'unstable' ] },
> > +    { 'name' :'ioregionfd-object',
> > +      'if': 'CONFIG_IOREGIONFD' }
> > + ] }
> >  
> >  ##
> >  # @ObjectOptions:
> > @@ -905,7 +930,8 @@
> >        'tls-creds-psk':              'TlsCredsPskProperties',
> >        'tls-creds-x509':             'TlsCredsX509Properties',
> >        'tls-cipher-suites':          'TlsCredsProperties',
> > -      'x-remote-object':            'RemoteObjectProperties'
> > +      'x-remote-object':            'RemoteObjectProperties',
> > +      'ioregionfd-object':          'IORegionFDObjectProperties'
> >    } }
> >  
> >  ##
> > diff --git a/include/hw/remote/ioregionfd.h b/include/hw/remote/ioregionfd.h
> > new file mode 100644
> > index 0000000000..c8a8b32ee0
> > --- /dev/null
> > +++ b/include/hw/remote/ioregionfd.h
> > @@ -0,0 +1,40 @@
> > +/*
> > + * Ioregionfd headers
> > + *
> > + * Copyright © 2018, 2022 Oracle and/or its affiliates.
> > + *
> > + * 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 IOREGIONFD_H
> > +#define IOREGIONFD_H
> > +
> > +#define PCI_BARS_NR 6
> > +
> > +typedef struct {
> > +    uint64_t val;
> > +    bool memory;
> > +} IORegionFDOp;
> > +
> > +typedef struct {
> > +    int fd;
> > +    char *devid;
> > +    uint32_t bar;
> > +    uint32_t start;
> > +    uint32_t size;
> > +    bool memory;
> > +} IORegionFD;
> > +
> > +struct IORegionFDObject {
> > +    /* private */
> > +    Object parent;
> > +
> > +    IORegionFD ioregfd;
> > +    QTAILQ_ENTRY(IORegionFDObject) next;
> > +};
> > +
> > +typedef struct IORegionFDObject IORegionFDObject;
> > +
> > +#endif /* IOREGIONFD_H */
> 
> [...]
>
Stefan Hajnoczi Feb. 16, 2022, 11:08 a.m. UTC | #5
On Tue, Feb 15, 2022 at 10:18:12AM -0800, Elena wrote:
> On Mon, Feb 14, 2022 at 02:37:21PM +0000, Stefan Hajnoczi wrote:
> > On Mon, Feb 07, 2022 at 11:22:18PM -0800, Elena Ufimtseva wrote:
> > > Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
> > > ---
> > >  meson.build                    |  15 ++-
> > >  qapi/qom.json                  |  32 +++++-
> > >  include/hw/remote/ioregionfd.h |  40 +++++++
> > >  hw/remote/ioregionfd.c         | 196 +++++++++++++++++++++++++++++++++
> > >  Kconfig.host                   |   3 +
> > >  MAINTAINERS                    |   2 +
> > >  hw/remote/Kconfig              |   4 +
> > >  hw/remote/meson.build          |   1 +
> > >  meson_options.txt              |   2 +
> > >  scripts/meson-buildoptions.sh  |   3 +
> > >  10 files changed, 294 insertions(+), 4 deletions(-)
> > >  create mode 100644 include/hw/remote/ioregionfd.h
> > >  create mode 100644 hw/remote/ioregionfd.c
> > > 
> > > diff --git a/meson.build b/meson.build
> > > index 96de1a6ef9..6483e754bd 100644
> > > --- a/meson.build
> > > +++ b/meson.build
> > > @@ -258,6 +258,17 @@ if targetos != 'linux' and get_option('multiprocess').enabled()
> > >  endif
> > >  multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
> > >  
> > > +# TODO: drop this limitation
> > 
> > What is the reason for the limitation?
> >
> 
> The idea is to limit use of this acceleration until the API is more
> generic and does not need mutliprocess.

Please document that intention so readers understand why a limitation
is in place.

Thanks,
Stefan
diff mbox series

Patch

diff --git a/meson.build b/meson.build
index 96de1a6ef9..6483e754bd 100644
--- a/meson.build
+++ b/meson.build
@@ -258,6 +258,17 @@  if targetos != 'linux' and get_option('multiprocess').enabled()
 endif
 multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled()
 
+# TODO: drop this limitation
+if not multiprocess_allowed and not get_option('ioregionfd').disabled()
+  error('To enable ioregiofd support, enable mutliprocess option.')
+endif
+ioregionfd_allowed = multiprocess_allowed and not get_option('ioregionfd').disabled()
+if ioregionfd_allowed
+    config_host += { 'CONFIG_IOREGIONFD': 'y' }
+else
+    config_host += { 'CONFIG_IOREGIONFD': 'n' }
+endif
+
 libm = cc.find_library('m', required: false)
 threads = dependency('threads')
 util = cc.find_library('util', required: false)
@@ -1837,7 +1848,8 @@  host_kconfig = \
   (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
   ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
   ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
-  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
+  (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
+  (ioregionfd_allowed ? ['CONFIG_IOREGIONFD=y'] : [])
 
 ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
 
@@ -3315,6 +3327,7 @@  summary_info += {'target list':       ' '.join(target_dirs)}
 if have_system
   summary_info += {'default devices':   get_option('default_devices')}
   summary_info += {'out of process emulation': multiprocess_allowed}
+  summary_info += {'ioregionfd support': ioregionfd_allowed}
 endif
 summary(summary_info, bool_yn: true, section: 'Targets and accelerators')
 
diff --git a/qapi/qom.json b/qapi/qom.json
index eeb5395ff3..439fb94c93 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -689,6 +689,29 @@ 
         'data': { 'chardev': 'str',
                   '*log': 'str' } }
 
+##
+# @IORegionFDObjectProperties:
+#
+# Describes ioregionfd for the device
+#
+# @devid: the id of the device to be associated with the ioregionfd
+#
+# @iofd: File descriptor
+#
+# @bar: BAR number to use with ioregionfd
+#
+# @start: offset from the BAR start address of ioregionfd
+#
+# @size: size of the ioregionfd
+##
+# Since: 2.9
+{ 'struct': 'IORegionFDObjectProperties',
+  'data': { 'devid': 'str',
+            'iofd': 'str',
+            'bar': 'int',
+            '*start': 'int',
+            '*size':'int' } }
+
 ##
 # @RemoteObjectProperties:
 #
@@ -842,8 +865,10 @@ 
     'tls-creds-psk',
     'tls-creds-x509',
     'tls-cipher-suites',
-    { 'name': 'x-remote-object', 'features': [ 'unstable' ] }
-  ] }
+    { 'name': 'x-remote-object', 'features': [ 'unstable' ] },
+    { 'name' :'ioregionfd-object',
+      'if': 'CONFIG_IOREGIONFD' }
+ ] }
 
 ##
 # @ObjectOptions:
@@ -905,7 +930,8 @@ 
       'tls-creds-psk':              'TlsCredsPskProperties',
       'tls-creds-x509':             'TlsCredsX509Properties',
       'tls-cipher-suites':          'TlsCredsProperties',
-      'x-remote-object':            'RemoteObjectProperties'
+      'x-remote-object':            'RemoteObjectProperties',
+      'ioregionfd-object':          'IORegionFDObjectProperties'
   } }
 
 ##
diff --git a/include/hw/remote/ioregionfd.h b/include/hw/remote/ioregionfd.h
new file mode 100644
index 0000000000..c8a8b32ee0
--- /dev/null
+++ b/include/hw/remote/ioregionfd.h
@@ -0,0 +1,40 @@ 
+/*
+ * Ioregionfd headers
+ *
+ * Copyright © 2018, 2022 Oracle and/or its affiliates.
+ *
+ * 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 IOREGIONFD_H
+#define IOREGIONFD_H
+
+#define PCI_BARS_NR 6
+
+typedef struct {
+    uint64_t val;
+    bool memory;
+} IORegionFDOp;
+
+typedef struct {
+    int fd;
+    char *devid;
+    uint32_t bar;
+    uint32_t start;
+    uint32_t size;
+    bool memory;
+} IORegionFD;
+
+struct IORegionFDObject {
+    /* private */
+    Object parent;
+
+    IORegionFD ioregfd;
+    QTAILQ_ENTRY(IORegionFDObject) next;
+};
+
+typedef struct IORegionFDObject IORegionFDObject;
+
+#endif /* IOREGIONFD_H */
diff --git a/hw/remote/ioregionfd.c b/hw/remote/ioregionfd.c
new file mode 100644
index 0000000000..ae95f702a6
--- /dev/null
+++ b/hw/remote/ioregionfd.c
@@ -0,0 +1,196 @@ 
+/*
+ * Memory manager for remote device
+ *
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
+ *
+ * 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 "sysemu/kvm.h"
+#include "linux/kvm.h"
+
+#include "exec/memory.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qom/object_interfaces.h"
+#include "exec/confidential-guest-support.h"
+#include "io/channel.h"
+#include "qemu/sockets.h"
+#include "qemu/cutils.h"
+#include "io/channel-socket.h"
+#include "monitor/monitor.h"
+#include "hw/remote/ioregionfd.h"
+#include "hw/pci/pci.h"
+#include "qapi/qapi-visit-qom.h"
+#include "hw/remote/remote.h"
+
+#define TYPE_IOREGIONFD_OBJECT "ioregionfd-object"
+OBJECT_DECLARE_TYPE(IORegionFDObject, IORegionFDObjectClass, IOREGIONFD_OBJECT)
+
+struct IORegionFDObjectClass {
+    ObjectClass parent_class;
+
+    unsigned int nr_ioregfds;
+    unsigned int max_ioregfds;
+};
+
+static void ioregionfd_object_init(Object *obj)
+{
+    IORegionFDObjectClass *k = IOREGIONFD_OBJECT_GET_CLASS(obj);
+
+    if (k->nr_ioregfds >= k->max_ioregfds) {
+        error_report("Reached max number of ioregions: %u", k->max_ioregfds);
+        return;
+    }
+}
+
+static void ioregionfd_object_set_fd(Object *obj, const char *str,
+                                     Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+    int fd = -1;
+
+    fd = monitor_fd_param(monitor_cur(), str, errp);
+    if (fd == -1) {
+        error_prepend(errp, "Could not parse ioregionfd fd %s:", str);
+        return;
+    }
+    o->ioregfd.fd = fd;
+}
+
+static void ioregionfd_object_set_devid(Object *obj, const char *str,
+                                        Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+
+    g_free(o->ioregfd.devid);
+
+    o->ioregfd.devid = g_strdup(str);
+}
+
+static char *ioregionfd_object_get_devid(Object *obj, Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+
+    return g_strdup(o->ioregfd.devid);
+}
+
+static void ioregionfd_object_set_bar(Object *obj, Visitor *v,
+                                      const char *name, void *opaque,
+                                      Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+    uint32_t value;
+
+    if (!visit_type_uint32(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value > PCI_BARS_NR) {
+        error_setg(errp, "BAR number cannot be larger than %d", PCI_BARS_NR);
+        return;
+    }
+
+    o->ioregfd.bar = value;
+}
+
+static void ioregionfd_object_set_start(Object *obj, Visitor *v,
+                                        const char *name, void *opaque,
+                                        Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+    int64_t value;
+
+    if (!visit_type_int(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value < 0) {
+        error_setg(errp, "BAR start %"PRId64" must be > 0", value);
+        return;
+    }
+
+    if (value > UINT32_MAX) {
+        error_setg(errp, "BAR start %"PRId64" is too big", value);
+        o->ioregfd.start = 0;
+        return;
+    }
+
+    o->ioregfd.start = value;
+}
+
+static void ioregionfd_object_set_size(Object *obj, Visitor *v,
+                                       const char *name, void *opaque,
+                                       Error **errp)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+    int64_t value;
+
+    if (!visit_type_int(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value < 0) {
+        error_setg(errp, "Invalid BAR size %"PRId64, value);
+        return;
+    }
+
+    if (value > UINT32_MAX) {
+        error_setg(errp, "BAR size %"PRId64" is too big", value);
+        o->ioregfd.size = 0;
+        return;
+    }
+
+
+    o->ioregfd.size = value;
+}
+
+static void ioregionfd_object_class_init(ObjectClass *klass, void *data)
+{
+    IORegionFDObjectClass *k = IOREGIONFD_OBJECT_CLASS(klass);
+
+    k->nr_ioregfds = 0;
+    k->max_ioregfds = 1;
+
+    object_class_property_add_str(klass, "devid", ioregionfd_object_get_devid,
+                                  ioregionfd_object_set_devid);
+    object_class_property_add_str(klass, "iofd", NULL,
+                                  ioregionfd_object_set_fd);
+    object_class_property_add(klass, "bar", "uint32", NULL,
+                              ioregionfd_object_set_bar, NULL, NULL);
+    object_class_property_add(klass, "start", "uint64", NULL,
+                              ioregionfd_object_set_start, NULL, NULL);
+    object_class_property_add(klass, "size", "uint64", NULL,
+                              ioregionfd_object_set_size, NULL, NULL);
+}
+
+/* Assume that Object user released all allocated structures. */
+static void ioregionfd_object_finalize(Object *obj)
+{
+    IORegionFDObject *o = IOREGIONFD_OBJECT(obj);
+    g_free(o->ioregfd.devid);
+}
+
+static const TypeInfo ioregionfd_object_info = {
+    .name = TYPE_IOREGIONFD_OBJECT,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(IORegionFDObject),
+    .instance_init = ioregionfd_object_init,
+    .instance_finalize = ioregionfd_object_finalize,
+    .class_size = sizeof(IORegionFDObjectClass),
+    .class_init = ioregionfd_object_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void register_types(void)
+{
+    type_register_static(&ioregionfd_object_info);
+}
+
+type_init(register_types);
diff --git a/Kconfig.host b/Kconfig.host
index 60b9c07b5e..af01b75770 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -45,3 +45,6 @@  config MULTIPROCESS_ALLOWED
 config FUZZ
     bool
     select SPARSE_MEM
+
+config IOREGIONFD
+    bool
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c60a29760..d29fa8a7de 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3454,6 +3454,8 @@  F: include/hw/remote/proxy-memory-listener.h
 F: hw/remote/iohub.c
 F: include/hw/remote/iohub.h
 F: include/hw/remote/remote.h
+F: include/hw/remote/ioregionfd.h
+F: hw/remote/ioregionfd.c
 
 EBPF:
 M: Jason Wang <jasowang@redhat.com>
diff --git a/hw/remote/Kconfig b/hw/remote/Kconfig
index 08c16e235f..caff3427e7 100644
--- a/hw/remote/Kconfig
+++ b/hw/remote/Kconfig
@@ -2,3 +2,7 @@  config MULTIPROCESS
     bool
     depends on PCI && PCI_EXPRESS && KVM
     select REMOTE_PCIHOST
+config IOREGIONFD
+    bool
+    default n
+    depends on MULTIPROCESS
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
index e6a5574242..b190c520c4 100644
--- a/hw/remote/meson.build
+++ b/hw/remote/meson.build
@@ -6,6 +6,7 @@  remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
 remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
 remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c'))
 remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iohub.c'))
+specific_ss.add(when: 'CONFIG_IOREGIONFD', if_true: files('ioregionfd.c'))
 
 specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c'))
 specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy-memory-listener.c'))
diff --git a/meson_options.txt b/meson_options.txt
index e392323732..52b338c1b8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -66,6 +66,8 @@  option('cfi_debug', type: 'boolean', value: 'false',
        description: 'Verbose errors in case of CFI violation')
 option('multiprocess', type: 'feature', value: 'auto',
        description: 'Out of process device emulation support')
+option('ioregionfd', type: 'feature', value: 'auto',
+       description: 'Fast-path IO/MMIO support')
 
 option('attr', type : 'feature', value : 'auto',
        description: 'attr/xattr support')
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 7a17ff4218..1cbd2984f5 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -98,6 +98,7 @@  meson_options_help() {
   printf "%s\n" '                  Xen PCI passthrough support'
   printf "%s\n" '  xkbcommon       xkbcommon support'
   printf "%s\n" '  zstd            zstd compression support'
+  printf "%s\n" '  ioregionfd      ioregionfd support'
 }
 _meson_option_parse() {
   case $1 in
@@ -270,6 +271,8 @@  _meson_option_parse() {
     --disable-xkbcommon) printf "%s" -Dxkbcommon=disabled ;;
     --enable-zstd) printf "%s" -Dzstd=enabled ;;
     --disable-zstd) printf "%s" -Dzstd=disabled ;;
+    --enable-ioregionfd) printf "%s" -Dioregionfd=enabled ;;
+    --disable-ioregionfd) printf "%s" -Dioregionfd=disabled ;;
     *) return 1 ;;
   esac
 }