patches and low-level development discussion
 help / color / mirror / code / Atom feed
* [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor
@ 2022-09-30 21:08 Alyssa Ross
  2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 1/9] crosvm: switch back to old git repo URL Alyssa Ross
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:08 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen, sternenseemann

Changes since v1
----------------

 - Fixed the cloud-hypervisor seccomp sandbox for the GPU device.

 - Worked around crosvm not handling wlroots's read-only keymaps in
   cloud-hypervisor.  (Thanks Puck.)

 - Switched to cherry-picks of sternenseemann's ocamlPackages.wayland
   and wayland-proxy-virtwl updates from upstream.

v1: https://spectrum-os.org/lists/archives/spectrum-devel/20220928170128.1583791-1-alyssa.ross@unikie.com/

Introduction
------------

This series contains all the changes needed to make it possible to run
Wayland over cross-domain virtio-gpu using cloud-hypervisor.  It only
contains changes needed to packages in Nixpkgs, so there's no Spectrum
integration here.  That's a separate patchset, of which I'll also be
sending v2 soon.

There's also still some work to do here, hence being marked RFC — in
the cloud-hypervisor patch you'll spot a few TODOs and FIXMEs — but
it's ready for other people to have a look at and test.

With these changes, it's possible to run a cloud-hypervisor VM with a
GPU attached as follows:

	crosvm device gpu --socket vhost-user-gpu.sock ...
	cloud-hypervisor --gpu socket=vhost-user-gpu.sock ...

Then in the guest, just run a Wayland application under
wayland-proxy-virtwl:

	wayland-proxy-virtwl --virtio-gpu hello-wayland

For Wayland over cross-domain virtio-gpu, which we're particularly
interested in, the full crosvm command line would be something like:

	crosvm device gpu --socket vhost-user-gpu.sock \
		--wayland-sock "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" \
		--params '{"context-types": "virgl:virgl2:cross-domain"}'

Overview
--------

We start by upgrading crosvm to a beta version (since very recent
changes changed their vhost-user implementation in a way that makes it
significantly easier to interoperate with from cloud-hypervisor), then
applying a few small fixes for cases where crosvm had made assumptions
that were violated by cloud-hypervisor.

Next, we apply patches to cloud-hypervisor and some of its
dependencies, to implement the frontend of the GPU device.

Finally, we upgrade wayland-proxy-virtwl (the program that speaks
virtio-gpu and acts as the Wayland compositor inside the guest) to a
version that supports virtio-gpu.  I'm using wayland-proxy-virtwl over
Sommelier here primary because Sommelier appears to have broken with
Linux 5.19, but another nice benefit is that wayland-proxy-virtwl is
maintained by somebody that we know and talk to sometimes on
discuss@spectrum-os.org.

Upstreamability
---------------

A question anybody looking at the volume of changes here should be
asking is: "To what extent is this upstreamable?".  It's a bit of a
mixed bag — most notably, cloud-hypervisor is not interested in
virtio-gpu[1], so we'll have to maintain the cloud-hypervisor patches
ourselves until we can come up with a more upstream-friendly solution
(e.g. a vfio-user implementation of virtio-gpu).  We also can't
upstream the changes to the vhost crate, as the protocol we are using
is crosvm specific, and so some standardisation work would need to
happen there.

But we can upstream the changes to crosvm, and the virtio-bindings
crate.  I've already started on the latter.  As for the patches to
Nixpkgs itself here, the updates to wayland-proxy-virtwl and the
wayland library it depends on are already upstream (thanks sterni), I
have an open PR[2] for the crosvm update (although to 105.0 rather
than 106.3 than here, since the 106 series is still in beta), and the
rustPlatform change is also upstreamable, but would require auditing
Nixpkgs for cargoSha256 values that would change as a result.

[1]: https://github.com/cloud-hypervisor/cloud-hypervisor/discussions/3960#discussioncomment-2542915
[2]: https://github.com/NixOS/nixpkgs/pull/193746

Alyssa Ross (7):
  crosvm: switch back to old git repo URL
  crosvm.updateScript: update release branch format
  crosvm: 104.0 -> 106.2
  crosvm.updateScript: don't vendor Cargo.lock
  crosvm: add fixes for cloud-hypervisor virtio-gpu
  rustPlatform: forward unpack hooks to cargo fetch
  cloud-hypervisor: add virtio-gpu support

sternenseemann (2):
  ocamlPackages.wayland: 1.0 -> 1.1
  wayland-proxy-virtwl: unstable-2021-12-05 -> unstable-2022-09-22

 .../0001-build-use-local-vhost.patch          |   39 +
 ...dings-regenerate-with-bindgen-0.60.1.patch | 2589 ++++++++++++
 ...0002-build-use-local-virtio-bindings.patch |   39 +
 ...gs-remove-workaround-for-old-bindgen.patch |   28 +
 ...-bindings-regenerate-with-Glibc-2.36.patch |  247 ++
 ...0003-virtio-devices-add-a-GPU-device.patch | 1279 ++++++
 ...-bindings-regenerate-with-Linux-5.19.patch | 1067 +++++
 ...tio-bindings-add-virtio-gpu-bindings.patch | 3587 +++++++++++++++++
 .../cloud-hypervisor/default.nix              |   64 +-
 ...ser-add-shared-memory-region-support.patch |  724 ++++
 .../virtualization/crosvm/Cargo.lock          | 2214 ----------
 .../crosvm/default-seccomp-policy-dir.diff    |   38 +-
 .../virtualization/crosvm/default.nix         |   15 +-
 ...-consider-shm-buuffers-when-setting-.patch |   34 +
 ...t_user-loosen-expected-message-order.patch |   71 +
 ...ces-vhost_user-remove-spurious-check.patch |   42 +
 .../virtualization/crosvm/update.py           |   15 +-
 .../rust/build-rust-package/default.nix       |    4 +-
 .../ocaml-modules/wayland/default.nix         |    8 +-
 .../wayland/wayland-proxy-virtwl/default.nix  |   17 +-
 20 files changed, 9857 insertions(+), 2264 deletions(-)
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0001-build-use-local-vhost.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0002-build-use-local-virtio-bindings.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0002-virtio-bindings-remove-workaround-for-old-bindgen.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-bindings-regenerate-with-Glibc-2.36.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-devices-add-a-GPU-device.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0004-virtio-bindings-regenerate-with-Linux-5.19.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0005-virtio-bindings-add-virtio-gpu-bindings.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/vhost-vhost_user-add-shared-memory-region-support.patch
 delete mode 100644 pkgs/applications/virtualization/crosvm/Cargo.lock
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-properly-consider-shm-buuffers-when-setting-.patch
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-vhost_user-loosen-expected-message-order.patch
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-vhost_user-remove-spurious-check.patch


base-commit: 768879638cfd6a54664b762ec98a7f8f45620c44
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 1/9] crosvm: switch back to old git repo URL
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
@ 2022-09-30 21:08 ` Alyssa Ross
  2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 2/9] crosvm.updateScript: update release branch format Alyssa Ross
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:08 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

Despite having moved the main repo to crosvm/crosvm, release branches
are still only being created on chromiumos/platform/crosvm.  So we
should have crosvm/crosvm as the homepage, but fetch from
chromiumos/platform/crosvm.

Link: https://github.com/NixOS/nixpkgs/pull/193746
Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 pkgs/applications/virtualization/crosvm/default.nix | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pkgs/applications/virtualization/crosvm/default.nix b/pkgs/applications/virtualization/crosvm/default.nix
index a4de1433ae7..ae216001c5e 100644
--- a/pkgs/applications/virtualization/crosvm/default.nix
+++ b/pkgs/applications/virtualization/crosvm/default.nix
@@ -8,7 +8,7 @@ rustPlatform.buildRustPackage rec {
   version = "104.0";
 
   src = fetchgit {
-    url = "https://chromium.googlesource.com/crosvm/crosvm";
+    url = "https://chromium.googlesource.com/chromiumos/platform/crosvm";
     rev = "265aab613b1eb31598ea0826f04810d9f010a2c6";
     sha256 = "OzbtPHs6BWK83RZ/6eCQHA61X6SY8FoBkaN70a37pvc=";
     fetchSubmodules = true;
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 2/9] crosvm.updateScript: update release branch format
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
  2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 1/9] crosvm: switch back to old git repo URL Alyssa Ross
@ 2022-09-30 21:08 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 3/9] crosvm: 104.0 -> 106.2 Alyssa Ross
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:08 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

For R106 and onwards, upstream has gone back to not having a
separation between chromeos and not.

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 pkgs/applications/virtualization/crosvm/update.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pkgs/applications/virtualization/crosvm/update.py b/pkgs/applications/virtualization/crosvm/update.py
index d912c49078c..64adec42957 100755
--- a/pkgs/applications/virtualization/crosvm/update.py
+++ b/pkgs/applications/virtualization/crosvm/update.py
@@ -34,7 +34,7 @@ with urlopen('https://chromiumdash.appspot.com/cros/download_serving_builds_csv?
 
 chrome_major_version = chrome_version[0]
 chromeos_tip_build = platform_version[0]
-release_branch = f'release-R{chrome_major_version}-{chromeos_tip_build}.B-chromeos'
+release_branch = f'release-R{chrome_major_version}-{chromeos_tip_build}.B'
 
 # Determine the git revision.
 with urlopen(f'https://chromium.googlesource.com/chromiumos/platform/crosvm/+/refs/heads/{release_branch}?format=JSON') as resp:
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 3/9] crosvm: 104.0 -> 106.2
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
  2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 1/9] crosvm: switch back to old git repo URL Alyssa Ross
  2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 2/9] crosvm.updateScript: update release branch format Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 4/9] crosvm.updateScript: don't vendor Cargo.lock Alyssa Ross
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

crosvm now includes a Cargo.lock again, so we don't need to vendor it
into Nixpkgs.

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 .../virtualization/crosvm/Cargo.lock          | 2214 -----------------
 .../crosvm/default-seccomp-policy-dir.diff    |   38 +-
 .../virtualization/crosvm/default.nix         |    9 +-
 3 files changed, 27 insertions(+), 2234 deletions(-)
 delete mode 100644 pkgs/applications/virtualization/crosvm/Cargo.lock

diff --git a/pkgs/applications/virtualization/crosvm/Cargo.lock b/pkgs/applications/virtualization/crosvm/Cargo.lock
deleted file mode 100644
index 646562bd27d..00000000000
--- a/pkgs/applications/virtualization/crosvm/Cargo.lock
+++ /dev/null
@@ -1,2214 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aarch64"
-version = "0.1.0"
-dependencies = [
- "arch",
- "base",
- "data_model",
- "devices",
- "hypervisor",
- "kernel_cmdline",
- "kernel_loader",
- "kvm",
- "kvm_sys",
- "libc",
- "memoffset 0.6.5",
- "minijail",
- "remain",
- "resources",
- "sync",
- "thiserror",
- "vm_control",
- "vm_memory",
-]
-
-[[package]]
-name = "acpi_tables"
-version = "0.1.0"
-dependencies = [
- "data_model",
- "tempfile",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "android_system_properties"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8"
-
-[[package]]
-name = "arch"
-version = "0.1.0"
-dependencies = [
- "acpi_tables",
- "anyhow",
- "base",
- "devices",
- "gdbstub_arch",
- "hypervisor",
- "kernel_cmdline",
- "libc",
- "minijail",
- "power_monitor",
- "remain",
- "resources",
- "sync",
- "thiserror",
- "vm_control",
- "vm_memory",
-]
-
-[[package]]
-name = "argh"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7e7e4aa7e40747e023c0761dafcb42333a9517575bbf1241747f68dd3177a62"
-dependencies = [
- "argh_derive",
- "argh_shared",
-]
-
-[[package]]
-name = "argh_derive"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69f2bd7ff6ed6414f4e5521bd509bae46454bbd513801767ced3f21a751ab4bc"
-dependencies = [
- "argh_shared",
- "heck",
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "argh_helpers"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "argh_shared"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47253b98986dafc7a3e1cf3259194f1f47ac61abb57a57f46ec09e48d004ecda"
-
-[[package]]
-name = "assertions"
-version = "0.1.0"
-
-[[package]]
-name = "async-task"
-version = "4.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
-
-[[package]]
-name = "async-trait"
-version = "0.1.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "audio_streams"
-version = "0.1.0"
-dependencies = [
- "async-trait",
- "futures",
- "remain",
- "thiserror",
-]
-
-[[package]]
-name = "autocfg"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
-dependencies = [
- "autocfg 1.1.0",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "balloon_control"
-version = "0.1.0"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "base"
-version = "0.1.0"
-dependencies = [
- "audio_streams",
- "base_event_token_derive",
- "cfg-if",
- "chrono",
- "data_model",
- "env_logger",
- "lazy_static",
- "libc",
- "log",
- "once_cell",
- "rand 0.8.5",
- "regex",
- "remain",
- "serde",
- "serde_json",
- "smallvec",
- "sync",
- "tempfile",
- "thiserror",
- "uuid",
- "win_util",
- "winapi",
-]
-
-[[package]]
-name = "base_event_token_derive"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "bit_field"
-version = "0.1.0"
-dependencies = [
- "bit_field_derive",
-]
-
-[[package]]
-name = "bit_field_derive"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "broker_ipc"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "base",
- "metrics",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
-
-[[package]]
-name = "byteorder"
-version = "1.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
-
-[[package]]
-name = "cbindgen"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51e3973b165dc0f435831a9e426de67e894de532754ff7a3f307c03ee5dec7dc"
-dependencies = [
- "clap",
- "heck",
- "indexmap",
- "log",
- "proc-macro2",
- "quote 1.0.21",
- "serde",
- "serde_json",
- "syn 1.0.99",
- "tempfile",
- "toml",
-]
-
-[[package]]
-name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
-dependencies = [
- "iana-time-zone",
- "js-sys",
- "num-integer",
- "num-traits",
- "serde",
- "time",
- "wasm-bindgen",
- "winapi",
-]
-
-[[package]]
-name = "clap"
-version = "2.34.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
-dependencies = [
- "ansi_term",
- "atty",
- "bitflags",
- "strsim",
- "textwrap",
- "unicode-width",
- "vec_map",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "const-sha1"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
-
-[[package]]
-name = "crc32fast"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "cros_async"
-version = "0.1.1"
-dependencies = [
- "anyhow",
- "async-task",
- "async-trait",
- "audio_streams",
- "base",
- "cfg-if",
- "data_model",
- "futures",
- "futures-executor",
- "futures-util",
- "intrusive-collections",
- "io_uring",
- "libc",
- "once_cell",
- "paste",
- "pin-utils",
- "remain",
- "serde",
- "slab",
- "smallvec",
- "sync",
- "tempfile",
- "thiserror",
- "win_util",
- "winapi",
-]
-
-[[package]]
-name = "cros_fuzz"
-version = "0.1.0"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
-dependencies = [
- "cfg-if",
- "once_cell",
-]
-
-[[package]]
-name = "crosvm"
-version = "0.1.0"
-dependencies = [
- "aarch64",
- "acpi_tables",
- "anyhow",
- "arch",
- "argh",
- "argh_helpers",
- "assertions",
- "audio_streams",
- "base",
- "bit_field",
- "broker_ipc",
- "cfg-if",
- "crosvm_plugin",
- "data_model",
- "devices",
- "disk",
- "enumn",
- "gdbstub",
- "gdbstub_arch",
- "hypervisor",
- "kernel_cmdline",
- "kernel_loader",
- "kvm",
- "kvm_sys",
- "lazy_static",
- "libc",
- "libcras",
- "log",
- "metrics",
- "minijail",
- "net_util",
- "p9",
- "protobuf",
- "protos",
- "remain",
- "resources",
- "rutabaga_gfx",
- "scudo",
- "serde_json",
- "serde_keyvalue",
- "sync",
- "tempfile",
- "terminal_size",
- "thiserror",
- "tube_transporter",
- "uuid",
- "vhost",
- "vm_control",
- "vm_memory",
- "x86_64",
-]
-
-[[package]]
-name = "crosvm-fuzz"
-version = "0.0.1"
-dependencies = [
- "base",
- "cros_fuzz",
- "data_model",
- "devices",
- "disk",
- "fuse",
- "hypervisor",
- "kernel_loader",
- "libc",
- "rand 0.6.5",
- "tempfile",
- "usb_util",
- "vm_memory",
-]
-
-[[package]]
-name = "crosvm_control"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "base",
- "cbindgen",
- "libc",
- "vm_control",
-]
-
-[[package]]
-name = "crosvm_plugin"
-version = "0.17.0"
-dependencies = [
- "base",
- "kvm",
- "kvm_sys",
- "libc",
- "protobuf",
- "protos",
-]
-
-[[package]]
-name = "data_model"
-version = "0.1.0"
-dependencies = [
- "assertions",
- "cfg-if",
- "libc",
- "remain",
- "serde",
- "thiserror",
- "winapi",
-]
-
-[[package]]
-name = "dbus"
-version = "0.9.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6"
-dependencies = [
- "libc",
- "libdbus-sys",
- "winapi",
-]
-
-[[package]]
-name = "derive-into-owned"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "576fce04d31d592013a5887ba8d9c3830adff329e5096d7e1eb5e8e61262ca62"
-dependencies = [
- "quote 0.3.15",
- "syn 0.11.11",
-]
-
-[[package]]
-name = "devices"
-version = "0.1.0"
-dependencies = [
- "acpi_tables",
- "anyhow",
- "argh",
- "async-task",
- "audio_streams",
- "balloon_control",
- "base",
- "bit_field",
- "cfg-if",
- "cros_async",
- "data_model",
- "dbus",
- "disk",
- "enumn",
- "fuse",
- "futures",
- "gpu_display",
- "hypervisor",
- "kvm_sys",
- "libc",
- "libcras",
- "libvda",
- "linux_input_sys",
- "memoffset 0.6.5",
- "minijail",
- "net_sys",
- "net_util",
- "once_cell",
- "p9",
- "power_monitor",
- "protobuf",
- "protos",
- "rand 0.7.3",
- "remain",
- "resources",
- "rutabaga_gfx",
- "serde",
- "serde_json",
- "serde_keyvalue",
- "smallvec",
- "sync",
- "system_api",
- "tempfile",
- "thiserror",
- "tpm2",
- "usb_util",
- "uuid",
- "vfio_sys",
- "vhost",
- "virtio_sys",
- "vm_control",
- "vm_memory",
- "vmm_vhost",
-]
-
-[[package]]
-name = "disk"
-version = "0.1.0"
-dependencies = [
- "async-trait",
- "base",
- "cfg-if",
- "crc32fast",
- "cros_async",
- "data_model",
- "futures",
- "libc",
- "protobuf",
- "protos",
- "remain",
- "serde",
- "tempfile",
- "thiserror",
- "uuid",
- "vm_memory",
-]
-
-[[package]]
-name = "downcast-rs"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
-
-[[package]]
-name = "either"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
-
-[[package]]
-name = "enumn"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "038b1afa59052df211f9efd58f8b1d84c242935ede1c3dbaed26b018a9e06ae2"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "fastrand"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
-dependencies = [
- "instant",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
-[[package]]
-name = "fuse"
-version = "0.1.0"
-dependencies = [
- "base",
- "bitflags",
- "crossbeam-utils",
- "data_model",
- "enumn",
- "libc",
- "remain",
- "thiserror",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
- "num_cpus",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
-
-[[package]]
-name = "futures-task"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
-
-[[package]]
-name = "futures-util"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "gdbstub"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c1f9371c87c11642ee94dcf92cb48b1484ba250b8e8bff3df71c28651f3f4e7"
-dependencies = [
- "bitflags",
- "cfg-if",
- "log",
- "managed",
- "num-traits",
- "paste",
-]
-
-[[package]]
-name = "gdbstub_arch"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c24f469ba9556c5a063d6df35a8a338025fccf96ecae44f330a156b686f7a268"
-dependencies = [
- "gdbstub",
- "num-traits",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "gpu_display"
-version = "0.1.0"
-dependencies = [
- "base",
- "cc",
- "data_model",
- "libc",
- "linux_input_sys",
- "pkg-config",
- "remain",
- "thiserror",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "heck"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
-name = "hypervisor"
-version = "0.1.0"
-dependencies = [
- "base",
- "bit_field",
- "bitflags",
- "data_model",
- "downcast-rs",
- "enumn",
- "fnv",
- "kvm",
- "kvm_sys",
- "libc",
- "memoffset 0.6.5",
- "serde",
- "sync",
- "tempfile",
- "vm_memory",
- "win_util",
- "winapi",
-]
-
-[[package]]
-name = "iana-time-zone"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf7d67cf4a22adc5be66e75ebdf769b3f2ea032041437a7061f97a63dad4b"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "js-sys",
- "wasm-bindgen",
- "winapi",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
-dependencies = [
- "autocfg 1.1.0",
- "hashbrown",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "integration_tests"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "arch",
- "base",
- "libc",
- "tempfile",
-]
-
-[[package]]
-name = "intrusive-collections"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe531a7789d7120f3e17d4f3f2cd95f54418ba7354f60b7b622b6644a07888a"
-dependencies = [
- "memoffset 0.5.6",
-]
-
-[[package]]
-name = "io_uring"
-version = "0.1.1"
-dependencies = [
- "base",
- "data_model",
- "libc",
- "remain",
- "sync",
- "tempfile",
- "thiserror",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
-
-[[package]]
-name = "js-sys"
-version = "0.3.59"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "kernel_cmdline"
-version = "0.1.0"
-dependencies = [
- "libc",
- "remain",
- "thiserror",
-]
-
-[[package]]
-name = "kernel_loader"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
- "libc",
- "remain",
- "tempfile",
- "thiserror",
- "vm_memory",
-]
-
-[[package]]
-name = "kvm"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
- "kvm_sys",
- "libc",
- "sync",
- "vm_memory",
-]
-
-[[package]]
-name = "kvm_sys"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
- "libc",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.131"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
-
-[[package]]
-name = "libcras"
-version = "0.1.0"
-
-[[package]]
-name = "libdbus-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b"
-dependencies = [
- "pkg-config",
-]
-
-[[package]]
-name = "libslirp-sys"
-version = "4.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2772370ce9b7fa05c7eae0bd033005e139a64d52cee498a7905b3eb5d243c5f4"
-dependencies = [
- "pkg-config",
-]
-
-[[package]]
-name = "libvda"
-version = "0.1.0"
-dependencies = [
- "enumn",
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "linux_input_sys"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
- "libc",
-]
-
-[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "managed"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
-
-[[package]]
-name = "memchr"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "memoffset"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
-dependencies = [
- "autocfg 1.1.0",
-]
-
-[[package]]
-name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg 1.1.0",
-]
-
-[[package]]
-name = "metrics"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "base",
- "cfg-if",
- "chrono",
- "lazy_static",
- "libc",
- "protobuf",
- "protoc-rust",
- "serde",
- "serde_json",
- "sync",
- "winapi",
- "wmi",
-]
-
-[[package]]
-name = "minijail"
-version = "0.2.3"
-dependencies = [
- "libc",
- "minijail-sys",
-]
-
-[[package]]
-name = "minijail-sys"
-version = "0.0.13"
-dependencies = [
- "libc",
- "pkg-config",
- "which",
-]
-
-[[package]]
-name = "net_sys"
-version = "0.1.0"
-dependencies = [
- "base",
- "libc",
-]
-
-[[package]]
-name = "net_util"
-version = "0.1.0"
-dependencies = [
- "base",
- "cfg-if",
- "cros_async",
- "data_model",
- "libc",
- "libslirp-sys",
- "metrics",
- "net_sys",
- "pcap-file",
- "remain",
- "serde",
- "smallvec",
- "thiserror",
- "virtio_sys",
- "winapi",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
-dependencies = [
- "autocfg 1.1.0",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
-dependencies = [
- "autocfg 1.1.0",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
-
-[[package]]
-name = "p9"
-version = "0.1.0"
-dependencies = [
- "libc",
- "wire_format_derive",
-]
-
-[[package]]
-name = "paste"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
-
-[[package]]
-name = "pcap-file"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ad13fed1a83120159aea81b265074f21d753d157dd16b10cc3790ecba40a341"
-dependencies = [
- "byteorder",
- "derive-into-owned",
- "thiserror",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
-
-[[package]]
-name = "power_monitor"
-version = "0.1.0"
-dependencies = [
- "base",
- "dbus",
- "protobuf",
- "protoc-rust",
- "remain",
- "thiserror",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "protobuf"
-version = "2.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96"
-dependencies = [
- "serde",
- "serde_derive",
-]
-
-[[package]]
-name = "protobuf-codegen"
-version = "2.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707"
-dependencies = [
- "protobuf",
-]
-
-[[package]]
-name = "protoc"
-version = "2.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2ef1dc036942fac2470fdb8a911f125404ee9129e9e807f3d12d8589001a38f"
-dependencies = [
- "log",
- "which",
-]
-
-[[package]]
-name = "protoc-rust"
-version = "2.27.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a9e315121c8e7e21396e940a3d27f92280a6d28e3931213bf6cbfea76c5cc94"
-dependencies = [
- "protobuf",
- "protobuf-codegen",
- "protoc",
- "tempfile",
-]
-
-[[package]]
-name = "protos"
-version = "0.1.0"
-dependencies = [
- "kvm_sys",
- "protobuf",
- "protoc-rust",
-]
-
-[[package]]
-name = "qcow_utils"
-version = "0.1.0"
-dependencies = [
- "base",
- "disk",
- "libc",
-]
-
-[[package]]
-name = "quote"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-
-[[package]]
-name = "quote"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
-dependencies = [
- "autocfg 0.1.8",
- "libc",
- "rand_chacha 0.1.1",
- "rand_core 0.4.2",
- "rand_hc 0.1.0",
- "rand_isaac",
- "rand_jitter",
- "rand_os",
- "rand_pcg",
- "rand_xorshift",
- "winapi",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc 0.2.0",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
-dependencies = [
- "autocfg 0.1.8",
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.6.3",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom 0.1.16",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
-dependencies = [
- "getrandom 0.2.7",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core 0.5.1",
-]
-
-[[package]]
-name = "rand_isaac"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rand_jitter"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
-dependencies = [
- "libc",
- "rand_core 0.4.2",
- "winapi",
-]
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-dependencies = [
- "cloudabi",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.4.2",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
-dependencies = [
- "autocfg 0.1.8",
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_xorshift"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "regex"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
-
-[[package]]
-name = "remain"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06df529c0d271b27ac4a2c260f5ce2914b60bd44702cecec7b9f271adbdde23b"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "resources"
-version = "0.1.0"
-dependencies = [
- "base",
- "libc",
- "remain",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "rutabaga_gfx"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "base",
- "data_model",
- "libc",
- "pkg-config",
- "remain",
- "serde",
- "sync",
- "thiserror",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
-
-[[package]]
-name = "scudo"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a043122e575636c0e47121917446b4f40803fc6defd8797369e7d2d47086d8e3"
-dependencies = [
- "libc",
- "scudo-sys",
-]
-
-[[package]]
-name = "scudo-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedac72a22df5e73d23abf6b26a9b124a3e10f0e5cc74b9aa8121c7e14cf106"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.143"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.143"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "serde_keyvalue"
-version = "0.1.0"
-dependencies = [
- "argh",
- "num-traits",
- "remain",
- "serde",
- "serde_keyvalue_derive",
- "thiserror",
-]
-
-[[package]]
-name = "serde_keyvalue_derive"
-version = "0.1.0"
-dependencies = [
- "argh",
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "slab"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
-dependencies = [
- "autocfg 1.1.0",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
-
-[[package]]
-name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "syn"
-version = "0.11.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
-dependencies = [
- "quote 0.3.15",
- "synom",
- "unicode-xid",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "unicode-ident",
-]
-
-[[package]]
-name = "sync"
-version = "0.1.0"
-
-[[package]]
-name = "synom"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "system_api"
-version = "0.1.0"
-
-[[package]]
-name = "tempfile"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
-dependencies = [
- "cfg-if",
- "fastrand",
- "libc",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "terminal_size"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "time"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
-dependencies = [
- "libc",
- "wasi 0.10.0+wasi-snapshot-preview1",
- "winapi",
-]
-
-[[package]]
-name = "toml"
-version = "0.5.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "tpm2"
-version = "0.1.0"
-dependencies = [
- "tpm2-sys",
-]
-
-[[package]]
-name = "tpm2-sys"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "pkg-config",
-]
-
-[[package]]
-name = "tube_transporter"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
- "rand 0.8.5",
- "serde",
- "serde_json",
- "thiserror",
- "win_util",
- "winapi",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "unicode-xid"
-version = "0.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
-
-[[package]]
-name = "usb_sys"
-version = "0.1.0"
-dependencies = [
- "base",
-]
-
-[[package]]
-name = "usb_util"
-version = "0.1.0"
-dependencies = [
- "assertions",
- "base",
- "data_model",
- "libc",
- "remain",
- "thiserror",
- "usb_sys",
-]
-
-[[package]]
-name = "uuid"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
-dependencies = [
- "getrandom 0.2.7",
-]
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "vfio_sys"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
-]
-
-[[package]]
-name = "vhost"
-version = "0.1.0"
-dependencies = [
- "assertions",
- "base",
- "libc",
- "net_util",
- "remain",
- "thiserror",
- "virtio_sys",
- "vm_memory",
-]
-
-[[package]]
-name = "virtio_sys"
-version = "0.1.0"
-dependencies = [
- "base",
- "data_model",
-]
-
-[[package]]
-name = "vm_control"
-version = "0.1.0"
-dependencies = [
- "balloon_control",
- "base",
- "data_model",
- "gdbstub_arch",
- "hypervisor",
- "libc",
- "remain",
- "resources",
- "rutabaga_gfx",
- "serde",
- "serde_json",
- "sync",
- "thiserror",
- "vm_memory",
-]
-
-[[package]]
-name = "vm_memory"
-version = "0.1.0"
-dependencies = [
- "base",
- "bitflags",
- "cfg-if",
- "cros_async",
- "data_model",
- "libc",
- "remain",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "vmm_vhost"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "base",
- "bitflags",
- "cfg-if",
- "data_model",
- "libc",
- "remain",
- "serde",
- "serde_json",
- "tempfile",
- "thiserror",
-]
-
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
-dependencies = [
- "quote 1.0.21",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.82"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
-
-[[package]]
-name = "which"
-version = "4.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
-dependencies = [
- "either",
- "lazy_static",
- "libc",
-]
-
-[[package]]
-name = "widestring"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
-
-[[package]]
-name = "win_util"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "lazy_static",
- "libc",
- "winapi",
- "windows",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a43e544233e20425d5a58e9671cf76d6aed9e6f211508c050facb29b188dc10f"
-dependencies = [
- "const-sha1",
- "windows_gen",
- "windows_macros",
-]
-
-[[package]]
-name = "windows_gen"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc6283570a39b3594e31c64a498f48058758cc063eb087d972bb6476ad134a16"
-
-[[package]]
-name = "windows_macros"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f757e7665f81f33ace9f89b0f0fc3a7c770e24ff4fa1475c6503bb35b4524893"
-dependencies = [
- "syn 1.0.99",
- "windows_gen",
-]
-
-[[package]]
-name = "wire_format_derive"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote 1.0.21",
- "syn 1.0.99",
-]
-
-[[package]]
-name = "wmi"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "757a458f9bfab0542c11feed99bd492cbe23add50515bd8eecf8c6973673d32d"
-dependencies = [
- "chrono",
- "log",
- "serde",
- "thiserror",
- "widestring",
- "winapi",
-]
-
-[[package]]
-name = "x86_64"
-version = "0.1.0"
-dependencies = [
- "acpi_tables",
- "anyhow",
- "arch",
- "assertions",
- "base",
- "data_model",
- "devices",
- "gdbstub_arch",
- "hypervisor",
- "kernel_cmdline",
- "kernel_loader",
- "libc",
- "minijail",
- "once_cell",
- "remain",
- "resources",
- "sync",
- "thiserror",
- "vm_control",
- "vm_memory",
-]
diff --git a/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff b/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff
index 0af27df9a19..b2ead32e98e 100644
--- a/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff
+++ b/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff
@@ -1,15 +1,23 @@
-diff --git i/src/crosvm.rs w/src/crosvm.rs
-index ab7c466b..636dc140 100644
---- i/src/crosvm.rs
-+++ w/src/crosvm.rs
-@@ -345,7 +345,9 @@ impl Default for JailConfig {
-     fn default() -> Self {
-         JailConfig {
-             pivot_root: PathBuf::from(option_env!("DEFAULT_PIVOT_ROOT").unwrap_or("/var/empty")),
--            seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR),
-+            seccomp_policy_dir: PathBuf::from(
-+                option_env!("DEFAULT_SECCOMP_POLICY_DIR").unwrap_or(SECCOMP_POLICY_DIR),
-+            ),
-             seccomp_log_failures: false,
-         }
-     }
+diff --git i/src/crosvm/config.rs w/src/crosvm/config.rs
+index 762ea8dbf8..e29cf0e2f6 100644
+--- i/src/crosvm/config.rs
++++ w/src/crosvm/config.rs
+@@ -64,7 +64,6 @@ cfg_if::cfg_if! {
+ 
+         static KVM_PATH: &str = "/dev/kvm";
+         static VHOST_NET_PATH: &str = "/dev/vhost-net";
+-        static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm";
+     } else if #[cfg(windows)] {
+         use base::{Event, Tube};
+ 
+@@ -533,7 +532,9 @@ fn jail_config_default_pivot_root() -> PathBuf {
+ 
+ #[cfg(unix)]
+ fn jail_config_default_seccomp_policy_dir() -> Option<PathBuf> {
+-    Some(PathBuf::from(SECCOMP_POLICY_DIR))
++    Some(PathBuf::from(
++        option_env!("DEFAULT_SECCOMP_POLICY_DIR").unwrap_or("/usr/share/policy/crosvm"),
++    ))
+ }
+ 
+ #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, serde_keyvalue::FromKeyValues)]
diff --git a/pkgs/applications/virtualization/crosvm/default.nix b/pkgs/applications/virtualization/crosvm/default.nix
index ae216001c5e..311a2a63ae2 100644
--- a/pkgs/applications/virtualization/crosvm/default.nix
+++ b/pkgs/applications/virtualization/crosvm/default.nix
@@ -5,12 +5,12 @@
 
 rustPlatform.buildRustPackage rec {
   pname = "crosvm";
-  version = "104.0";
+  version = "106.2";
 
   src = fetchgit {
     url = "https://chromium.googlesource.com/chromiumos/platform/crosvm";
-    rev = "265aab613b1eb31598ea0826f04810d9f010a2c6";
-    sha256 = "OzbtPHs6BWK83RZ/6eCQHA61X6SY8FoBkaN70a37pvc=";
+    rev = "d58d398581724e81ce57a8dfaeef62c175c06552";
+    sha256 = "huZELmB1oH5RyasmpEXIcJ/mB4fi6fMofj1N01COeI8=";
     fetchSubmodules = true;
   };
 
@@ -20,7 +20,7 @@ rustPlatform.buildRustPackage rec {
     ./default-seccomp-policy-dir.diff
   ];
 
-  cargoLock.lockFile = ./Cargo.lock;
+  cargoSha256 = "18mj0zc6yfwyrw6v1vl089dhh04kv2pzb99bygnn8nymdlx4fjqa";
 
   nativeBuildInputs = [ minijail-tools pkg-config protobuf wayland-scanner ];
 
@@ -31,7 +31,6 @@ rustPlatform.buildRustPackage rec {
   arch = stdenv.hostPlatform.parsed.cpu.name;
 
   postPatch = ''
-    cp ${cargoLock.lockFile} Cargo.lock
     sed -i "s|/usr/share/policy/crosvm/|$PWD/seccomp/$arch/|g" \
         seccomp/$arch/*.policy
   '';
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 4/9] crosvm.updateScript: don't vendor Cargo.lock
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (2 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 3/9] crosvm: 104.0 -> 106.2 Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 5/9] crosvm: add fixes for cloud-hypervisor virtio-gpu Alyssa Ross
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

This is no longer required as crosvm now includes a Cargo.lock in-tree
again.

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 pkgs/applications/virtualization/crosvm/update.py | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/pkgs/applications/virtualization/crosvm/update.py b/pkgs/applications/virtualization/crosvm/update.py
index 64adec42957..7a94aedefdb 100755
--- a/pkgs/applications/virtualization/crosvm/update.py
+++ b/pkgs/applications/virtualization/crosvm/update.py
@@ -50,16 +50,3 @@ with urlopen(f'https://chromium.googlesource.com/chromiumos/platform/crosvm/+log
 
 # Update the version, git revision, and hash in crosvm's default.nix.
 subprocess.run(['update-source-version', 'crosvm', f'--rev={rev}', version])
-
-# Find the path to crosvm's default.nix, so Cargo.lock can be written
-# into the same directory.
-argv = ['nix-instantiate', '--eval', '--json', '-A', 'crosvm.meta.position']
-position = json.loads(subprocess.check_output(argv).decode('utf-8'))
-filename = re.match(r'[^:]*', position)[0]
-
-# Generate a Cargo.lock
-run = ['.',
-       dirname(abspath(__file__)) + '/generate-cargo.sh',
-       dirname(filename) + '/Cargo.lock']
-expr = '(import ./. {}).crosvm.overrideAttrs (_: { dontCargoSetupPostUnpack = true; })'
-subprocess.run(['nix-shell', '-E', expr, '--run', shlex.join(run)])
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 5/9] crosvm: add fixes for cloud-hypervisor virtio-gpu
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (3 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 4/9] crosvm.updateScript: don't vendor Cargo.lock Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 6/9] rustPlatform: forward unpack hooks to cargo fetch Alyssa Ross
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 .../virtualization/crosvm/default.nix         |  4 ++
 ...-consider-shm-buuffers-when-setting-.patch | 34 +++++++++
 ...t_user-loosen-expected-message-order.patch | 71 +++++++++++++++++++
 ...ces-vhost_user-remove-spurious-check.patch | 42 +++++++++++
 4 files changed, 151 insertions(+)
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-properly-consider-shm-buuffers-when-setting-.patch
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-vhost_user-loosen-expected-message-order.patch
 create mode 100644 pkgs/applications/virtualization/crosvm/devices-vhost_user-remove-spurious-check.patch

diff --git a/pkgs/applications/virtualization/crosvm/default.nix b/pkgs/applications/virtualization/crosvm/default.nix
index 311a2a63ae2..40e30dcd819 100644
--- a/pkgs/applications/virtualization/crosvm/default.nix
+++ b/pkgs/applications/virtualization/crosvm/default.nix
@@ -18,6 +18,10 @@ rustPlatform.buildRustPackage rec {
 
   patches = [
     ./default-seccomp-policy-dir.diff
+
+    ./devices-properly-consider-shm-buuffers-when-setting-.patch
+    ./devices-vhost_user-remove-spurious-check.patch
+    ./devices-vhost_user-loosen-expected-message-order.patch
   ];
 
   cargoSha256 = "18mj0zc6yfwyrw6v1vl089dhh04kv2pzb99bygnn8nymdlx4fjqa";
diff --git a/pkgs/applications/virtualization/crosvm/devices-properly-consider-shm-buuffers-when-setting-.patch b/pkgs/applications/virtualization/crosvm/devices-properly-consider-shm-buuffers-when-setting-.patch
new file mode 100644
index 00000000000..2f0f95c532a
--- /dev/null
+++ b/pkgs/applications/virtualization/crosvm/devices-properly-consider-shm-buuffers-when-setting-.patch
@@ -0,0 +1,34 @@
+From f5afb62e138017f28966d8fa20b44fe00f301d7d Mon Sep 17 00:00:00 2001
+From: Puck Meerburg <puck@puckipedia.com>
+Date: Mon, 26 Sep 2022 22:40:53 +0000
+Subject: [PATCH crosvm 1/3] devices: properly consider shm buuffers when
+ setting gpu_blob flag
+
+---
+ devices/src/virtio/gpu/virtio_gpu.rs | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/devices/src/virtio/gpu/virtio_gpu.rs b/devices/src/virtio/gpu/virtio_gpu.rs
+index 698215727a..ed97942f7a 100644
+--- a/devices/src/virtio/gpu/virtio_gpu.rs
++++ b/devices/src/virtio/gpu/virtio_gpu.rs
+@@ -26,6 +26,7 @@ use rutabaga_gfx::RutabagaHandle;
+ use rutabaga_gfx::RutabagaIovec;
+ use rutabaga_gfx::Transfer3D;
+ use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_DMABUF;
++use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_SHM;
+ use sync::Mutex;
+ use vm_control::VmMemorySource;
+ use vm_memory::udmabuf::UdmabufDriver;
+@@ -731,7 +732,7 @@ impl VirtioGpu {
+                     descriptor: export.os_handle,
+                     offset: 0,
+                     size: resource.size,
+-                    gpu_blob: true,
++                    gpu_blob: export.handle_type != RUTABAGA_MEM_HANDLE_TYPE_SHM,
+                 },
+             }
+         } else {
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/crosvm/devices-vhost_user-loosen-expected-message-order.patch b/pkgs/applications/virtualization/crosvm/devices-vhost_user-loosen-expected-message-order.patch
new file mode 100644
index 00000000000..bcfab6eace1
--- /dev/null
+++ b/pkgs/applications/virtualization/crosvm/devices-vhost_user-loosen-expected-message-order.patch
@@ -0,0 +1,71 @@
+From 6ac11f04ea3344ca0c3873ee9526a8863c9529ae Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 28 Sep 2022 15:27:39 +0000
+Subject: [PATCH crosvm 3/3] devices: vhost_user: loosen expected message order
+
+Prior to this patch, the code assumed get_shared_memory_regions()
+would be called before set_slave_req_fd(), since
+get_shared_memory_regions() was the only place that set self.shmid,
+and set_slave_req_fd() required it to be set.  There's nothing in the
+vhost-user spec that enforces this ordering though, so it could fail
+when used with a non-crosvm frontend.
+
+To fix this, just don't store the shmid here at all, and fetch it from
+the backend when it's required.  set_slave_req_fd() should only be
+called once, and the two backends that implement
+get_shared_memory_region() (Wl and Gpu) both have trivial
+implementations, so there shouldn't be any performance reason to cache
+shmid here.
+
+TEST=Run cloud-hypervisor against a crosvm vhost-user backend
+
+Change-Id: Idb44aeb1dfe1aeff70081987fe6d7d215887d2e4
+---
+ devices/src/virtio/vhost/user/device/handler.rs | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/devices/src/virtio/vhost/user/device/handler.rs b/devices/src/virtio/vhost/user/device/handler.rs
+index 932d948959..27b4eb1619 100644
+--- a/devices/src/virtio/vhost/user/device/handler.rs
++++ b/devices/src/virtio/vhost/user/device/handler.rs
+@@ -408,7 +408,6 @@ where
+     mem: Option<GuestMemory>,
+     backend: Box<dyn VhostUserBackend>,
+     ops: O,
+-    shmid: Option<u8>,
+ }
+ 
+ impl DeviceRequestHandler<VhostUserRegularOps> {
+@@ -436,7 +435,6 @@ where
+             mem: None,
+             backend,
+             ops,
+-            shmid: None,
+         }
+     }
+ }
+@@ -696,7 +694,12 @@ impl<O: VhostUserPlatformOps> VhostUserSlaveReqHandlerMut for DeviceRequestHandl
+     }
+ 
+     fn set_slave_req_fd(&mut self, ep: Box<dyn Endpoint<SlaveReq>>) {
+-        let shmid = self.shmid.expect("unexpected slave_req_fd");
++        let shmid = self
++            .backend
++            .get_shared_memory_region()
++            .expect("unexpected slave_req_fd")
++            .id;
++
+         let frontend = Slave::new(ep);
+         self.backend
+             .set_shared_memory_mapper(Box::new(VhostShmemMapper {
+@@ -738,7 +741,6 @@ impl<O: VhostUserPlatformOps> VhostUserSlaveReqHandlerMut for DeviceRequestHandl
+ 
+     fn get_shared_memory_regions(&mut self) -> VhostResult<Vec<VhostSharedMemoryRegion>> {
+         Ok(if let Some(r) = self.backend.get_shared_memory_region() {
+-            self.shmid = Some(r.id);
+             vec![VhostSharedMemoryRegion::new(r.id, r.length)]
+         } else {
+             Vec::new()
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/crosvm/devices-vhost_user-remove-spurious-check.patch b/pkgs/applications/virtualization/crosvm/devices-vhost_user-remove-spurious-check.patch
new file mode 100644
index 00000000000..e8ea4db2357
--- /dev/null
+++ b/pkgs/applications/virtualization/crosvm/devices-vhost_user-remove-spurious-check.patch
@@ -0,0 +1,42 @@
+From e895a064f24d0101a230790bdd6adff6cda898d5 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 28 Sep 2022 15:19:26 +0000
+Subject: [PATCH crosvm 2/3] devices: vhost_user: remove spurious check
+
+"size" is the amount of data the caller wants to read, not the size of
+the data available to read, so this check doesn't make any sense.
+It's completely valid to read 4 bytes of a 16 byte config space,
+starting at offset 8, but that would fail this check.  crosvm doesn't
+seem to do this, but cloud-hypervisor does, so this caused crashes
+when running cloud-hypervisor against a crosvm vhost-user backend.
+
+I suspect what this code meant to do is check whether offset + size
+would be beyond the end of the config space, but in this part of the
+code we don't know the size of the config space, so it's not possible
+to check that here.
+
+TEST=Run cloud-hypervisor against a crosvm vhost-user backend
+
+Change-Id: I8a3d7960fb67bf8de37cb3f158081d6421859725
+---
+ devices/src/virtio/vhost/user/device/handler.rs | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/devices/src/virtio/vhost/user/device/handler.rs b/devices/src/virtio/vhost/user/device/handler.rs
+index 32e4aaf876..932d948959 100644
+--- a/devices/src/virtio/vhost/user/device/handler.rs
++++ b/devices/src/virtio/vhost/user/device/handler.rs
+@@ -680,10 +680,6 @@ impl<O: VhostUserPlatformOps> VhostUserSlaveReqHandlerMut for DeviceRequestHandl
+         size: u32,
+         _flags: VhostUserConfigFlags,
+     ) -> VhostResult<Vec<u8>> {
+-        if offset >= size {
+-            return Err(VhostError::InvalidParam);
+-        }
+-
+         let mut data = vec![0; size as usize];
+         self.backend.read_config(u64::from(offset), &mut data);
+         Ok(data)
+-- 
+2.37.1
+
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 6/9] rustPlatform: forward unpack hooks to cargo fetch
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (4 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 5/9] crosvm: add fixes for cloud-hypervisor virtio-gpu Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 7/9] cloud-hypervisor: add virtio-gpu support Alyssa Ross
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

Sometimes it's more ergonomic to set up the build environment in
hooks, to add to the default behaviour rather than replacing it.  It's
very surprising that the fetcher works fine with a custom unpackPhase,
but not with custom preUnpack or postUnpack.

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 pkgs/build-support/rust/build-rust-package/default.nix | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/pkgs/build-support/rust/build-rust-package/default.nix b/pkgs/build-support/rust/build-rust-package/default.nix
index db0d2c53bb1..c35f906ba08 100644
--- a/pkgs/build-support/rust/build-rust-package/default.nix
+++ b/pkgs/build-support/rust/build-rust-package/default.nix
@@ -22,7 +22,9 @@
 
 , src ? null
 , srcs ? null
+, preUnpack ? null
 , unpackPhase ? null
+, postUnpack ? null
 , cargoPatches ? []
 , patches ? []
 , sourceRoot ? null
@@ -63,7 +65,7 @@ let
     if cargoVendorDir != null then null
     else if cargoLock != null then importCargoLock cargoLock
     else fetchCargoTarball ({
-      inherit src srcs sourceRoot unpackPhase cargoUpdateHook;
+      inherit src srcs sourceRoot preUnpack unpackPhase postUnpack cargoUpdateHook;
       name = cargoDepsName;
       patches = cargoPatches;
     } // lib.optionalAttrs (args ? cargoHash) {
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 7/9] cloud-hypervisor: add virtio-gpu support
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (5 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 6/9] rustPlatform: forward unpack hooks to cargo fetch Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 8/9] ocamlPackages.wayland: 1.0 -> 1.1 Alyssa Ross
  2022-09-30 21:12 ` [RFC PATCH nixpkgs v2 9/9] wayland-proxy-virtwl: unstable-2021-12-05 -> unstable-2022-09-22 Alyssa Ross
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen

The virtio-bindings changes update the bindings for recent kernels,
and the vhost change is cherry-picked from crosvm's fork of the crate
to add support for their custom extensions.

Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 .../0001-build-use-local-vhost.patch          |   39 +
 ...dings-regenerate-with-bindgen-0.60.1.patch | 2589 ++++++++++++
 ...0002-build-use-local-virtio-bindings.patch |   39 +
 ...gs-remove-workaround-for-old-bindgen.patch |   28 +
 ...-bindings-regenerate-with-Glibc-2.36.patch |  247 ++
 ...0003-virtio-devices-add-a-GPU-device.patch | 1279 ++++++
 ...-bindings-regenerate-with-Linux-5.19.patch | 1067 +++++
 ...tio-bindings-add-virtio-gpu-bindings.patch | 3587 +++++++++++++++++
 .../cloud-hypervisor/default.nix              |   64 +-
 ...ser-add-shared-memory-region-support.patch |  724 ++++
 10 files changed, 9661 insertions(+), 2 deletions(-)
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0001-build-use-local-vhost.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0002-build-use-local-virtio-bindings.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0002-virtio-bindings-remove-workaround-for-old-bindgen.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-bindings-regenerate-with-Glibc-2.36.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-devices-add-a-GPU-device.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0004-virtio-bindings-regenerate-with-Linux-5.19.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/0005-virtio-bindings-add-virtio-gpu-bindings.patch
 create mode 100644 pkgs/applications/virtualization/cloud-hypervisor/vhost-vhost_user-add-shared-memory-region-support.patch

diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0001-build-use-local-vhost.patch b/pkgs/applications/virtualization/cloud-hypervisor/0001-build-use-local-vhost.patch
new file mode 100644
index 00000000000..c4152ae3504
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0001-build-use-local-vhost.patch
@@ -0,0 +1,39 @@
+From 53848d798c617110c5c3f975db47a9555bc276f4 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 28 Sep 2022 12:18:19 +0000
+Subject: [PATCH 1/3] build: use local vhost
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ Cargo.lock | 2 --
+ Cargo.toml | 1 +
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/Cargo.lock b/Cargo.lock
+index 5d026652..b869b6ee 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -1256,8 +1256,6 @@ dependencies = [
+ [[package]]
+ name = "vhost"
+ version = "0.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "53567fd9ab820e4f3cc156f24146882fee3c365194c3e1dea74723265f27fc88"
+ dependencies = [
+  "bitflags",
+  "libc",
+diff --git a/Cargo.toml b/Cargo.toml
+index ba8377bb..2294b4c3 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -41,6 +41,7 @@ clap = { version = "3.2.17", features = ["cargo"] }
+ kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0-tdx" }
+ kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
+ versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
++vhost = { path = "../vhost" }
+ 
+ [dev-dependencies]
+ dirs = "4.0.0"
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch b/pkgs/applications/virtualization/cloud-hypervisor/0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch
new file mode 100644
index 00000000000..c5ba66e8b36
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch
@@ -0,0 +1,2589 @@
+From c3c2f34c2f89156769d37bc8b450ace9ff7fdbe9 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Tue, 30 Aug 2022 16:18:51 +0000
+Subject: [PATCH 1/5] virtio-bindings: regenerate with bindgen 0.60.1
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ crates/virtio-bindings/CONTRIBUTING.md    |   4 +-
+ crates/virtio-bindings/src/virtio_blk.rs  | 958 +++++++++++++---------
+ crates/virtio-bindings/src/virtio_net.rs  | 817 +++++++++++-------
+ crates/virtio-bindings/src/virtio_ring.rs | 540 +++++++-----
+ 4 files changed, 1426 insertions(+), 893 deletions(-)
+
+diff --git a/crates/virtio-bindings/CONTRIBUTING.md b/crates/virtio-bindings/CONTRIBUTING.md
+index 18c4653..1b3da2f 100644
+--- a/crates/virtio-bindings/CONTRIBUTING.md
++++ b/crates/virtio-bindings/CONTRIBUTING.md
+@@ -4,9 +4,9 @@
+ 
+ ### Bindgen
+ The bindings are currently generated using
+-[bindgen](https://crates.io/crates/bindgen) version 0.49.0:
++[bindgen](https://crates.io/crates/bindgen) version 0.60.1:
+ ```bash
+-cargo install bindgen --vers 0.49.0
++cargo install bindgen --vers 0.60.1
+ ```
+ 
+ ### Linux Kernel
+diff --git a/crates/virtio-bindings/src/virtio_blk.rs b/crates/virtio-bindings/src/virtio_blk.rs
+index 80ddab0..94daca3 100644
+--- a/crates/virtio-bindings/src/virtio_blk.rs
++++ b/crates/virtio-bindings/src/virtio_blk.rs
+@@ -1,4 +1,4 @@
+-/* automatically generated by rust-bindgen */
++/* automatically generated by rust-bindgen 0.60.1 */
+ 
+ pub const __BITS_PER_LONG: u32 = 64;
+ pub const __FD_SETSIZE: u32 = 1024;
+@@ -83,16 +83,23 @@ fn bindgen_test_layout___kernel_fd_set() {
+         8usize,
+         concat!("Alignment of ", stringify!(__kernel_fd_set))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fd_set>())).fds_bits as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fd_set),
+-            "::",
+-            stringify!(fds_bits)
+-        )
+-    );
++    fn test_field_fds_bits() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fd_set>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fd_set),
++                "::",
++                stringify!(fds_bits)
++            )
++        );
++    }
++    test_field_fds_bits();
+ }
+ pub type __kernel_sighandler_t =
+     ::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
+@@ -133,16 +140,23 @@ fn bindgen_test_layout___kernel_fsid_t() {
+         4usize,
+         concat!("Alignment of ", stringify!(__kernel_fsid_t))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fsid_t>())).val as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fsid_t),
+-            "::",
+-            stringify!(val)
+-        )
+-    );
++    fn test_field_val() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fsid_t>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).val) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fsid_t),
++                "::",
++                stringify!(val)
++            )
++        );
++    }
++    test_field_val();
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
+@@ -214,45 +228,60 @@ fn bindgen_test_layout_virtio_blk_config_virtio_blk_geometry() {
+             stringify!(virtio_blk_config_virtio_blk_geometry)
+         )
+     );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config_virtio_blk_geometry>())).cylinders as *const _
+-                as usize
+-        },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config_virtio_blk_geometry),
+-            "::",
+-            stringify!(cylinders)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config_virtio_blk_geometry>())).heads as *const _
+-                as usize
+-        },
+-        2usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config_virtio_blk_geometry),
+-            "::",
+-            stringify!(heads)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config_virtio_blk_geometry>())).sectors as *const _
+-                as usize
+-        },
+-        3usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config_virtio_blk_geometry),
+-            "::",
+-            stringify!(sectors)
+-        )
+-    );
++    fn test_field_cylinders() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_blk_config_virtio_blk_geometry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).cylinders) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config_virtio_blk_geometry),
++                "::",
++                stringify!(cylinders)
++            )
++        );
++    }
++    test_field_cylinders();
++    fn test_field_heads() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_blk_config_virtio_blk_geometry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).heads) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config_virtio_blk_geometry),
++                "::",
++                stringify!(heads)
++            )
++        );
++    }
++    test_field_heads();
++    fn test_field_sectors() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_blk_config_virtio_blk_geometry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).sectors) as usize - ptr as usize
++            },
++            3usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config_virtio_blk_geometry),
++                "::",
++                stringify!(sectors)
++            )
++        );
++    }
++    test_field_sectors();
+ }
+ #[test]
+ fn bindgen_test_layout_virtio_blk_config() {
+@@ -266,215 +295,329 @@ fn bindgen_test_layout_virtio_blk_config() {
+         1usize,
+         concat!("Alignment of ", stringify!(virtio_blk_config))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).capacity as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(capacity)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).size_max as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(size_max)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).seg_max as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(seg_max)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).geometry as *const _ as usize },
+-        16usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(geometry)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).blk_size as *const _ as usize },
+-        20usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(blk_size)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).physical_block_exp as *const _ as usize
+-        },
+-        24usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(physical_block_exp)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).alignment_offset as *const _ as usize
+-        },
+-        25usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(alignment_offset)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).min_io_size as *const _ as usize },
+-        26usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(min_io_size)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).opt_io_size as *const _ as usize },
+-        28usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(opt_io_size)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).wce as *const _ as usize },
+-        32usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(wce)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).unused as *const _ as usize },
+-        33usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(unused)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).num_queues as *const _ as usize },
+-        34usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(num_queues)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).max_discard_sectors as *const _ as usize
+-        },
+-        36usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(max_discard_sectors)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).max_discard_seg as *const _ as usize
+-        },
+-        40usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(max_discard_seg)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).discard_sector_alignment as *const _
+-                as usize
+-        },
+-        44usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(discard_sector_alignment)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).max_write_zeroes_sectors as *const _
+-                as usize
+-        },
+-        48usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(max_write_zeroes_sectors)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).max_write_zeroes_seg as *const _ as usize
+-        },
+-        52usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(max_write_zeroes_seg)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_config>())).write_zeroes_may_unmap as *const _
+-                as usize
+-        },
+-        56usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(write_zeroes_may_unmap)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_config>())).unused1 as *const _ as usize },
+-        57usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_config),
+-            "::",
+-            stringify!(unused1)
+-        )
+-    );
++    fn test_field_capacity() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capacity) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(capacity)
++            )
++        );
++    }
++    test_field_capacity();
++    fn test_field_size_max() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).size_max) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(size_max)
++            )
++        );
++    }
++    test_field_size_max();
++    fn test_field_seg_max() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).seg_max) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(seg_max)
++            )
++        );
++    }
++    test_field_seg_max();
++    fn test_field_geometry() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).geometry) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(geometry)
++            )
++        );
++    }
++    test_field_geometry();
++    fn test_field_blk_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).blk_size) as usize - ptr as usize
++            },
++            20usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(blk_size)
++            )
++        );
++    }
++    test_field_blk_size();
++    fn test_field_physical_block_exp() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).physical_block_exp) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(physical_block_exp)
++            )
++        );
++    }
++    test_field_physical_block_exp();
++    fn test_field_alignment_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).alignment_offset) as usize - ptr as usize
++            },
++            25usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(alignment_offset)
++            )
++        );
++    }
++    test_field_alignment_offset();
++    fn test_field_min_io_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).min_io_size) as usize - ptr as usize
++            },
++            26usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(min_io_size)
++            )
++        );
++    }
++    test_field_min_io_size();
++    fn test_field_opt_io_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).opt_io_size) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(opt_io_size)
++            )
++        );
++    }
++    test_field_opt_io_size();
++    fn test_field_wce() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).wce) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(wce)
++            )
++        );
++    }
++    test_field_wce();
++    fn test_field_unused() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).unused) as usize - ptr as usize
++            },
++            33usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(unused)
++            )
++        );
++    }
++    test_field_unused();
++    fn test_field_num_queues() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_queues) as usize - ptr as usize
++            },
++            34usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(num_queues)
++            )
++        );
++    }
++    test_field_num_queues();
++    fn test_field_max_discard_sectors() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_discard_sectors) as usize - ptr as usize
++            },
++            36usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(max_discard_sectors)
++            )
++        );
++    }
++    test_field_max_discard_sectors();
++    fn test_field_max_discard_seg() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_discard_seg) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(max_discard_seg)
++            )
++        );
++    }
++    test_field_max_discard_seg();
++    fn test_field_discard_sector_alignment() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).discard_sector_alignment) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(discard_sector_alignment)
++            )
++        );
++    }
++    test_field_discard_sector_alignment();
++    fn test_field_max_write_zeroes_sectors() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_write_zeroes_sectors) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(max_write_zeroes_sectors)
++            )
++        );
++    }
++    test_field_max_write_zeroes_sectors();
++    fn test_field_max_write_zeroes_seg() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_write_zeroes_seg) as usize - ptr as usize
++            },
++            52usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(max_write_zeroes_seg)
++            )
++        );
++    }
++    test_field_max_write_zeroes_seg();
++    fn test_field_write_zeroes_may_unmap() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).write_zeroes_may_unmap) as usize - ptr as usize
++            },
++            56usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(write_zeroes_may_unmap)
++            )
++        );
++    }
++    test_field_write_zeroes_may_unmap();
++    fn test_field_unused1() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).unused1) as usize - ptr as usize
++            },
++            57usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_config),
++                "::",
++                stringify!(unused1)
++            )
++        );
++    }
++    test_field_unused1();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -495,36 +638,57 @@ fn bindgen_test_layout_virtio_blk_outhdr() {
+         8usize,
+         concat!("Alignment of ", stringify!(virtio_blk_outhdr))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_outhdr>())).type_ as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_outhdr),
+-            "::",
+-            stringify!(type_)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_outhdr>())).ioprio as *const _ as usize },
+-        4usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_outhdr),
+-            "::",
+-            stringify!(ioprio)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_blk_outhdr>())).sector as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_outhdr),
+-            "::",
+-            stringify!(sector)
+-        )
+-    );
++    fn test_field_type() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_outhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_outhdr),
++                "::",
++                stringify!(type_)
++            )
++        );
++    }
++    test_field_type();
++    fn test_field_ioprio() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_outhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).ioprio) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_outhdr),
++                "::",
++                stringify!(ioprio)
++            )
++        );
++    }
++    test_field_ioprio();
++    fn test_field_sector() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_outhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).sector) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_outhdr),
++                "::",
++                stringify!(sector)
++            )
++        );
++    }
++    test_field_sector();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -545,43 +709,57 @@ fn bindgen_test_layout_virtio_blk_discard_write_zeroes() {
+         8usize,
+         concat!("Alignment of ", stringify!(virtio_blk_discard_write_zeroes))
+     );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_discard_write_zeroes>())).sector as *const _ as usize
+-        },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_discard_write_zeroes),
+-            "::",
+-            stringify!(sector)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_discard_write_zeroes>())).num_sectors as *const _
+-                as usize
+-        },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_discard_write_zeroes),
+-            "::",
+-            stringify!(num_sectors)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_blk_discard_write_zeroes>())).flags as *const _ as usize
+-        },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_blk_discard_write_zeroes),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
++    fn test_field_sector() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_discard_write_zeroes>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).sector) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_discard_write_zeroes),
++                "::",
++                stringify!(sector)
++            )
++        );
++    }
++    test_field_sector();
++    fn test_field_num_sectors() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_discard_write_zeroes>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_sectors) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_discard_write_zeroes),
++                "::",
++                stringify!(num_sectors)
++            )
++        );
++    }
++    test_field_num_sectors();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_blk_discard_write_zeroes>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_blk_discard_write_zeroes),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -603,44 +781,72 @@ fn bindgen_test_layout_virtio_scsi_inhdr() {
+         4usize,
+         concat!("Alignment of ", stringify!(virtio_scsi_inhdr))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_scsi_inhdr>())).errors as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_scsi_inhdr),
+-            "::",
+-            stringify!(errors)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_scsi_inhdr>())).data_len as *const _ as usize },
+-        4usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_scsi_inhdr),
+-            "::",
+-            stringify!(data_len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_scsi_inhdr>())).sense_len as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_scsi_inhdr),
+-            "::",
+-            stringify!(sense_len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_scsi_inhdr>())).residual as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_scsi_inhdr),
+-            "::",
+-            stringify!(residual)
+-        )
+-    );
++    fn test_field_errors() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_scsi_inhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).errors) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_scsi_inhdr),
++                "::",
++                stringify!(errors)
++            )
++        );
++    }
++    test_field_errors();
++    fn test_field_data_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_scsi_inhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).data_len) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_scsi_inhdr),
++                "::",
++                stringify!(data_len)
++            )
++        );
++    }
++    test_field_data_len();
++    fn test_field_sense_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_scsi_inhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).sense_len) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_scsi_inhdr),
++                "::",
++                stringify!(sense_len)
++            )
++        );
++    }
++    test_field_sense_len();
++    fn test_field_residual() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_scsi_inhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).residual) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_scsi_inhdr),
++                "::",
++                stringify!(residual)
++            )
++        );
++    }
++    test_field_residual();
+ }
+diff --git a/crates/virtio-bindings/src/virtio_net.rs b/crates/virtio-bindings/src/virtio_net.rs
+index c788791..479392e 100644
+--- a/crates/virtio-bindings/src/virtio_net.rs
++++ b/crates/virtio-bindings/src/virtio_net.rs
+@@ -1,20 +1,20 @@
+-/* automatically generated by rust-bindgen */
++/* automatically generated by rust-bindgen 0.60.1 */
+ 
+ #[repr(C)]
+ #[derive(Default)]
+ pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
+ impl<T> __IncompleteArrayField<T> {
+     #[inline]
+-    pub fn new() -> Self {
++    pub const fn new() -> Self {
+         __IncompleteArrayField(::std::marker::PhantomData, [])
+     }
+     #[inline]
+-    pub unsafe fn as_ptr(&self) -> *const T {
+-        ::std::mem::transmute(self)
++    pub fn as_ptr(&self) -> *const T {
++        self as *const _ as *const T
+     }
+     #[inline]
+-    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
+-        ::std::mem::transmute(self)
++    pub fn as_mut_ptr(&mut self) -> *mut T {
++        self as *mut _ as *mut T
+     }
+     #[inline]
+     pub unsafe fn as_slice(&self, len: usize) -> &[T] {
+@@ -30,12 +30,6 @@ impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+         fmt.write_str("__IncompleteArrayField")
+     }
+ }
+-impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
+-    #[inline]
+-    fn clone(&self) -> Self {
+-        Self::new()
+-    }
+-}
+ pub const __BITS_PER_LONG: u32 = 64;
+ pub const __FD_SETSIZE: u32 = 1024;
+ pub const VIRTIO_ID_NET: u32 = 1;
+@@ -250,16 +244,23 @@ fn bindgen_test_layout___kernel_fd_set() {
+         8usize,
+         concat!("Alignment of ", stringify!(__kernel_fd_set))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fd_set>())).fds_bits as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fd_set),
+-            "::",
+-            stringify!(fds_bits)
+-        )
+-    );
++    fn test_field_fds_bits() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fd_set>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fd_set),
++                "::",
++                stringify!(fds_bits)
++            )
++        );
++    }
++    test_field_fds_bits();
+ }
+ pub type __kernel_sighandler_t =
+     ::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
+@@ -300,16 +301,23 @@ fn bindgen_test_layout___kernel_fsid_t() {
+         4usize,
+         concat!("Alignment of ", stringify!(__kernel_fsid_t))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fsid_t>())).val as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fsid_t),
+-            "::",
+-            stringify!(val)
+-        )
+-    );
++    fn test_field_val() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fsid_t>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).val) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fsid_t),
++                "::",
++                stringify!(val)
++            )
++        );
++    }
++    test_field_val();
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
+@@ -352,36 +360,57 @@ fn bindgen_test_layout_ethhdr() {
+         1usize,
+         concat!("Alignment of ", stringify!(ethhdr))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<ethhdr>())).h_dest as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(ethhdr),
+-            "::",
+-            stringify!(h_dest)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<ethhdr>())).h_source as *const _ as usize },
+-        6usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(ethhdr),
+-            "::",
+-            stringify!(h_source)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<ethhdr>())).h_proto as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(ethhdr),
+-            "::",
+-            stringify!(h_proto)
+-        )
+-    );
++    fn test_field_h_dest() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<ethhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).h_dest) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(ethhdr),
++                "::",
++                stringify!(h_dest)
++            )
++        );
++    }
++    test_field_h_dest();
++    fn test_field_h_source() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<ethhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).h_source) as usize - ptr as usize
++            },
++            6usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(ethhdr),
++                "::",
++                stringify!(h_source)
++            )
++        );
++    }
++    test_field_h_source();
++    fn test_field_h_proto() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<ethhdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).h_proto) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(ethhdr),
++                "::",
++                stringify!(h_proto)
++            )
++        );
++    }
++    test_field_h_proto();
+ }
+ #[repr(C, packed)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -405,68 +434,108 @@ fn bindgen_test_layout_virtio_net_config() {
+         1usize,
+         concat!("Alignment of ", stringify!(virtio_net_config))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_config>())).mac as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(mac)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_config>())).status as *const _ as usize },
+-        6usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(status)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_net_config>())).max_virtqueue_pairs as *const _ as usize
+-        },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(max_virtqueue_pairs)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_config>())).mtu as *const _ as usize },
+-        10usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(mtu)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_config>())).speed as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(speed)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_config>())).duplex as *const _ as usize },
+-        16usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_config),
+-            "::",
+-            stringify!(duplex)
+-        )
+-    );
++    fn test_field_mac() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).mac) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(mac)
++            )
++        );
++    }
++    test_field_mac();
++    fn test_field_status() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).status) as usize - ptr as usize
++            },
++            6usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(status)
++            )
++        );
++    }
++    test_field_status();
++    fn test_field_max_virtqueue_pairs() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_virtqueue_pairs) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(max_virtqueue_pairs)
++            )
++        );
++    }
++    test_field_max_virtqueue_pairs();
++    fn test_field_mtu() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).mtu) as usize - ptr as usize
++            },
++            10usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(mtu)
++            )
++        );
++    }
++    test_field_mtu();
++    fn test_field_speed() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).speed) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(speed)
++            )
++        );
++    }
++    test_field_speed();
++    fn test_field_duplex() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).duplex) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(duplex)
++            )
++        );
++    }
++    test_field_duplex();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -491,76 +560,125 @@ fn bindgen_test_layout_virtio_net_hdr_v1() {
+         2usize,
+         concat!("Alignment of ", stringify!(virtio_net_hdr_v1))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).flags as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).gso_type as *const _ as usize },
+-        1usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(gso_type)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).hdr_len as *const _ as usize },
+-        2usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(hdr_len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).gso_size as *const _ as usize },
+-        4usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(gso_size)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).csum_start as *const _ as usize },
+-        6usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(csum_start)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).csum_offset as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(csum_offset)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_v1>())).num_buffers as *const _ as usize },
+-        10usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_v1),
+-            "::",
+-            stringify!(num_buffers)
+-        )
+-    );
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_gso_type() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).gso_type) as usize - ptr as usize
++            },
++            1usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(gso_type)
++            )
++        );
++    }
++    test_field_gso_type();
++    fn test_field_hdr_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr_len) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(hdr_len)
++            )
++        );
++    }
++    test_field_hdr_len();
++    fn test_field_gso_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).gso_size) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(gso_size)
++            )
++        );
++    }
++    test_field_gso_size();
++    fn test_field_csum_start() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_start) as usize - ptr as usize
++            },
++            6usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(csum_start)
++            )
++        );
++    }
++    test_field_csum_start();
++    fn test_field_csum_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_offset) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(csum_offset)
++            )
++        );
++    }
++    test_field_csum_offset();
++    fn test_field_num_buffers() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_buffers) as usize - ptr as usize
++            },
++            10usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1),
++                "::",
++                stringify!(num_buffers)
++            )
++        );
++    }
++    test_field_num_buffers();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -584,66 +702,108 @@ fn bindgen_test_layout_virtio_net_hdr() {
+         2usize,
+         concat!("Alignment of ", stringify!(virtio_net_hdr))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).flags as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).gso_type as *const _ as usize },
+-        1usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(gso_type)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).hdr_len as *const _ as usize },
+-        2usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(hdr_len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).gso_size as *const _ as usize },
+-        4usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(gso_size)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).csum_start as *const _ as usize },
+-        6usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(csum_start)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr>())).csum_offset as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr),
+-            "::",
+-            stringify!(csum_offset)
+-        )
+-    );
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_gso_type() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).gso_type) as usize - ptr as usize
++            },
++            1usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(gso_type)
++            )
++        );
++    }
++    test_field_gso_type();
++    fn test_field_hdr_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr_len) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(hdr_len)
++            )
++        );
++    }
++    test_field_hdr_len();
++    fn test_field_gso_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).gso_size) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(gso_size)
++            )
++        );
++    }
++    test_field_gso_size();
++    fn test_field_csum_start() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_start) as usize - ptr as usize
++            },
++            6usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(csum_start)
++            )
++        );
++    }
++    test_field_csum_start();
++    fn test_field_csum_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_offset) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr),
++                "::",
++                stringify!(csum_offset)
++            )
++        );
++    }
++    test_field_csum_offset();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -663,28 +823,40 @@ fn bindgen_test_layout_virtio_net_hdr_mrg_rxbuf() {
+         2usize,
+         concat!("Alignment of ", stringify!(virtio_net_hdr_mrg_rxbuf))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_hdr_mrg_rxbuf>())).hdr as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_mrg_rxbuf),
+-            "::",
+-            stringify!(hdr)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_net_hdr_mrg_rxbuf>())).num_buffers as *const _ as usize
+-        },
+-        10usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_hdr_mrg_rxbuf),
+-            "::",
+-            stringify!(num_buffers)
+-        )
+-    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_mrg_rxbuf>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_mrg_rxbuf),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_num_buffers() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_mrg_rxbuf>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_buffers) as usize - ptr as usize
++            },
++            10usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_mrg_rxbuf),
++                "::",
++                stringify!(num_buffers)
++            )
++        );
++    }
++    test_field_num_buffers();
+ }
+ #[repr(C, packed)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -704,30 +876,43 @@ fn bindgen_test_layout_virtio_net_ctrl_hdr() {
+         1usize,
+         concat!("Alignment of ", stringify!(virtio_net_ctrl_hdr))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_ctrl_hdr>())).class as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_ctrl_hdr),
+-            "::",
+-            stringify!(class)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<virtio_net_ctrl_hdr>())).cmd as *const _ as usize },
+-        1usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_ctrl_hdr),
+-            "::",
+-            stringify!(cmd)
+-        )
+-    );
++    fn test_field_class() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).class) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_ctrl_hdr),
++                "::",
++                stringify!(class)
++            )
++        );
++    }
++    test_field_class();
++    fn test_field_cmd() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).cmd) as usize - ptr as usize
++            },
++            1usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_ctrl_hdr),
++                "::",
++                stringify!(cmd)
++            )
++        );
++    }
++    test_field_cmd();
+ }
+ pub type virtio_net_ctrl_ack = __u8;
+ #[repr(C, packed)]
+-#[derive(Default)]
+ pub struct virtio_net_ctrl_mac {
+     pub entries: __virtio32,
+     pub macs: __IncompleteArrayField<[__u8; 6usize]>,
+@@ -745,6 +930,15 @@ fn bindgen_test_layout_virtio_net_ctrl_mac() {
+         concat!("Alignment of ", stringify!(virtio_net_ctrl_mac))
+     );
+ }
++impl Default for virtio_net_ctrl_mac {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
++}
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+ pub struct virtio_net_ctrl_mq {
+@@ -762,16 +956,21 @@ fn bindgen_test_layout_virtio_net_ctrl_mq() {
+         2usize,
+         concat!("Alignment of ", stringify!(virtio_net_ctrl_mq))
+     );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<virtio_net_ctrl_mq>())).virtqueue_pairs as *const _ as usize
+-        },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(virtio_net_ctrl_mq),
+-            "::",
+-            stringify!(virtqueue_pairs)
+-        )
+-    );
++    fn test_field_virtqueue_pairs() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_ctrl_mq>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).virtqueue_pairs) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_ctrl_mq),
++                "::",
++                stringify!(virtqueue_pairs)
++            )
++        );
++    }
++    test_field_virtqueue_pairs();
+ }
+diff --git a/crates/virtio-bindings/src/virtio_ring.rs b/crates/virtio-bindings/src/virtio_ring.rs
+index 0d51550..13fa409 100644
+--- a/crates/virtio-bindings/src/virtio_ring.rs
++++ b/crates/virtio-bindings/src/virtio_ring.rs
+@@ -1,20 +1,20 @@
+-/* automatically generated by rust-bindgen */
++/* automatically generated by rust-bindgen 0.60.1 */
+ 
+ #[repr(C)]
+ #[derive(Default)]
+ pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
+ impl<T> __IncompleteArrayField<T> {
+     #[inline]
+-    pub fn new() -> Self {
++    pub const fn new() -> Self {
+         __IncompleteArrayField(::std::marker::PhantomData, [])
+     }
+     #[inline]
+-    pub unsafe fn as_ptr(&self) -> *const T {
+-        ::std::mem::transmute(self)
++    pub fn as_ptr(&self) -> *const T {
++        self as *const _ as *const T
+     }
+     #[inline]
+-    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
+-        ::std::mem::transmute(self)
++    pub fn as_mut_ptr(&mut self) -> *mut T {
++        self as *mut _ as *mut T
+     }
+     #[inline]
+     pub unsafe fn as_slice(&self, len: usize) -> &[T] {
+@@ -30,12 +30,6 @@ impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+         fmt.write_str("__IncompleteArrayField")
+     }
+ }
+-impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
+-    #[inline]
+-    fn clone(&self) -> Self {
+-        Self::new()
+-    }
+-}
+ pub const _STDINT_H: u32 = 1;
+ pub const _FEATURES_H: u32 = 1;
+ pub const _DEFAULT_SOURCE: u32 = 1;
+@@ -190,16 +184,23 @@ fn bindgen_test_layout___fsid_t() {
+         4usize,
+         concat!("Alignment of ", stringify!(__fsid_t))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__fsid_t>())).__val as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__fsid_t),
+-            "::",
+-            stringify!(__val)
+-        )
+-    );
++    fn test_field___val() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__fsid_t>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).__val) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__fsid_t),
++                "::",
++                stringify!(__val)
++            )
++        );
++    }
++    test_field___val();
+ }
+ pub type __clock_t = ::std::os::raw::c_long;
+ pub type __rlim_t = ::std::os::raw::c_ulong;
+@@ -271,16 +272,23 @@ fn bindgen_test_layout___kernel_fd_set() {
+         8usize,
+         concat!("Alignment of ", stringify!(__kernel_fd_set))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fd_set>())).fds_bits as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fd_set),
+-            "::",
+-            stringify!(fds_bits)
+-        )
+-    );
++    fn test_field_fds_bits() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fd_set>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fd_set),
++                "::",
++                stringify!(fds_bits)
++            )
++        );
++    }
++    test_field_fds_bits();
+ }
+ pub type __kernel_sighandler_t =
+     ::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
+@@ -321,16 +329,23 @@ fn bindgen_test_layout___kernel_fsid_t() {
+         4usize,
+         concat!("Alignment of ", stringify!(__kernel_fsid_t))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<__kernel_fsid_t>())).val as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(__kernel_fsid_t),
+-            "::",
+-            stringify!(val)
+-        )
+-    );
++    fn test_field_val() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fsid_t>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).val) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fsid_t),
++                "::",
++                stringify!(val)
++            )
++        );
++    }
++    test_field_val();
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
+@@ -374,46 +389,74 @@ fn bindgen_test_layout_vring_desc() {
+         8usize,
+         concat!("Alignment of ", stringify!(vring_desc))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_desc>())).addr as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_desc),
+-            "::",
+-            stringify!(addr)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_desc>())).len as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_desc),
+-            "::",
+-            stringify!(len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_desc>())).flags as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_desc),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_desc>())).next as *const _ as usize },
+-        14usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_desc),
+-            "::",
+-            stringify!(next)
+-        )
+-    );
++    fn test_field_addr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_desc),
++                "::",
++                stringify!(addr)
++            )
++        );
++    }
++    test_field_addr();
++    fn test_field_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_desc),
++                "::",
++                stringify!(len)
++            )
++        );
++    }
++    test_field_len();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_desc),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_next() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).next) as usize - ptr as usize
++            },
++            14usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_desc),
++                "::",
++                stringify!(next)
++            )
++        );
++    }
++    test_field_next();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default)]
+@@ -453,26 +496,40 @@ fn bindgen_test_layout_vring_used_elem() {
+         4usize,
+         concat!("Alignment of ", stringify!(vring_used_elem))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_used_elem>())).id as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_used_elem),
+-            "::",
+-            stringify!(id)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_used_elem>())).len as *const _ as usize },
+-        4usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_used_elem),
+-            "::",
+-            stringify!(len)
+-        )
+-    );
++    fn test_field_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_used_elem>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_used_elem),
++                "::",
++                stringify!(id)
++            )
++        );
++    }
++    test_field_id();
++    fn test_field_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_used_elem>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_used_elem),
++                "::",
++                stringify!(len)
++            )
++        );
++    }
++    test_field_len();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default)]
+@@ -480,7 +537,6 @@ pub struct vring_used {
+     pub flags: __virtio16,
+     pub idx: __virtio16,
+     pub ring: __IncompleteArrayField<vring_used_elem>,
+-    pub __bindgen_align: [u32; 0usize],
+ }
+ #[test]
+ fn bindgen_test_layout_vring_used() {
+@@ -515,50 +571,82 @@ fn bindgen_test_layout_vring() {
+         8usize,
+         concat!("Alignment of ", stringify!(vring))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring>())).num as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring),
+-            "::",
+-            stringify!(num)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring>())).desc as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring),
+-            "::",
+-            stringify!(desc)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring>())).avail as *const _ as usize },
+-        16usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring),
+-            "::",
+-            stringify!(avail)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring>())).used as *const _ as usize },
+-        24usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring),
+-            "::",
+-            stringify!(used)
+-        )
+-    );
++    fn test_field_num() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring),
++                "::",
++                stringify!(num)
++            )
++        );
++    }
++    test_field_num();
++    fn test_field_desc() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).desc) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring),
++                "::",
++                stringify!(desc)
++            )
++        );
++    }
++    test_field_desc();
++    fn test_field_avail() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).avail) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring),
++                "::",
++                stringify!(avail)
++            )
++        );
++    }
++    test_field_avail();
++    fn test_field_used() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).used) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring),
++                "::",
++                stringify!(used)
++            )
++        );
++    }
++    test_field_used();
+ }
+ impl Default for vring {
+     fn default() -> Self {
+-        unsafe { ::std::mem::zeroed() }
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
+     }
+ }
+ #[repr(C)]
+@@ -579,28 +667,40 @@ fn bindgen_test_layout_vring_packed_desc_event() {
+         2usize,
+         concat!("Alignment of ", stringify!(vring_packed_desc_event))
+     );
+-    assert_eq!(
+-        unsafe {
+-            &(*(::std::ptr::null::<vring_packed_desc_event>())).off_wrap as *const _ as usize
+-        },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc_event),
+-            "::",
+-            stringify!(off_wrap)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_packed_desc_event>())).flags as *const _ as usize },
+-        2usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc_event),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
++    fn test_field_off_wrap() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc_event>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).off_wrap) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc_event),
++                "::",
++                stringify!(off_wrap)
++            )
++        );
++    }
++    test_field_off_wrap();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc_event>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc_event),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -622,44 +722,72 @@ fn bindgen_test_layout_vring_packed_desc() {
+         8usize,
+         concat!("Alignment of ", stringify!(vring_packed_desc))
+     );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_packed_desc>())).addr as *const _ as usize },
+-        0usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc),
+-            "::",
+-            stringify!(addr)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_packed_desc>())).len as *const _ as usize },
+-        8usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc),
+-            "::",
+-            stringify!(len)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_packed_desc>())).id as *const _ as usize },
+-        12usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc),
+-            "::",
+-            stringify!(id)
+-        )
+-    );
+-    assert_eq!(
+-        unsafe { &(*(::std::ptr::null::<vring_packed_desc>())).flags as *const _ as usize },
+-        14usize,
+-        concat!(
+-            "Offset of field: ",
+-            stringify!(vring_packed_desc),
+-            "::",
+-            stringify!(flags)
+-        )
+-    );
++    fn test_field_addr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc),
++                "::",
++                stringify!(addr)
++            )
++        );
++    }
++    test_field_addr();
++    fn test_field_len() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc),
++                "::",
++                stringify!(len)
++            )
++        );
++    }
++    test_field_len();
++    fn test_field_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc),
++                "::",
++                stringify!(id)
++            )
++        );
++    }
++    test_field_id();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_packed_desc>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            14usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_packed_desc),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
+ }
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0002-build-use-local-virtio-bindings.patch b/pkgs/applications/virtualization/cloud-hypervisor/0002-build-use-local-virtio-bindings.patch
new file mode 100644
index 00000000000..e5d56924154
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0002-build-use-local-virtio-bindings.patch
@@ -0,0 +1,39 @@
+From f8d05ec6b4b581069da14fe54df93b932223cd24 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 28 Sep 2022 12:30:42 +0000
+Subject: [PATCH 2/3] build: use local virtio-bindings
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ Cargo.lock | 2 --
+ Cargo.toml | 1 +
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/Cargo.lock b/Cargo.lock
+index b869b6ee..d119f28e 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -1319,8 +1319,6 @@ dependencies = [
+ [[package]]
+ name = "virtio-bindings"
+ version = "0.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b"
+ 
+ [[package]]
+ name = "virtio-devices"
+diff --git a/Cargo.toml b/Cargo.toml
+index 2294b4c3..8900236a 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -42,6 +42,7 @@ kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branc
+ kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
+ versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
+ vhost = { path = "../vhost" }
++virtio-bindings = { path = "../virtio-bindings" }
+ 
+ [dev-dependencies]
+ dirs = "4.0.0"
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0002-virtio-bindings-remove-workaround-for-old-bindgen.patch b/pkgs/applications/virtualization/cloud-hypervisor/0002-virtio-bindings-remove-workaround-for-old-bindgen.patch
new file mode 100644
index 00000000000..3bf339d320f
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0002-virtio-bindings-remove-workaround-for-old-bindgen.patch
@@ -0,0 +1,28 @@
+From f29e97e490efac68d3d8c92a50716fb2db76e7df Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 31 Aug 2022 16:37:13 +0000
+Subject: [PATCH 2/5] virtio-bindings: remove workaround for old bindgen
+
+The linked issue was fixed in bindgen 0.60.0.
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ crates/virtio-bindings/src/lib.rs | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/crates/virtio-bindings/src/lib.rs b/crates/virtio-bindings/src/lib.rs
+index 257ebfc..9702f17 100644
+--- a/crates/virtio-bindings/src/lib.rs
++++ b/crates/virtio-bindings/src/lib.rs
+@@ -5,8 +5,6 @@
+ #![allow(non_upper_case_globals)]
+ #![allow(non_camel_case_types)]
+ #![allow(non_snake_case)]
+-// Keep this until https://github.com/rust-lang/rust-bindgen/issues/1651 is fixed.
+-#![cfg_attr(test, allow(deref_nullptr, unaligned_references))]
+ 
+ pub mod virtio_blk;
+ pub mod virtio_net;
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-bindings-regenerate-with-Glibc-2.36.patch b/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-bindings-regenerate-with-Glibc-2.36.patch
new file mode 100644
index 00000000000..99efa76e393
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-bindings-regenerate-with-Glibc-2.36.patch
@@ -0,0 +1,247 @@
+From e83b5b0a8d2c3b7a380d7741d7e20824cdc8245f Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 31 Aug 2022 16:28:41 +0000
+Subject: [PATCH 3/5] virtio-bindings: regenerate with Glibc 2.36
+
+In future, it would be good to exclude a lot of these Glibc
+re-exports.  They're probably not required for all the virtio bindings
+we want to expose.
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ crates/virtio-bindings/src/virtio_net.rs  |  34 ++++++
+ crates/virtio-bindings/src/virtio_ring.rs | 122 +++++++++++++++++++++-
+ 2 files changed, 151 insertions(+), 5 deletions(-)
+
+diff --git a/crates/virtio-bindings/src/virtio_net.rs b/crates/virtio-bindings/src/virtio_net.rs
+index 479392e..5707375 100644
+--- a/crates/virtio-bindings/src/virtio_net.rs
++++ b/crates/virtio-bindings/src/virtio_net.rs
+@@ -929,6 +929,40 @@ fn bindgen_test_layout_virtio_net_ctrl_mac() {
+         1usize,
+         concat!("Alignment of ", stringify!(virtio_net_ctrl_mac))
+     );
++    fn test_field_entries() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_ctrl_mac>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_ctrl_mac),
++                "::",
++                stringify!(entries)
++            )
++        );
++    }
++    test_field_entries();
++    fn test_field_macs() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_ctrl_mac>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).macs) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_ctrl_mac),
++                "::",
++                stringify!(macs)
++            )
++        );
++    }
++    test_field_macs();
+ }
+ impl Default for virtio_net_ctrl_mac {
+     fn default() -> Self {
+diff --git a/crates/virtio-bindings/src/virtio_ring.rs b/crates/virtio-bindings/src/virtio_ring.rs
+index 13fa409..60b84ab 100644
+--- a/crates/virtio-bindings/src/virtio_ring.rs
++++ b/crates/virtio-bindings/src/virtio_ring.rs
+@@ -33,6 +33,7 @@ impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+ pub const _STDINT_H: u32 = 1;
+ pub const _FEATURES_H: u32 = 1;
+ pub const _DEFAULT_SOURCE: u32 = 1;
++pub const __GLIBC_USE_ISOC2X: u32 = 0;
+ pub const __USE_ISOC11: u32 = 1;
+ pub const __USE_ISOC99: u32 = 1;
+ pub const __USE_ISOC95: u32 = 1;
+@@ -46,6 +47,10 @@ pub const __USE_POSIX199506: u32 = 1;
+ pub const __USE_XOPEN2K: u32 = 1;
+ pub const __USE_XOPEN2K8: u32 = 1;
+ pub const _ATFILE_SOURCE: u32 = 1;
++pub const __WORDSIZE: u32 = 64;
++pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1;
++pub const __SYSCALL_WORDSIZE: u32 = 64;
++pub const __TIMESIZE: u32 = 64;
+ pub const __USE_MISC: u32 = 1;
+ pub const __USE_ATFILE: u32 = 1;
+ pub const __USE_FORTIFY_LEVEL: u32 = 0;
+@@ -53,27 +58,31 @@ pub const __GLIBC_USE_DEPRECATED_GETS: u32 = 0;
+ pub const __GLIBC_USE_DEPRECATED_SCANF: u32 = 0;
+ pub const _STDC_PREDEF_H: u32 = 1;
+ pub const __STDC_IEC_559__: u32 = 1;
++pub const __STDC_IEC_60559_BFP__: u32 = 201404;
+ pub const __STDC_IEC_559_COMPLEX__: u32 = 1;
++pub const __STDC_IEC_60559_COMPLEX__: u32 = 201404;
+ pub const __STDC_ISO_10646__: u32 = 201706;
+ pub const __GNU_LIBRARY__: u32 = 6;
+ pub const __GLIBC__: u32 = 2;
+-pub const __GLIBC_MINOR__: u32 = 29;
++pub const __GLIBC_MINOR__: u32 = 36;
+ pub const _SYS_CDEFS_H: u32 = 1;
+ pub const __glibc_c99_flexarr_available: u32 = 1;
+-pub const __WORDSIZE: u32 = 64;
+-pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1;
+-pub const __SYSCALL_WORDSIZE: u32 = 64;
++pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0;
+ pub const __HAVE_GENERIC_SELECTION: u32 = 1;
+ pub const __GLIBC_USE_LIB_EXT2: u32 = 0;
+ pub const __GLIBC_USE_IEC_60559_BFP_EXT: u32 = 0;
++pub const __GLIBC_USE_IEC_60559_BFP_EXT_C2X: u32 = 0;
++pub const __GLIBC_USE_IEC_60559_EXT: u32 = 0;
+ pub const __GLIBC_USE_IEC_60559_FUNCS_EXT: u32 = 0;
++pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X: u32 = 0;
+ pub const __GLIBC_USE_IEC_60559_TYPES_EXT: u32 = 0;
+ pub const _BITS_TYPES_H: u32 = 1;
+-pub const __TIMESIZE: u32 = 64;
+ pub const _BITS_TYPESIZES_H: u32 = 1;
+ pub const __OFF_T_MATCHES_OFF64_T: u32 = 1;
+ pub const __INO_T_MATCHES_INO64_T: u32 = 1;
+ pub const __RLIM_T_MATCHES_RLIM64_T: u32 = 1;
++pub const __STATFS_MATCHES_STATFS64: u32 = 1;
++pub const __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64: u32 = 1;
+ pub const __FD_SETSIZE: u32 = 1024;
+ pub const _BITS_TIME64_H: u32 = 1;
+ pub const _BITS_WCHAR_H: u32 = 1;
+@@ -209,6 +218,7 @@ pub type __id_t = ::std::os::raw::c_uint;
+ pub type __time_t = ::std::os::raw::c_long;
+ pub type __useconds_t = ::std::os::raw::c_uint;
+ pub type __suseconds_t = ::std::os::raw::c_long;
++pub type __suseconds64_t = ::std::os::raw::c_long;
+ pub type __daddr_t = ::std::os::raw::c_int;
+ pub type __key_t = ::std::os::raw::c_int;
+ pub type __clockid_t = ::std::os::raw::c_int;
+@@ -477,6 +487,57 @@ fn bindgen_test_layout_vring_avail() {
+         2usize,
+         concat!("Alignment of ", stringify!(vring_avail))
+     );
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_avail>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_avail),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_idx() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_avail>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).idx) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_avail),
++                "::",
++                stringify!(idx)
++            )
++        );
++    }
++    test_field_idx();
++    fn test_field_ring() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_avail>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).ring) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_avail),
++                "::",
++                stringify!(ring)
++            )
++        );
++    }
++    test_field_ring();
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+@@ -550,6 +611,57 @@ fn bindgen_test_layout_vring_used() {
+         4usize,
+         concat!("Alignment of ", stringify!(vring_used))
+     );
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_used>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_used),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_idx() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_used>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).idx) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_used),
++                "::",
++                stringify!(idx)
++            )
++        );
++    }
++    test_field_idx();
++    fn test_field_ring() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<vring_used>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).ring) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(vring_used),
++                "::",
++                stringify!(ring)
++            )
++        );
++    }
++    test_field_ring();
+ }
+ #[repr(C)]
+ #[derive(Debug, Copy, Clone, PartialEq)]
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-devices-add-a-GPU-device.patch b/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-devices-add-a-GPU-device.patch
new file mode 100644
index 00000000000..20b1f9da3af
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0003-virtio-devices-add-a-GPU-device.patch
@@ -0,0 +1,1279 @@
+From cadce3914276387389d10fd2d180c85c46d77f20 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 7 Sep 2022 14:16:29 +0000
+Subject: [PATCH 3/3] virtio-devices: add a GPU device
+
+This adds support for exposing a virtio-gpu device to guest by
+implementing a vhost-user frontend compatible with crosvm's GPU device
+backend.
+
+Note that this is not the same as the "vhost-user-gpu" protocol
+implemented by QEMU.
+
+Adding a GPU device from the command line looks like this:
+
+    --gpu socket=/path/to/crosvm-gpu-vhost-user.sock
+
+As a workaround, We fall back to trying to map shared memory as
+read-only if it can't be mapped read-write, because wlroots' keymaps
+are read-only, and crosvm does not properly handle this, causing
+cloud-hypervisor to crash.
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+Co-authored-by: Puck Meerburg <puck@puckipedia.com>
+Signed-off-by: Puck Meerburg <puck@puckipedia.com>
+---
+ Cargo.lock                                    |   1 +
+ src/main.rs                                   |   9 +
+ virtio-devices/src/device.rs                  |   8 +-
+ virtio-devices/src/lib.rs                     |   2 +
+ virtio-devices/src/seccomp_filters.rs         |  10 +
+ virtio-devices/src/transport/pci_device.rs    |   4 +-
+ virtio-devices/src/vhost_user/gpu.rs          | 372 ++++++++++++++++++
+ virtio-devices/src/vhost_user/mod.rs          |   2 +
+ .../src/vhost_user/vu_common_ctrl.rs          |  14 +-
+ vmm/Cargo.toml                                |   1 +
+ vmm/src/api/mod.rs                            |   7 +
+ vmm/src/config.rs                             | 123 ++++++
+ vmm/src/device_manager.rs                     | 140 ++++++-
+ vmm/src/lib.rs                                |  83 ++++
+ vmm/src/vm.rs                                 |  33 +-
+ 15 files changed, 793 insertions(+), 16 deletions(-)
+ create mode 100644 virtio-devices/src/vhost_user/gpu.rs
+
+diff --git a/Cargo.lock b/Cargo.lock
+index d119f28e..c8a20cef 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -1463,6 +1463,7 @@ dependencies = [
+  "vfio-ioctls",
+  "vfio_user",
+  "vhdx",
++ "virtio-bindings",
+  "virtio-devices",
+  "virtio-queue",
+  "vm-allocator",
+diff --git a/src/main.rs b/src/main.rs
+index 8725129a..eac7a126 100644
+--- a/src/main.rs
++++ b/src/main.rs
+@@ -263,6 +263,14 @@ fn create_app<'a>(
+                 .min_values(1)
+                 .group("vm-config"),
+         )
++        .arg(
++            Arg::new("gpu")
++                .long("gpu")
++                .help(config::GpuConfig::SYNTAX)
++                .takes_value(true)
++                .min_values(1)
++                .group("vm-config"),
++        )
+         .arg(
+             Arg::new("pmem")
+                 .long("pmem")
+@@ -724,6 +732,7 @@ mod unit_tests {
+             },
+             balloon: None,
+             fs: None,
++            gpu: None,
+             pmem: None,
+             serial: ConsoleConfig {
+                 file: None,
+diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs
+index c09adbb2..8bdbb7b9 100644
+--- a/virtio-devices/src/device.rs
++++ b/virtio-devices/src/device.rs
+@@ -11,7 +11,7 @@ use crate::{
+     VIRTIO_F_RING_INDIRECT_DESC,
+ };
+ use libc::EFD_NONBLOCK;
+-use std::collections::HashMap;
++use std::collections::{BTreeMap, HashMap};
+ use std::io::Write;
+ use std::num::Wrapping;
+ use std::sync::{
+@@ -47,19 +47,19 @@ pub struct UserspaceMapping {
+     pub mergeable: bool,
+ }
+ 
+-#[derive(Clone)]
++#[derive(Clone, Debug)]
+ pub struct VirtioSharedMemory {
+     pub offset: u64,
+     pub len: u64,
+ }
+ 
+-#[derive(Clone)]
++#[derive(Clone, Debug)]
+ pub struct VirtioSharedMemoryList {
+     pub host_addr: u64,
+     pub mem_slot: u32,
+     pub addr: GuestAddress,
+     pub len: GuestUsize,
+-    pub region_list: Vec<VirtioSharedMemory>,
++    pub region_list: BTreeMap<u8, VirtioSharedMemory>,
+ }
+ 
+ /// Trait for virtio devices to be driven by a virtio transport.
+diff --git a/virtio-devices/src/lib.rs b/virtio-devices/src/lib.rs
+index 8316d1ce..d1e31f27 100644
+--- a/virtio-devices/src/lib.rs
++++ b/virtio-devices/src/lib.rs
+@@ -88,6 +88,8 @@ pub enum ActivateError {
+     ThreadSpawn(std::io::Error),
+     #[error("Failed to setup vhost-user-fs daemon: {0}")]
+     VhostUserFsSetup(vhost_user::Error),
++    #[error("Failed to setup vhost-user-gpu daemon: {0}")]
++    VhostUserGpuSetup(vhost_user::Error),
+     #[error("Failed to setup vhost-user-blk daemon: {0}")]
+     VhostUserBlkSetup(vhost_user::Error),
+     #[error("Failed to create seccomp filter: {0}")]
+diff --git a/virtio-devices/src/seccomp_filters.rs b/virtio-devices/src/seccomp_filters.rs
+index 6044231b..a1ec89d8 100644
+--- a/virtio-devices/src/seccomp_filters.rs
++++ b/virtio-devices/src/seccomp_filters.rs
+@@ -22,6 +22,7 @@ pub enum Thread {
+     VirtioRng,
+     VirtioVhostBlock,
+     VirtioVhostFs,
++    VirtioVhostGpu,
+     VirtioVhostNet,
+     VirtioVhostNetCtl,
+     VirtioVsock,
+@@ -168,6 +169,14 @@ fn virtio_vhost_fs_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
+     ]
+ }
+ 
++fn virtio_vhost_gpu_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
++    vec![
++        (libc::SYS_getcwd, vec![]),
++        (libc::SYS_recvmsg, vec![]),
++        (libc::SYS_sendmsg, vec![]),
++    ]
++}
++
+ fn virtio_vhost_net_ctl_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
+     vec![]
+ }
+@@ -230,6 +239,7 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec<SeccompRule>)> {
+         Thread::VirtioRng => virtio_rng_thread_rules(),
+         Thread::VirtioVhostBlock => virtio_vhost_block_thread_rules(),
+         Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules(),
++        Thread::VirtioVhostGpu => virtio_vhost_gpu_thread_rules(),
+         Thread::VirtioVhostNet => virtio_vhost_net_thread_rules(),
+         Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules(),
+         Thread::VirtioVsock => virtio_vsock_thread_rules(),
+diff --git a/virtio-devices/src/transport/pci_device.rs b/virtio-devices/src/transport/pci_device.rs
+index 748d4328..6b0d0daa 100644
+--- a/virtio-devices/src/transport/pci_device.rs
++++ b/virtio-devices/src/transport/pci_device.rs
+@@ -949,11 +949,11 @@ impl PciDevice for VirtioPciDevice {
+ 
+             bars.push(bar);
+ 
+-            for (idx, shm) in shm_list.region_list.iter().enumerate() {
++            for (shmid, shm) in shm_list.region_list.iter() {
+                 let shm_cap = VirtioPciCap64::new(
+                     PciCapabilityType::SharedMemoryConfig,
+                     VIRTIO_SHM_BAR_INDEX as u8,
+-                    idx as u8,
++                    *shmid,
+                     shm.offset,
+                     shm.len,
+                 );
+diff --git a/virtio-devices/src/vhost_user/gpu.rs b/virtio-devices/src/vhost_user/gpu.rs
+new file mode 100644
+index 00000000..2eb18445
+--- /dev/null
++++ b/virtio-devices/src/vhost_user/gpu.rs
+@@ -0,0 +1,372 @@
++// Copyright 2019 Intel Corporation. All Rights Reserved.
++// Copyright 2022 Unikie
++// Copyright 2022 Puck Meerburg
++// SPDX-License-Identifier: Apache-2.0
++
++use crate::seccomp_filters::Thread;
++use crate::thread_helper::spawn_virtio_thread;
++use crate::vhost_user::vu_common_ctrl::VhostUserHandle;
++use crate::vhost_user::{Error, Result, VhostUserCommon};
++use crate::{
++    ActivateError, ActivateResult, GuestMemoryMmap, GuestRegionMmap, MmapRegion, UserspaceMapping,
++    VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterrupt, VirtioSharedMemoryList,
++    VIRTIO_F_VERSION_1,
++};
++use seccompiler::SeccompAction;
++use std::io::{self, Write};
++use std::os::unix::prelude::AsRawFd;
++use std::sync::{Arc, Barrier, Mutex};
++use std::thread;
++use vhost::vhost_user::message::{
++    VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserShmemMapMsg, VhostUserShmemUnmapMsg,
++    VhostUserVirtioFeatures,
++};
++use vhost::vhost_user::{
++    HandlerResult, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
++};
++use virtio_bindings::virtio_gpu::{
++    VIRTIO_GPU_F_CONTEXT_INIT, VIRTIO_GPU_F_RESOURCE_BLOB, VIRTIO_GPU_F_RESOURCE_UUID,
++    VIRTIO_GPU_F_VIRGL,
++};
++use virtio_queue::Queue;
++use vm_memory::GuestMemoryAtomic;
++use vm_migration::Pausable;
++use vmm_sys_util::eventfd::EventFd;
++
++const QUEUE_SIZES: &[u16] = &[256, 16];
++const NUM_QUEUES: u16 = QUEUE_SIZES.len() as _;
++
++struct SlaveReqHandler {
++    cache_size: u64,
++    mmap_cache_addr: u64,
++}
++
++impl SlaveReqHandler {
++    // Make sure request is within cache range
++    fn is_req_valid(&self, offset: u64, len: u64) -> bool {
++        let end = match offset.checked_add(len) {
++            Some(n) => n,
++            None => return false,
++        };
++
++        !(offset >= self.cache_size || end > self.cache_size)
++    }
++}
++
++impl VhostUserMasterReqHandler for SlaveReqHandler {
++    fn shmem_map(&self, req: &VhostUserShmemMapMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
++        if !self.is_req_valid(req.shm_offset, req.len) {
++            return Err(io::Error::from_raw_os_error(libc::EINVAL));
++        }
++
++        let addr = self.mmap_cache_addr + req.shm_offset;
++        let mut ret = unsafe {
++            libc::mmap(
++                addr as *mut libc::c_void,
++                req.len as usize,
++                req.flags.bits() as i32,
++                libc::MAP_SHARED | libc::MAP_FIXED,
++                fd.as_raw_fd(),
++                req.fd_offset as libc::off_t,
++            )
++        };
++
++        if ret == libc::MAP_FAILED {
++            ret = unsafe {
++                libc::mmap(
++                    addr as *mut libc::c_void,
++                    req.len as usize,
++                    (req.flags.bits() as i32) & !libc::PROT_WRITE,
++                    libc::MAP_SHARED | libc::MAP_FIXED,
++                    fd.as_raw_fd(),
++                    req.fd_offset as libc::off_t,
++                )
++            };
++        }
++
++        if ret == libc::MAP_FAILED {
++            return Err(io::Error::last_os_error());
++        }
++
++        Ok(0)
++    }
++
++    fn shmem_unmap(&self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++        if !self.is_req_valid(req.shm_offset, req.len) {
++            return Err(io::Error::from_raw_os_error(libc::EINVAL));
++        }
++
++        let addr = self.mmap_cache_addr + req.shm_offset;
++        let ret = unsafe {
++            libc::mmap(
++                addr as *mut libc::c_void,
++                req.len as usize,
++                libc::PROT_NONE,
++                libc::MAP_ANONYMOUS | libc::MAP_PRIVATE | libc::MAP_FIXED,
++                -1,
++                0,
++            )
++        };
++        if ret == libc::MAP_FAILED {
++            return Err(io::Error::last_os_error());
++        }
++
++        Ok(0)
++    }
++}
++
++#[derive(Default)]
++#[repr(C, packed)]
++pub struct VirtioGpuConfig {
++    pub events_read: u32,
++    pub events_clear: u32,
++    pub num_scanouts: u32,
++    pub num_capsets: u32,
++}
++
++pub struct Gpu {
++    common: VirtioCommon,
++    vu_common: VhostUserCommon,
++    id: String,
++    // Hold ownership of the memory that is allocated for the device
++    // which will be automatically dropped when the device is dropped
++    cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
++    slave_req_support: bool,
++    epoll_thread: Option<thread::JoinHandle<()>>,
++    seccomp_action: SeccompAction,
++    exit_evt: EventFd,
++}
++
++impl Gpu {
++    /// Create a new virtio-gpu device.
++    pub fn new(
++        id: String,
++        path: &str,
++        cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
++        seccomp_action: SeccompAction,
++        restoring: bool,
++        exit_evt: EventFd,
++        iommu: bool,
++    ) -> Result<Gpu> {
++        assert!(!restoring);
++
++        // Connect to the vhost-user socket.
++        let mut vu = VhostUserHandle::connect_vhost_user(false, path, NUM_QUEUES as u64, false)?;
++
++        let avail_features = 1 << VIRTIO_F_VERSION_1
++            | 1 << VIRTIO_GPU_F_VIRGL
++            | 1 << VIRTIO_GPU_F_RESOURCE_UUID
++            | 1 << VIRTIO_GPU_F_RESOURCE_BLOB
++            | 1 << VIRTIO_GPU_F_CONTEXT_INIT
++            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
++
++        let avail_protocol_features =
++            VhostUserProtocolFeatures::CONFIG | VhostUserProtocolFeatures::SLAVE_REQ;
++
++        let (acked_features, acked_protocol_features) =
++            vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
++
++        Ok(Gpu {
++            common: VirtioCommon {
++                device_type: VirtioDeviceType::Gpu as u32,
++                avail_features: acked_features,
++                // If part of the available features that have been acked, the
++                // PROTOCOL_FEATURES bit must be already set through the VIRTIO
++                // acked features as we know the guest would never ack it, this
++                // the feature would be lost.
++                acked_features: acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(),
++                paused_sync: Some(Arc::new(Barrier::new(NUM_QUEUES as usize))),
++                queue_sizes: QUEUE_SIZES.to_vec(),
++                min_queues: NUM_QUEUES,
++                ..Default::default()
++            },
++            vu_common: VhostUserCommon {
++                vu: Some(Arc::new(Mutex::new(vu))),
++                acked_protocol_features,
++                socket_path: path.to_string(),
++                vu_num_queues: NUM_QUEUES as usize,
++                ..Default::default()
++            },
++            id,
++            slave_req_support: acked_protocol_features
++                & VhostUserProtocolFeatures::SLAVE_REQ.bits()
++                != 0,
++            cache,
++            seccomp_action,
++            epoll_thread: None,
++            exit_evt,
++        })
++    }
++}
++
++impl Drop for Gpu {
++    fn drop(&mut self) {
++        if let Some(kill_evt) = self.common.kill_evt.take() {
++            // Ignore the result because there is nothing we can do about it.
++            let _ = kill_evt.write(1);
++        }
++    }
++}
++
++impl VirtioDevice for Gpu {
++    fn device_type(&self) -> u32 {
++        self.common.device_type
++    }
++
++    fn queue_max_sizes(&self) -> &[u16] {
++        &self.common.queue_sizes
++    }
++
++    fn features(&self) -> u64 {
++        self.common.avail_features
++    }
++
++    fn ack_features(&mut self, value: u64) {
++        self.common.ack_features(value)
++    }
++
++    fn read_config(&self, offset: u64, mut data: &mut [u8]) {
++        if let Some(vu) = &self.vu_common.vu {
++            if let Err(e) = vu
++                .lock()
++                .unwrap()
++                .socket_handle()
++                .get_config(
++                    offset as u32,
++                    data.len() as u32,
++                    VhostUserConfigFlags::WRITABLE,
++                    &data,
++                )
++                .map_err(|e| format!("{:?}", e))
++                .and_then(|(_, config)| data.write_all(&config).map_err(|e| format!("{:?}", e)))
++            {
++                error!("Failed getting vhost-user-gpu configuration: {:?}", e);
++            } else {
++                eprintln!("read_config({}, {:?})", offset, data);
++            }
++        }
++    }
++
++    fn activate(
++        &mut self,
++        mem: GuestMemoryAtomic<GuestMemoryMmap>,
++        interrupt_cb: Arc<dyn VirtioInterrupt>,
++        queues: Vec<(usize, Queue, EventFd)>,
++    ) -> ActivateResult {
++        self.common.activate(&queues, &interrupt_cb)?;
++
++        // Initialize slave communication.
++        let slave_req_handler = if self.slave_req_support {
++            if let Some(cache) = self.cache.as_ref() {
++                let vu_master_req_handler = Arc::new(SlaveReqHandler {
++                    cache_size: cache.0.len,
++                    mmap_cache_addr: cache.0.host_addr,
++                });
++
++                let mut req_handler =
++                    MasterReqHandler::new(vu_master_req_handler).map_err(|e| {
++                        ActivateError::VhostUserGpuSetup(Error::MasterReqHandlerCreation(e))
++                    })?;
++
++                if self.vu_common.acked_protocol_features
++                    & VhostUserProtocolFeatures::REPLY_ACK.bits()
++                    != 0
++                {
++                    req_handler.set_reply_ack_flag(true);
++                }
++
++                Some(req_handler)
++            } else {
++                None
++            }
++        } else {
++            None
++        };
++
++        // Run a dedicated thread for handling potential reconnections with
++        // the backend.
++        let (kill_evt, pause_evt) = self.common.dup_eventfds();
++
++        let mut handler = self.vu_common.activate(
++            mem,
++            queues,
++            interrupt_cb,
++            self.common.acked_features,
++            slave_req_handler,
++            kill_evt,
++            pause_evt,
++        )?;
++
++        let paused = self.common.paused.clone();
++        let paused_sync = self.common.paused_sync.clone();
++
++        let mut epoll_threads = Vec::new();
++        spawn_virtio_thread(
++            &self.id,
++            &self.seccomp_action,
++            Thread::VirtioVhostGpu,
++            &mut epoll_threads,
++            &self.exit_evt,
++            move || handler.run(paused, paused_sync.unwrap()),
++        )?;
++        self.epoll_thread = Some(epoll_threads.remove(0));
++
++        event!("virtio-device", "activated", "id", &self.id);
++        Ok(())
++    }
++
++    fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
++        // We first must resume the virtio thread if it was paused.
++        if self.common.pause_evt.take().is_some() {
++            self.common.resume().ok()?;
++        }
++
++        if let Some(vu) = &self.vu_common.vu {
++            if let Err(e) = vu.lock().unwrap().reset_vhost_user() {
++                error!("Failed to reset vhost-user daemon: {:?}", e);
++                return None;
++            }
++        }
++
++        if let Some(kill_evt) = self.common.kill_evt.take() {
++            // Ignore the result because there is nothing we can do about it.
++            let _ = kill_evt.write(1);
++        }
++
++        event!("virtio-device", "reset", "id", &self.id);
++
++        // Return the interrupt
++        Some(self.common.interrupt_cb.take().unwrap())
++    }
++
++    fn shutdown(&mut self) {
++        self.vu_common.shutdown()
++    }
++
++    fn get_shm_regions(&self) -> Option<VirtioSharedMemoryList> {
++        // It would be possible to the size of the region from the
++        // backend over vhost-user, but since we need to know the size
++        // up front in cloud-hypervisor to construct Self, it wouldn't
++        // help.  The user is thereforce responsible for configuring
++        // the correct region size in VM configuration.
++        self.cache.as_ref().map(|cache| cache.0.clone())
++    }
++
++    fn set_shm_regions(
++        &mut self,
++        shm_regions: VirtioSharedMemoryList,
++    ) -> std::result::Result<(), crate::Error> {
++        todo!("set_shm_regions({:?})", shm_regions)
++    }
++
++    fn add_memory_region(
++        &mut self,
++        region: &Arc<GuestRegionMmap>,
++    ) -> std::result::Result<(), crate::Error> {
++        todo!("add_memory_region({:?})", region)
++    }
++
++    fn userspace_mappings(&self) -> Vec<UserspaceMapping> {
++        todo!()
++    }
++}
+diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs
+index 81c48edf..669a962b 100644
+--- a/virtio-devices/src/vhost_user/mod.rs
++++ b/virtio-devices/src/vhost_user/mod.rs
+@@ -31,11 +31,13 @@ use vu_common_ctrl::VhostUserHandle;
+ 
+ pub mod blk;
+ pub mod fs;
++pub mod gpu;
+ pub mod net;
+ pub mod vu_common_ctrl;
+ 
+ pub use self::blk::Blk;
+ pub use self::fs::*;
++pub use self::gpu::*;
+ pub use self::net::Net;
+ pub use self::vu_common_ctrl::VhostUserConfig;
+ 
+diff --git a/virtio-devices/src/vhost_user/vu_common_ctrl.rs b/virtio-devices/src/vhost_user/vu_common_ctrl.rs
+index 0ab0bdda..fd6716a2 100644
+--- a/virtio-devices/src/vhost_user/vu_common_ctrl.rs
++++ b/virtio-devices/src/vhost_user/vu_common_ctrl.rs
+@@ -199,6 +199,14 @@ impl VhostUserHandle {
+                 .map_err(Error::VhostUserSetInflight)?;
+         }
+ 
++        // FIXME: crosvm's vhost-user backend requires this to come first.
++        // Can we fix that in crosvm?
++        if let Some(slave_req_handler) = slave_req_handler {
++            self.vu
++                .set_slave_request_fd(&slave_req_handler.get_tx_raw_fd())
++                .map_err(Error::VhostUserSetSlaveRequestFd)?;
++        }
++
+         let mut vrings_info = Vec::new();
+         for (queue_index, queue, queue_evt) in queues.iter() {
+             let actual_size: usize = queue.size().try_into().unwrap();
+@@ -267,12 +275,6 @@ impl VhostUserHandle {
+ 
+         self.enable_vhost_user_vrings(self.queue_indexes.clone(), true)?;
+ 
+-        if let Some(slave_req_handler) = slave_req_handler {
+-            self.vu
+-                .set_slave_request_fd(&slave_req_handler.get_tx_raw_fd())
+-                .map_err(Error::VhostUserSetSlaveRequestFd)?;
+-        }
+-
+         self.vrings_info = Some(vrings_info);
+         self.ready = true;
+ 
+diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml
+index c95384b5..87a36722 100644
+--- a/vmm/Cargo.toml
++++ b/vmm/Cargo.toml
+@@ -49,6 +49,7 @@ versionize_derive = "0.1.4"
+ vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
+ vfio_user = { path = "../vfio_user" }
+ vhdx = { path = "../vhdx" }
++virtio-bindings = "0.1.0"
+ virtio-devices = { path = "../virtio-devices" }
+ virtio-queue = "0.5.0"
+ vm-allocator = { path = "../vm-allocator" }
+diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs
+index 0513ef37..9a9942fc 100644
+--- a/vmm/src/api/mod.rs
++++ b/vmm/src/api/mod.rs
+@@ -34,6 +34,7 @@ pub use self::http::start_http_path_thread;
+ pub mod http;
+ pub mod http_endpoint;
+ 
++use crate::config::GpuConfig;
+ use crate::config::{
+     DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, RestoreConfig, UserDeviceConfig,
+     VdpaConfig, VmConfig, VsockConfig,
+@@ -132,6 +133,9 @@ pub enum ApiError {
+     /// The fs could not be added to the VM.
+     VmAddFs(VmError),
+ 
++    /// The gpu could not be added to the VM.
++    VmAddGpu(VmError),
++
+     /// The pmem device could not be added to the VM.
+     VmAddPmem(VmError),
+ 
+@@ -301,6 +305,9 @@ pub enum ApiRequest {
+     /// Add a fs to the VM.
+     VmAddFs(Arc<FsConfig>, Sender<ApiResponse>),
+ 
++    /// Add a gpu to the VM.
++    VmAddGpu(Arc<GpuConfig>, Sender<ApiResponse>),
++
+     /// Add a pmem device to the VM.
+     VmAddPmem(Arc<PmemConfig>, Sender<ApiResponse>),
+ 
+diff --git a/vmm/src/config.rs b/vmm/src/config.rs
+index 9d72f8fe..193f948d 100644
+--- a/vmm/src/config.rs
++++ b/vmm/src/config.rs
+@@ -43,6 +43,8 @@ pub enum Error {
+     ParseFsTagMissing,
+     /// Filesystem socket is missing
+     ParseFsSockMissing,
++    /// GPU socket is missing
++    ParseGpuSockMissing,
+     /// Missing persistent memory file parameter.
+     ParsePmemFileMissing,
+     /// Missing vsock socket path parameter.
+@@ -71,6 +73,8 @@ pub enum Error {
+     ParseBalloon(OptionParserError),
+     /// Error parsing filesystem parameters
+     ParseFileSystem(OptionParserError),
++    /// Error parsing GPU parameters
++    ParseGpu(OptionParserError),
+     /// Error parsing persistent memory parameters
+     ParsePersistentMemory(OptionParserError),
+     /// Failed parsing console
+@@ -292,6 +296,8 @@ impl fmt::Display for Error {
+             ParseFileSystem(o) => write!(f, "Error parsing --fs: {}", o),
+             ParseFsSockMissing => write!(f, "Error parsing --fs: socket missing"),
+             ParseFsTagMissing => write!(f, "Error parsing --fs: tag missing"),
++            ParseGpu(o) => write!(f, "Error parsing --gpu: {}", o),
++            ParseGpuSockMissing => write!(f, "Error parsing --gpu: socket missing"),
+             ParsePersistentMemory(o) => write!(f, "Error parsing --pmem: {}", o),
+             ParsePmemFileMissing => write!(f, "Error parsing --pmem: file missing"),
+             ParseVsock(o) => write!(f, "Error parsing --vsock: {}", o),
+@@ -352,6 +358,7 @@ pub struct VmParams<'a> {
+     pub rng: &'a str,
+     pub balloon: Option<&'a str>,
+     pub fs: Option<Vec<&'a str>>,
++    pub gpu: Option<Vec<&'a str>>,
+     pub pmem: Option<Vec<&'a str>>,
+     pub serial: &'a str,
+     pub console: &'a str,
+@@ -387,6 +394,7 @@ impl<'a> VmParams<'a> {
+         let console = args.value_of("console").unwrap();
+         let balloon = args.value_of("balloon");
+         let fs: Option<Vec<&str>> = args.values_of("fs").map(|x| x.collect());
++        let gpu: Option<Vec<&str>> = args.values_of("gpu").map(|x| x.collect());
+         let pmem: Option<Vec<&str>> = args.values_of("pmem").map(|x| x.collect());
+         let devices: Option<Vec<&str>> = args.values_of("device").map(|x| x.collect());
+         let user_devices: Option<Vec<&str>> = args.values_of("user-device").map(|x| x.collect());
+@@ -414,6 +422,7 @@ impl<'a> VmParams<'a> {
+             rng,
+             balloon,
+             fs,
++            gpu,
+             pmem,
+             serial,
+             console,
+@@ -1668,6 +1677,73 @@ impl FsConfig {
+     }
+ }
+ 
++#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
++pub struct GpuConfig {
++    pub socket: PathBuf,
++    #[serde(default = "default_gpuconfig_cache_size")]
++    pub cache_size: u64,
++    pub id: Option<String>,
++    pub pci_segment: u16,
++}
++
++fn default_gpuconfig_cache_size() -> u64 {
++    1 << 33
++}
++
++impl GpuConfig {
++    pub const SYNTAX: &'static str =
++        "GPU parameters \"socket=<socket_path>,cache_size=<default 8GiB>,\
++        id=<device_id>,pci_segment=<segment_id>\"";
++
++    pub fn parse(gpu: &str) -> Result<Self> {
++        let mut parser = OptionParser::new();
++        parser
++            .add("socket")
++            .add("cache_size")
++            .add("id")
++            .add("pci_segment");
++        parser.parse(gpu).map_err(Error::ParseGpu)?;
++
++        let socket = PathBuf::from(parser.get("socket").ok_or(Error::ParseGpuSockMissing)?);
++        let cache_size = parser
++            .convert::<ByteSized>("cache_size")
++            .map_err(Error::ParseGpu)?
++            .unwrap_or_else(|| ByteSized(default_gpuconfig_cache_size()))
++            .0;
++        let id = parser.get("id");
++
++        let pci_segment = parser
++            .convert("pci_segment")
++            .map_err(Error::ParseGpu)?
++            .unwrap_or_default();
++
++        Ok(GpuConfig {
++            socket,
++            cache_size,
++            id,
++            pci_segment,
++        })
++    }
++
++    pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> {
++        if let Some(platform_config) = vm_config.platform.as_ref() {
++            if self.pci_segment >= platform_config.num_pci_segments {
++                return Err(ValidationError::InvalidPciSegment(self.pci_segment));
++            }
++
++            if let Some(iommu_segments) = platform_config.iommu_segments.as_ref() {
++                if iommu_segments.contains(&self.pci_segment) {
++                    return Err(ValidationError::IommuNotSupportedOnSegment(
++                        self.pci_segment,
++                    ));
++                }
++            }
++        }
++
++        Ok(())
++    }
++}
++
+ #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
+ pub struct PmemConfig {
+     pub file: PathBuf,
+@@ -2280,6 +2356,7 @@ pub struct VmConfig {
+     pub rng: RngConfig,
+     pub balloon: Option<BalloonConfig>,
+     pub fs: Option<Vec<FsConfig>>,
++    pub gpu: Option<Vec<GpuConfig>>,
+     pub pmem: Option<Vec<PmemConfig>>,
+     #[serde(default = "ConsoleConfig::default_serial")]
+     pub serial: ConsoleConfig,
+@@ -2415,6 +2492,17 @@ impl VmConfig {
+             }
+         }
+ 
++        if let Some(gpus) = &self.gpu {
++            if !gpus.is_empty() && !self.memory.shared {
++                return Err(ValidationError::VhostUserRequiresSharedMemory);
++            }
++            for gpu in gpus {
++                gpu.validate(self)?;
++
++                Self::validate_identifier(&mut id_list, &gpu.id)?;
++            }
++        }
++
+         if let Some(pmems) = &self.pmem {
+             for pmem in pmems {
+                 pmem.validate(self)?;
+@@ -2600,6 +2688,15 @@ impl VmConfig {
+             fs = Some(fs_config_list);
+         }
+ 
++        let mut gpu: Option<Vec<GpuConfig>> = None;
++        if let Some(gpu_list) = &vm_params.gpu {
++            let mut gpu_config_list = Vec::new();
++            for item in gpu_list.iter() {
++                gpu_config_list.push(GpuConfig::parse(item)?);
++            }
++            gpu = Some(gpu_config_list);
++        }
++
+         let mut pmem: Option<Vec<PmemConfig>> = None;
+         if let Some(pmem_list) = &vm_params.pmem {
+             let mut pmem_config_list = Vec::new();
+@@ -2704,6 +2801,7 @@ impl VmConfig {
+             rng,
+             balloon,
+             fs,
++            gpu,
+             pmem,
+             serial,
+             console,
+@@ -3078,6 +3176,21 @@ mod tests {
+         Ok(())
+     }
+ 
++    #[test]
++    fn test_parse_gpu() -> Result<()> {
++        // "socket" must be supplied
++        assert!(GpuConfig::parse("").is_err());
++        assert_eq!(
++            GpuConfig::parse("socket=/tmp/sock")?,
++            GpuConfig {
++                socket: PathBuf::from("/tmp/sock"),
++                ..Default::default()
++            }
++        );
++
++        Ok(())
++    }
++
+     #[test]
+     fn test_pmem_parsing() -> Result<()> {
+         // Must always give a file and size
+@@ -3303,6 +3416,7 @@ mod tests {
+             },
+             balloon: None,
+             fs: None,
++            gpu: None,
+             pmem: None,
+             serial: ConsoleConfig {
+                 file: None,
+@@ -3457,6 +3571,15 @@ mod tests {
+             Err(ValidationError::VhostUserRequiresSharedMemory)
+         );
+ 
++        let mut invalid_config = valid_config.clone();
++        invalid_config.gpu = Some(vec![GpuConfig {
++            ..Default::default()
++        }]);
++        assert_eq!(
++            invalid_config.validate(),
++            Err(ValidationError::VhostUserRequiresSharedMemory)
++        );
++
+         let mut still_valid_config = valid_config.clone();
+         still_valid_config.memory.shared = true;
+         assert!(still_valid_config.validate().is_ok());
+diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs
+index 19ce15be..81a28446 100644
+--- a/vmm/src/device_manager.rs
++++ b/vmm/src/device_manager.rs
+@@ -10,8 +10,8 @@
+ //
+ 
+ use crate::config::{
+-    ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig,
+-    VdpaConfig, VhostMode, VmConfig, VsockConfig,
++    ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, GpuConfig, NetConfig, PmemConfig,
++    UserDeviceConfig, VdpaConfig, VhostMode, VmConfig, VsockConfig,
+ };
+ use crate::device_tree::{DeviceNode, DeviceTree};
+ use crate::interrupt::LegacyUserspaceInterruptManager;
+@@ -68,6 +68,7 @@ use std::collections::{BTreeSet, HashMap};
+ use std::convert::TryInto;
+ use std::fs::{read_link, File, OpenOptions};
+ use std::io::{self, stdout, Seek, SeekFrom};
++use std::iter::once;
+ use std::mem::zeroed;
+ use std::num::Wrapping;
+ use std::os::unix::fs::OpenOptionsExt;
+@@ -77,11 +78,13 @@ use std::result;
+ use std::sync::{Arc, Mutex};
+ use std::time::Instant;
+ use vfio_ioctls::{VfioContainer, VfioDevice, VfioDeviceFd};
++use virtio_bindings::virtio_gpu::virtio_gpu_shm_id_VIRTIO_GPU_SHM_ID_HOST_VISIBLE as VIRTIO_GPU_SHM_ID_HOST_VISIBLE;
+ use virtio_devices::transport::VirtioTransport;
+ use virtio_devices::transport::{VirtioPciDevice, VirtioPciDeviceActivator};
+ use virtio_devices::vhost_user::VhostUserConfig;
+ use virtio_devices::{
+     AccessPlatformMapping, ActivateError, VdpaDmaMapping, VirtioMemMappingSource,
++    VirtioSharedMemory, VirtioSharedMemoryList,
+ };
+ use virtio_devices::{Endpoint, IommuMapping};
+ use vm_allocator::{AddressAllocator, SystemAllocator};
+@@ -124,6 +127,7 @@ const CONSOLE_DEVICE_NAME: &str = "__console";
+ // identifiers if the user doesn't give one
+ const DISK_DEVICE_NAME_PREFIX: &str = "_disk";
+ const FS_DEVICE_NAME_PREFIX: &str = "_fs";
++const GPU_DEVICE_NAME_PREFIX: &str = "_gpu";
+ const NET_DEVICE_NAME_PREFIX: &str = "_net";
+ const PMEM_DEVICE_NAME_PREFIX: &str = "_pmem";
+ const VDPA_DEVICE_NAME_PREFIX: &str = "_vdpa";
+@@ -160,9 +164,15 @@ pub enum DeviceManagerError {
+     /// Cannot create virtio-fs device
+     CreateVirtioFs(virtio_devices::vhost_user::Error),
+ 
++    /// Cannot create virtio-gpu device
++    CreateVirtioGpu(virtio_devices::vhost_user::Error),
++
+     /// Virtio-fs device was created without a socket.
+     NoVirtioFsSock,
+ 
++    /// Virtio-gpu device was created without a socket.
++    NoVirtioGpuSock,
++
+     /// Cannot create vhost-user-blk device
+     CreateVhostUserBlk(virtio_devices::vhost_user::Error),
+ 
+@@ -244,6 +254,9 @@ pub enum DeviceManagerError {
+     /// Cannot find a memory range for virtio-fs
+     FsRangeAllocation,
+ 
++    /// Cannot find a memory range for virtio-gpu
++    GpuRangeAllocation,
++
+     /// Error creating serial output file
+     SerialOutputFileOpen(io::Error),
+ 
+@@ -2064,6 +2077,9 @@ impl DeviceManager {
+         // Add virtio-fs if required
+         devices.append(&mut self.make_virtio_fs_devices()?);
+ 
++        // Add virtio-gpu if required
++        devices.append(&mut self.make_virtio_gpu_devices()?);
++
+         // Add virtio-pmem if required
+         devices.append(&mut self.make_virtio_pmem_devices()?);
+ 
+@@ -2514,6 +2530,119 @@ impl DeviceManager {
+         Ok(devices)
+     }
+ 
++    fn make_virtio_gpu_device(
++        &mut self,
++        gpu_cfg: &mut GpuConfig,
++    ) -> DeviceManagerResult<MetaVirtioDevice> {
++        let id = if let Some(id) = &gpu_cfg.id {
++            id.clone()
++        } else {
++            let id = self.next_device_name(GPU_DEVICE_NAME_PREFIX)?;
++            gpu_cfg.id = Some(id.clone());
++            id
++        };
++
++        info!("Creating virtio-gpu device: {:?}", gpu_cfg);
++
++        let mut node = device_node!(id);
++
++        if let Some(gpu_socket) = gpu_cfg.socket.to_str() {
++            let cache_size = gpu_cfg.cache_size;
++            // In crosvm, the 8 GiB bar is 8 GiB-aligned.
++            let cache_base = self.pci_segments[gpu_cfg.pci_segment as usize]
++                .allocator
++                .lock()
++                .unwrap()
++                .allocate(None, cache_size as GuestUsize, Some(cache_size))
++                .ok_or(DeviceManagerError::GpuRangeAllocation)?
++                .raw_value();
++
++            // Update the node with correct resource information.
++            node.resources.push(Resource::MmioAddressRange {
++                base: cache_base,
++                size: cache_size,
++            });
++
++            let mmap_region = MmapRegion::build(
++                None,
++                cache_size as usize,
++                libc::PROT_NONE,
++                libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
++            )
++            .map_err(DeviceManagerError::NewMmapRegion)?;
++            let host_addr: u64 = mmap_region.as_ptr() as u64;
++
++            let mem_slot = self
++                .memory_manager
++                .lock()
++                .unwrap()
++                .create_userspace_mapping(cache_base, cache_size, host_addr, false, false, false)
++                .map_err(DeviceManagerError::MemoryManager)?;
++
++            let region_list = once((
++                VIRTIO_GPU_SHM_ID_HOST_VISIBLE as u8,
++                VirtioSharedMemory {
++                    offset: 0,
++                    len: cache_size,
++                },
++            ))
++            .collect();
++
++            let cache = Some((
++                VirtioSharedMemoryList {
++                    host_addr,
++                    mem_slot,
++                    addr: GuestAddress(cache_base),
++                    len: cache_size as GuestUsize,
++                    region_list,
++                },
++                mmap_region,
++            ));
++
++            let virtio_gpu_device = Arc::new(Mutex::new(
++                virtio_devices::vhost_user::Gpu::new(
++                    id.clone(),
++                    gpu_socket,
++                    cache,
++                    self.seccomp_action.clone(),
++                    self.restoring,
++                    self.exit_evt
++                        .try_clone()
++                        .map_err(DeviceManagerError::EventFd)?,
++                    self.force_iommu,
++                )
++                .map_err(DeviceManagerError::CreateVirtioGpu)?,
++            ));
++
++            self.device_tree.lock().unwrap().insert(id.clone(), node);
++
++            Ok(MetaVirtioDevice {
++                virtio_device: Arc::clone(&virtio_gpu_device)
++                    as Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
++                iommu: false,
++                id,
++                pci_segment: gpu_cfg.pci_segment,
++                dma_handler: None,
++            })
++        } else {
++            Err(DeviceManagerError::NoVirtioGpuSock)
++        }
++    }
++
++    fn make_virtio_gpu_devices(&mut self) -> DeviceManagerResult<Vec<MetaVirtioDevice>> {
++        let mut devices = Vec::new();
++
++        let mut gpu_devices = self.config.lock().unwrap().gpu.clone();
++        if let Some(gpu_list_cfg) = &mut gpu_devices {
++            for gpu_cfg in gpu_list_cfg.iter_mut() {
++                devices.push(self.make_virtio_gpu_device(gpu_cfg)?);
++            }
++        }
++        self.config.lock().unwrap().gpu = gpu_devices;
++
++        Ok(devices)
++    }
++
+     fn make_virtio_pmem_device(
+         &mut self,
+         pmem_cfg: &mut PmemConfig,
+@@ -4004,6 +4133,13 @@ impl DeviceManager {
+         self.hotplug_virtio_pci_device(device)
+     }
+ 
++    pub fn add_gpu(&mut self, gpu_cfg: &mut GpuConfig) -> DeviceManagerResult<PciDeviceInfo> {
++        self.validate_identifier(&gpu_cfg.id)?;
++
++        let device = self.make_virtio_gpu_device(gpu_cfg)?;
++        self.hotplug_virtio_pci_device(device)
++    }
++
+     pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
+         self.validate_identifier(&pmem_cfg.id)?;
+ 
+diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs
+index a114488b..5baaa29f 100644
+--- a/vmm/src/lib.rs
++++ b/vmm/src/lib.rs
+@@ -26,6 +26,7 @@ use crate::migration::{recv_vm_config, recv_vm_state};
+ use crate::seccomp_filters::{get_seccomp_filter, Thread};
+ use crate::vm::{Error as VmError, Vm, VmState};
+ use anyhow::anyhow;
++use config::GpuConfig;
+ use libc::{EFD_NONBLOCK, SIGINT, SIGTERM};
+ use memory_manager::MemoryManagerSnapshotData;
+ use pci::PciBdf;
+@@ -969,6 +970,32 @@ impl Vmm {
+         }
+     }
+ 
++    fn vm_add_gpu(&mut self, gpu_cfg: GpuConfig) -> result::Result<Option<Vec<u8>>, VmError> {
++        self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
++
++        {
++            // Validate the configuration change in a cloned configuration
++            let mut config = self.vm_config.as_ref().unwrap().lock().unwrap().clone();
++            add_to_config(&mut config.gpu, gpu_cfg.clone());
++            config.validate().map_err(VmError::ConfigValidation)?;
++        }
++
++        if let Some(ref mut vm) = self.vm {
++            let info = vm.add_gpu(gpu_cfg).map_err(|e| {
++                error!("Error when adding new gpu to the VM: {:?}", e);
++                e
++            })?;
++            serde_json::to_vec(&info)
++                .map(Some)
++                .map_err(VmError::SerializeJson)
++        } else {
++            // Update VmConfig by adding the new device.
++            let mut config = self.vm_config.as_ref().unwrap().lock().unwrap();
++            add_to_config(&mut config.gpu, gpu_cfg);
++            Ok(None)
++        }
++    }
++
+     fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> result::Result<Option<Vec<u8>>, VmError> {
+         self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
+ 
+@@ -1858,6 +1885,13 @@ impl Vmm {
+                                         .map(ApiResponsePayload::VmAction);
+                                     sender.send(response).map_err(Error::ApiResponseSend)?;
+                                 }
++                                ApiRequest::VmAddGpu(add_gpu_data, sender) => {
++                                    let response = self
++                                        .vm_add_gpu(add_gpu_data.as_ref().clone())
++                                        .map_err(ApiError::VmAddGpu)
++                                        .map(ApiResponsePayload::VmAction);
++                                    sender.send(response).map_err(Error::ApiResponseSend)?;
++                                }
+                                 ApiRequest::VmAddPmem(add_pmem_data, sender) => {
+                                     let response = self
+                                         .vm_add_pmem(add_pmem_data.as_ref().clone())
+@@ -2027,6 +2061,7 @@ mod unit_tests {
+             },
+             balloon: None,
+             fs: None,
++            gpu: None,
+             pmem: None,
+             serial: ConsoleConfig {
+                 file: None,
+@@ -2253,6 +2288,54 @@ mod unit_tests {
+         );
+     }
+ 
++    #[test]
++    fn test_vmm_vm_cold_add_gpu() {
++        let mut vmm = create_dummy_vmm();
++        let gpu_config = GpuConfig::parse("socket=/tmp/sock").unwrap();
++
++        assert!(matches!(
++            vmm.vm_add_gpu(gpu_config.clone()),
++            Err(VmError::VmNotCreated)
++        ));
++
++        let _ = vmm.vm_create(create_dummy_vm_config());
++        assert!(vmm
++            .vm_config
++            .as_ref()
++            .unwrap()
++            .lock()
++            .unwrap()
++            .gpu
++            .is_none());
++
++        let result = vmm.vm_add_gpu(gpu_config.clone());
++        assert!(result.is_ok());
++        assert!(result.unwrap().is_none());
++        assert_eq!(
++            vmm.vm_config
++                .as_ref()
++                .unwrap()
++                .lock()
++                .unwrap()
++                .gpu
++                .clone()
++                .unwrap()
++                .len(),
++            1
++        );
++        assert_eq!(
++            vmm.vm_config
++                .as_ref()
++                .unwrap()
++                .lock()
++                .unwrap()
++                .gpu
++                .clone()
++                .unwrap()[0],
++            gpu_config
++        );
++    }
++
+     #[test]
+     fn test_vmm_vm_cold_add_pmem() {
+         let mut vmm = create_dummy_vmm();
+diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs
+index 87278d5c..30a0c896 100644
+--- a/vmm/src/vm.rs
++++ b/vmm/src/vm.rs
+@@ -12,8 +12,8 @@
+ //
+ 
+ use crate::config::{
+-    add_to_config, DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, PmemConfig,
+-    UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig,
++    add_to_config, DeviceConfig, DiskConfig, FsConfig, GpuConfig, HotplugMethod, NetConfig,
++    PmemConfig, UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig,
+ };
+ use crate::config::{NumaConfig, PayloadConfig};
+ #[cfg(feature = "guest_debug")]
+@@ -1555,6 +1555,11 @@ impl Vm {
+             fs.retain(|dev| dev.id.as_ref() != Some(&id));
+         }
+ 
++        // Remove if gpu device
++        if let Some(gpu) = config.gpu.as_mut() {
++            gpu.retain(|dev| dev.id.as_ref() != Some(&id));
++        }
++
+         // Remove if net device
+         if let Some(net) = config.net.as_mut() {
+             net.retain(|dev| dev.id.as_ref() != Some(&id));
+@@ -1633,6 +1638,30 @@ impl Vm {
+         Ok(pci_device_info)
+     }
+ 
++    pub fn add_gpu(&mut self, mut gpu_cfg: GpuConfig) -> Result<PciDeviceInfo> {
++        let pci_device_info = self
++            .device_manager
++            .lock()
++            .unwrap()
++            .add_gpu(&mut gpu_cfg)
++            .map_err(Error::DeviceManager)?;
++
++        // Update VmConfig by adding the new device. This is important to
++        // ensure the device would be created in case of a reboot.
++        {
++            let mut config = self.config.lock().unwrap();
++            add_to_config(&mut config.gpu, gpu_cfg);
++        }
++
++        self.device_manager
++            .lock()
++            .unwrap()
++            .notify_hotplug(AcpiNotificationFlags::PCI_DEVICES_CHANGED)
++            .map_err(Error::DeviceManager)?;
++
++        Ok(pci_device_info)
++    }
++
+     pub fn add_pmem(&mut self, mut pmem_cfg: PmemConfig) -> Result<PciDeviceInfo> {
+         let pci_device_info = self
+             .device_manager
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0004-virtio-bindings-regenerate-with-Linux-5.19.patch b/pkgs/applications/virtualization/cloud-hypervisor/0004-virtio-bindings-regenerate-with-Linux-5.19.patch
new file mode 100644
index 00000000000..92129dc52bd
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0004-virtio-bindings-regenerate-with-Linux-5.19.patch
@@ -0,0 +1,1067 @@
+From b7806189fb4407221f33ea8869b89bbaa997f4b1 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 31 Aug 2022 17:10:30 +0000
+Subject: [PATCH 4/5] virtio-bindings: regenerate with Linux 5.19
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ crates/virtio-bindings/src/virtio_blk.rs  |  61 +-
+ crates/virtio-bindings/src/virtio_net.rs  | 749 ++++++++++++++++++++--
+ crates/virtio-bindings/src/virtio_ring.rs |  13 +-
+ 3 files changed, 765 insertions(+), 58 deletions(-)
+
+diff --git a/crates/virtio-bindings/src/virtio_blk.rs b/crates/virtio-bindings/src/virtio_blk.rs
+index 94daca3..71151a3 100644
+--- a/crates/virtio-bindings/src/virtio_blk.rs
++++ b/crates/virtio-bindings/src/virtio_blk.rs
+@@ -7,15 +7,47 @@ pub const VIRTIO_ID_BLOCK: u32 = 2;
+ pub const VIRTIO_ID_CONSOLE: u32 = 3;
+ pub const VIRTIO_ID_RNG: u32 = 4;
+ pub const VIRTIO_ID_BALLOON: u32 = 5;
++pub const VIRTIO_ID_IOMEM: u32 = 6;
+ pub const VIRTIO_ID_RPMSG: u32 = 7;
+ pub const VIRTIO_ID_SCSI: u32 = 8;
+ pub const VIRTIO_ID_9P: u32 = 9;
++pub const VIRTIO_ID_MAC80211_WLAN: u32 = 10;
+ pub const VIRTIO_ID_RPROC_SERIAL: u32 = 11;
+ pub const VIRTIO_ID_CAIF: u32 = 12;
++pub const VIRTIO_ID_MEMORY_BALLOON: u32 = 13;
+ pub const VIRTIO_ID_GPU: u32 = 16;
++pub const VIRTIO_ID_CLOCK: u32 = 17;
+ pub const VIRTIO_ID_INPUT: u32 = 18;
+ pub const VIRTIO_ID_VSOCK: u32 = 19;
+ pub const VIRTIO_ID_CRYPTO: u32 = 20;
++pub const VIRTIO_ID_SIGNAL_DIST: u32 = 21;
++pub const VIRTIO_ID_PSTORE: u32 = 22;
++pub const VIRTIO_ID_IOMMU: u32 = 23;
++pub const VIRTIO_ID_MEM: u32 = 24;
++pub const VIRTIO_ID_SOUND: u32 = 25;
++pub const VIRTIO_ID_FS: u32 = 26;
++pub const VIRTIO_ID_PMEM: u32 = 27;
++pub const VIRTIO_ID_RPMB: u32 = 28;
++pub const VIRTIO_ID_MAC80211_HWSIM: u32 = 29;
++pub const VIRTIO_ID_VIDEO_ENCODER: u32 = 30;
++pub const VIRTIO_ID_VIDEO_DECODER: u32 = 31;
++pub const VIRTIO_ID_SCMI: u32 = 32;
++pub const VIRTIO_ID_NITRO_SEC_MOD: u32 = 33;
++pub const VIRTIO_ID_I2C_ADAPTER: u32 = 34;
++pub const VIRTIO_ID_WATCHDOG: u32 = 35;
++pub const VIRTIO_ID_CAN: u32 = 36;
++pub const VIRTIO_ID_DMABUF: u32 = 37;
++pub const VIRTIO_ID_PARAM_SERV: u32 = 38;
++pub const VIRTIO_ID_AUDIO_POLICY: u32 = 39;
++pub const VIRTIO_ID_BT: u32 = 40;
++pub const VIRTIO_ID_GPIO: u32 = 41;
++pub const VIRTIO_TRANS_ID_NET: u32 = 4096;
++pub const VIRTIO_TRANS_ID_BLOCK: u32 = 4097;
++pub const VIRTIO_TRANS_ID_BALLOON: u32 = 4098;
++pub const VIRTIO_TRANS_ID_CONSOLE: u32 = 4099;
++pub const VIRTIO_TRANS_ID_SCSI: u32 = 4100;
++pub const VIRTIO_TRANS_ID_RNG: u32 = 4101;
++pub const VIRTIO_TRANS_ID_9P: u32 = 4105;
+ pub const VIRTIO_CONFIG_S_ACKNOWLEDGE: u32 = 1;
+ pub const VIRTIO_CONFIG_S_DRIVER: u32 = 2;
+ pub const VIRTIO_CONFIG_S_DRIVER_OK: u32 = 4;
+@@ -27,8 +59,10 @@ pub const VIRTIO_TRANSPORT_F_END: u32 = 38;
+ pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24;
+ pub const VIRTIO_F_ANY_LAYOUT: u32 = 27;
+ pub const VIRTIO_F_VERSION_1: u32 = 32;
++pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
+ pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33;
+ pub const VIRTIO_F_RING_PACKED: u32 = 34;
++pub const VIRTIO_F_IN_ORDER: u32 = 35;
+ pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36;
+ pub const VIRTIO_F_SR_IOV: u32 = 37;
+ pub const VIRTIO_BLK_F_SIZE_MAX: u32 = 1;
+@@ -160,6 +194,7 @@ fn bindgen_test_layout___kernel_fsid_t() {
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
++pub type __kernel_old_time_t = __kernel_long_t;
+ pub type __kernel_time_t = __kernel_long_t;
+ pub type __kernel_time64_t = ::std::os::raw::c_longlong;
+ pub type __kernel_clock_t = __kernel_long_t;
+@@ -183,30 +218,30 @@ pub type __virtio64 = __u64;
+ #[repr(C, packed)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+ pub struct virtio_blk_config {
+-    pub capacity: __u64,
+-    pub size_max: __u32,
+-    pub seg_max: __u32,
++    pub capacity: __virtio64,
++    pub size_max: __virtio32,
++    pub seg_max: __virtio32,
+     pub geometry: virtio_blk_config_virtio_blk_geometry,
+-    pub blk_size: __u32,
++    pub blk_size: __virtio32,
+     pub physical_block_exp: __u8,
+     pub alignment_offset: __u8,
+-    pub min_io_size: __u16,
+-    pub opt_io_size: __u32,
++    pub min_io_size: __virtio16,
++    pub opt_io_size: __virtio32,
+     pub wce: __u8,
+     pub unused: __u8,
+-    pub num_queues: __u16,
+-    pub max_discard_sectors: __u32,
+-    pub max_discard_seg: __u32,
+-    pub discard_sector_alignment: __u32,
+-    pub max_write_zeroes_sectors: __u32,
+-    pub max_write_zeroes_seg: __u32,
++    pub num_queues: __virtio16,
++    pub max_discard_sectors: __virtio32,
++    pub max_discard_seg: __virtio32,
++    pub discard_sector_alignment: __virtio32,
++    pub max_write_zeroes_sectors: __virtio32,
++    pub max_write_zeroes_seg: __virtio32,
+     pub write_zeroes_may_unmap: __u8,
+     pub unused1: [__u8; 3usize],
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+ pub struct virtio_blk_config_virtio_blk_geometry {
+-    pub cylinders: __u16,
++    pub cylinders: __virtio16,
+     pub heads: __u8,
+     pub sectors: __u8,
+ }
+diff --git a/crates/virtio-bindings/src/virtio_net.rs b/crates/virtio-bindings/src/virtio_net.rs
+index 5707375..f66f69a 100644
+--- a/crates/virtio-bindings/src/virtio_net.rs
++++ b/crates/virtio-bindings/src/virtio_net.rs
+@@ -37,15 +37,47 @@ pub const VIRTIO_ID_BLOCK: u32 = 2;
+ pub const VIRTIO_ID_CONSOLE: u32 = 3;
+ pub const VIRTIO_ID_RNG: u32 = 4;
+ pub const VIRTIO_ID_BALLOON: u32 = 5;
++pub const VIRTIO_ID_IOMEM: u32 = 6;
+ pub const VIRTIO_ID_RPMSG: u32 = 7;
+ pub const VIRTIO_ID_SCSI: u32 = 8;
+ pub const VIRTIO_ID_9P: u32 = 9;
++pub const VIRTIO_ID_MAC80211_WLAN: u32 = 10;
+ pub const VIRTIO_ID_RPROC_SERIAL: u32 = 11;
+ pub const VIRTIO_ID_CAIF: u32 = 12;
++pub const VIRTIO_ID_MEMORY_BALLOON: u32 = 13;
+ pub const VIRTIO_ID_GPU: u32 = 16;
++pub const VIRTIO_ID_CLOCK: u32 = 17;
+ pub const VIRTIO_ID_INPUT: u32 = 18;
+ pub const VIRTIO_ID_VSOCK: u32 = 19;
+ pub const VIRTIO_ID_CRYPTO: u32 = 20;
++pub const VIRTIO_ID_SIGNAL_DIST: u32 = 21;
++pub const VIRTIO_ID_PSTORE: u32 = 22;
++pub const VIRTIO_ID_IOMMU: u32 = 23;
++pub const VIRTIO_ID_MEM: u32 = 24;
++pub const VIRTIO_ID_SOUND: u32 = 25;
++pub const VIRTIO_ID_FS: u32 = 26;
++pub const VIRTIO_ID_PMEM: u32 = 27;
++pub const VIRTIO_ID_RPMB: u32 = 28;
++pub const VIRTIO_ID_MAC80211_HWSIM: u32 = 29;
++pub const VIRTIO_ID_VIDEO_ENCODER: u32 = 30;
++pub const VIRTIO_ID_VIDEO_DECODER: u32 = 31;
++pub const VIRTIO_ID_SCMI: u32 = 32;
++pub const VIRTIO_ID_NITRO_SEC_MOD: u32 = 33;
++pub const VIRTIO_ID_I2C_ADAPTER: u32 = 34;
++pub const VIRTIO_ID_WATCHDOG: u32 = 35;
++pub const VIRTIO_ID_CAN: u32 = 36;
++pub const VIRTIO_ID_DMABUF: u32 = 37;
++pub const VIRTIO_ID_PARAM_SERV: u32 = 38;
++pub const VIRTIO_ID_AUDIO_POLICY: u32 = 39;
++pub const VIRTIO_ID_BT: u32 = 40;
++pub const VIRTIO_ID_GPIO: u32 = 41;
++pub const VIRTIO_TRANS_ID_NET: u32 = 4096;
++pub const VIRTIO_TRANS_ID_BLOCK: u32 = 4097;
++pub const VIRTIO_TRANS_ID_BALLOON: u32 = 4098;
++pub const VIRTIO_TRANS_ID_CONSOLE: u32 = 4099;
++pub const VIRTIO_TRANS_ID_SCSI: u32 = 4100;
++pub const VIRTIO_TRANS_ID_RNG: u32 = 4101;
++pub const VIRTIO_TRANS_ID_9P: u32 = 4105;
+ pub const VIRTIO_CONFIG_S_ACKNOWLEDGE: u32 = 1;
+ pub const VIRTIO_CONFIG_S_DRIVER: u32 = 2;
+ pub const VIRTIO_CONFIG_S_DRIVER_OK: u32 = 4;
+@@ -57,8 +89,10 @@ pub const VIRTIO_TRANSPORT_F_END: u32 = 38;
+ pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24;
+ pub const VIRTIO_F_ANY_LAYOUT: u32 = 27;
+ pub const VIRTIO_F_VERSION_1: u32 = 32;
++pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
+ pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33;
+ pub const VIRTIO_F_RING_PACKED: u32 = 34;
++pub const VIRTIO_F_IN_ORDER: u32 = 35;
+ pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36;
+ pub const VIRTIO_F_SR_IOV: u32 = 37;
+ pub const ETH_ALEN: u32 = 6;
+@@ -109,17 +143,23 @@ pub const ETH_P_PPP_SES: u32 = 34916;
+ pub const ETH_P_LINK_CTL: u32 = 34924;
+ pub const ETH_P_ATMFATE: u32 = 34948;
+ pub const ETH_P_PAE: u32 = 34958;
++pub const ETH_P_PROFINET: u32 = 34962;
++pub const ETH_P_REALTEK: u32 = 34969;
+ pub const ETH_P_AOE: u32 = 34978;
++pub const ETH_P_ETHERCAT: u32 = 34980;
+ pub const ETH_P_8021AD: u32 = 34984;
+ pub const ETH_P_802_EX1: u32 = 34997;
+ pub const ETH_P_PREAUTH: u32 = 35015;
+ pub const ETH_P_TIPC: u32 = 35018;
++pub const ETH_P_LLDP: u32 = 35020;
++pub const ETH_P_MRP: u32 = 35043;
+ pub const ETH_P_MACSEC: u32 = 35045;
+ pub const ETH_P_8021AH: u32 = 35047;
+ pub const ETH_P_MVRP: u32 = 35061;
+ pub const ETH_P_1588: u32 = 35063;
+ pub const ETH_P_NCSI: u32 = 35064;
+ pub const ETH_P_PRP: u32 = 35067;
++pub const ETH_P_CFM: u32 = 35074;
+ pub const ETH_P_FCOE: u32 = 35078;
+ pub const ETH_P_IBOE: u32 = 35093;
+ pub const ETH_P_TDLS: u32 = 35085;
+@@ -132,6 +172,7 @@ pub const ETH_P_QINQ1: u32 = 37120;
+ pub const ETH_P_QINQ2: u32 = 37376;
+ pub const ETH_P_QINQ3: u32 = 37632;
+ pub const ETH_P_EDSA: u32 = 56026;
++pub const ETH_P_DSA_8021Q: u32 = 56027;
+ pub const ETH_P_IFE: u32 = 60734;
+ pub const ETH_P_AF_IUCV: u32 = 64507;
+ pub const ETH_P_802_3_MIN: u32 = 1536;
+@@ -161,6 +202,7 @@ pub const ETH_P_IEEE802154: u32 = 246;
+ pub const ETH_P_CAIF: u32 = 247;
+ pub const ETH_P_XDSA: u32 = 248;
+ pub const ETH_P_MAP: u32 = 249;
++pub const ETH_P_MCTP: u32 = 250;
+ pub const __UAPI_DEF_ETHHDR: u32 = 1;
+ pub const VIRTIO_NET_F_CSUM: u32 = 0;
+ pub const VIRTIO_NET_F_GUEST_CSUM: u32 = 1;
+@@ -184,18 +226,41 @@ pub const VIRTIO_NET_F_CTRL_RX_EXTRA: u32 = 20;
+ pub const VIRTIO_NET_F_GUEST_ANNOUNCE: u32 = 21;
+ pub const VIRTIO_NET_F_MQ: u32 = 22;
+ pub const VIRTIO_NET_F_CTRL_MAC_ADDR: u32 = 23;
++pub const VIRTIO_NET_F_HASH_REPORT: u32 = 57;
++pub const VIRTIO_NET_F_RSS: u32 = 60;
++pub const VIRTIO_NET_F_RSC_EXT: u32 = 61;
+ pub const VIRTIO_NET_F_STANDBY: u32 = 62;
+ pub const VIRTIO_NET_F_SPEED_DUPLEX: u32 = 63;
+ pub const VIRTIO_NET_F_GSO: u32 = 6;
+ pub const VIRTIO_NET_S_LINK_UP: u32 = 1;
+ pub const VIRTIO_NET_S_ANNOUNCE: u32 = 2;
++pub const VIRTIO_NET_RSS_HASH_TYPE_IPv4: u32 = 1;
++pub const VIRTIO_NET_RSS_HASH_TYPE_TCPv4: u32 = 2;
++pub const VIRTIO_NET_RSS_HASH_TYPE_UDPv4: u32 = 4;
++pub const VIRTIO_NET_RSS_HASH_TYPE_IPv6: u32 = 8;
++pub const VIRTIO_NET_RSS_HASH_TYPE_TCPv6: u32 = 16;
++pub const VIRTIO_NET_RSS_HASH_TYPE_UDPv6: u32 = 32;
++pub const VIRTIO_NET_RSS_HASH_TYPE_IP_EX: u32 = 64;
++pub const VIRTIO_NET_RSS_HASH_TYPE_TCP_EX: u32 = 128;
++pub const VIRTIO_NET_RSS_HASH_TYPE_UDP_EX: u32 = 256;
+ pub const VIRTIO_NET_HDR_F_NEEDS_CSUM: u32 = 1;
+ pub const VIRTIO_NET_HDR_F_DATA_VALID: u32 = 2;
++pub const VIRTIO_NET_HDR_F_RSC_INFO: u32 = 4;
+ pub const VIRTIO_NET_HDR_GSO_NONE: u32 = 0;
+ pub const VIRTIO_NET_HDR_GSO_TCPV4: u32 = 1;
+ pub const VIRTIO_NET_HDR_GSO_UDP: u32 = 3;
+ pub const VIRTIO_NET_HDR_GSO_TCPV6: u32 = 4;
+ pub const VIRTIO_NET_HDR_GSO_ECN: u32 = 128;
++pub const VIRTIO_NET_HASH_REPORT_NONE: u32 = 0;
++pub const VIRTIO_NET_HASH_REPORT_IPv4: u32 = 1;
++pub const VIRTIO_NET_HASH_REPORT_TCPv4: u32 = 2;
++pub const VIRTIO_NET_HASH_REPORT_UDPv4: u32 = 3;
++pub const VIRTIO_NET_HASH_REPORT_IPv6: u32 = 4;
++pub const VIRTIO_NET_HASH_REPORT_TCPv6: u32 = 5;
++pub const VIRTIO_NET_HASH_REPORT_UDPv6: u32 = 6;
++pub const VIRTIO_NET_HASH_REPORT_IPv6_EX: u32 = 7;
++pub const VIRTIO_NET_HASH_REPORT_TCPv6_EX: u32 = 8;
++pub const VIRTIO_NET_HASH_REPORT_UDPv6_EX: u32 = 9;
+ pub const VIRTIO_NET_OK: u32 = 0;
+ pub const VIRTIO_NET_ERR: u32 = 1;
+ pub const VIRTIO_NET_CTRL_RX: u32 = 0;
+@@ -217,6 +282,8 @@ pub const VIRTIO_NET_CTRL_MQ: u32 = 4;
+ pub const VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET: u32 = 0;
+ pub const VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN: u32 = 1;
+ pub const VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX: u32 = 32768;
++pub const VIRTIO_NET_CTRL_MQ_RSS_CONFIG: u32 = 1;
++pub const VIRTIO_NET_CTRL_MQ_HASH_CONFIG: u32 = 2;
+ pub const VIRTIO_NET_CTRL_GUEST_OFFLOADS: u32 = 5;
+ pub const VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET: u32 = 0;
+ pub type __s8 = ::std::os::raw::c_schar;
+@@ -321,6 +388,7 @@ fn bindgen_test_layout___kernel_fsid_t() {
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
++pub type __kernel_old_time_t = __kernel_long_t;
+ pub type __kernel_time_t = __kernel_long_t;
+ pub type __kernel_time64_t = ::std::os::raw::c_longlong;
+ pub type __kernel_clock_t = __kernel_long_t;
+@@ -416,17 +484,20 @@ fn bindgen_test_layout_ethhdr() {
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+ pub struct virtio_net_config {
+     pub mac: [__u8; 6usize],
+-    pub status: __u16,
+-    pub max_virtqueue_pairs: __u16,
+-    pub mtu: __u16,
+-    pub speed: __u32,
++    pub status: __virtio16,
++    pub max_virtqueue_pairs: __virtio16,
++    pub mtu: __virtio16,
++    pub speed: __le32,
+     pub duplex: __u8,
++    pub rss_max_key_size: __u8,
++    pub rss_max_indirection_table_length: __le16,
++    pub supported_hash_types: __le32,
+ }
+ #[test]
+ fn bindgen_test_layout_virtio_net_config() {
+     assert_eq!(
+         ::std::mem::size_of::<virtio_net_config>(),
+-        17usize,
++        24usize,
+         concat!("Size of: ", stringify!(virtio_net_config))
+     );
+     assert_eq!(
+@@ -536,17 +607,308 @@ fn bindgen_test_layout_virtio_net_config() {
+         );
+     }
+     test_field_duplex();
++    fn test_field_rss_max_key_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).rss_max_key_size) as usize - ptr as usize
++            },
++            17usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(rss_max_key_size)
++            )
++        );
++    }
++    test_field_rss_max_key_size();
++    fn test_field_rss_max_indirection_table_length() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).rss_max_indirection_table_length) as usize
++                    - ptr as usize
++            },
++            18usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(rss_max_indirection_table_length)
++            )
++        );
++    }
++    test_field_rss_max_indirection_table_length();
++    fn test_field_supported_hash_types() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).supported_hash_types) as usize - ptr as usize
++            },
++            20usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_config),
++                "::",
++                stringify!(supported_hash_types)
++            )
++        );
++    }
++    test_field_supported_hash_types();
+ }
+ #[repr(C)]
+-#[derive(Debug, Default, Copy, Clone, PartialEq)]
++#[derive(Copy, Clone)]
+ pub struct virtio_net_hdr_v1 {
+     pub flags: __u8,
+     pub gso_type: __u8,
+     pub hdr_len: __virtio16,
+     pub gso_size: __virtio16,
++    pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1,
++    pub num_buffers: __virtio16,
++}
++#[repr(C)]
++#[derive(Copy, Clone)]
++pub union virtio_net_hdr_v1__bindgen_ty_1 {
++    pub __bindgen_anon_1: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1,
++    pub csum: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2,
++    pub rsc: virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3,
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1 {
+     pub csum_start: __virtio16,
+     pub csum_offset: __virtio16,
+-    pub num_buffers: __virtio16,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1>(),
++        4usize,
++        concat!(
++            "Size of: ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1)
++        )
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1>(),
++        2usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1)
++        )
++    );
++    fn test_field_csum_start() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_start) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1),
++                "::",
++                stringify!(csum_start)
++            )
++        );
++    }
++    test_field_csum_start();
++    fn test_field_csum_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum_offset) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_1),
++                "::",
++                stringify!(csum_offset)
++            )
++        );
++    }
++    test_field_csum_offset();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2 {
++    pub start: __virtio16,
++    pub offset: __virtio16,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2>(),
++        4usize,
++        concat!(
++            "Size of: ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2)
++        )
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2>(),
++        2usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2)
++        )
++    );
++    fn test_field_start() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).start) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2),
++                "::",
++                stringify!(start)
++            )
++        );
++    }
++    test_field_start();
++    fn test_field_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_2),
++                "::",
++                stringify!(offset)
++            )
++        );
++    }
++    test_field_offset();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3 {
++    pub segments: __le16,
++    pub dup_acks: __le16,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3>(),
++        4usize,
++        concat!(
++            "Size of: ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3)
++        )
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3>(),
++        2usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3)
++        )
++    );
++    fn test_field_segments() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).segments) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3),
++                "::",
++                stringify!(segments)
++            )
++        );
++    }
++    test_field_segments();
++    fn test_field_dup_acks() {
++        assert_eq!(
++            unsafe {
++                let uninit = :: std :: mem :: MaybeUninit :: < virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3 > :: uninit () ;
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).dup_acks) as usize - ptr as usize
++            },
++            2usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1__bindgen_ty_3),
++                "::",
++                stringify!(dup_acks)
++            )
++        );
++    }
++    test_field_dup_acks();
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hdr_v1__bindgen_ty_1() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hdr_v1__bindgen_ty_1>(),
++        4usize,
++        concat!("Size of: ", stringify!(virtio_net_hdr_v1__bindgen_ty_1))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hdr_v1__bindgen_ty_1>(),
++        2usize,
++        concat!("Alignment of ", stringify!(virtio_net_hdr_v1__bindgen_ty_1))
++    );
++    fn test_field_csum() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1__bindgen_ty_1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).csum) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1),
++                "::",
++                stringify!(csum)
++            )
++        );
++    }
++    test_field_csum();
++    fn test_field_rsc() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1__bindgen_ty_1>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).rsc) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1__bindgen_ty_1),
++                "::",
++                stringify!(rsc)
++            )
++        );
++    }
++    test_field_rsc();
++}
++impl Default for virtio_net_hdr_v1__bindgen_ty_1 {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
+ }
+ #[test]
+ fn bindgen_test_layout_virtio_net_hdr_v1() {
+@@ -628,40 +990,6 @@ fn bindgen_test_layout_virtio_net_hdr_v1() {
+         );
+     }
+     test_field_gso_size();
+-    fn test_field_csum_start() {
+-        assert_eq!(
+-            unsafe {
+-                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
+-                let ptr = uninit.as_ptr();
+-                ::std::ptr::addr_of!((*ptr).csum_start) as usize - ptr as usize
+-            },
+-            6usize,
+-            concat!(
+-                "Offset of field: ",
+-                stringify!(virtio_net_hdr_v1),
+-                "::",
+-                stringify!(csum_start)
+-            )
+-        );
+-    }
+-    test_field_csum_start();
+-    fn test_field_csum_offset() {
+-        assert_eq!(
+-            unsafe {
+-                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1>::uninit();
+-                let ptr = uninit.as_ptr();
+-                ::std::ptr::addr_of!((*ptr).csum_offset) as usize - ptr as usize
+-            },
+-            8usize,
+-            concat!(
+-                "Offset of field: ",
+-                stringify!(virtio_net_hdr_v1),
+-                "::",
+-                stringify!(csum_offset)
+-            )
+-        );
+-    }
+-    test_field_csum_offset();
+     fn test_field_num_buffers() {
+         assert_eq!(
+             unsafe {
+@@ -680,6 +1008,113 @@ fn bindgen_test_layout_virtio_net_hdr_v1() {
+     }
+     test_field_num_buffers();
+ }
++impl Default for virtio_net_hdr_v1 {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
++}
++#[repr(C)]
++#[derive(Copy, Clone)]
++pub struct virtio_net_hdr_v1_hash {
++    pub hdr: virtio_net_hdr_v1,
++    pub hash_value: __le32,
++    pub hash_report: __le16,
++    pub padding: __le16,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hdr_v1_hash() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hdr_v1_hash>(),
++        20usize,
++        concat!("Size of: ", stringify!(virtio_net_hdr_v1_hash))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hdr_v1_hash>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_net_hdr_v1_hash))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1_hash>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1_hash),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_hash_value() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1_hash>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_value) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1_hash),
++                "::",
++                stringify!(hash_value)
++            )
++        );
++    }
++    test_field_hash_value();
++    fn test_field_hash_report() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1_hash>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_report) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1_hash),
++                "::",
++                stringify!(hash_report)
++            )
++        );
++    }
++    test_field_hash_report();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hdr_v1_hash>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            18usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hdr_v1_hash),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++impl Default for virtio_net_hdr_v1_hash {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
++}
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone, PartialEq)]
+ pub struct virtio_net_hdr {
+@@ -1008,3 +1443,235 @@ fn bindgen_test_layout_virtio_net_ctrl_mq() {
+     }
+     test_field_virtqueue_pairs();
+ }
++#[repr(C)]
++#[derive(Debug, Default)]
++pub struct virtio_net_rss_config {
++    pub hash_types: __le32,
++    pub indirection_table_mask: __le16,
++    pub unclassified_queue: __le16,
++    pub indirection_table: [__le16; 1usize],
++    pub max_tx_vq: __le16,
++    pub hash_key_length: __u8,
++    pub hash_key_data: __IncompleteArrayField<__u8>,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_rss_config() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_rss_config>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_net_rss_config))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_rss_config>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_net_rss_config))
++    );
++    fn test_field_hash_types() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_types) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(hash_types)
++            )
++        );
++    }
++    test_field_hash_types();
++    fn test_field_indirection_table_mask() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).indirection_table_mask) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(indirection_table_mask)
++            )
++        );
++    }
++    test_field_indirection_table_mask();
++    fn test_field_unclassified_queue() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).unclassified_queue) as usize - ptr as usize
++            },
++            6usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(unclassified_queue)
++            )
++        );
++    }
++    test_field_unclassified_queue();
++    fn test_field_indirection_table() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).indirection_table) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(indirection_table)
++            )
++        );
++    }
++    test_field_indirection_table();
++    fn test_field_max_tx_vq() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).max_tx_vq) as usize - ptr as usize
++            },
++            10usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(max_tx_vq)
++            )
++        );
++    }
++    test_field_max_tx_vq();
++    fn test_field_hash_key_length() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_key_length) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(hash_key_length)
++            )
++        );
++    }
++    test_field_hash_key_length();
++    fn test_field_hash_key_data() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_rss_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_key_data) as usize - ptr as usize
++            },
++            13usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_rss_config),
++                "::",
++                stringify!(hash_key_data)
++            )
++        );
++    }
++    test_field_hash_key_data();
++}
++#[repr(C)]
++#[derive(Debug, Default)]
++pub struct virtio_net_hash_config {
++    pub hash_types: __le32,
++    pub reserved: [__le16; 4usize],
++    pub hash_key_length: __u8,
++    pub hash_key_data: __IncompleteArrayField<__u8>,
++}
++#[test]
++fn bindgen_test_layout_virtio_net_hash_config() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_net_hash_config>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_net_hash_config))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_net_hash_config>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_net_hash_config))
++    );
++    fn test_field_hash_types() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hash_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_types) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hash_config),
++                "::",
++                stringify!(hash_types)
++            )
++        );
++    }
++    test_field_hash_types();
++    fn test_field_reserved() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hash_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hash_config),
++                "::",
++                stringify!(reserved)
++            )
++        );
++    }
++    test_field_reserved();
++    fn test_field_hash_key_length() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hash_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_key_length) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hash_config),
++                "::",
++                stringify!(hash_key_length)
++            )
++        );
++    }
++    test_field_hash_key_length();
++    fn test_field_hash_key_data() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_net_hash_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hash_key_data) as usize - ptr as usize
++            },
++            13usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_net_hash_config),
++                "::",
++                stringify!(hash_key_data)
++            )
++        );
++    }
++    test_field_hash_key_data();
++}
+diff --git a/crates/virtio-bindings/src/virtio_ring.rs b/crates/virtio-bindings/src/virtio_ring.rs
+index 60b84ab..20b4545 100644
+--- a/crates/virtio-bindings/src/virtio_ring.rs
++++ b/crates/virtio-bindings/src/virtio_ring.rs
+@@ -359,6 +359,7 @@ fn bindgen_test_layout___kernel_fsid_t() {
+ }
+ pub type __kernel_off_t = __kernel_long_t;
+ pub type __kernel_loff_t = ::std::os::raw::c_longlong;
++pub type __kernel_old_time_t = __kernel_long_t;
+ pub type __kernel_time_t = __kernel_long_t;
+ pub type __kernel_time64_t = ::std::os::raw::c_longlong;
+ pub type __kernel_clock_t = __kernel_long_t;
+@@ -592,12 +593,13 @@ fn bindgen_test_layout_vring_used_elem() {
+     }
+     test_field_len();
+ }
++pub type vring_used_elem_t = vring_used_elem;
+ #[repr(C)]
+ #[derive(Debug, Default)]
+ pub struct vring_used {
+     pub flags: __virtio16,
+     pub idx: __virtio16,
+-    pub ring: __IncompleteArrayField<vring_used_elem>,
++    pub ring: __IncompleteArrayField<vring_used_elem_t>,
+ }
+ #[test]
+ fn bindgen_test_layout_vring_used() {
+@@ -663,13 +665,16 @@ fn bindgen_test_layout_vring_used() {
+     }
+     test_field_ring();
+ }
++pub type vring_desc_t = vring_desc;
++pub type vring_avail_t = vring_avail;
++pub type vring_used_t = vring_used;
+ #[repr(C)]
+ #[derive(Debug, Copy, Clone, PartialEq)]
+ pub struct vring {
+     pub num: ::std::os::raw::c_uint,
+-    pub desc: *mut vring_desc,
+-    pub avail: *mut vring_avail,
+-    pub used: *mut vring_used,
++    pub desc: *mut vring_desc_t,
++    pub avail: *mut vring_avail_t,
++    pub used: *mut vring_used_t,
+ }
+ #[test]
+ fn bindgen_test_layout_vring() {
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/0005-virtio-bindings-add-virtio-gpu-bindings.patch b/pkgs/applications/virtualization/cloud-hypervisor/0005-virtio-bindings-add-virtio-gpu-bindings.patch
new file mode 100644
index 00000000000..6747399d670
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/0005-virtio-bindings-add-virtio-gpu-bindings.patch
@@ -0,0 +1,3587 @@
+From ffd586ecc6762da0e1ea870e0858391f9c158d8b Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <alyssa.ross@unikie.com>
+Date: Wed, 31 Aug 2022 17:11:12 +0000
+Subject: [PATCH 5/5] virtio-bindings: add virtio-gpu bindings
+
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ crates/virtio-bindings/CONTRIBUTING.md   |    8 +-
+ crates/virtio-bindings/src/lib.rs        |    1 +
+ crates/virtio-bindings/src/virtio_gpu.rs | 3532 ++++++++++++++++++++++
+ 3 files changed, 3537 insertions(+), 4 deletions(-)
+ create mode 100644 crates/virtio-bindings/src/virtio_gpu.rs
+
+diff --git a/crates/virtio-bindings/CONTRIBUTING.md b/crates/virtio-bindings/CONTRIBUTING.md
+index 1b3da2f..d435078 100644
+--- a/crates/virtio-bindings/CONTRIBUTING.md
++++ b/crates/virtio-bindings/CONTRIBUTING.md
+@@ -30,12 +30,12 @@ git checkout v5.0
+ 
+ # Step 2: Generate the bindings from the kernel headers. We need to
+ # generate a file for each one of the virtio headers we're interested on.
+-# For the moment, we're generating "virtio_blk", "virtio_net" and
+-# "virtio_ring". Feel free to add additional header files if you need them
+-# for your project.
++# For the moment, we're generating "virtio_blk", "virtio_gpu", "virtio_net"
++# and "virtio_ring". Feel free to add additional header files if you need
++# them for your project.
+ make headers_install INSTALL_HDR_PATH=v5_0_headers
+ cd v5_0_headers
+-for i in virtio_blk virtio_net virtio_ring ; do \
++for i in virtio_blk virtio_gpu virtio_net virtio_ring ; do \
+     bindgen include/linux/$i.h -o $i.rs \
+     --with-derive-default \
+     --with-derive-partialeq \
+diff --git a/crates/virtio-bindings/src/lib.rs b/crates/virtio-bindings/src/lib.rs
+index 9702f17..543f630 100644
+--- a/crates/virtio-bindings/src/lib.rs
++++ b/crates/virtio-bindings/src/lib.rs
+@@ -7,6 +7,7 @@
+ #![allow(non_snake_case)]
+ 
+ pub mod virtio_blk;
++pub mod virtio_gpu;
+ pub mod virtio_net;
+ pub mod virtio_ring;
+ 
+diff --git a/crates/virtio-bindings/src/virtio_gpu.rs b/crates/virtio-bindings/src/virtio_gpu.rs
+new file mode 100644
+index 0000000..b1f9e5f
+--- /dev/null
++++ b/crates/virtio-bindings/src/virtio_gpu.rs
+@@ -0,0 +1,3532 @@
++/* automatically generated by rust-bindgen 0.60.1 */
++
++#[repr(C)]
++#[derive(Default)]
++pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
++impl<T> __IncompleteArrayField<T> {
++    #[inline]
++    pub const fn new() -> Self {
++        __IncompleteArrayField(::std::marker::PhantomData, [])
++    }
++    #[inline]
++    pub fn as_ptr(&self) -> *const T {
++        self as *const _ as *const T
++    }
++    #[inline]
++    pub fn as_mut_ptr(&mut self) -> *mut T {
++        self as *mut _ as *mut T
++    }
++    #[inline]
++    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
++        ::std::slice::from_raw_parts(self.as_ptr(), len)
++    }
++    #[inline]
++    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
++        ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
++    }
++}
++impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
++    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
++        fmt.write_str("__IncompleteArrayField")
++    }
++}
++pub const __BITS_PER_LONG: u32 = 64;
++pub const __FD_SETSIZE: u32 = 1024;
++pub const VIRTIO_GPU_F_VIRGL: u32 = 0;
++pub const VIRTIO_GPU_F_EDID: u32 = 1;
++pub const VIRTIO_GPU_F_RESOURCE_UUID: u32 = 2;
++pub const VIRTIO_GPU_F_RESOURCE_BLOB: u32 = 3;
++pub const VIRTIO_GPU_F_CONTEXT_INIT: u32 = 4;
++pub const VIRTIO_GPU_FLAG_FENCE: u32 = 1;
++pub const VIRTIO_GPU_FLAG_INFO_RING_IDX: u32 = 2;
++pub const VIRTIO_GPU_MAX_SCANOUTS: u32 = 16;
++pub const VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP: u32 = 1;
++pub const VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK: u32 = 255;
++pub const VIRTIO_GPU_CAPSET_VIRGL: u32 = 1;
++pub const VIRTIO_GPU_CAPSET_VIRGL2: u32 = 2;
++pub const VIRTIO_GPU_EVENT_DISPLAY: u32 = 1;
++pub const VIRTIO_GPU_BLOB_MEM_GUEST: u32 = 1;
++pub const VIRTIO_GPU_BLOB_MEM_HOST3D: u32 = 2;
++pub const VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST: u32 = 3;
++pub const VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE: u32 = 1;
++pub const VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE: u32 = 2;
++pub const VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE: u32 = 4;
++pub const VIRTIO_GPU_MAP_CACHE_MASK: u32 = 15;
++pub const VIRTIO_GPU_MAP_CACHE_NONE: u32 = 0;
++pub const VIRTIO_GPU_MAP_CACHE_CACHED: u32 = 1;
++pub const VIRTIO_GPU_MAP_CACHE_UNCACHED: u32 = 2;
++pub const VIRTIO_GPU_MAP_CACHE_WC: u32 = 3;
++pub type __s8 = ::std::os::raw::c_schar;
++pub type __u8 = ::std::os::raw::c_uchar;
++pub type __s16 = ::std::os::raw::c_short;
++pub type __u16 = ::std::os::raw::c_ushort;
++pub type __s32 = ::std::os::raw::c_int;
++pub type __u32 = ::std::os::raw::c_uint;
++pub type __s64 = ::std::os::raw::c_longlong;
++pub type __u64 = ::std::os::raw::c_ulonglong;
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct __kernel_fd_set {
++    pub fds_bits: [::std::os::raw::c_ulong; 16usize],
++}
++#[test]
++fn bindgen_test_layout___kernel_fd_set() {
++    assert_eq!(
++        ::std::mem::size_of::<__kernel_fd_set>(),
++        128usize,
++        concat!("Size of: ", stringify!(__kernel_fd_set))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<__kernel_fd_set>(),
++        8usize,
++        concat!("Alignment of ", stringify!(__kernel_fd_set))
++    );
++    fn test_field_fds_bits() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fd_set>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fd_set),
++                "::",
++                stringify!(fds_bits)
++            )
++        );
++    }
++    test_field_fds_bits();
++}
++pub type __kernel_sighandler_t =
++    ::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
++pub type __kernel_key_t = ::std::os::raw::c_int;
++pub type __kernel_mqd_t = ::std::os::raw::c_int;
++pub type __kernel_old_uid_t = ::std::os::raw::c_ushort;
++pub type __kernel_old_gid_t = ::std::os::raw::c_ushort;
++pub type __kernel_old_dev_t = ::std::os::raw::c_ulong;
++pub type __kernel_long_t = ::std::os::raw::c_long;
++pub type __kernel_ulong_t = ::std::os::raw::c_ulong;
++pub type __kernel_ino_t = __kernel_ulong_t;
++pub type __kernel_mode_t = ::std::os::raw::c_uint;
++pub type __kernel_pid_t = ::std::os::raw::c_int;
++pub type __kernel_ipc_pid_t = ::std::os::raw::c_int;
++pub type __kernel_uid_t = ::std::os::raw::c_uint;
++pub type __kernel_gid_t = ::std::os::raw::c_uint;
++pub type __kernel_suseconds_t = __kernel_long_t;
++pub type __kernel_daddr_t = ::std::os::raw::c_int;
++pub type __kernel_uid32_t = ::std::os::raw::c_uint;
++pub type __kernel_gid32_t = ::std::os::raw::c_uint;
++pub type __kernel_size_t = __kernel_ulong_t;
++pub type __kernel_ssize_t = __kernel_long_t;
++pub type __kernel_ptrdiff_t = __kernel_long_t;
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct __kernel_fsid_t {
++    pub val: [::std::os::raw::c_int; 2usize],
++}
++#[test]
++fn bindgen_test_layout___kernel_fsid_t() {
++    assert_eq!(
++        ::std::mem::size_of::<__kernel_fsid_t>(),
++        8usize,
++        concat!("Size of: ", stringify!(__kernel_fsid_t))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<__kernel_fsid_t>(),
++        4usize,
++        concat!("Alignment of ", stringify!(__kernel_fsid_t))
++    );
++    fn test_field_val() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<__kernel_fsid_t>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).val) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(__kernel_fsid_t),
++                "::",
++                stringify!(val)
++            )
++        );
++    }
++    test_field_val();
++}
++pub type __kernel_off_t = __kernel_long_t;
++pub type __kernel_loff_t = ::std::os::raw::c_longlong;
++pub type __kernel_old_time_t = __kernel_long_t;
++pub type __kernel_time_t = __kernel_long_t;
++pub type __kernel_time64_t = ::std::os::raw::c_longlong;
++pub type __kernel_clock_t = __kernel_long_t;
++pub type __kernel_timer_t = ::std::os::raw::c_int;
++pub type __kernel_clockid_t = ::std::os::raw::c_int;
++pub type __kernel_caddr_t = *mut ::std::os::raw::c_char;
++pub type __kernel_uid16_t = ::std::os::raw::c_ushort;
++pub type __kernel_gid16_t = ::std::os::raw::c_ushort;
++pub type __le16 = __u16;
++pub type __be16 = __u16;
++pub type __le32 = __u32;
++pub type __be32 = __u32;
++pub type __le64 = __u64;
++pub type __be64 = __u64;
++pub type __sum16 = __u16;
++pub type __wsum = __u32;
++pub type __poll_t = ::std::os::raw::c_uint;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_UNDEFINED: virtio_gpu_ctrl_type = 0;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_GET_DISPLAY_INFO: virtio_gpu_ctrl_type = 256;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: virtio_gpu_ctrl_type = 257;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_UNREF: virtio_gpu_ctrl_type = 258;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_SET_SCANOUT: virtio_gpu_ctrl_type = 259;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_FLUSH: virtio_gpu_ctrl_type = 260;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: virtio_gpu_ctrl_type = 261;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: virtio_gpu_ctrl_type = 262;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: virtio_gpu_ctrl_type = 263;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_GET_CAPSET_INFO: virtio_gpu_ctrl_type = 264;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_GET_CAPSET: virtio_gpu_ctrl_type = 265;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_GET_EDID: virtio_gpu_ctrl_type = 266;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID: virtio_gpu_ctrl_type = 267;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB: virtio_gpu_ctrl_type = 268;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_SET_SCANOUT_BLOB: virtio_gpu_ctrl_type = 269;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_CTX_CREATE: virtio_gpu_ctrl_type = 512;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_CTX_DESTROY: virtio_gpu_ctrl_type = 513;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE: virtio_gpu_ctrl_type = 514;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE: virtio_gpu_ctrl_type = 515;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_CREATE_3D: virtio_gpu_ctrl_type = 516;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D: virtio_gpu_ctrl_type = 517;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D: virtio_gpu_ctrl_type = 518;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_SUBMIT_3D: virtio_gpu_ctrl_type = 519;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB: virtio_gpu_ctrl_type = 520;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB: virtio_gpu_ctrl_type = 521;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_UPDATE_CURSOR: virtio_gpu_ctrl_type = 768;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_CMD_MOVE_CURSOR: virtio_gpu_ctrl_type = 769;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_NODATA: virtio_gpu_ctrl_type = 4352;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_DISPLAY_INFO: virtio_gpu_ctrl_type = 4353;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_CAPSET_INFO: virtio_gpu_ctrl_type = 4354;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_CAPSET: virtio_gpu_ctrl_type = 4355;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_EDID: virtio_gpu_ctrl_type = 4356;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_RESOURCE_UUID: virtio_gpu_ctrl_type = 4357;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_OK_MAP_INFO: virtio_gpu_ctrl_type = 4358;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_UNSPEC: virtio_gpu_ctrl_type = 4608;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY: virtio_gpu_ctrl_type = 4609;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID: virtio_gpu_ctrl_type = 4610;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID: virtio_gpu_ctrl_type = 4611;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID: virtio_gpu_ctrl_type = 4612;
++pub const virtio_gpu_ctrl_type_VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER: virtio_gpu_ctrl_type = 4613;
++pub type virtio_gpu_ctrl_type = ::std::os::raw::c_uint;
++pub const virtio_gpu_shm_id_VIRTIO_GPU_SHM_ID_UNDEFINED: virtio_gpu_shm_id = 0;
++pub const virtio_gpu_shm_id_VIRTIO_GPU_SHM_ID_HOST_VISIBLE: virtio_gpu_shm_id = 1;
++pub type virtio_gpu_shm_id = ::std::os::raw::c_uint;
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_ctrl_hdr {
++    pub type_: __le32,
++    pub flags: __le32,
++    pub fence_id: __le64,
++    pub ctx_id: __le32,
++    pub ring_idx: __u8,
++    pub padding: [__u8; 3usize],
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_ctrl_hdr() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_ctrl_hdr>(),
++        24usize,
++        concat!("Size of: ", stringify!(virtio_gpu_ctrl_hdr))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_ctrl_hdr>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_ctrl_hdr))
++    );
++    fn test_field_type() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(type_)
++            )
++        );
++    }
++    test_field_type();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_fence_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).fence_id) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(fence_id)
++            )
++        );
++    }
++    test_field_fence_id();
++    fn test_field_ctx_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).ctx_id) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(ctx_id)
++            )
++        );
++    }
++    test_field_ctx_id();
++    fn test_field_ring_idx() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).ring_idx) as usize - ptr as usize
++            },
++            20usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(ring_idx)
++            )
++        );
++    }
++    test_field_ring_idx();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctrl_hdr>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            21usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctrl_hdr),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_cursor_pos {
++    pub scanout_id: __le32,
++    pub x: __le32,
++    pub y: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_cursor_pos() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_cursor_pos>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_gpu_cursor_pos))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_cursor_pos>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_cursor_pos))
++    );
++    fn test_field_scanout_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cursor_pos>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).scanout_id) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cursor_pos),
++                "::",
++                stringify!(scanout_id)
++            )
++        );
++    }
++    test_field_scanout_id();
++    fn test_field_x() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cursor_pos>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cursor_pos),
++                "::",
++                stringify!(x)
++            )
++        );
++    }
++    test_field_x();
++    fn test_field_y() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cursor_pos>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cursor_pos),
++                "::",
++                stringify!(y)
++            )
++        );
++    }
++    test_field_y();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cursor_pos>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cursor_pos),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_update_cursor {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub pos: virtio_gpu_cursor_pos,
++    pub resource_id: __le32,
++    pub hot_x: __le32,
++    pub hot_y: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_update_cursor() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_update_cursor>(),
++        56usize,
++        concat!("Size of: ", stringify!(virtio_gpu_update_cursor))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_update_cursor>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_update_cursor))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_pos() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).pos) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(pos)
++            )
++        );
++    }
++    test_field_pos();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_hot_x() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hot_x) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(hot_x)
++            )
++        );
++    }
++    test_field_hot_x();
++    fn test_field_hot_y() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hot_y) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(hot_y)
++            )
++        );
++    }
++    test_field_hot_y();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_update_cursor>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            52usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_update_cursor),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_rect {
++    pub x: __le32,
++    pub y: __le32,
++    pub width: __le32,
++    pub height: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_rect() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_rect>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_gpu_rect))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_rect>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_rect))
++    );
++    fn test_field_x() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_rect>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_rect),
++                "::",
++                stringify!(x)
++            )
++        );
++    }
++    test_field_x();
++    fn test_field_y() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_rect>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_rect),
++                "::",
++                stringify!(y)
++            )
++        );
++    }
++    test_field_y();
++    fn test_field_width() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_rect>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).width) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_rect),
++                "::",
++                stringify!(width)
++            )
++        );
++    }
++    test_field_width();
++    fn test_field_height() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_rect>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).height) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_rect),
++                "::",
++                stringify!(height)
++            )
++        );
++    }
++    test_field_height();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_unref {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_unref() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_unref>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_unref))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_unref>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_unref))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unref>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unref),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unref>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unref),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unref>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unref),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_create_2d {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub format: __le32,
++    pub width: __le32,
++    pub height: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_create_2d() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_create_2d>(),
++        40usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_create_2d))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_create_2d>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_create_2d))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_2d),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_2d),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_format() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_2d),
++                "::",
++                stringify!(format)
++            )
++        );
++    }
++    test_field_format();
++    fn test_field_width() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).width) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_2d),
++                "::",
++                stringify!(width)
++            )
++        );
++    }
++    test_field_width();
++    fn test_field_height() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).height) as usize - ptr as usize
++            },
++            36usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_2d),
++                "::",
++                stringify!(height)
++            )
++        );
++    }
++    test_field_height();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_set_scanout {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub r: virtio_gpu_rect,
++    pub scanout_id: __le32,
++    pub resource_id: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_set_scanout() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_set_scanout>(),
++        48usize,
++        concat!("Size of: ", stringify!(virtio_gpu_set_scanout))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_set_scanout>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_set_scanout))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_r() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout),
++                "::",
++                stringify!(r)
++            )
++        );
++    }
++    test_field_r();
++    fn test_field_scanout_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).scanout_id) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout),
++                "::",
++                stringify!(scanout_id)
++            )
++        );
++    }
++    test_field_scanout_id();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_flush {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub r: virtio_gpu_rect,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_flush() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_flush>(),
++        48usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_flush))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_flush>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_flush))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_flush>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_flush),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_r() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_flush>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_flush),
++                "::",
++                stringify!(r)
++            )
++        );
++    }
++    test_field_r();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_flush>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_flush),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_flush>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_flush),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_transfer_to_host_2d {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub r: virtio_gpu_rect,
++    pub offset: __le64,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_transfer_to_host_2d() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_transfer_to_host_2d>(),
++        56usize,
++        concat!("Size of: ", stringify!(virtio_gpu_transfer_to_host_2d))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_transfer_to_host_2d>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_transfer_to_host_2d))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_to_host_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_to_host_2d),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_r() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_to_host_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_to_host_2d),
++                "::",
++                stringify!(r)
++            )
++        );
++    }
++    test_field_r();
++    fn test_field_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_to_host_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_to_host_2d),
++                "::",
++                stringify!(offset)
++            )
++        );
++    }
++    test_field_offset();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_to_host_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_to_host_2d),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_to_host_2d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            52usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_to_host_2d),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_mem_entry {
++    pub addr: __le64,
++    pub length: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_mem_entry() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_mem_entry>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_gpu_mem_entry))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_mem_entry>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_mem_entry))
++    );
++    fn test_field_addr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_mem_entry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_mem_entry),
++                "::",
++                stringify!(addr)
++            )
++        );
++    }
++    test_field_addr();
++    fn test_field_length() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_mem_entry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_mem_entry),
++                "::",
++                stringify!(length)
++            )
++        );
++    }
++    test_field_length();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_mem_entry>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_mem_entry),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_attach_backing {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub nr_entries: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_attach_backing() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_attach_backing>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_attach_backing))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_attach_backing>(),
++        8usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_gpu_resource_attach_backing)
++        )
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_attach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_attach_backing),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_attach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_attach_backing),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_nr_entries() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_attach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).nr_entries) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_attach_backing),
++                "::",
++                stringify!(nr_entries)
++            )
++        );
++    }
++    test_field_nr_entries();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_detach_backing {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_detach_backing() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_detach_backing>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_detach_backing))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_detach_backing>(),
++        8usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_gpu_resource_detach_backing)
++        )
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_detach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_detach_backing),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_detach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_detach_backing),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit =
++                    ::std::mem::MaybeUninit::<virtio_gpu_resource_detach_backing>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_detach_backing),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_display_info {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub pmodes: [virtio_gpu_resp_display_info_virtio_gpu_display_one; 16usize],
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_display_info_virtio_gpu_display_one {
++    pub r: virtio_gpu_rect,
++    pub enabled: __le32,
++    pub flags: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_display_info_virtio_gpu_display_one() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_display_info_virtio_gpu_display_one>(),
++        24usize,
++        concat!(
++            "Size of: ",
++            stringify!(virtio_gpu_resp_display_info_virtio_gpu_display_one)
++        )
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_display_info_virtio_gpu_display_one>(),
++        4usize,
++        concat!(
++            "Alignment of ",
++            stringify!(virtio_gpu_resp_display_info_virtio_gpu_display_one)
++        )
++    );
++    fn test_field_r() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<
++                    virtio_gpu_resp_display_info_virtio_gpu_display_one,
++                >::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_display_info_virtio_gpu_display_one),
++                "::",
++                stringify!(r)
++            )
++        );
++    }
++    test_field_r();
++    fn test_field_enabled() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<
++                    virtio_gpu_resp_display_info_virtio_gpu_display_one,
++                >::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).enabled) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_display_info_virtio_gpu_display_one),
++                "::",
++                stringify!(enabled)
++            )
++        );
++    }
++    test_field_enabled();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<
++                    virtio_gpu_resp_display_info_virtio_gpu_display_one,
++                >::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            20usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_display_info_virtio_gpu_display_one),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_display_info() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_display_info>(),
++        408usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_display_info))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_display_info>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_display_info))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_display_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_display_info),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_pmodes() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_display_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).pmodes) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_display_info),
++                "::",
++                stringify!(pmodes)
++            )
++        );
++    }
++    test_field_pmodes();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_box {
++    pub x: __le32,
++    pub y: __le32,
++    pub z: __le32,
++    pub w: __le32,
++    pub h: __le32,
++    pub d: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_box() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_box>(),
++        24usize,
++        concat!("Size of: ", stringify!(virtio_gpu_box))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_box>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_box))
++    );
++    fn test_field_x() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(x)
++            )
++        );
++    }
++    test_field_x();
++    fn test_field_y() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(y)
++            )
++        );
++    }
++    test_field_y();
++    fn test_field_z() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).z) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(z)
++            )
++        );
++    }
++    test_field_z();
++    fn test_field_w() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).w) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(w)
++            )
++        );
++    }
++    test_field_w();
++    fn test_field_h() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).h) as usize - ptr as usize
++            },
++            16usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(h)
++            )
++        );
++    }
++    test_field_h();
++    fn test_field_d() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_box>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).d) as usize - ptr as usize
++            },
++            20usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_box),
++                "::",
++                stringify!(d)
++            )
++        );
++    }
++    test_field_d();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_transfer_host_3d {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub box_: virtio_gpu_box,
++    pub offset: __le64,
++    pub resource_id: __le32,
++    pub level: __le32,
++    pub stride: __le32,
++    pub layer_stride: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_transfer_host_3d() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_transfer_host_3d>(),
++        72usize,
++        concat!("Size of: ", stringify!(virtio_gpu_transfer_host_3d))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_transfer_host_3d>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_transfer_host_3d))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_box() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).box_) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(box_)
++            )
++        );
++    }
++    test_field_box();
++    fn test_field_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(offset)
++            )
++        );
++    }
++    test_field_offset();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            56usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_level() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).level) as usize - ptr as usize
++            },
++            60usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(level)
++            )
++        );
++    }
++    test_field_level();
++    fn test_field_stride() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).stride) as usize - ptr as usize
++            },
++            64usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(stride)
++            )
++        );
++    }
++    test_field_stride();
++    fn test_field_layer_stride() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_transfer_host_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).layer_stride) as usize - ptr as usize
++            },
++            68usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_transfer_host_3d),
++                "::",
++                stringify!(layer_stride)
++            )
++        );
++    }
++    test_field_layer_stride();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_create_3d {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub target: __le32,
++    pub format: __le32,
++    pub bind: __le32,
++    pub width: __le32,
++    pub height: __le32,
++    pub depth: __le32,
++    pub array_size: __le32,
++    pub last_level: __le32,
++    pub nr_samples: __le32,
++    pub flags: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_create_3d() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_create_3d>(),
++        72usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_create_3d))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_create_3d>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_create_3d))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_target() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).target) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(target)
++            )
++        );
++    }
++    test_field_target();
++    fn test_field_format() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(format)
++            )
++        );
++    }
++    test_field_format();
++    fn test_field_bind() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).bind) as usize - ptr as usize
++            },
++            36usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(bind)
++            )
++        );
++    }
++    test_field_bind();
++    fn test_field_width() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).width) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(width)
++            )
++        );
++    }
++    test_field_width();
++    fn test_field_height() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).height) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(height)
++            )
++        );
++    }
++    test_field_height();
++    fn test_field_depth() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).depth) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(depth)
++            )
++        );
++    }
++    test_field_depth();
++    fn test_field_array_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).array_size) as usize - ptr as usize
++            },
++            52usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(array_size)
++            )
++        );
++    }
++    test_field_array_size();
++    fn test_field_last_level() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).last_level) as usize - ptr as usize
++            },
++            56usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(last_level)
++            )
++        );
++    }
++    test_field_last_level();
++    fn test_field_nr_samples() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).nr_samples) as usize - ptr as usize
++            },
++            60usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(nr_samples)
++            )
++        );
++    }
++    test_field_nr_samples();
++    fn test_field_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize
++            },
++            64usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(flags)
++            )
++        );
++    }
++    test_field_flags();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_3d>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            68usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_3d),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_ctx_create {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub nlen: __le32,
++    pub context_init: __le32,
++    pub debug_name: [::std::os::raw::c_char; 64usize],
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_ctx_create() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_ctx_create>(),
++        96usize,
++        concat!("Size of: ", stringify!(virtio_gpu_ctx_create))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_ctx_create>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_ctx_create))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_create>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_create),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_nlen() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_create>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).nlen) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_create),
++                "::",
++                stringify!(nlen)
++            )
++        );
++    }
++    test_field_nlen();
++    fn test_field_context_init() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_create>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).context_init) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_create),
++                "::",
++                stringify!(context_init)
++            )
++        );
++    }
++    test_field_context_init();
++    fn test_field_debug_name() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_create>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).debug_name) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_create),
++                "::",
++                stringify!(debug_name)
++            )
++        );
++    }
++    test_field_debug_name();
++}
++impl Default for virtio_gpu_ctx_create {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_ctx_destroy {
++    pub hdr: virtio_gpu_ctrl_hdr,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_ctx_destroy() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_ctx_destroy>(),
++        24usize,
++        concat!("Size of: ", stringify!(virtio_gpu_ctx_destroy))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_ctx_destroy>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_ctx_destroy))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_destroy>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_destroy),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_ctx_resource {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_ctx_resource() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_ctx_resource>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_ctx_resource))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_ctx_resource>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_ctx_resource))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_resource>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_resource),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_resource>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_resource),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_ctx_resource>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_ctx_resource),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_cmd_submit {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub size: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_cmd_submit() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_cmd_submit>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_cmd_submit))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_cmd_submit>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_cmd_submit))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_submit>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_submit),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_submit>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_submit),
++                "::",
++                stringify!(size)
++            )
++        );
++    }
++    test_field_size();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_submit>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_submit),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_get_capset_info {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub capset_index: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_get_capset_info() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_get_capset_info>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_get_capset_info))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_get_capset_info>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_get_capset_info))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset_info),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_capset_index() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_index) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset_info),
++                "::",
++                stringify!(capset_index)
++            )
++        );
++    }
++    test_field_capset_index();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset_info),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_capset_info {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub capset_id: __le32,
++    pub capset_max_version: __le32,
++    pub capset_max_size: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_capset_info() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_capset_info>(),
++        40usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_capset_info))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_capset_info>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_capset_info))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset_info),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_capset_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset_info),
++                "::",
++                stringify!(capset_id)
++            )
++        );
++    }
++    test_field_capset_id();
++    fn test_field_capset_max_version() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_max_version) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset_info),
++                "::",
++                stringify!(capset_max_version)
++            )
++        );
++    }
++    test_field_capset_max_version();
++    fn test_field_capset_max_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_max_size) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset_info),
++                "::",
++                stringify!(capset_max_size)
++            )
++        );
++    }
++    test_field_capset_max_size();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            36usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset_info),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_get_capset {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub capset_id: __le32,
++    pub capset_version: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_get_capset() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_get_capset>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_get_capset))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_get_capset>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_get_capset))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_capset_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset),
++                "::",
++                stringify!(capset_id)
++            )
++        );
++    }
++    test_field_capset_id();
++    fn test_field_capset_version() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_get_capset>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_version) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_get_capset),
++                "::",
++                stringify!(capset_version)
++            )
++        );
++    }
++    test_field_capset_version();
++}
++#[repr(C)]
++#[derive(Debug, Default)]
++pub struct virtio_gpu_resp_capset {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub capset_data: __IncompleteArrayField<__u8>,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_capset() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_capset>(),
++        24usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_capset))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_capset>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_capset))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_capset_data() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_capset>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).capset_data) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_capset),
++                "::",
++                stringify!(capset_data)
++            )
++        );
++    }
++    test_field_capset_data();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_cmd_get_edid {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub scanout: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_cmd_get_edid() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_cmd_get_edid>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_cmd_get_edid))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_cmd_get_edid>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_cmd_get_edid))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_get_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_get_edid),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_scanout() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_get_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).scanout) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_get_edid),
++                "::",
++                stringify!(scanout)
++            )
++        );
++    }
++    test_field_scanout();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_cmd_get_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_cmd_get_edid),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_edid {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub size: __le32,
++    pub padding: __le32,
++    pub edid: [__u8; 1024usize],
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_edid() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_edid>(),
++        1056usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_edid))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_edid>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_edid))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_edid),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_edid),
++                "::",
++                stringify!(size)
++            )
++        );
++    }
++    test_field_size();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_edid),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++    fn test_field_edid() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_edid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).edid) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_edid),
++                "::",
++                stringify!(edid)
++            )
++        );
++    }
++    test_field_edid();
++}
++impl Default for virtio_gpu_resp_edid {
++    fn default() -> Self {
++        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
++        unsafe {
++            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
++            s.assume_init()
++        }
++    }
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_config {
++    pub events_read: __le32,
++    pub events_clear: __le32,
++    pub num_scanouts: __le32,
++    pub num_capsets: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_config() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_config>(),
++        16usize,
++        concat!("Size of: ", stringify!(virtio_gpu_config))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_config>(),
++        4usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_config))
++    );
++    fn test_field_events_read() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).events_read) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_config),
++                "::",
++                stringify!(events_read)
++            )
++        );
++    }
++    test_field_events_read();
++    fn test_field_events_clear() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).events_clear) as usize - ptr as usize
++            },
++            4usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_config),
++                "::",
++                stringify!(events_clear)
++            )
++        );
++    }
++    test_field_events_clear();
++    fn test_field_num_scanouts() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_scanouts) as usize - ptr as usize
++            },
++            8usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_config),
++                "::",
++                stringify!(num_scanouts)
++            )
++        );
++    }
++    test_field_num_scanouts();
++    fn test_field_num_capsets() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_config>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).num_capsets) as usize - ptr as usize
++            },
++            12usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_config),
++                "::",
++                stringify!(num_capsets)
++            )
++        );
++    }
++    test_field_num_capsets();
++}
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: virtio_gpu_formats = 1;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: virtio_gpu_formats = 2;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM: virtio_gpu_formats = 3;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM: virtio_gpu_formats = 4;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM: virtio_gpu_formats = 67;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM: virtio_gpu_formats = 68;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM: virtio_gpu_formats = 121;
++pub const virtio_gpu_formats_VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM: virtio_gpu_formats = 134;
++pub type virtio_gpu_formats = ::std::os::raw::c_uint;
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_assign_uuid {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_assign_uuid() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_assign_uuid>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_assign_uuid))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_assign_uuid>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_assign_uuid))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_assign_uuid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_assign_uuid),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_assign_uuid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_assign_uuid),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_assign_uuid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_assign_uuid),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_resource_uuid {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub uuid: [__u8; 16usize],
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_resource_uuid() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_resource_uuid>(),
++        40usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_resource_uuid))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_resource_uuid>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_resource_uuid))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_resource_uuid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_resource_uuid),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_uuid() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_resource_uuid>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).uuid) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_resource_uuid),
++                "::",
++                stringify!(uuid)
++            )
++        );
++    }
++    test_field_uuid();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_create_blob {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub blob_mem: __le32,
++    pub blob_flags: __le32,
++    pub nr_entries: __le32,
++    pub blob_id: __le64,
++    pub size: __le64,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_create_blob() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_create_blob>(),
++        56usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_create_blob))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_create_blob>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_create_blob))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_blob_mem() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).blob_mem) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(blob_mem)
++            )
++        );
++    }
++    test_field_blob_mem();
++    fn test_field_blob_flags() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).blob_flags) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(blob_flags)
++            )
++        );
++    }
++    test_field_blob_flags();
++    fn test_field_nr_entries() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).nr_entries) as usize - ptr as usize
++            },
++            36usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(nr_entries)
++            )
++        );
++    }
++    test_field_nr_entries();
++    fn test_field_blob_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).blob_id) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(blob_id)
++            )
++        );
++    }
++    test_field_blob_id();
++    fn test_field_size() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_create_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_create_blob),
++                "::",
++                stringify!(size)
++            )
++        );
++    }
++    test_field_size();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_set_scanout_blob {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub r: virtio_gpu_rect,
++    pub scanout_id: __le32,
++    pub resource_id: __le32,
++    pub width: __le32,
++    pub height: __le32,
++    pub format: __le32,
++    pub padding: __le32,
++    pub strides: [__le32; 4usize],
++    pub offsets: [__le32; 4usize],
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_set_scanout_blob() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_set_scanout_blob>(),
++        96usize,
++        concat!("Size of: ", stringify!(virtio_gpu_set_scanout_blob))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_set_scanout_blob>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_set_scanout_blob))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_r() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(r)
++            )
++        );
++    }
++    test_field_r();
++    fn test_field_scanout_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).scanout_id) as usize - ptr as usize
++            },
++            40usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(scanout_id)
++            )
++        );
++    }
++    test_field_scanout_id();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            44usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_width() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).width) as usize - ptr as usize
++            },
++            48usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(width)
++            )
++        );
++    }
++    test_field_width();
++    fn test_field_height() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).height) as usize - ptr as usize
++            },
++            52usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(height)
++            )
++        );
++    }
++    test_field_height();
++    fn test_field_format() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize
++            },
++            56usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(format)
++            )
++        );
++    }
++    test_field_format();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            60usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++    fn test_field_strides() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).strides) as usize - ptr as usize
++            },
++            64usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(strides)
++            )
++        );
++    }
++    test_field_strides();
++    fn test_field_offsets() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_set_scanout_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).offsets) as usize - ptr as usize
++            },
++            80usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_set_scanout_blob),
++                "::",
++                stringify!(offsets)
++            )
++        );
++    }
++    test_field_offsets();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_map_blob {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++    pub offset: __le64,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_map_blob() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_map_blob>(),
++        40usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_map_blob))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_map_blob>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_map_blob))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_map_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_map_blob),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_map_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_map_blob),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_map_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_map_blob),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++    fn test_field_offset() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_map_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize
++            },
++            32usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_map_blob),
++                "::",
++                stringify!(offset)
++            )
++        );
++    }
++    test_field_offset();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resp_map_info {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub map_info: __u32,
++    pub padding: __u32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resp_map_info() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resp_map_info>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resp_map_info))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resp_map_info>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resp_map_info))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_map_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_map_info),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_map_info() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_map_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).map_info) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_map_info),
++                "::",
++                stringify!(map_info)
++            )
++        );
++    }
++    test_field_map_info();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resp_map_info>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resp_map_info),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
++#[repr(C)]
++#[derive(Debug, Default, Copy, Clone, PartialEq)]
++pub struct virtio_gpu_resource_unmap_blob {
++    pub hdr: virtio_gpu_ctrl_hdr,
++    pub resource_id: __le32,
++    pub padding: __le32,
++}
++#[test]
++fn bindgen_test_layout_virtio_gpu_resource_unmap_blob() {
++    assert_eq!(
++        ::std::mem::size_of::<virtio_gpu_resource_unmap_blob>(),
++        32usize,
++        concat!("Size of: ", stringify!(virtio_gpu_resource_unmap_blob))
++    );
++    assert_eq!(
++        ::std::mem::align_of::<virtio_gpu_resource_unmap_blob>(),
++        8usize,
++        concat!("Alignment of ", stringify!(virtio_gpu_resource_unmap_blob))
++    );
++    fn test_field_hdr() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unmap_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).hdr) as usize - ptr as usize
++            },
++            0usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unmap_blob),
++                "::",
++                stringify!(hdr)
++            )
++        );
++    }
++    test_field_hdr();
++    fn test_field_resource_id() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unmap_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).resource_id) as usize - ptr as usize
++            },
++            24usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unmap_blob),
++                "::",
++                stringify!(resource_id)
++            )
++        );
++    }
++    test_field_resource_id();
++    fn test_field_padding() {
++        assert_eq!(
++            unsafe {
++                let uninit = ::std::mem::MaybeUninit::<virtio_gpu_resource_unmap_blob>::uninit();
++                let ptr = uninit.as_ptr();
++                ::std::ptr::addr_of!((*ptr).padding) as usize - ptr as usize
++            },
++            28usize,
++            concat!(
++                "Offset of field: ",
++                stringify!(virtio_gpu_resource_unmap_blob),
++                "::",
++                stringify!(padding)
++            )
++        );
++    }
++    test_field_padding();
++}
+-- 
+2.37.1
+
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/default.nix b/pkgs/applications/virtualization/cloud-hypervisor/default.nix
index 2fb2836a6c0..cbef9798f53 100644
--- a/pkgs/applications/virtualization/cloud-hypervisor/default.nix
+++ b/pkgs/applications/virtualization/cloud-hypervisor/default.nix
@@ -1,4 +1,6 @@
-{ lib, stdenv, fetchFromGitHub, rustPlatform, pkg-config, dtc, openssl }:
+{ lib, stdenv, fetchCrate, fetchFromGitHub, fetchpatch, rustPlatform
+, pkg-config, dtc, openssl
+}:
 
 rustPlatform.buildRustPackage rec {
   pname = "cloud-hypervisor";
@@ -11,10 +13,68 @@ rustPlatform.buildRustPackage rec {
     sha256 = "sha256-choTT20TVp42nN/vS6xCDA7Mbf1ZuAE1tFQZn49g9ak=";
   };
 
+  vhost = fetchCrate {
+    pname = "vhost";
+    version = "0.4.0";
+    sha256 = "sha256-72tvycgdTI3pK1EpGoBEI0WajX7SYZvTI0lbU8ybdsc=";
+  };
+
+  vm-virtio = fetchFromGitHub {
+    owner = "rust-vmm";
+    repo = "vm-virtio";
+    rev = "7e203db6ed044217acd80dec5967c15d979491f8";
+    sha256 = "sha256-QLukQCPeWpletbKqhIruvevLMEepnQ4fKWVH42H7QM8=";
+  };
+
+  postUnpack = ''
+    unpackFile ${vhost}
+    mv vhost-* vhost
+
+    unpackFile ${vm-virtio}/crates/virtio-bindings
+
+    chmod -R +w vhost virtio-bindings
+  '';
+
+  cargoPatches = [
+    ./0001-build-use-local-vhost.patch
+    ./0002-build-use-local-virtio-bindings.patch
+    ./0003-virtio-devices-add-a-GPU-device.patch
+  ];
+
+  vhostPatches = [
+    ./vhost-vhost_user-add-shared-memory-region-support.patch
+  ];
+
+  virtioBindingsPatches = [
+    # https://github.com/rust-vmm/vm-virtio/pull/194
+    ./0001-virtio-bindings-regenerate-with-bindgen-0.60.1.patch
+    ./0002-virtio-bindings-remove-workaround-for-old-bindgen.patch
+    ./0003-virtio-bindings-regenerate-with-Glibc-2.36.patch
+    ./0004-virtio-bindings-regenerate-with-Linux-5.19.patch
+
+    ./0005-virtio-bindings-add-virtio-gpu-bindings.patch
+  ];
+
+  postPatch = ''
+    pushd ../vhost
+    for patch in $vhostPatches; do
+        echo applying patch $patch
+        patch -p1 < $patch
+    done
+    popd
+
+    pushd ../virtio-bindings
+    for patch in $virtioBindingsPatches; do
+        echo applying patch $patch
+        patch -p3 < $patch
+    done
+    popd
+  '';
+
   nativeBuildInputs = [ pkg-config ];
   buildInputs = [ openssl ] ++ lib.optional stdenv.isAarch64 dtc;
 
-  cargoSha256 = "sha256-mmyaT24he33wLI3zLOOKhVtzrPRyWzKgXUvc37suy5E=";
+  cargoSha256 = "164vr9xxrlpllac5db69ggasczq5vqb9zv60dkwbqabn8qm5cr1x";
 
   OPENSSL_NO_VENDOR = true;
 
diff --git a/pkgs/applications/virtualization/cloud-hypervisor/vhost-vhost_user-add-shared-memory-region-support.patch b/pkgs/applications/virtualization/cloud-hypervisor/vhost-vhost_user-add-shared-memory-region-support.patch
new file mode 100644
index 00000000000..728399548f8
--- /dev/null
+++ b/pkgs/applications/virtualization/cloud-hypervisor/vhost-vhost_user-add-shared-memory-region-support.patch
@@ -0,0 +1,724 @@
+From b72b87aed5542df7d912750f9745f9854c9cf482 Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 15 Jun 2022 16:45:12 +0900
+Subject: [PATCH] vhost_user: add shared memory region support
+
+Add support for shared memory regions to vhost-user. This is adding
+support for a front-end message to query for necessary shared memory
+regions plus back-end message to support mapping/unmapping files from
+the shared memory region.
+
+go/vvu-shared-memory
+
+BUG=b:201745804
+TEST=compiles
+
+Change-Id: I35c5d260ee09175b68f6778b81883e0070ee0265
+Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3716344
+Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
+Commit-Queue: David Stevens <stevensd@chromium.org>
+Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
+Tested-by: kokoro <noreply+kokoro@google.com>
+(cherry-picked from commit f436e2706011fa5f34dc415972434aa3299ebc43)
+Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
+---
+ src/vhost_user/dummy_slave.rs        |   4 +
+ src/vhost_user/master.rs             |  24 +++++
+ src/vhost_user/master_req_handler.rs |  78 ++++++++++++---
+ src/vhost_user/message.rs            | 140 +++++++++++++++++++++++++--
+ src/vhost_user/mod.rs                |   2 +-
+ src/vhost_user/slave_fs_cache.rs     |  67 ++++++++-----
+ src/vhost_user/slave_req_handler.rs  |  27 +++++-
+ 7 files changed, 292 insertions(+), 50 deletions(-)
+
+diff --git a/src/vhost_user/dummy_slave.rs b/src/vhost_user/dummy_slave.rs
+index 222a5bb3..5389e3fb 100644
+--- a/src/vhost_user/dummy_slave.rs
++++ b/src/vhost_user/dummy_slave.rs
+@@ -271,4 +271,8 @@ impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler {
+     fn remove_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion) -> Result<()> {
+         Ok(())
+     }
++
++    fn get_shared_memory_regions(&mut self) -> Result<Vec<VhostSharedMemoryRegion>> {
++        Ok(Vec::new())
++    }
+ }
+diff --git a/src/vhost_user/master.rs b/src/vhost_user/master.rs
+index 711b6739..1ad47aaa 100644
+--- a/src/vhost_user/master.rs
++++ b/src/vhost_user/master.rs
+@@ -72,6 +72,9 @@ pub trait VhostUserMaster: VhostBackend {
+ 
+     /// Remove a guest memory mapping from vhost.
+     fn remove_mem_region(&mut self, region: &VhostUserMemoryRegionInfo) -> Result<()>;
++
++    /// Gets the shared memory regions used by the device.
++    fn get_shared_memory_regions(&self) -> Result<Vec<VhostSharedMemoryRegion>>;
+ }
+ 
+ fn error_code<T>(err: VhostUserError) -> Result<T> {
+@@ -552,6 +555,27 @@ impl VhostUserMaster for Master {
+         let hdr = node.send_request_with_body(MasterReq::REM_MEM_REG, &body, None)?;
+         node.wait_for_ack(&hdr).map_err(|e| e.into())
+     }
++
++    fn get_shared_memory_regions(&self) -> Result<Vec<VhostSharedMemoryRegion>> {
++        let mut node = self.node();
++        let hdr = node.send_request_header(MasterReq::GET_SHARED_MEMORY_REGIONS, None)?;
++        let (body_reply, buf_reply, rfds) = node.recv_reply_with_payload::<VhostUserU64>(&hdr)?;
++        let struct_size = mem::size_of::<VhostSharedMemoryRegion>();
++        if rfds.is_some() || buf_reply.len() != body_reply.value as usize * struct_size {
++            return error_code(VhostUserError::InvalidMessage);
++        }
++        let mut regions = Vec::new();
++        let mut offset = 0;
++        for _ in 0..body_reply.value {
++            regions.push(
++                // Can't fail because the input is the correct size.
++                VhostSharedMemoryRegion::from_slice(&buf_reply[offset..(offset + struct_size)])
++                    .unwrap().clone(),
++            );
++            offset += struct_size;
++        }
++        Ok(regions)
++    }
+ }
+ 
+ impl AsRawFd for Master {
+diff --git a/src/vhost_user/master_req_handler.rs b/src/vhost_user/master_req_handler.rs
+index 0ecda4e3..d0d6529b 100644
+--- a/src/vhost_user/master_req_handler.rs
++++ b/src/vhost_user/master_req_handler.rs
+@@ -17,7 +17,7 @@ use super::{Error, HandlerResult, Result};
+ /// request services from masters. The [VhostUserMasterReqHandler] trait defines services provided
+ /// by masters, and it's used both on the master side and slave side.
+ /// - on the slave side, a stub forwarder implementing [VhostUserMasterReqHandler] will proxy
+-///   service requests to masters. The [SlaveFsCacheReq] is an example stub forwarder.
++///   service requests to masters. The [Slave] is an example stub forwarder.
+ /// - on the master side, the [MasterReqHandler] will forward service requests to a handler
+ ///   implementing [VhostUserMasterReqHandler].
+ ///
+@@ -26,13 +26,27 @@ use super::{Error, HandlerResult, Result};
+ ///
+ /// [VhostUserMasterReqHandler]: trait.VhostUserMasterReqHandler.html
+ /// [MasterReqHandler]: struct.MasterReqHandler.html
+-/// [SlaveFsCacheReq]: struct.SlaveFsCacheReq.html
++/// [Slave]: struct.Slave.html
+ pub trait VhostUserMasterReqHandler {
+     /// Handle device configuration change notifications.
+     fn handle_config_change(&self) -> HandlerResult<u64> {
+         Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
+     }
+ 
++    /// Handle shared memory region mapping requests.
++    fn shmem_map(
++        &self,
++        _req: &VhostUserShmemMapMsg,
++        _fd: &dyn AsRawFd,
++    ) -> HandlerResult<u64> {
++        Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
++    }
++
++    /// Handle shared memory region unmapping requests.
++    fn shmem_unmap(&self, _req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++        Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
++    }
++
+     /// Handle virtio-fs map file requests.
+     fn fs_slave_map(&self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult<u64> {
+         Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
+@@ -66,6 +80,20 @@ pub trait VhostUserMasterReqHandlerMut {
+         Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
+     }
+ 
++    /// Handle shared memory region mapping requests.
++    fn shmem_map(
++        &mut self,
++        _req: &VhostUserShmemMapMsg,
++        _fd: &dyn AsRawFd,
++    ) -> HandlerResult<u64> {
++        Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
++    }
++
++    /// Handle shared memory region unmapping requests.
++    fn shmem_unmap(&mut self, _req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++        Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
++    }
++
+     /// Handle virtio-fs map file requests.
+     fn fs_slave_map(&mut self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawFd) -> HandlerResult<u64> {
+         Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
+@@ -95,6 +123,18 @@ impl<S: VhostUserMasterReqHandlerMut> VhostUserMasterReqHandler for Mutex<S> {
+         self.lock().unwrap().handle_config_change()
+     }
+ 
++    fn shmem_map(
++        &self,
++        req: &VhostUserShmemMapMsg,
++        fd: &dyn AsRawFd,
++    ) -> HandlerResult<u64> {
++        self.lock().unwrap().shmem_map(req, fd)
++    }
++
++    fn shmem_unmap(&self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++        self.lock().unwrap().shmem_unmap(req)
++    }
++
+     fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
+         self.lock().unwrap().fs_slave_map(fs, fd)
+     }
+@@ -222,6 +262,19 @@ impl<S: VhostUserMasterReqHandler> MasterReqHandler<S> {
+                     .handle_config_change()
+                     .map_err(Error::ReqHandlerError)
+             }
++            SlaveReq::SHMEM_MAP => {
++                let msg = self.extract_msg_body::<VhostUserShmemMapMsg>(&hdr, size, &buf)?;
++                // check_attached_files() has validated files
++                self.backend
++                    .shmem_map(&msg, &files.unwrap()[0])
++                    .map_err(Error::ReqHandlerError)
++            }
++            SlaveReq::SHMEM_UNMAP => {
++                let msg = self.extract_msg_body::<VhostUserShmemUnmapMsg>(&hdr, size, &buf)?;
++                self.backend
++                    .shmem_unmap(&msg)
++                    .map_err(Error::ReqHandlerError)
++            }
+             SlaveReq::FS_MAP => {
+                 let msg = self.extract_msg_body::<VhostUserFSSlaveMsg>(&hdr, size, &buf)?;
+                 // check_attached_files() has validated files
+@@ -251,7 +304,7 @@ impl<S: VhostUserMasterReqHandler> MasterReqHandler<S> {
+             _ => Err(Error::InvalidMessage),
+         };
+ 
+-        self.send_ack_message(&hdr, &res)?;
++        self.send_reply(&hdr, &res)?;
+ 
+         res
+     }
+@@ -285,7 +338,7 @@ impl<S: VhostUserMasterReqHandler> MasterReqHandler<S> {
+         files: &Option<Vec<File>>,
+     ) -> Result<()> {
+         match hdr.get_code() {
+-            SlaveReq::FS_MAP | SlaveReq::FS_IO => {
++            SlaveReq::SHMEM_MAP | SlaveReq::FS_MAP | SlaveReq::FS_IO => {
+                 // Expect a single file is passed.
+                 match files {
+                     Some(files) if files.len() == 1 => Ok(()),
+@@ -326,12 +379,11 @@ impl<S: VhostUserMasterReqHandler> MasterReqHandler<S> {
+         ))
+     }
+ 
+-    fn send_ack_message(
+-        &mut self,
+-        req: &VhostUserMsgHeader<SlaveReq>,
+-        res: &Result<u64>,
+-    ) -> Result<()> {
+-        if self.reply_ack_negotiated && req.is_need_reply() {
++    fn send_reply(&mut self, req: &VhostUserMsgHeader<SlaveReq>, res: &Result<u64>) -> Result<()> {
++        if req.get_code() == SlaveReq::SHMEM_MAP
++            || req.get_code() == SlaveReq::SHMEM_UNMAP
++            || (self.reply_ack_negotiated && req.is_need_reply())
++        {
+             let hdr = self.new_reply_header::<VhostUserU64>(req)?;
+             let def_err = libc::EINVAL;
+             let val = match res {
+@@ -362,7 +414,7 @@ mod tests {
+     use super::*;
+ 
+     #[cfg(feature = "vhost-user-slave")]
+-    use crate::vhost_user::SlaveFsCacheReq;
++    use crate::vhost_user::Slave;
+     #[cfg(feature = "vhost-user-slave")]
+     use std::os::unix::io::FromRawFd;
+ 
+@@ -410,7 +462,7 @@ mod tests {
+             panic!("failed to duplicated tx fd!");
+         }
+         let stream = unsafe { UnixStream::from_raw_fd(fd) };
+-        let fs_cache = SlaveFsCacheReq::from_stream(stream);
++        let fs_cache = Slave::from_stream(stream);
+ 
+         std::thread::spawn(move || {
+             let res = handler.handle_request().unwrap();
+@@ -440,7 +492,7 @@ mod tests {
+             panic!("failed to duplicated tx fd!");
+         }
+         let stream = unsafe { UnixStream::from_raw_fd(fd) };
+-        let fs_cache = SlaveFsCacheReq::from_stream(stream);
++        let fs_cache = Slave::from_stream(stream);
+ 
+         std::thread::spawn(move || {
+             let res = handler.handle_request().unwrap();
+diff --git a/src/vhost_user/message.rs b/src/vhost_user/message.rs
+index d61c17a1..66139972 100644
+--- a/src/vhost_user/message.rs
++++ b/src/vhost_user/message.rs
+@@ -139,8 +139,10 @@ pub enum MasterReq {
+     /// Query the backend for its device status as defined in the VIRTIO
+     /// specification.
+     GET_STATUS = 40,
++    /// Get a list of the device's shared memory regions.
++    GET_SHARED_MEMORY_REGIONS = 41,
+     /// Upper bound of valid commands.
+-    MAX_CMD = 41,
++    MAX_CMD = 42,
+ }
+ 
+ impl From<MasterReq> for u32 {
+@@ -171,16 +173,20 @@ pub enum SlaveReq {
+     VRING_CALL = 4,
+     /// Indicate that an error occurred on the specific vring.
+     VRING_ERR = 5,
++    /// Indicates a request to map a fd into a shared memory region.
++    SHMEM_MAP = 6,
++    /// Indicates a request to unmap part of a shared memory region.
++    SHMEM_UNMAP = 7,
+     /// Virtio-fs draft: map file content into the window.
+-    FS_MAP = 6,
++    FS_MAP = 8,
+     /// Virtio-fs draft: unmap file content from the window.
+-    FS_UNMAP = 7,
++    FS_UNMAP = 9,
+     /// Virtio-fs draft: sync file content.
+-    FS_SYNC = 8,
++    FS_SYNC = 10,
+     /// Virtio-fs draft: perform a read/write from an fd directly to GPA.
+-    FS_IO = 9,
++    FS_IO = 11,
+     /// Upper bound of valid commands.
+-    MAX_CMD = 10,
++    MAX_CMD = 12,
+ }
+ 
+ impl From<SlaveReq> for u32 {
+@@ -817,7 +823,7 @@ pub const VHOST_USER_FS_SLAVE_ENTRIES: usize = 8;
+ 
+ /// Slave request message to update the MMIO window.
+ #[repr(packed)]
+-#[derive(Default)]
++#[derive(Clone, Copy, Default)]
+ pub struct VhostUserFSSlaveMsg {
+     /// File offset.
+     pub fd_offset: [u64; VHOST_USER_FS_SLAVE_ENTRIES],
+@@ -828,6 +834,8 @@ pub struct VhostUserFSSlaveMsg {
+     /// Flags for the mmap operation
+     pub flags: [VhostUserFSSlaveMsgFlags; VHOST_USER_FS_SLAVE_ENTRIES],
+ }
++// Safe because it only has data and has no implicit padding.
++unsafe impl ByteValued for VhostUserFSSlaveMsg {}
+ 
+ impl VhostUserMsgValidator for VhostUserFSSlaveMsg {
+     fn is_valid(&self) -> bool {
+@@ -843,6 +851,99 @@ impl VhostUserMsgValidator for VhostUserFSSlaveMsg {
+     }
+ }
+ 
++bitflags! {
++    #[derive(Default)]
++    /// Flags for SHMEM_MAP messages.
++    pub struct VhostUserShmemMapMsgFlags: u8 {
++        /// Empty permission.
++        const EMPTY = 0x0;
++        /// Read permission.
++        const MAP_R = 0x1;
++        /// Write permission.
++        const MAP_W = 0x2;
++    }
++}
++
++/// Slave request message to map a file into a shared memory region.
++#[repr(C, packed)]
++#[derive(Default, Copy, Clone)]
++pub struct VhostUserShmemMapMsg {
++    /// Flags for the mmap operation
++    pub flags: VhostUserShmemMapMsgFlags,
++    /// Shared memory region id.
++    pub shmid: u8,
++    padding: [u8; 6],
++    /// Offset into the shared memory region.
++    pub shm_offset: u64,
++    /// File offset.
++    pub fd_offset: u64,
++    /// Size of region to map.
++    pub len: u64,
++}
++// Safe because it only has data and has no implicit padding.
++unsafe impl ByteValued for VhostUserShmemMapMsg {}
++
++impl VhostUserMsgValidator for VhostUserShmemMapMsg {
++    fn is_valid(&self) -> bool {
++        (self.flags.bits() & !VhostUserFSSlaveMsgFlags::all().bits() as u8) == 0
++            && self.fd_offset.checked_add(self.len).is_some()
++            && self.shm_offset.checked_add(self.len).is_some()
++    }
++}
++
++impl VhostUserShmemMapMsg {
++    /// New instance of VhostUserShmemMapMsg struct
++    pub fn new(
++        shmid: u8,
++        shm_offset: u64,
++        fd_offset: u64,
++        len: u64,
++        flags: VhostUserShmemMapMsgFlags,
++    ) -> Self {
++        Self {
++            flags,
++            shmid,
++            padding: [0; 6],
++            shm_offset,
++            fd_offset,
++            len,
++        }
++    }
++}
++
++/// Slave request message to unmap part of a shared memory region.
++#[repr(C, packed)]
++#[derive(Default, Copy, Clone)]
++pub struct VhostUserShmemUnmapMsg {
++    /// Shared memory region id.
++    pub shmid: u8,
++    padding: [u8; 7],
++    /// Offset into the shared memory region.
++    pub shm_offset: u64,
++    /// Size of region to unmap.
++    pub len: u64,
++}
++// Safe because it only has data and has no implicit padding.
++unsafe impl ByteValued for VhostUserShmemUnmapMsg {}
++
++impl VhostUserMsgValidator for VhostUserShmemUnmapMsg {
++    fn is_valid(&self) -> bool {
++        self.shm_offset.checked_add(self.len).is_some()
++    }
++}
++
++impl VhostUserShmemUnmapMsg {
++    /// New instance of VhostUserShmemUnmapMsg struct
++    pub fn new(shmid: u8, shm_offset: u64, len: u64) -> Self {
++        Self {
++            shmid,
++            padding: [0; 7],
++            shm_offset,
++            len,
++        }
++    }
++}
++
+ /// Inflight I/O descriptor state for split virtqueues
+ #[repr(packed)]
+ #[derive(Clone, Copy, Default)]
+@@ -974,6 +1075,31 @@ impl QueueRegionPacked {
+     }
+ }
+ 
++/// Virtio shared memory descriptor.
++#[repr(packed)]
++#[derive(Default, Copy, Clone)]
++pub struct VhostSharedMemoryRegion {
++    /// The shared memory region's shmid.
++    pub id: u8,
++    /// Padding
++    padding: [u8; 7],
++    /// The length of the shared memory region.
++    pub length: u64,
++}
++// Safe because it only has data and has no implicit padding.
++unsafe impl ByteValued for VhostSharedMemoryRegion {}
++
++impl VhostSharedMemoryRegion {
++    /// New instance of VhostSharedMemoryRegion struct
++    pub fn new(id: u8, length: u64) -> Self {
++        VhostSharedMemoryRegion {
++            id,
++            padding: [0; 7],
++            length,
++        }
++    }
++}
++
+ #[cfg(test)]
+ mod tests {
+     use super::*;
+diff --git a/src/vhost_user/mod.rs b/src/vhost_user/mod.rs
+index 6b1afb8c..a2f0af88 100644
+--- a/src/vhost_user/mod.rs
++++ b/src/vhost_user/mod.rs
+@@ -50,7 +50,7 @@ pub use self::slave_req_handler::{
+ #[cfg(feature = "vhost-user-slave")]
+ mod slave_fs_cache;
+ #[cfg(feature = "vhost-user-slave")]
+-pub use self::slave_fs_cache::SlaveFsCacheReq;
++pub use self::slave_fs_cache::Slave;
+ 
+ /// Errors for vhost-user operations
+ #[derive(Debug)]
+diff --git a/src/vhost_user/slave_fs_cache.rs b/src/vhost_user/slave_fs_cache.rs
+index e9ad7cf6..369d682a 100644
+--- a/src/vhost_user/slave_fs_cache.rs
++++ b/src/vhost_user/slave_fs_cache.rs
+@@ -7,11 +7,13 @@ use std::os::unix::io::{AsRawFd, RawFd};
+ use std::os::unix::net::UnixStream;
+ use std::sync::{Arc, Mutex, MutexGuard};
+ 
++use vm_memory::ByteValued;
++
+ use super::connection::Endpoint;
+ use super::message::*;
+ use super::{Error, HandlerResult, Result, VhostUserMasterReqHandler};
+ 
+-struct SlaveFsCacheReqInternal {
++struct SlaveInternal {
+     sock: Endpoint<SlaveReq>,
+ 
+     // Protocol feature VHOST_USER_PROTOCOL_F_REPLY_ACK has been negotiated.
+@@ -21,7 +23,7 @@ struct SlaveFsCacheReqInternal {
+     error: Option<i32>,
+ }
+ 
+-impl SlaveFsCacheReqInternal {
++impl SlaveInternal {
+     fn check_state(&self) -> Result<u64> {
+         match self.error {
+             Some(e) => Err(Error::SocketBroken(std::io::Error::from_raw_os_error(e))),
+@@ -29,27 +31,30 @@ impl SlaveFsCacheReqInternal {
+         }
+     }
+ 
+-    fn send_message(
++    fn send_message<T: ByteValued>(
+         &mut self,
+         request: SlaveReq,
+-        fs: &VhostUserFSSlaveMsg,
++        msg: &T,
+         fds: Option<&[RawFd]>,
+     ) -> Result<u64> {
+         self.check_state()?;
+ 
+-        let len = mem::size_of::<VhostUserFSSlaveMsg>();
++        let len = mem::size_of::<T>();
+         let mut hdr = VhostUserMsgHeader::new(request, 0, len as u32);
+         if self.reply_ack_negotiated {
+             hdr.set_need_reply(true);
+         }
+-        self.sock.send_message(&hdr, fs, fds)?;
++        self.sock.send_message(&hdr, msg, fds)?;
+ 
+-        self.wait_for_ack(&hdr)
++        self.wait_for_reply(&hdr)
+     }
+ 
+-    fn wait_for_ack(&mut self, hdr: &VhostUserMsgHeader<SlaveReq>) -> Result<u64> {
++    fn wait_for_reply(&mut self, hdr: &VhostUserMsgHeader<SlaveReq>) -> Result<u64> {
+         self.check_state()?;
+-        if !self.reply_ack_negotiated {
++        if hdr.get_code() != SlaveReq::SHMEM_MAP
++            && hdr.get_code() != SlaveReq::SHMEM_UNMAP
++            && !self.reply_ack_negotiated
++        {
+             return Ok(0);
+         }
+ 
+@@ -68,22 +73,22 @@ impl SlaveFsCacheReqInternal {
+ /// Request proxy to send vhost-user-fs slave requests to the master through the slave
+ /// communication channel.
+ ///
+-/// The [SlaveFsCacheReq] acts as a message proxy to forward vhost-user-fs slave requests to the
++/// The [Slave] acts as a message proxy to forward vhost-user-fs slave requests to the
+ /// master through the vhost-user slave communication channel. The forwarded messages will be
+ /// handled by the [MasterReqHandler] server.
+ ///
+-/// [SlaveFsCacheReq]: struct.SlaveFsCacheReq.html
++/// [Slave]: struct.Slave.html
+ /// [MasterReqHandler]: struct.MasterReqHandler.html
+ #[derive(Clone)]
+-pub struct SlaveFsCacheReq {
++pub struct Slave {
+     // underlying Unix domain socket for communication
+-    node: Arc<Mutex<SlaveFsCacheReqInternal>>,
++    node: Arc<Mutex<SlaveInternal>>,
+ }
+ 
+-impl SlaveFsCacheReq {
++impl Slave {
+     fn new(ep: Endpoint<SlaveReq>) -> Self {
+-        SlaveFsCacheReq {
+-            node: Arc::new(Mutex::new(SlaveFsCacheReqInternal {
++        Slave {
++            node: Arc::new(Mutex::new(SlaveInternal {
+                 sock: ep,
+                 reply_ack_negotiated: false,
+                 error: None,
+@@ -91,18 +96,18 @@ impl SlaveFsCacheReq {
+         }
+     }
+ 
+-    fn node(&self) -> MutexGuard<SlaveFsCacheReqInternal> {
++    fn node(&self) -> MutexGuard<SlaveInternal> {
+         self.node.lock().unwrap()
+     }
+ 
+-    fn send_message(
++    fn send_message<T: ByteValued>(
+         &self,
+         request: SlaveReq,
+-        fs: &VhostUserFSSlaveMsg,
++        msg: &T,
+         fds: Option<&[RawFd]>,
+     ) -> io::Result<u64> {
+         self.node()
+-            .send_message(request, fs, fds)
++            .send_message(request, msg, fds)
+             .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{}", e)))
+     }
+ 
+@@ -126,7 +131,21 @@ impl SlaveFsCacheReq {
+     }
+ }
+ 
+-impl VhostUserMasterReqHandler for SlaveFsCacheReq {
++impl VhostUserMasterReqHandler for Slave {
++    /// Handle shared memory region mapping requests.
++    fn shmem_map(
++        &self,
++        req: &VhostUserShmemMapMsg,
++        fd: &dyn AsRawFd,
++    ) -> HandlerResult<u64> {
++        self.send_message(SlaveReq::SHMEM_MAP, req, Some(&[fd.as_raw_fd()]))
++    }
++
++    /// Handle shared memory region unmapping requests.
++    fn shmem_unmap(&self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++        self.send_message(SlaveReq::SHMEM_UNMAP, req, None)
++    }
++
+     /// Forward vhost-user-fs map file requests to the slave.
+     fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
+         self.send_message(SlaveReq::FS_MAP, fs, Some(&[fd.as_raw_fd()]))
+@@ -147,7 +166,7 @@ mod tests {
+     #[test]
+     fn test_slave_fs_cache_req_set_failed() {
+         let (p1, _p2) = UnixStream::pair().unwrap();
+-        let fs_cache = SlaveFsCacheReq::from_stream(p1);
++        let fs_cache = Slave::from_stream(p1);
+ 
+         assert!(fs_cache.node().error.is_none());
+         fs_cache.set_failed(libc::EAGAIN);
+@@ -157,7 +176,7 @@ mod tests {
+     #[test]
+     fn test_slave_fs_cache_send_failure() {
+         let (p1, p2) = UnixStream::pair().unwrap();
+-        let fs_cache = SlaveFsCacheReq::from_stream(p1);
++        let fs_cache = Slave::from_stream(p1);
+ 
+         fs_cache.set_failed(libc::ECONNRESET);
+         fs_cache
+@@ -172,7 +191,7 @@ mod tests {
+     #[test]
+     fn test_slave_fs_cache_recv_negative() {
+         let (p1, p2) = UnixStream::pair().unwrap();
+-        let fs_cache = SlaveFsCacheReq::from_stream(p1);
++        let fs_cache = Slave::from_stream(p1);
+         let mut master = Endpoint::<SlaveReq>::from_stream(p2);
+ 
+         let len = mem::size_of::<VhostUserFSSlaveMsg>();
+diff --git a/src/vhost_user/slave_req_handler.rs b/src/vhost_user/slave_req_handler.rs
+index f43159ad..ee313ffd 100644
+--- a/src/vhost_user/slave_req_handler.rs
++++ b/src/vhost_user/slave_req_handler.rs
+@@ -8,9 +8,11 @@ use std::os::unix::net::UnixStream;
+ use std::slice;
+ use std::sync::{Arc, Mutex};
+ 
++use vm_memory::ByteValued;
++
+ use super::connection::Endpoint;
+ use super::message::*;
+-use super::slave_fs_cache::SlaveFsCacheReq;
++use super::slave_fs_cache::Slave;
+ use super::{take_single_file, Error, Result};
+ 
+ /// Services provided to the master by the slave with interior mutability.
+@@ -62,12 +64,13 @@ pub trait VhostUserSlaveReqHandler {
+     fn set_vring_enable(&self, index: u32, enable: bool) -> Result<()>;
+     fn get_config(&self, offset: u32, size: u32, flags: VhostUserConfigFlags) -> Result<Vec<u8>>;
+     fn set_config(&self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>;
+-    fn set_slave_req_fd(&self, _vu_req: SlaveFsCacheReq) {}
++    fn set_slave_req_fd(&self, _vu_req: Slave) {}
+     fn get_inflight_fd(&self, inflight: &VhostUserInflight) -> Result<(VhostUserInflight, File)>;
+     fn set_inflight_fd(&self, inflight: &VhostUserInflight, file: File) -> Result<()>;
+     fn get_max_mem_slots(&self) -> Result<u64>;
+     fn add_mem_region(&self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()>;
+     fn remove_mem_region(&self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
++    fn get_shared_memory_regions(&self) -> Result<Vec<VhostSharedMemoryRegion>>;
+ }
+ 
+ /// Services provided to the master by the slave without interior mutability.
+@@ -107,7 +110,7 @@ pub trait VhostUserSlaveReqHandlerMut {
+         flags: VhostUserConfigFlags,
+     ) -> Result<Vec<u8>>;
+     fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>;
+-    fn set_slave_req_fd(&mut self, _vu_req: SlaveFsCacheReq) {}
++    fn set_slave_req_fd(&mut self, _vu_req: Slave) {}
+     fn get_inflight_fd(
+         &mut self,
+         inflight: &VhostUserInflight,
+@@ -116,6 +119,7 @@ pub trait VhostUserSlaveReqHandlerMut {
+     fn get_max_mem_slots(&mut self) -> Result<u64>;
+     fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()>;
+     fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
++    fn get_shared_memory_regions(&mut self) -> Result<Vec<VhostSharedMemoryRegion>>;
+ }
+ 
+ impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
+@@ -201,7 +205,7 @@ impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
+         self.lock().unwrap().set_config(offset, buf, flags)
+     }
+ 
+-    fn set_slave_req_fd(&self, vu_req: SlaveFsCacheReq) {
++    fn set_slave_req_fd(&self, vu_req: Slave) {
+         self.lock().unwrap().set_slave_req_fd(vu_req)
+     }
+ 
+@@ -224,6 +228,10 @@ impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
+     fn remove_mem_region(&self, region: &VhostUserSingleMemoryRegion) -> Result<()> {
+         self.lock().unwrap().remove_mem_region(region)
+     }
++
++    fn get_shared_memory_regions(&self) -> Result<Vec<VhostSharedMemoryRegion>> {
++        self.lock().unwrap().get_shared_memory_regions()
++    }
+ }
+ 
+ /// Server to handle service requests from masters from the master communication channel.
+@@ -528,6 +536,15 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
+                 let res = self.backend.remove_mem_region(&msg);
+                 self.send_ack_message(&hdr, res)?;
+             }
++            MasterReq::GET_SHARED_MEMORY_REGIONS => {
++                let regions = self.backend.get_shared_memory_regions()?;
++                let mut buf = Vec::new();
++                let msg = VhostUserU64::new(regions.len() as u64);
++                for r in regions {
++                    buf.extend_from_slice(r.as_slice())
++                }
++                self.send_reply_with_payload(&hdr, &msg, buf.as_slice())?;
++            }
+             _ => {
+                 return Err(Error::InvalidMessage);
+             }
+@@ -641,7 +658,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
+     fn set_slave_req_fd(&mut self, files: Option<Vec<File>>) -> Result<()> {
+         let file = take_single_file(files).ok_or(Error::InvalidMessage)?;
+         let sock = unsafe { UnixStream::from_raw_fd(file.into_raw_fd()) };
+-        let vu_req = SlaveFsCacheReq::from_stream(sock);
++        let vu_req = Slave::from_stream(sock);
+         self.backend.set_slave_req_fd(vu_req);
+         Ok(())
+     }
+-- 
+2.37.1
+
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 8/9] ocamlPackages.wayland: 1.0 -> 1.1
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (6 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 7/9] cloud-hypervisor: add virtio-gpu support Alyssa Ross
@ 2022-09-30 21:09 ` Alyssa Ross
  2022-09-30 21:12 ` [RFC PATCH nixpkgs v2 9/9] wayland-proxy-virtwl: unstable-2021-12-05 -> unstable-2022-09-22 Alyssa Ross
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:09 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen, sternenseemann

From: sternenseemann <sternenseemann@systemli.org>

(cherry picked from commit 2f27431460d4339a5c5c4b0de8ab5e7ac660591a)
Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 pkgs/development/ocaml-modules/wayland/default.nix | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/pkgs/development/ocaml-modules/wayland/default.nix b/pkgs/development/ocaml-modules/wayland/default.nix
index 12c385eac72..f7ade2ec807 100644
--- a/pkgs/development/ocaml-modules/wayland/default.nix
+++ b/pkgs/development/ocaml-modules/wayland/default.nix
@@ -12,15 +12,13 @@
 
 buildDunePackage rec {
   pname = "wayland";
-  version = "1.0";
+  version = "1.1";
 
-  minimumOCamlVersion = "4.08";
-
-  useDune2 = true;
+  minimalOCamlVersion = "4.08";
 
   src = fetchurl {
     url = "https://github.com/talex5/ocaml-wayland/releases/download/v${version}/wayland-${version}.tbz";
-    sha256 = "bf8fd0057242d11f1c265c11cfa5de3c517ec0ad5994eae45e1efe3aac034510";
+    sha256 = "0b7czgh08i6xcx3fsz6vd19sfyngwi0i27jdzg8cnjgrgwnagv6d";
   };
 
   propagatedBuildInputs = [
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH nixpkgs v2 9/9] wayland-proxy-virtwl: unstable-2021-12-05 -> unstable-2022-09-22
  2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
                   ` (7 preceding siblings ...)
  2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 8/9] ocamlPackages.wayland: 1.0 -> 1.1 Alyssa Ross
@ 2022-09-30 21:12 ` Alyssa Ross
  8 siblings, 0 replies; 10+ messages in thread
From: Alyssa Ross @ 2022-09-30 21:12 UTC (permalink / raw)
  To: devel; +Cc: Puck Meerburg, Ville Ilvonen, sternenseemann

From: sternenseemann <sternenseemann@systemli.org>

Co-authored-by: Alyssa Ross <hi@alyssa.is>
(cherry picked from commit 5cac465ec618cdc6e9077b447b4a5b138e482ddb)
Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
---
 .../wayland/wayland-proxy-virtwl/default.nix    | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/pkgs/tools/wayland/wayland-proxy-virtwl/default.nix b/pkgs/tools/wayland/wayland-proxy-virtwl/default.nix
index 8c7708c3e3d..3931fe9c3da 100644
--- a/pkgs/tools/wayland/wayland-proxy-virtwl/default.nix
+++ b/pkgs/tools/wayland/wayland-proxy-virtwl/default.nix
@@ -1,17 +1,19 @@
 { lib
 , fetchFromGitHub
 , ocamlPackages
+, pkg-config
+, libdrm
 }:
 
 ocamlPackages.buildDunePackage rec {
   pname = "wayland-proxy-virtwl";
-  version = "unstable-2021-12-05";
+  version = "unstable-2022-09-22";
 
   src = fetchFromGitHub {
     owner = "talex5";
     repo = pname;
-    rev = "d7f58d405514dd031f2f12e402c8c6a58e62a885";
-    sha256 = "0riwaqdlrx2gzkrb02v4zdl4ivpmz9g5w87lj3bhqs0l3s6c249s";
+    rev = "5940346db2a4427f21c7b30a2593b179af36a935";
+    sha256 = "0jnr5q52nb3yqr7ykvvb902xsad24cdi9imkslcsa5cnzb4095rw";
   };
 
   postPatch = ''
@@ -19,21 +21,22 @@ ocamlPackages.buildDunePackage rec {
     rm -r ocaml-wayland
   '';
 
-  useDune2 = true;
-  minimumOCamlVersion = "4.08";
+  minimalOCamlVersion = "4.12";
 
   strictDeps = true;
   nativeBuildInputs = [
     ocamlPackages.ppx_cstruct
+    pkg-config
   ];
 
-  buildInputs = with ocamlPackages; [
+  buildInputs = [ libdrm ] ++ (with ocamlPackages; [
+    dune-configurator
     wayland
     cmdliner
     logs
     cstruct-lwt
     ppx_cstruct
-  ];
+  ]);
 
   doCheck = true;
 
-- 
2.37.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-09-30 21:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-30 21:08 [RFC PATCH nixpkgs v2 0/9] virtio-gpu with crosvm and cloud-hypervisor Alyssa Ross
2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 1/9] crosvm: switch back to old git repo URL Alyssa Ross
2022-09-30 21:08 ` [RFC PATCH nixpkgs v2 2/9] crosvm.updateScript: update release branch format Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 3/9] crosvm: 104.0 -> 106.2 Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 4/9] crosvm.updateScript: don't vendor Cargo.lock Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 5/9] crosvm: add fixes for cloud-hypervisor virtio-gpu Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 6/9] rustPlatform: forward unpack hooks to cargo fetch Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 7/9] cloud-hypervisor: add virtio-gpu support Alyssa Ross
2022-09-30 21:09 ` [RFC PATCH nixpkgs v2 8/9] ocamlPackages.wayland: 1.0 -> 1.1 Alyssa Ross
2022-09-30 21:12 ` [RFC PATCH nixpkgs v2 9/9] wayland-proxy-virtwl: unstable-2021-12-05 -> unstable-2022-09-22 Alyssa Ross

Code repositories for project(s) associated with this public inbox

	https://spectrum-os.org/git/crosvm
	https://spectrum-os.org/git/doc
	https://spectrum-os.org/git/mktuntap
	https://spectrum-os.org/git/nixpkgs
	https://spectrum-os.org/git/spectrum
	https://spectrum-os.org/git/ucspi-vsock
	https://spectrum-os.org/git/www

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).