Compare commits

..

228 Commits
v15.0 ... v16.0

Author SHA1 Message Date
Rob Bradford
5ed8e01faf build: Release v16.0
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-10 16:59:52 +01:00
Sebastien Boeuf
1a5c6631a5 virtio-devices: vhost_user: Reconnection for slave request handler
Add the support for reconnecting the backend request handler after a
disconnection/crash happened.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-10 16:17:23 +02:00
Sebastien Boeuf
acec7e34fc virtio-devices: vhost_user: Factorize slave request handler
Since the slave request handler is common to all vhost-user devices, the
same way the reconnection is, it makes sense to handle the requests from
the backend through the same thread.

The reconnection thread now handles both a reconnection as well as any
request coming from the backend.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-10 16:17:23 +02:00
Jiachen Zhang
deca570544 virtio-devices: vhost_user: fs: Support socket reconnection handling
This commit enables socket reconnection for vhost-user-fs backends. Note
that, till this commit:

- The re-establish of the slave communication channel is no supported. So
the socket reconnection does not support virtiofsd with DAX enabled.

- Inflight I/O tracking and restoring is not supported. Therefore, only
virtio-fs daemons that are not processing inflight requests can work
normally after reconnection.

- To make the restarted virtiofsd work normally after reconnection, the
internal status of virtiofsd should also be recovered. This is not the
work of cloud-hypervisor. If the virtio-fs daemon does not support
saving or restoring its internal status, then a re-mount in guest after
socket reconnection should be performed.

Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
2021-06-10 16:17:23 +02:00
Michael Zhao
7cfb2139d0 tests: Enable pty test case on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-10 15:05:25 +02:00
Michael Zhao
1a7a76511f vmm: Enable pty console on AArch64
Allowed syscall "SYS_readlinkat" on AArch64 which is required by pty.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-10 15:05:25 +02:00
Bo Chen
8a22b2987f docs: Add documentation for live migration
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-10 12:07:14 +02:00
Henry Wang
1eb8a4671f arch: aarch64: Remove hardcoded host IPA size
With the ability of getting host IPA size in `hypervisor` crate,
we can query the host IPA size through ioctl instead of hardcoding
a maximum IPA size. Therefore this commit removes the hardcoded
maximum host IPA size.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-06-10 12:06:17 +02:00
Henry Wang
2fe3586eba hypervisor: support AArch64 get_host_ipa_limit
Not all AArch64 platforms support IPAs up to 40 bits. Since the
kvm-ioctl crate now supports `get_host_ipa_limit` for AArch64,
when creating the VM, it is better to get the IPA size from the
host and use that to create the VM.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-06-10 12:06:17 +02:00
Henry Wang
805cb303d5 hypervisor: Add get_host_ipa_limit for AArch64
This commit adds a helper `get_host_ipa_limit` to the AArch64
`KvmHypervisor` struct. This helper can be used to get the
`Host_IPA_Limit`, which is the maximum possible value for
IPA_Bits on the host and is dependent on the CPU capability
and the kernel configuration.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-06-10 12:06:17 +02:00
Michael Zhao
97307a7fc1 tests: Remove test_aarch64_pe_boot case
test_aarch64_pe_boot was added at the very beginning of AArch64 support.
Now it can be combined to test_vmlinux_boot.

Renamed test_vmlinux_boot to test_direct_kernel_boot for generality.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-10 10:10:53 +02:00
Michael Zhao
6ed1f83a87 tests: Enable the boot_noacpi case on AArch64
Enabled test case test_vmlinux_boot_noacpi on AArch64 and renamed it
test_direct_kernel_boot_noacpi for generality.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-10 10:10:53 +02:00
Michael Zhao
04aff2e2f9 tests: Enable test_console_file case on AArch64
This test case could have been ready on AArch64 since the serial issue
was fixed.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-10 10:10:53 +02:00
dependabot[bot]
0268089ac6 build: bump syn from 1.0.72 to 1.0.73 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.72 to 1.0.73.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.72...1.0.73)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-10 08:10:14 +00:00
dependabot[bot]
5d5d338e10 build: bump syn from 1.0.72 to 1.0.73
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.72 to 1.0.73.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.72...1.0.73)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-10 10:09:57 +02:00
Sebastien Boeuf
8f1404eeef deps: Update Cargo.lock to include uuid crate
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-09 14:35:07 +01:00
Sebastien Boeuf
9dba097224 ci: Update guest cloud image by installing "stress" utility
Some new integration tests will require the "stress" binary to be
present in the guest in order to run correctly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-09 14:34:55 +01:00
Michael Zhao
ce5c5833cb tests: Add a simple test case for ACPI on AArch64
In the test case, the guest boots from EDK2.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-09 18:36:59 +08:00
Henry Wang
3cb2b72e92 tests: Build EDK2 for AArch64 integration test
This commit added support for building the edk2 binary dedicated
for the Cloud Hypervisor (CLOUDHV_EFI.fd).

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-06-09 18:36:59 +08:00
Michael Zhao
88fda7c305 aarch64, acpi: Change PCIe high space for EDK2
EDK2 requires the beginning of PCIe high space above 4G address.
In CLH the space follows the RAM. If the RAM space is small, the PCIe
high space could fall bellow 4G.
Here we put it above 512G in FDT to workaround the EDK2 check only when
ACPI is enabled, because EDK2 collects PCIe information from FDT.
The address written in ACPI is not impacted.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-09 18:36:59 +08:00
Jianyong Wu
b8b5dccfd8 aarch64: Enable UEFI image loading
Implemented an architecture specific function for loading UEFI binary.

Changed the logic of loading kernel image:
1. First try to load the image as kernel in PE format;
2. If failed, try again to load it as formatless UEFI binary.

Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2021-06-09 18:36:59 +08:00
Jianyong Wu
6880692a78 vmm, acpi: Add DSM method to ACPI
_DSM (Device Specific Method) is a control method that enables devices
to provide device specific control functions. Linux kernel will evaluate
this device then initialize preserve_config in acpi pci initialization.

Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2021-06-09 18:36:59 +08:00
dependabot[bot]
76911fbeb4 build: bump libc from 0.2.95 to 0.2.96 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.95 to 0.2.96.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.95...0.2.96)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-09 07:28:02 +00:00
dependabot[bot]
0eb245e177 build: bump vhost from e4ba734 to 30ba3e7
Bumps [vhost](https://github.com/rust-vmm/vhost) from `e4ba734` to `30ba3e7`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](e4ba734144...30ba3e7bbe)

---
updated-dependencies:
- dependency-name: vhost
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-09 07:27:50 +00:00
dependabot[bot]
c866ccb3a1 build: bump libc from 0.2.95 to 0.2.96
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.95 to 0.2.96.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.95...0.2.96)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-09 07:27:37 +00:00
Sebastien Boeuf
bb68e0bc3b tests: Re-enable virtiofsd tests
Re-enable virtiofsd testing now that issues with capstone repository
have been resolved.

This reverts commit a14c70019a.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-08 20:13:41 +02:00
dependabot[bot]
f81f4490b0 build: bump vfio-ioctls from 5cb8550 to 0f7eb6f
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio-ioctls) from `5cb8550` to `0f7eb6f`.
- [Release notes](https://github.com/rust-vmm/vfio-ioctls/releases)
- [Commits](5cb8550556...0f7eb6f855)

---
updated-dependencies:
- dependency-name: vfio-ioctls
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-08 07:52:19 +00:00
Wei Liu
c419d3286b hypervisor: emulator: emulate OR instruction
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-06-07 11:54:57 -07:00
Wei Liu
d76743ed0b hypervisor: x86: make debug output more useful
The debug output should show the range of memory read from / written to.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-06-07 11:54:57 -07:00
Sebastien Boeuf
1e2aa769e5 test_infra, tests: Introduce exec_host_command_output() function
This new function allows for better readability of the code by
factorizing a few of lines of code into a single one.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 16:25:41 +02:00
Sebastien Boeuf
8091c28dd5 tests: Make sure exec_host_command_status() succeeds
It's important to verify the actual exit code returned from the new
function exec_host_command_status() to ensure the command ran
successfully.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 16:25:41 +02:00
Sebastien Boeuf
eca1df4e2d test_infra, tests: Introduce exec_host_command_status() function
This new function allows for better readability of the code by
factorizing a bunch of lines of code into a single one.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 16:25:41 +02:00
Sebastien Boeuf
3d8728488d tests: Remove ssh_command_ok()
There's no need for ssh_command_ok() anymore since ssh_command() now
returns an error in case the executed command returned with an exit code
different than 0.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 16:25:41 +02:00
Jiachen Zhang
650cbce017 virtio-devices: vhost_user: blk: Support socket reconnection handling
This commit enables socket reconnection for vhost-user-blk backends.

Note that, till this commit, inflight I/O trakcing and restoring is not
supported. Therefore, only vhost-user-blk backend that are not processing
inflight requests can work normally after reconnection.

Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
2021-06-04 11:14:24 +02:00
Jiachen Zhang
058946772a virtio-devices: vhost_user: Set proper avail index to vhost-user backend
We should try to read the last avail index from the vring memory aera. This
is necessary when handling vhost-user socket reconnection.

Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
2021-06-04 11:14:24 +02:00
Sebastien Boeuf
b443900cc2 tests: Extend OVS DPDK test with reconnection
Make sure the reconnection functionaliity is well tested from the OVS
DPDK integration test.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 11:13:44 +02:00
Sebastien Boeuf
8fad60bada tests: Improve OVS DPDK integration test
In order to simplify and speed up the OVS DPDK test, we switch from
using 'iperf3' to 'netcat' to validate the connectivity is functional.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 11:13:44 +02:00
Sebastien Boeuf
2e8a552c24 tests: Use OVS DPDK in client mode
Since OVS DPDK deprecated the use for the server mode, let's make sure
the integration test uses the client mode instead. This means the OVS
backend is the client and the VMM acts as the server, therefore the
reason why we use "vhost_mode=server".

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 11:13:44 +02:00
Sebastien Boeuf
7c917c0e74 tests: Re-enable test_ovs_dpdk
Re-enable the OVS DPDK integration test by assigning both VMs to the
NUMA node 0. This ensures the processes are being run on NUMA node 0,
preventing OVS DPDK from abnormal functioning.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-04 11:13:44 +02:00
dependabot[bot]
aee54fc8f3 build: bump addr2line from 0.15.1 to 0.15.2
Bumps [addr2line](https://github.com/gimli-rs/addr2line) from 0.15.1 to 0.15.2.
- [Release notes](https://github.com/gimli-rs/addr2line/releases)
- [Changelog](https://github.com/gimli-rs/addr2line/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/addr2line/compare/0.15.1...0.15.2)

---
updated-dependencies:
- dependency-name: addr2line
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-04 08:23:13 +00:00
dependabot[bot]
e10e1f6eed build: bump backtrace from 0.3.59 to 0.3.60
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.59 to 0.3.60.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.59...0.3.60)

---
updated-dependencies:
- dependency-name: backtrace
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-04 07:55:36 +00:00
Rob Bradford
0ccb597baf tests: Adapt commands for new SSH non-zero exit behaviour
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-03 13:28:25 -07:00
Rob Bradford
a3cbc1ff72 tests: Use sudo when testing disks with dd
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-03 13:28:25 -07:00
Rob Bradford
e7cf513064 test_infra: Return an error if SSH executed command exits with non-zero
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-03 13:28:25 -07:00
Rob Bradford
3dc15a9259 vmm: tdx: Don't access same locked structure twice
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-03 17:29:05 +02:00
Henry Wang
bcee2fbd2d build: bump vm-fdt from 956b5a5 to 2e4ebde
Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-06-03 14:13:02 +02:00
Bo Chen
1b87f332b0 block_util: Mark dirty pages manually with "VolatileSlice::as_ptr()"
As discussed in the working PR in the upstream vm-memory crate repo,
some special functions (e.g. return raw pointers to the wrapped guest
memory) require manual dirty page tracking from their users (e.g.the
VMM). One of the special functions is `VolatileSlice::as_ptr(), which is
used in our code base for supporting async block I/O. This patch
manually mark dirty for guest pages touched while reading from block
devices.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-03 08:34:45 +01:00
Bo Chen
7839e121f6 vmm: Add dirty pages tracked by vm_memory::bitmap to live migration
Live migration currently handles guest memory writes from the guest
through the KVM dirty page tracking and sends those dirty pages to the
destination. This patch augments the live migration support with dirty
page tracking of writes from the VMM to the guest memory(e.g. virtio
devices).

Fixes: #2458

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-03 08:34:45 +01:00
Bo Chen
2c4fa258a6 virtio-devices, vmm: Deprecate "GuestMemory::with_regions(_mut)"
Function "GuestMemory::with_regions(_mut)" were mainly temporary methods
to access the regions in `GuestMemory` as the lack of iterator-based
access, and hence they are deprecated in the upstream vm-memory crate [1].

[1] https://github.com/rust-vmm/vm-memory/issues/133

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-03 08:34:45 +01:00
Bo Chen
0e0159db0c fuzz: Fix the building error with the updated vm-memory crate
Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-03 08:34:45 +01:00
Bo Chen
b5bcdbaf48 misc: Upgrade to use the vm-memory crate w/ dirty-page-tracking
As the first step to complete live-migration with tracking dirty-pages
written by the VMM, this commit patches the dependent vm-memory crate to
the upstream version with the dirty-page-tracking capability. Most
changes are due to the updated `GuestMemoryMmap`, `GuestRegionMmap`, and
`MmapRegion` structs which are taking an additional generic type
parameter to specify what 'bitmap backend' is used.

The above changes should be transparent to the rest of the code base,
e.g. all unit/integration tests should pass without additional changes.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-06-03 08:34:45 +01:00
Muminul Islam
c7b794a7c5 hypervisor: Fix MSHV set_xsave API call
MSHV set_xsave got changed to fix the Snapshot and restore issue.
This patch fixes the API call.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-06-03 08:30:50 +01:00
Rob Bradford
280bef834b virtio-devices: Add helper to VirtioCommon for EventFd duplication
Add a helper to VirtioCommon which returns duplicates of the EventFds
for kill and pause event.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-02 12:39:10 -07:00
Sebastien Boeuf
df92495e31 virtio-devices: vhost_user: Fix connection retry logic
The logic was reversed, causing the retry to fail consistently.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 17:31:30 +02:00
Sebastien Boeuf
e62aafdf58 virtio-devices: Update seccomp filters for vhost-user-net control queue
The control queue was missing rt_sigprocmask syscall, which was causing
a crash when the VM was shutdown.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 17:31:18 +02:00
Rob Bradford
a14c70019a tests: Don't test virtiofsd
The CI is failing due the git server that the submodules required for
this fork of QEMU need to build from is unavailable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
(cherry picked from commit 2aec0a92a5)
2021-06-02 16:12:30 +02:00
Sebastien Boeuf
48c8649891 virtio-devices: vhost_user: Retry connecting the backend
When in client mode, the VMM will retry connecting the backend for a
minute before giving up.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 11:59:13 +02:00
Sebastien Boeuf
b4eb015d86 virtio-devices: vhost_user: Move reconnection code to module
The reconnection code is moved to the vhost-user module as it is a
common place to be shared across all vhost-user devices.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 11:59:13 +02:00
Sebastien Boeuf
3e00247a47 virtio-devices: vhost_user: Factorize backend connection
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 11:59:13 +02:00
Sebastien Boeuf
6bce7f7937 virtio-devices: vhost_user: net: Handle reconnection
This commit implements the reconnection feature for vhost-user-net in
case the connection with the backend is shutdown.

The guest has no knowledge about what happens when a disconnection
occurs, which simplifies the code to handle the reconnection. The
reconnection happens with the backend, and the VMM goes through the
vhost-user setup once again.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-02 11:59:13 +02:00
dependabot[bot]
f3d3d8daed build: bump signal-hook from 0.3.8 to 0.3.9
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.8 to 0.3.9.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.8...v0.3.9)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-02 07:48:03 +00:00
dependabot[bot]
dcddfbff91 build: bump signal-hook from 0.3.8 to 0.3.9 in /fuzz
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.8 to 0.3.9.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/v0.3.8...v0.3.9)

---
updated-dependencies:
- dependency-name: signal-hook
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-02 07:22:10 +00:00
dependabot[bot]
787426d4e6 build: bump signal-hook-registry from 1.3.0 to 1.4.0 in /fuzz
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/vorner/signal-hook/releases)
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.3.0...registry-v1.4.0)

---
updated-dependencies:
- dependency-name: signal-hook-registry
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-02 07:22:08 +00:00
Rob Bradford
c357adae44 vmm: tdx: Clear unsupported KVM PV features
This matches with the features that QEMU clears as they are not
supported with TDX.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 23:00:54 +02:00
Rob Bradford
9f5325fd52 hypervisor: tdx: Unconditionally enable TDX debug
For now enable the TDX attribute for TDX debug.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 09:50:22 -07:00
Michael Zhao
7f3fa39d81 vmm: Remove enable_interrupt_controller()
After adding "get_interrupt_controller()" function in DeviceManager,
"enable_interrupt_controller()" became redundant, because the latter
one is the a simple wrapper on the interrupt controller.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-01 16:56:43 +01:00
Michael Zhao
9a5f3fc2a7 vmm: Remove "gicr" handling from DeviceManager
The function used to calculate "gicr-typer" value has nothing with
DeviceManager. Now it is moved to AArch64 specific files.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-01 16:56:43 +01:00
Michael Zhao
7932cd22ca vmm: Remove GIC entity set/get from DeviceManager
Moved the set/get functions from vmm::DeviceManager to devices::Gic.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-01 16:56:43 +01:00
Michael Zhao
195eba188a vmm: Split create_gic() from configure_system()
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-06-01 16:56:43 +01:00
Rob Bradford
9341cce8b3 tests: Temporarily disable test_ovs_dpdk
This test is flaking out regularly, particularly on the musl build.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 17:46:58 +02:00
Rob Bradford
2ac7232288 virtio-devices: vsock: Implement versioning for state
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 14:23:09 +02:00
Rob Bradford
905135fe8c virtio-devices: transport: Versionize VirtioPciDevice state
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 14:23:09 +02:00
Rob Bradford
57f532a760 virtio-devices, vm-virtio: Refactor queue state saving/restoring
Use a separate QueueState structure which can be versioned.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 14:23:09 +02:00
Rob Bradford
831dff8b4e virtio-devices: transport: Version common PCI config state
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-06-01 14:23:09 +02:00
Sebastien Boeuf
4db7530f28 ci: Add OVS-DPDK integration test
In order to avoid regression regarding OVS-DPDK support, a new
integration test is added. This test consists of running two VMs, both
attached to a distinct OVS port, where both ports are connected to an
OVS bridge. Once the VM are running, the test validates the connection
between the two VMs works correctly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-01 12:17:23 +02:00
Sebastien Boeuf
239e2adc68 tests: Introduce ssh_command_ok()
Adding a new function ssh_command_ok() as a wrapper around the existing
ssh_command() function. The goal being to identify if the command
returned without any error.

This new function allow for a bit of factorization through the codebase.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-06-01 12:17:23 +02:00
Muminul Islam
1c60591eab rpm: Update version to 15.0
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2021-05-31 09:56:30 +02:00
Michael Zhao
5e53bbf405 arch: Bump vm-fdt from 13ab882 to 956b5a5
Interface of vm-fdt changed.
Updated aarch64 code to adapt.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-28 10:53:55 +02:00
Sebastien Boeuf
fbaceea4c0 resources: Add ovs-dpdk install to Dockerfile
The Dockerfile is extended with some new instructions to install the
OVS-DPDK packages. This will be useful for writing new integration tests
and make sure OVS-DPDK is working properly.

This also updates the Rust toolchain from 1.51.0 to 1.52.1.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-27 13:51:06 +01:00
dependabot[bot]
56ec5ca260 build: bump libfuzzer-sys from 0.4.1 to 0.4.2 in /fuzz
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.4.1 to 0.4.2.
- [Release notes](https://github.com/rust-fuzz/libfuzzer/releases)
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.1...0.4.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-27 07:26:29 +00:00
Rob Bradford
3ffd2cb9be pci: Versionize PCI state
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-26 22:29:35 +02:00
Rob Bradford
cacec04df6 arch: Remove serde usage
With the only struct using it now using Versionize then the serde
dependency can be removed.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-26 22:27:41 +02:00
Rob Bradford
72ec98b8a8 arch: aarch64: Versionize Gicv3State
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-26 22:27:41 +02:00
Sebastien Boeuf
a174ad011e vhost_user_net: Move control queue handling out
We recently realized the control queue is not meant to be handled by the
backend, that's why we move it out of vhost-user-net implementation.

Revert "vhost_user_net: Handle control queue"
This reverts commit af88ff1c49.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-26 16:09:32 +01:00
Sebastien Boeuf
e9cc23ea94 virtio-devices: vhost_user: net: Move control queue back
We thought we could move the control queue to the backend as it was
making some good sense. Unfortunately, doing so was a wrong design
decision as it broke the compatibility with OVS-DPDK backend.

This is why this commit moves the control queue back to the VMM side,
meaning an additional thread is being run for handling the communication
with the guest.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-26 16:09:32 +01:00
dependabot[bot]
6c245f6cf1 build: Manual seccomp bump
Seccomp needs to be bumped in the main tree and fuzz at the same time.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-26 14:39:43 +02:00
dependabot[bot]
dd92715ed2 build: Bump libc from 0.2.94 to 0.2.95
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.94 to 0.2.95.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.94...0.2.95)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-26 07:18:40 +00:00
dependabot[bot]
b3d1278838 build: Bump libc from 0.2.94 to 0.2.95 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.94 to 0.2.95.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.94...0.2.95)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-26 06:51:19 +00:00
Sebastien Boeuf
92c2101f7c virtio-devices: vhost_user: Enable most virtio reserved features
A lot of the VIRTIO reserved features should be supported or not by the
vhost-user backend. That means on the VMM side, these features should be
available, so that they don't get lost during the negotiation.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-25 12:12:22 +02:00
Michael Zhao
ff46fb69d0 aarch64: Fix IRQ number setting for ACPI
On FDT, VMM can allocate IRQ from 0 for devices.
But on ACPI, the lowest range below 32 has to be avoided.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-25 10:20:37 +02:00
Henry Wang
efc583c13e acpi: AArch64: Enable PSCI in FADT
This commit enables the PSCI (Power State Coordination Interface)
for the AArch64 platform, which allows the VMM to manage the power
status of the guest. Also, multiple vCPUs can be brought up using
PSCI.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-25 10:20:37 +02:00
Henry Wang
d882f8c928 acpi: Implement IORT for AArch64
This commit implements the IO Remapping Table (IORT) for AArch64.
The IORT is one of the required ACPI table for AArch64, since
it describes the GICv3ITS node.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-25 10:20:37 +02:00
Henry Wang
213da7d862 acpi: Implement SPCR on AArch64
This commit implements an AArch64-required ACPI table: Serial
Port Console Redirection Table (SPCR). The table provides
information about the configuration and use of the serial port
or non-legacy UART interface.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-25 10:20:37 +02:00
Henry Wang
9c5528490e acpi: Implement GTDT on AArch64
This commit implements an AArch64-specific ACPI table: Generic
Timer Description Table (GTDT). The GTDT provides OSPM with
information about a system’s Generic Timers configuration.

The Generic Timer (GT) is a standard timer interface implemented
on ARM processor-based systems.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-25 10:20:37 +02:00
Michael Zhao
7bfb51489b acpi: Implement MCFG for AArch64
Added the final PCI bus number in MCFG table. This field is mandatory on
AArch64. On X86 it is optional.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-25 10:20:37 +02:00
Michael Zhao
e1ef141112 acpi: Enable DSDT for CpuManager on AArch64
Simplified definition block of CPU's on AArch64. It is not complete yet.
Guest boots. But more is to do in future:
- Fix the error in ACPI definition blocks (seen in boot messages)
- Implement CPU hot-plug controller

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-25 10:20:37 +02:00
Michael Zhao
5f27d649a6 acpi: Enable DSDT for DeviceManager on AArch64
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-25 10:20:37 +02:00
Michael Zhao
cab103d172 acpi: Implement MADT on AArch64
Added following structures in MADT table:
- GICC: GIC CPU interface structure
- GICD: GIC Distributor structure
- GICR: GIC Redistributor Structure
- GICITS: GIC Interrupt Translation Service Structure

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-25 10:20:37 +02:00
dependabot[bot]
084fdd9d10 build: Bump cc from 1.0.67 to 1.0.68
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.67 to 1.0.68.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.67...1.0.68)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-25 07:48:52 +00:00
dependabot[bot]
74c064e477 build: Bump cc from 1.0.67 to 1.0.68 in /fuzz
Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.67 to 1.0.68.
- [Release notes](https://github.com/alexcrichton/cc-rs/releases)
- [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.67...1.0.68)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-25 07:48:30 +00:00
dependabot[bot]
14f27e4219 build: Bump arc-swap from 1.2.0 to 1.3.0
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/vorner/arc-swap/releases)
- [Changelog](https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/arc-swap/compare/v1.2.0...v1.3.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 09:43:06 +00:00
dependabot[bot]
9a8ff68bc1 build: Bump thiserror from 1.0.24 to 1.0.25 in /fuzz
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.24 to 1.0.25.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.24...1.0.25)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 09:20:09 +00:00
dependabot[bot]
b461200211 build: Bump arc-swap from 1.2.0 to 1.3.0 in /fuzz
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/vorner/arc-swap/releases)
- [Changelog](https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/arc-swap/compare/v1.2.0...v1.3.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 08:44:19 +00:00
dependabot[bot]
aba2513322 build: Bump vcpkg from 0.2.12 to 0.2.13
Bumps [vcpkg](https://github.com/mcgoo/vcpkg-rs) from 0.2.12 to 0.2.13.
- [Release notes](https://github.com/mcgoo/vcpkg-rs/releases)
- [Changelog](https://github.com/mcgoo/vcpkg-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mcgoo/vcpkg-rs/compare/vcpkg-rs-0.2.12...vcpkg-rs-0.2.13)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 08:44:12 +00:00
dependabot[bot]
cb8fc4dc9f build: Bump thiserror from 1.0.24 to 1.0.25
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.24 to 1.0.25.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.24...1.0.25)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 08:44:06 +00:00
Sebastien Boeuf
47be87c7cc virtio-devices: vhost_user: Don't set features before ACK from guest
The VIRTIO features should not be set before they are acked from the
guest. This code was only present to overcome a vhost crate limitation
that was expecting the VIRTIO features to be set before we could fetch
and set the protocol features.

The vhost crate has been recently fixed by removing the limitation,
therefore there's no need for this workaround in the Cloud Hypervisor
codebase anymore.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-24 00:34:46 +02:00
dependabot[bot]
66d52199a7 build: Bump vhost from f338330 to e4ba734
Bumps [vhost](https://github.com/rust-vmm/vhost) from `f338330` to `e4ba734`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](f338330bd7...e4ba734144)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-21 15:58:27 +00:00
Rob Bradford
f840327ffb vmm: Version MemoryManager state
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-21 15:29:52 +02:00
Rob Bradford
719e36049b block_util: Remove unrequired serde usage from block_util
These structs are now versioned instead.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-21 15:12:23 +02:00
Sebastien Boeuf
f583f993ee virtio-devices: Remove the need for net_util in the crate
Everything that was shared in the net_util.rs file has been now moved to
the net_util crate. The only remaining bit was only used by the
virtio-net implementation, that is why this commit moves this code to
virtio-net, and since there's nothing left in net_util.rs, it can be
removed.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 14:39:56 +02:00
Sebastien Boeuf
bcb1dfb86f virtio-devices: net: Rely on net_util crate for control queue
Since the net_util crate contains the common code needed for processing
the control queue, let's use it and remove the duplicate from inside the
virtio-devices crate.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 14:39:56 +02:00
Sebastien Boeuf
d7a69f8aa1 net_util: Move virtio-net helpers to net_util crate
Moving helpers to the net_util crate since we don't want virtio-net
common code to be split between two places. The net_util crate should be
the only place to host virtio-net common code.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 14:39:56 +02:00
Sebastien Boeuf
f36b5f3e3c virtio-devices: vhost_user: Factorize features negotiation
Factorize the virtio features and vhost-user protocol features
negotiation through a common function that blk, fs and net
implementations can directly rely on.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
cdaa4d3ad7 virtio-devices: vhost_user: Set features once acknowledged by guest
Make sure the virtio features are set upon device activation. At the
time the device is activated, we know the guest acknowledged the
features, which mean it's safe to set them back to the backend.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
8c73af048a virtio-devices: vhost_user: fs: Cleanup device creation
Prepare the device creation so that it can be factorized in a follow up
commit.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
e2121c5d75 virtio-devices: vhost_user: net: Cleanup device creation
Prepare the device creation so that it can be factorized in a follow up
commit.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
9a7199a116 virtio-devices: vhost_user: blk: Cleanup device creation
Prepare the device creation so that it can be factorized in a follow up
commit.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
c549bbd72a vhost_user_net: Extend list of supported virtio features
Extend the current list of available virtio features in order to make it
work correctly with the VMM side.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
Sebastien Boeuf
c39d43dee1 vhost_user_blk: Extend list of supported virtio features
Extend the current list of available virtio features in order to make it
work correctly with the VMM side.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-21 12:03:54 +02:00
dependabot[bot]
b76e0b358f build: Bump arbitrary from 1.0.0 to 1.0.1 in /fuzz
Bumps [arbitrary](https://github.com/rust-fuzz/arbitrary) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/rust-fuzz/arbitrary/releases)
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-21 07:21:28 +00:00
dependabot[bot]
9bc309b416 build: Bump getrandom from 0.2.2 to 0.2.3
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/rust-random/getrandom/releases)
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.2...v0.2.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-21 07:21:22 +00:00
renlei4
65a39f43cb vmm: support restore KVM clock in migration
In migration, vm object is created by new_from_migration with
NULL kvm clock. so vm.set_clock will not be called during vm resume.
If the guest using kvm-clock, the ticks will be stopped after migration.

As clock was already saved to snapshot, add a method to restore it before
vm resume in migration. after that, guest's kvm-clock works well.

Signed-off-by: Ren Lei <ren.lei4@zte.com.cn>
2021-05-20 14:32:49 +01:00
ren lei
324c924ca4 vmm: fix KVM clock lost during restore form snapshot
Connecting a restored KVM clock vm will take long time, as clock
is NOT restored immediately after vm resume from snapshot.

this is because 9ce6c3b incorrectly remove vm_snapshot.clock, and
always pass None to new_from_memory_manager, which will result to
kvm_set_clock() never be called during restore from snapshot.

Fixes: 9ce6c3b
Signed-off-by: Ren Lei <ren.lei4@zte.com.cn>
2021-05-20 11:31:01 +02:00
dependabot[bot]
75ad89670b build: Bump proc-macro2 from 1.0.26 to 1.0.27 in /fuzz
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.26 to 1.0.27.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.26...1.0.27)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-20 09:44:25 +02:00
dependabot[bot]
d4f01bdb43 build: Bump proc-macro2 from 1.0.26 to 1.0.27
Bumps [proc-macro2](https://github.com/alexcrichton/proc-macro2) from 1.0.26 to 1.0.27.
- [Release notes](https://github.com/alexcrichton/proc-macro2/releases)
- [Commits](https://github.com/alexcrichton/proc-macro2/compare/1.0.26...1.0.27)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-20 09:44:11 +02:00
Michael Zhao
e1c9a956da scripts: Fix an obsolete sha1sam
Updated the sha1sum of bionic-server-cloudimg-arm64.qcow2.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-20 13:42:34 +08:00
Sebastien Boeuf
c2137e33a0 vhost_user_backend: Don't discard events when queue is not enabled
The vhost crate does not support the need_reply flag yet, meaning we
can't be sure the backend is properly setup before the guest goes on.

One can run in a race condition where the VMM enables the vring, but
never gets any acknowledgement, meaning it assumes everything went well
and finalize the virtio device activation. Once the device is seen as
ready by the guest, it keeps going by sending some messages through the
virtqueues. Problem is, if it took some time for the backend to enable
the queue, one of the backend thread might receive a kick from the guest
while the corresponding queue is not enabled. This leads to the loss of
the event as it is discarded because the queue is not enabled.

Until vhost crate allows for requests with ACK, the way to mitigate this
issue is by ignoring an event coming up on a queue that has not been
enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-19 18:21:47 +02:00
Rob Bradford
c05010887f virtio-devices: seccomp: Cleanup unused seccomp filter entries
The threads in question are no longer created and so no longer need
seccomp rules for them.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 18:21:47 +02:00
Sebastien Boeuf
334aa8c941 virtio-devices: vhost_user: Don't set features twice
The virtio features are negotiated and set at the time the device is
created, hence there's no need to set the features again while going
through the vhost-user setup that is performed upon queue activation.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-19 18:21:47 +02:00
Sebastien Boeuf
5d2df70a79 virtio-devices: vhost_user: net: Remove control queue
Now that the control queue is correctly handled by the backend, there's
no need to handle it as well from the VMM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-19 18:21:47 +02:00
Sebastien Boeuf
af88ff1c49 vhost_user_net: Handle control queue
The virtio-net control queue must be handled by the backend, the same
way all other queues already are.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-19 18:21:47 +02:00
Sebastien Boeuf
40dc3e7c10 net_util: Introduce virtio-net control queue handling code
This code is ported from the net_util.rs in virtio-devices. The point
being to move it to the net_util crate so that it can later be reused
from vhost-user-net backend.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-19 18:21:47 +02:00
Anatol Belski
56b9149325 tests: Pull common code into a separate method
Yet another small refactoring step for WindowsGuest
after f56471566b.

For this particular case - there's currently neither overloading nor
default argument support in Rust (except a macro or other tricky stuff),
so keep the timeout and other options default for now.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2021-05-19 16:41:08 +01:00
Rob Bradford
7ae631e0c1 vmm: Hypervisor::check_required_extensions() is not x86_64 only
This function is implemented for aarch64 so should be called on it.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 17:11:30 +02:00
Rob Bradford
84454f142d hypervisor: Remove panic from Hypervisor::check_required_extensions()
Remove the panic by replacing the .expect() with a cleaner error
handling.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 17:11:30 +02:00
Rob Bradford
a335cbb8d5 hypervisor: Unconditional build Hypervisor::create_vm_with_type()
Mark it as unreachable for now in the default implementation as this is
currently only used on tdx code path which is KVM only.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 17:11:30 +02:00
Rob Bradford
0cf9218d3f hypervisor, vmm: Add default Hypervisor::check_required_extensions()
This allows the removal of KVM specific compile time checks on this
function.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 17:11:30 +02:00
Rob Bradford
2439625785 hypervisor: Cleanup unused Hypervisor trait members
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-19 17:11:30 +02:00
Anatol Belski
01e2826f26 tests: Implement disk hotplug test
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2021-05-19 10:39:46 +02:00
Michael Zhao
01acea3102 acpi: Refactor create_acpi_tables()
Split the code of create_acpi_tables() into multiple functions for
easy extension in future.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-19 09:59:59 +02:00
dependabot[bot]
5ae04349da build: Bump vhost from e5b930b to f338330
Bumps [vhost](https://github.com/rust-vmm/vhost) from `e5b930b` to `f338330`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](e5b930b73a...f338330bd7)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-19 09:53:49 +02:00
Michael Zhao
aca6fdbd0e scripts: Test ACPI build on AArch64
Added a step to verify ACPI build.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-18 23:24:09 +02:00
Michael Zhao
e4bb6409ae aarch64: Change memory layout for UEFI & ACPI
Before this change, the FDT was loaded at the end of RAM. The address of
FDT was not fixed.
While UEFI (edk2 now) requires fixed address to find FDT and RSDP.
Now the FDT is moved to the beginning of RAM, which is a fixed address.
RSDP is wrote to 2 MiB after FDT, also a fixed address.
Kernel comes 2 MiB after RSDP.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2021-05-18 23:24:09 +02:00
Rob Bradford
b282ff44d4 vmm: Enhance boot with info!() level messages
These messages are predominantly during the boot process but will also
occur during events such as hotplug.

These cover all the significant steps of the boot and can be helpful for
diagnosing performance and functionality issues during the boot.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-18 20:45:38 +02:00
Dayu Liu
8160c2884b docs: Fix some typos in docs and comments
Fix some typos or misspellings without functional change.

Signed-off-by: Dayu Liu <liu.dayu@zte.com.cn>
2021-05-18 17:19:12 +01:00
dependabot[bot]
c91b16d2a1 build: Bump kvm-ioctls from 0.8.0 to 0.9.0 in /fuzz
Bumps [kvm-ioctls](https://github.com/rust-vmm/kvm-ioctls) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/rust-vmm/kvm-ioctls/releases)
- [Changelog](https://github.com/rust-vmm/kvm-ioctls/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/kvm-ioctls/compare/v0.8.0...v0.9.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-18 16:07:35 +00:00
Anatol Belski
65429cebae docker: Add ntfs-3g to the package list
This will make `mkfs.ntfs` available in the next image update, so then
it can be used in the tests.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2021-05-18 17:07:19 +01:00
dependabot[bot]
4449b0d3c2 build: Bump pnet from 0.27.2 to 0.28.0
Bumps [pnet](https://github.com/libpnet/libpnet) from 0.27.2 to 0.28.0.
- [Release notes](https://github.com/libpnet/libpnet/releases)
- [Commits](https://github.com/libpnet/libpnet/compare/v0.27.2...v0.28.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-17 10:43:21 +02:00
dependabot[bot]
589f93da92 build: Bump kvm-ioctls from 0.8.0 to 0.9.0
Bumps [kvm-ioctls](https://github.com/rust-vmm/kvm-ioctls) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/rust-vmm/kvm-ioctls/releases)
- [Changelog](https://github.com/rust-vmm/kvm-ioctls/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/kvm-ioctls/compare/v0.8.0...v0.9.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-17 10:16:12 +02:00
Rob Bradford
5296bd10c1 vmm: tdx: Reorder TDX ioctls
Separate the population of the memory and the HOB from the TDX
initialisation of the memory so that the latter can happen after the CPU
is initialised.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-17 07:39:52 +02:00
dependabot[bot]
d100c014bc build: Bump iced-x86 from 1.11.2 to 1.11.3 in /fuzz
Bumps [iced-x86](https://github.com/icedland/iced) from 1.11.2 to 1.11.3.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.11.2...v1.11.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-14 09:02:28 +00:00
dependabot[bot]
2cf75116d9 build: Bump libfuzzer-sys from 0.4.0 to 0.4.1 in /fuzz
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.4.0 to 0.4.1.
- [Release notes](https://github.com/rust-fuzz/libfuzzer/releases)
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.0...0.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-14 08:22:06 +00:00
dependabot[bot]
a45f7ac1bc build: Bump iced-x86 from 1.11.2 to 1.11.3
Bumps [iced-x86](https://github.com/icedland/iced) from 1.11.2 to 1.11.3.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.11.2...v1.11.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-14 08:20:39 +00:00
dependabot[bot]
e75de542df build: Bump serde_derive from 1.0.125 to 1.0.126
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.125 to 1.0.126.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.125...v1.0.126)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-13 09:51:55 +00:00
dependabot[bot]
252963190b build: Bump serde from 1.0.125 to 1.0.126
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.125 to 1.0.126.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.125...v1.0.126)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-13 09:22:55 +00:00
dependabot[bot]
93de4c67e5 build: Bump serde from 1.0.125 to 1.0.126 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.125 to 1.0.126.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.125...v1.0.126)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-13 08:55:01 +00:00
dependabot[bot]
23791a45c8 build: Bump serde_derive from 1.0.125 to 1.0.126 in /fuzz
Bumps [serde_derive](https://github.com/serde-rs/serde) from 1.0.125 to 1.0.126.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.125...v1.0.126)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-13 08:17:45 +00:00
Sebastien Boeuf
355e7468e4 virtio-devices: vhost-user: Don't run threads for net and block
Some refactoring is performed in order to always expect the irqfd to be
provided by VirtioInterrupt trait. In case no irqfd is available, we
simply fail initializing the vhost-user device. This allows for further
simplification since we can assume the interrupt will always be
triggered directly by the vhost-user backend without proxying through
the VMM. This allows for complete removal of the dedicated thread for
both block and net.

vhost-user-fs is a bit more complex as it requires the slave request
protocol feature in order to support DAX. That's why we still need the
VMM to interfere and therefore run a dedicated thread for it.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-13 09:16:27 +01:00
Rob Bradford
496ceed1d0 misc: Remove unnecessary "extern crate"
Now all crates use edition = "2018" then the majority of the "extern
crate" statements can be removed. Only those for importing macros need
to remain.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
1205bce0ef devices: Move to versioned snapshots
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
c03fe508c1 net_get, net_util: Move crate to rust 2018 edition
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
6895e634cc arch: Move crate to rust 2018 edition
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
86015bef78 devices: Move crate to rust 2018 edition
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
bd724fc304 virtio-devices: Stop deriving unnecessary traits
These structs only need to derive Versionize now.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 17:26:11 +02:00
Rob Bradford
6e6f66de2e build: Bulk upgrade dependencies including fuzz
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-12 13:57:16 +01:00
dependabot[bot]
daa935b5c9 build: Bump vfio-ioctls from ed8d253 to 5cb8550
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio-ioctls) from `ed8d253` to `5cb8550`.
- [Release notes](https://github.com/rust-vmm/vfio-ioctls/releases)
- [Commits](ed8d253457...5cb8550556)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 10:54:02 +02:00
dependabot[bot]
6fa1ec4f3c build: Bump vm-fdt from 8d81555 to 13ab882
Bumps [vm-fdt](https://github.com/rust-vmm/vm-fdt) from `8d81555` to `13ab882`.
- [Release notes](https://github.com/rust-vmm/vm-fdt/releases)
- [Commits](8d81555c14...13ab882e2f)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 09:55:45 +02:00
dependabot[bot]
363ca66c2d build: Bump vhost from cc4da71 to e5b930b
Bumps [vhost](https://github.com/rust-vmm/vhost) from `cc4da71` to `e5b930b`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](cc4da710ac...e5b930b73a)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 09:55:29 +02:00
Rob Bradford
b8f5911c4e misc: Remove unused errors from public interface
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-11 13:37:19 +02:00
Rob Bradford
30b74e74cd vmm: tdx: Reject attempt to use --kernel with --tdx
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-10 15:12:41 +01:00
Rob Bradford
c400702272 virtio-devices: Version state structures
Version the state for device state for the virtio devices.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-10 14:40:27 +01:00
Rob Bradford
dce846fdfd build: Use versionize_derive from Cloud Hypervisor fork
This allows the use of #[derive(Versionize)] on packed structs.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-10 14:40:27 +01:00
Rob Bradford
bbda08717f vm-migration: Add versioned versions of snapshot & state API
This will allow progressive porting of parts of the VMM to using
versioned state. A new trait VersionMapped is introduced with a default
implementation that returns an empty VersionMap to ease implementation.

If a struct is updated the the trait will need to be fully implemented
with VersionMapped::version_map() returning a new VersionMap handling
the change.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-10 14:40:27 +01:00
dependabot[bot]
2eeeaf5753 build: Bump backtrace from 0.3.58 to 0.3.59
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.58 to 0.3.59.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.58...0.3.59)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 14:28:08 +01:00
dependabot[bot]
7299202d01 build: Bump vhost from c4cd1d3 to cc4da71
Bumps [vhost](https://github.com/rust-vmm/vhost) from `c4cd1d3` to `cc4da71`.
- [Release notes](https://github.com/rust-vmm/vhost/releases)
- [Commits](c4cd1d375e...cc4da710ac)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 13:47:40 +02:00
Henry Wang
1f63350eba resources: Remove libfdt in docker image
Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-07 18:49:17 +02:00
Henry Wang
cb26ad511b github-workflows: Remove libfdt installation
Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-07 18:49:17 +02:00
Henry Wang
139621778b arch: aarch64: Use vm_fdt crate methods
This commit moves the libfdt helpers to vm_fdt crate methods
when creating the FDT.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
2021-05-07 18:49:17 +02:00
Sebastien Boeuf
ae4e01adc9 tests: vfio: Increase time for memory hotplug
Bump the sleep time before checking the guest RAM size from 10 to 30
seconds. This will help the VFIO baremetal CI passing more consistently.

Fixes #2606

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-07 18:44:31 +02:00
Rob Bradford
6d6cafafb2 tests: Fix clippy issues in integration tests
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Rob Bradford
0d3c5c966b virtio-devices: mem: Address clippy issue
error: all if blocks contain the same code at the start
   --> virtio-devices/src/mem.rs:508:9
    |
508 | /         if plug {
509 | |             let handlers =
    self.dma_mapping_handlers.lock().unwrap();
    |
|_____________________________________________________________________^
    |
    = note: `-D clippy::branches-sharing-code` implied by `-D warnings`
    = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
help: consider moving the start statements out like this
    |
508 |         let handlers = self.dma_mapping_handlers.lock().unwrap();
509 |         if plug {
    |

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Rob Bradford
18012d9ee8 virtio-devices: iommu: Address clippy issue
error: usage of `contains_key` followed by `insert` on a `BTreeMap`
   --> virtio-devices/src/iommu.rs:439:17
    |
439 | /                 if !mappings.contains_key(&domain) {
440 | |                     mappings.insert(domain, BTreeMap::new());
441 | |                 }
    | |_________________^ help: try this:
`mappings.entry(domain).or_insert_with(|| BTreeMap::new());`
    |
    = note: `-D clippy::map-entry` implied by `-D warnings`
    = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#map_entry

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Rob Bradford
a6da5f9e77 virtio-devices: vsock: Address clippy issue
Issue from beta version of clippy:

  --> virtio-devices/src/vsock/csm/txbuf.rs:69:34
   |
69 |                 Box::new(unsafe {mem::MaybeUninit::<[u8;
   Self::SIZE]>::uninit().assume_init()}));
   |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[deny(clippy::uninit_assumed_init)]` on by default
   = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init

Fix backported Firecracker a8c9dffad439557081f3435a7819bf89b87870e7.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Rob Bradford
c418074360 virtio-devices: vhost_user: fs: Don't reference packed struct
error: reference to packed field is unaligned
  --> virtio-devices/src/vhost_user/fs.rs:85:21
   |
85 |                     fs.flags[i].bits() as i32,
   |                     ^^^^^^^^^^^
   |
   = note: `-D unaligned-references` implied by `-D warnings`
   = warning: this was previously accepted by the compiler but is being
phased out; it will become a hard error in a future release!
   = note: for more information, see issue #82523
<https://github.com/rust-lang/rust/issues/82523>
   = note: fields of packed structs are not properly aligned, and
creating a misaligned reference is undefined behavior (even if that
reference is never dereferenced)

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Rob Bradford
f0b64547c2 net_gen, net_util: Regenerate bindings
Regernating the bindings required some minor changes to accomodate
changes around the accessing of unions.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 14:31:57 +02:00
Sebastien Boeuf
1f94208090 Jenkinsfile: Don't wait for a node that is not being used
Since SGX and VFIO tests don't need to be run on pull requests, we
should not have to wait for the corresponding node (bionic-sgx or
bionic-vfio) to become available in order to skip them.

Fixes #2607

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-07 11:56:36 +01:00
Sebastien Boeuf
5268bf5a8c tests: Re-enable virtiofsd tests
Re-enable virtiofsd testing now that issues with capstone repository
have been resolved.

This reverts commit 2aec0a92a5.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-07 11:16:36 +02:00
dependabot[bot]
a097e29292 build: Bump openssl-sys from 0.9.62 to 0.9.63
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.62 to 0.9.63.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.62...openssl-sys-v0.9.63)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-07 11:03:36 +02:00
dependabot[bot]
9f07c7940f build: Bump regex from 1.5.3 to 1.5.4
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.3 to 1.5.4.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.3...1.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-07 11:03:21 +02:00
Yi Wang
1adcf5225b virtio-device: fix some misspelled words in comment
Fix some trivial spelling problem.
No functional change.

Signed-off-by: Yi Wang <wang.yi59@zte.com.cn>
2021-05-07 09:07:36 +02:00
Wei Liu
c439324451 tests: add a Windows multiple queues test
Create as many queues as there are boot CPUs for block and twice as many
for net.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2021-05-07 08:57:13 +02:00
Sebastien Boeuf
66b46a277e tests: Remove unused code from Windows integration tests
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-07 08:57:13 +02:00
Sebastien Boeuf
9adfc04f75 tests: Wait for dnsmasq process to terminate
Make sure the dnsmasq process terminates after we sent the kill signal.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-07 08:57:13 +02:00
Rob Bradford
28f383bae9 hypervisor: aarch64: Safer calculation of offset_of
Use a safer method for calculating struct member offsets.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-07 07:16:09 +08:00
Rob Bradford
b04e437cfd arch: Move mpspec to arch crate and simplify
Remove unnecessary code for these structs. Moving this also allows the
removal of the arch_gen crate.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-06 19:42:52 +01:00
Sebastien Boeuf
0a00df2e7e tests: Dynamically assign IPs for Windows integration tests
Relying on dnsmasq running on the host, the Windows guest are now
getting allocated with the expected IP addresses. This allows for
multiple VMs, therefore multiple tests to run in parallel.

The end goal is to reduce the time spent running Windows integration
tests.

Fixes #1891

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-06 17:27:33 +02:00
Sebastien Boeuf
aa76c9db2e tests: Rename Windows specific functions
Let's keep the function names as simple as possible.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-06 15:17:27 +02:00
Sebastien Boeuf
f56471566b tests: Introduce WindowsGuest structure for further factorization
This new wrapping structure allows for a better factorization of the
Windows specific code. This makes each test simpler and easier to read.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-06 15:17:27 +02:00
Sebastien Boeuf
14544d64e4 tests: Factorize shutdown and reboot functions for Windows
Add some factorization for both functions rebooting and shutting down a
Windows guest.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-06 15:17:27 +02:00
Sebastien Boeuf
2646b24047 tests: Remove references from Guest and DiskConfig
By using a Box around the DiskConfig trait, it becomes Sized. For that
reason, we can pass the DiskConfig to the Guest so that it can own it.
This allows for further simplification as the Guest does not need to be
bound to a specific lifetime, which makes things easier.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-06 15:17:27 +02:00
Bo Chen
ac2469077f docs: Update documentation vhost-user-net-testing.md
Updated the obsoleted instructions and scripts, based on Open vSwitch
v2.13.1, DPDK stable v19.11.3, and Cloud Hypervisor v15.0 (on Ubuntu
20.04.1).

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-05-06 09:22:28 +02:00
Sebastien Boeuf
b2b577257f tests: Add integration test for vhost-user-net client mode
Refactor the existing vhost-user-net integration tests in order to
extend it with an extra test for vhost-user client mode.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-05 16:05:51 +02:00
Sebastien Boeuf
8f9ffe5417 vhost_user_net: Add client mode
Relying on latest changes from vhost_user_backend crate, this patch
enables the client mode support for vhost-user-net backend.
In this mode, the backend behaves as a client instead of the default
mode where it behaves as the server.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-05 16:05:51 +02:00
Sebastien Boeuf
a4a0751051 vhost_user_backend: Add client mode support
Introduce some new code to support running a vhost-user backend as a
client instead of the default server mode.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-05 16:05:51 +02:00
Sebastien Boeuf
904aea76ab vhost_user_backend: Rename start() to start_server()
The point being to identify clearly that we're running the backend as a
server. This anticipates the addition of a new function for running the
backend as a client.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-05 16:05:51 +02:00
Sebastien Boeuf
b5c6b04b36 virtio-devices, vmm: vhost: net: Add client mode support
Adding the support for an OVS vhost-user backend to connect as the
vhost-user client. This means we introduce with this patch a new
option to our `--net` parameter. This option is called 'server' in order
to ask the VMM to run as the server for the vhost-user socket.

Fixes #1745

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-05 16:05:51 +02:00
Rob Bradford
656b9f97f9 virtio-devices: net: Loop over enabled queue pairs when activating
In some situations (booting with OVMF) fewer queues will be enabled
therefore we should iterate over the number of enabled queues (as passed
into VirtioDevice::activate()) rather than the number of create tap
devices.

Fixes: #2578

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-05 10:19:38 +02:00
Bo Chen
db66cb6e9b docs: Update documentation vhost-user-blk-testing.md
Updated the obsoleted path of `vhost` the in spdk folder and fixed some
formatting issues.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2021-05-04 22:18:35 +02:00
Rob Bradford
7e0ccce225 vmm: config: Validate that vCPUs is sufficient for MQ queue count
Fixes: #2563

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-04 19:49:34 +02:00
Rob Bradford
2ad615cd32 vmm: Validate config upon hotplug
Create a temporary copy of the config, add the new device and validate
that. This needs to be done separately to adding it to the config to
avoid race conditions that might be result in config changes being
overwritten.

Fixes: #2564

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-04 19:49:20 +02:00
Rob Bradford
151668b260 vmm: Simplify adding devices to config
To handle that devices are stored in an Option<Vec<T>> and reduce
duplicated code use generic function to add the devices to the the
struct.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-04 19:49:20 +02:00
Rob Bradford
f237789753 vmm: Output config used for booting VM at info!() level
This helps with debugging VM behaviour when the VM is created via an
API.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-04 14:27:04 +01:00
dependabot[bot]
0f7cae4130 build: Bump syn from 1.0.71 to 1.0.72
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.71 to 1.0.72.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.71...1.0.72)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-04 15:18:12 +02:00
Sebastien Boeuf
b5be62a167 tests: Extend VFIO baremetal integration tests
Relying on guest Ubuntu image 21.04, including a 5.11 kernel, this patch
adds some additional tests to the VFIO baremetal integration tests. It
adds a test for ACPI memory hotplug, another one for virtio-mem memory
hotplug, and finally a test for hotplugging the NVIDIA card.

The existing test already taking care of the reboot has been renamed.

The script running "cargo test" has been modified to run only one thread
at a time, so that each test run sequentially. This is mandatory since
the card can't be shared across multiple VMs.

Fixes #2404

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-04 15:01:29 +02:00
Sebastien Boeuf
6eaf44ec61 tests: Update journalctl command to get reboot count
In order to support most recent Ubuntu distributions, we must update
the way of detecting a reboot through the journal since there is no
more "-- Reboot --" logs.

Using the `--list-boots` option is the preferred way for getting the
boot count information from journalctl command. We simply need to add 1
to the count in order to get the reboot count.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-04 15:01:29 +02:00
Sebastien Boeuf
8ee0377456 tests: Update VFIO baremetal test to rely on Ubuntu 21.04
Moving to latest Ubuntu version as the guest image is needed to move to
more recent guest kernel (5.11). With more recent kernels, we'll be able
to add hotplug and virtio-mem tests to the VFIO baremetal CI.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-05-04 15:01:29 +02:00
dependabot[bot]
d42502fab9 build: Bump rustc-demangle from 0.1.18 to 0.1.19
Bumps [rustc-demangle](https://github.com/alexcrichton/rustc-demangle) from 0.1.18 to 0.1.19.
- [Release notes](https://github.com/alexcrichton/rustc-demangle/releases)
- [Commits](https://github.com/alexcrichton/rustc-demangle/compare/0.1.18...0.1.19)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-04 13:18:38 +01:00
dependabot[bot]
b534619d37 build: Bump syn from 1.0.71 to 1.0.72 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.71 to 1.0.72.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.71...1.0.72)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-04 13:18:05 +01:00
Rob Bradford
2aec0a92a5 tests: Don't test virtiofsd
The CI is failing due the git server that the submodules required for
this fork of QEMU need to build from is unavailable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-05-04 12:14:37 +01:00
dependabot[bot]
7c3b361fa6 build: Bump regex from 1.4.6 to 1.5.3
Bumps [regex](https://github.com/rust-lang/regex) from 1.4.6 to 1.5.3.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.4.6...1.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-03 14:11:59 +02:00
Rob Bradford
da8136e49d arch, vmm: Remove support for LinuxBoot
By supporting just PVH boot on x86-64 we simplify our boot path
substatially.

Fixes: #2231

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-04-30 16:16:48 +02:00
Rob Bradford
1f4a34ffc8 tests: Remove last tests using bzImage
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-04-30 16:16:48 +02:00
Mikko Ylinen
3b18caf229 sgx: update virt EPC device path and docs
The latest kvm-sgx code has renamed sgx_virt_epc device node
to sgx_vepc. Update cloud-hypervisor code and documentation to
follow this.

Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
2021-04-30 16:16:01 +02:00
dependabot[bot]
7ca4d40d49 build: Bump iced-x86 from 1.11.1 to 1.11.2
Bumps [iced-x86](https://github.com/icedland/iced) from 1.11.1 to 1.11.2.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.11.1...v1.11.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 16:15:34 +02:00
dependabot[bot]
d844f6113d build: Bump libz-sys from 1.1.2 to 1.1.3
Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/rust-lang/libz-sys/releases)
- [Commits](https://github.com/rust-lang/libz-sys/compare/1.1.2...1.1.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 16:15:20 +02:00
dependabot[bot]
8eb3aa56ca build: Bump iced-x86 from 1.11.1 to 1.11.2 in /fuzz
Bumps [iced-x86](https://github.com/icedland/iced) from 1.11.1 to 1.11.2.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.11.1...v1.11.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 16:15:05 +02:00
dependabot[bot]
f446a0f97f build: Bump unicode-xid from 0.2.1 to 0.2.2 in /fuzz
Bumps [unicode-xid](https://github.com/unicode-rs/unicode-xid) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/unicode-rs/unicode-xid/releases)
- [Commits](https://github.com/unicode-rs/unicode-xid/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 16:14:48 +02:00
dependabot-preview[bot]
e3efa9a5e2 build: Upgrade to GitHub-native Dependabot
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2021-04-29 18:56:06 +02:00
157 changed files with 6528 additions and 9404 deletions

18
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 3
allow:
- dependency-type: direct
- dependency-type: indirect
- package-ecosystem: cargo
directory: "/fuzz"
schedule:
interval: daily
open-pull-requests-limit: 3
allow:
- dependency-type: direct
- dependency-type: indirect

View File

@@ -29,8 +29,6 @@ jobs:
target: ${{ matrix.target }}
override: true
components: rustfmt, clippy
- name: Install arm64 libfdt
run: wget http://ftp.us.debian.org/debian/pool/main/d/device-tree-compiler/libfdt-dev_1.6.0-1_arm64.deb && dpkg-deb -xv libfdt-dev_1.6.0-1_arm64.deb ./tlibfdtdev && mkdir -p target/debug/deps && sudo cp ./tlibfdtdev/usr/lib/aarch64-linux-gnu/libfdt.a target/debug/deps/libfdt.a && echo "libfdt installed"
- name: Formatting (rustfmt)
run: cargo fmt -- --check
- name: Clippy (kvm)

449
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "cloud-hypervisor"
version = "15.0.0"
version = "16.0.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
default-run = "cloud-hypervisor"
@@ -19,13 +19,13 @@ clap = { version = "2.33.3", features = ["wrap_help"] }
epoll = "4.3.1"
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
libc = "0.2.94"
libc = "0.2.96"
log = { version = "0.4.14", features = ["std"] }
option_parser = { path = "option_parser" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.2" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.4" }
serde_json = "1.0.64"
signal-hook = "0.3.8"
thiserror = "1.0.24"
signal-hook = "0.3.9"
thiserror = "1.0.25"
vmm = { path = "vmm" }
vmm-sys-util = "0.8.0"
vm-memory = "0.5.0"
@@ -36,6 +36,8 @@ clap = { version = "2.33.3", features = ["wrap_help"] }
# List of patched crates
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
vm-memory = { git = "https://github.com/rust-vmm/vm-memory", rev = "5bd7138758183a73ac0da27ce40c004d95f1a7e9"}
[dev-dependencies]
credibility = "0.1.3"
@@ -66,7 +68,6 @@ members = [
"acpi_tables",
"api_client",
"arch",
"arch_gen",
"block_util",
"devices",
"event_monitor",

15
Jenkinsfile vendored
View File

@@ -46,6 +46,7 @@ pipeline{
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "sudo modprobe openvswitch"
sh "scripts/dev_cli.sh tests --integration"
}
}
@@ -69,6 +70,7 @@ pipeline{
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "sudo modprobe openvswitch"
sh "scripts/dev_cli.sh tests --integration"
}
}
@@ -98,6 +100,7 @@ pipeline{
timeout(time: 1, unit: 'HOURS')
}
steps {
sh "sudo modprobe openvswitch"
sh "scripts/dev_cli.sh tests --integration --libc musl"
}
}
@@ -105,7 +108,10 @@ pipeline{
}
stage ('Worker build SGX') {
agent { node { label 'bionic-sgx' } }
when { branch 'master' }
when {
beforeAgent true
branch 'master'
}
stages {
stage ('Checkout') {
steps {
@@ -138,7 +144,10 @@ pipeline{
}
stage ('Worker build VFIO') {
agent { node { label 'bionic-vfio' } }
when { branch 'master' }
when {
beforeAgent true
branch 'master'
}
stages {
stage ('Checkout') {
steps {
@@ -170,7 +179,7 @@ pipeline{
}
}
stage ('Worker build - Windows guest') {
agent { node { label 'groovy-win' } }
agent { node { label 'groovy' } }
stages {
stage ('Checkout') {
steps {

View File

@@ -205,7 +205,7 @@ $ popd
#### Booting the guest VM
Now we can directly boot into our custom kernel and make it use the Ubuntu root partition.
If we want to have 4 vCPUs and 512 MBytes of memory:
If we want to have 4 vCPUs and 1024 MBytes of memory:
```shell
$ pushd $CLOUDH

View File

@@ -6,4 +6,3 @@ edition = "2018"
[dependencies]
vm-memory = "0.5.0"

View File

@@ -22,6 +22,15 @@ impl GenericAddress {
address: u64::from(address),
}
}
pub fn mmio_address<T>(address: u64) -> Self {
GenericAddress {
address_space_id: 0,
register_bit_width: 8 * std::mem::size_of::<T>() as u8,
register_bit_offset: 0,
access_size: std::mem::size_of::<T>() as u8,
address,
}
}
}
pub struct Sdt {

View File

@@ -2,6 +2,7 @@
name = "arch"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
[features]
default = []
@@ -11,16 +12,16 @@ tdx = []
[dependencies]
acpi_tables = { path = "../acpi_tables", optional = true }
anyhow = "1.0"
arch_gen = { path = "../arch_gen" }
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
libc = "0.2.94"
libc = "0.2.96"
linux-loader = { version = "0.3.0", features = ["elf", "bzimage", "pe"] }
log = "0.4.14"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
thiserror = "1.0"
vm-memory = { version = "0.5.0", features = ["backend-mmap"] }
versionize = "0.1.6"
versionize_derive = "0.1.4"
vm-fdt = { git = "https://github.com/rust-vmm/vm-fdt", branch = "master" }
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }

View File

@@ -6,23 +6,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
use libc::{c_char, c_int, c_void};
use std::collections::HashMap;
use std::ffi::{CStr, CString, NulError};
use std::ffi::CStr;
use std::fmt::Debug;
use std::ptr::null;
use std::{io, result};
use std::result;
use super::super::DeviceType;
use super::super::GuestMemoryMmap;
use super::super::InitramfsConfig;
use super::get_fdt_addr;
use super::gic::GicDevice;
use super::layout::{
FDT_MAX_SIZE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, PCI_MMCONFIG_SIZE,
PCI_MMCONFIG_START,
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
PCI_HIGH_BASE, PCI_MMCONFIG_SIZE, PCI_MMCONFIG_START,
};
use crate::aarch64::fdt::Error::CstringFdtTransform;
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
use vm_fdt::{FdtWriter, FdtWriterResult};
use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
const GIC_PHANDLE: u32 = 1;
@@ -51,22 +50,6 @@ const IRQ_TYPE_LEVEL_HI: u32 = 4;
// System Power Down
const KEY_POWER: u32 = 116;
// This links to libfdt which handles the creation of the binary blob
// flattened device tree (fdt) that is passed to the kernel and indicates
// the hardware configuration of the machine.
#[link(name = "fdt")]
extern "C" {
fn fdt_create(buf: *mut c_void, bufsize: c_int) -> c_int;
fn fdt_finish_reservemap(fdt: *mut c_void) -> c_int;
fn fdt_begin_node(fdt: *mut c_void, name: *const c_char) -> c_int;
fn fdt_property(fdt: *mut c_void, name: *const c_char, val: *const c_void, len: c_int)
-> c_int;
fn fdt_end_node(fdt: *mut c_void) -> c_int;
fn fdt_open_into(fdt: *const c_void, buf: *mut c_void, bufsize: c_int) -> c_int;
fn fdt_finish(fdt: *const c_void) -> c_int;
fn fdt_pack(fdt: *mut c_void) -> c_int;
}
/// Trait for devices to be added to the Flattened Device Tree.
pub trait DeviceInfoForFdt {
/// Returns the address where this device will be loaded.
@@ -80,16 +63,6 @@ pub trait DeviceInfoForFdt {
/// Errors thrown while configuring the Flattened Device Tree for aarch64.
#[derive(Debug)]
pub enum Error {
/// Failed to append node to the FDT.
AppendFdtNode(io::Error),
/// Failed to append a property to the FDT.
AppendFdtProperty(io::Error),
/// Syscall for creating FDT failed.
CreateFdt(io::Error),
/// Failed to obtain a C style string.
CstringFdtTransform(NulError),
/// Failure in calling syscall for terminating this FDT.
FinishFdtReserveMap(io::Error),
/// Failure in writing FDT in memory.
WriteFdtToMemory(GuestMemoryError),
}
@@ -104,29 +77,27 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
gic_device: &dyn GicDevice,
initrd: &Option<InitramfsConfig>,
pci_space_address: &(u64, u64),
) -> Result<Vec<u8>> {
) -> FdtWriterResult<Vec<u8>> {
// Allocate stuff necessary for the holding the blob.
let mut fdt = vec![0; FDT_MAX_SIZE];
allocate_fdt(&mut fdt)?;
let mut fdt = FdtWriter::new(&[]).unwrap();
// For an explanation why these nodes were introduced in the blob take a look at
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L845
// Look for "Required nodes and properties".
// Header or the root node as per above mentioned documentation.
append_begin_node(&mut fdt, "")?;
append_property_string(&mut fdt, "compatible", "linux,dummy-virt")?;
let root_node = fdt.begin_node("")?;
fdt.property_string("compatible", "linux,dummy-virt")?;
// For info on #address-cells and size-cells read "Note about cells and address representation"
// from the above mentioned txt file.
append_property_u32(&mut fdt, "#address-cells", ADDRESS_CELLS)?;
append_property_u32(&mut fdt, "#size-cells", SIZE_CELLS)?;
fdt.property_u32("#address-cells", ADDRESS_CELLS)?;
fdt.property_u32("#size-cells", SIZE_CELLS)?;
// This is not mandatory but we use it to point the root node to the node
// containing description of the interrupt controller for this VM.
append_property_u32(&mut fdt, "interrupt-parent", GIC_PHANDLE)?;
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
create_cpu_nodes(&mut fdt, &vcpu_mpidr)?;
create_memory_node(&mut fdt, guest_mem)?;
create_chosen_node(&mut fdt, cmdline, initrd)?;
create_chosen_node(&mut fdt, cmdline.to_str().unwrap(), initrd)?;
create_gic_node(&mut fdt, gic_device)?;
create_timer_node(&mut fdt)?;
create_clock_node(&mut fdt)?;
@@ -135,307 +106,136 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
create_pci_nodes(&mut fdt, pci_space_address.0, pci_space_address.1)?;
// End Header node.
append_end_node(&mut fdt)?;
fdt.end_node(root_node)?;
// Allocate another buffer so we can format and then write fdt to guest.
let mut fdt_final = vec![0; FDT_MAX_SIZE];
finish_fdt(&mut fdt, &mut fdt_final)?;
let fdt_final = fdt.finish()?;
// Write FDT to memory.
let fdt_address = GuestAddress(get_fdt_addr(&guest_mem));
guest_mem
.write_slice(fdt_final.as_slice(), fdt_address)
.map_err(Error::WriteFdtToMemory)?;
Ok(fdt_final)
}
// Following are auxiliary functions for allocating and finishing the FDT.
fn allocate_fdt(fdt: &mut Vec<u8>) -> Result<()> {
// Safe since we allocated this array with FDT_MAX_SIZE.
let mut fdt_ret = unsafe { fdt_create(fdt.as_mut_ptr() as *mut c_void, FDT_MAX_SIZE as c_int) };
if fdt_ret != 0 {
return Err(Error::CreateFdt(io::Error::last_os_error()));
}
// The flattened device trees created with fdt_create() contains a list of
// reserved memory areas. We need to call `fdt_finish_reservemap` so as to make sure that there is a
// terminator in the reservemap list and whatever happened to be at the
// start of the FDT data section would end up being interpreted as
// reservemap entries.
// Safe since we previously allocated this array.
fdt_ret = unsafe { fdt_finish_reservemap(fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
pub fn write_fdt_to_memory(fdt_final: Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
// Write FDT to memory.
let fdt_address = GuestAddress(get_fdt_addr());
guest_mem
.write_slice(fdt_final.as_slice(), fdt_address)
.map_err(Error::WriteFdtToMemory)?;
Ok(())
}
fn finish_fdt(from_fdt: &mut Vec<u8>, to_fdt: &mut Vec<u8>) -> Result<()> {
// Safe since we allocated `fdt_final` and previously passed in its size.
let mut fdt_ret = unsafe { fdt_finish(from_fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
// Safe because we allocated both arrays with the correct size.
fdt_ret = unsafe {
fdt_open_into(
from_fdt.as_mut_ptr() as *mut c_void,
to_fdt.as_mut_ptr() as *mut c_void,
FDT_MAX_SIZE as i32,
)
};
if fdt_ret != 0 {
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
// Safe since we allocated `to_fdt`.
fdt_ret = unsafe { fdt_pack(to_fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::FinishFdtReserveMap(io::Error::last_os_error()));
}
Ok(())
}
// Following are auxiliary functions for appending nodes to FDT.
fn append_begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt and converted name to a CString
let fdt_ret = unsafe { fdt_begin_node(fdt.as_mut_ptr() as *mut c_void, cstr_name.as_ptr()) };
if fdt_ret != 0 {
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
}
Ok(())
}
fn append_end_node(fdt: &mut Vec<u8>) -> Result<()> {
// Safe because we allocated fdt.
let fdt_ret = unsafe { fdt_end_node(fdt.as_mut_ptr() as *mut c_void) };
if fdt_ret != 0 {
return Err(Error::AppendFdtNode(io::Error::last_os_error()));
}
Ok(())
}
// Following are auxiliary functions for appending property nodes to the nodes of the FDT.
fn append_property_u32(fdt: &mut Vec<u8>, name: &str, val: u32) -> Result<()> {
append_property(fdt, name, &to_be32(val))
}
fn append_property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<()> {
append_property(fdt, name, &to_be64(val))
}
fn append_property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<()> {
let cstr_value = CString::new(value).map_err(CstringFdtTransform)?;
append_property_cstring(fdt, name, &cstr_value)
}
fn append_property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) -> Result<()> {
let value_bytes = cstr_value.to_bytes_with_nul();
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt, converted name and value to CStrings
let fdt_ret = unsafe {
fdt_property(
fdt.as_mut_ptr() as *mut c_void,
cstr_name.as_ptr(),
value_bytes.as_ptr() as *mut c_void,
value_bytes.len() as i32,
)
};
if fdt_ret != 0 {
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
fn append_property_null(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
// Safe because we allocated fdt, converted name to a CString
let fdt_ret = unsafe {
fdt_property(
fdt.as_mut_ptr() as *mut c_void,
cstr_name.as_ptr(),
null(),
0,
)
};
if fdt_ret != 0 {
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
fn append_property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<()> {
let cstr_name = CString::new(name).map_err(CstringFdtTransform)?;
let val_ptr = val.as_ptr() as *const c_void;
// Safe because we allocated fdt and converted name to a CString
let fdt_ret = unsafe {
fdt_property(
fdt.as_mut_ptr() as *mut c_void,
cstr_name.as_ptr(),
val_ptr,
val.len() as i32,
)
};
if fdt_ret != 0 {
return Err(Error::AppendFdtProperty(io::Error::last_os_error()));
}
Ok(())
}
// Auxiliary functions for writing u32/u64 numbers in big endian order.
fn to_be32(input: u32) -> [u8; 4] {
u32::to_be_bytes(input)
}
fn to_be64(input: u64) -> [u8; 8] {
u64::to_be_bytes(input)
}
// Helper functions for generating a properly formatted byte vector using 32-bit/64-bit cells.
fn generate_prop32(cells: &[u32]) -> Vec<u8> {
let mut ret: Vec<u8> = Vec::new();
for &e in cells {
ret.extend(to_be32(e).iter());
}
ret
}
fn generate_prop64(cells: &[u64]) -> Vec<u8> {
let mut ret: Vec<u8> = Vec::new();
for &e in cells {
ret.extend(to_be64(e).iter());
}
ret
}
// Following are the auxiliary function for creating the different nodes that we append to our FDT.
fn create_cpu_nodes(fdt: &mut Vec<u8>, vcpu_mpidr: &[u64]) -> Result<()> {
fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_mpidr: &[u64]) -> FdtWriterResult<()> {
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/arm/cpus.yaml.
append_begin_node(fdt, "cpus")?;
// As per documentation, on ARM v8 64-bit systems value should be set to 2.
append_property_u32(fdt, "#address-cells", 0x02)?;
append_property_u32(fdt, "#size-cells", 0x0)?;
let cpus_node = fdt.begin_node("cpus")?;
fdt.property_u32("#address-cells", 0x1)?;
fdt.property_u32("#size-cells", 0x0)?;
let num_cpus = vcpu_mpidr.len();
for (cpu_index, mpidr) in vcpu_mpidr.iter().enumerate().take(num_cpus) {
let cpu_name = format!("cpu@{:x}", cpu_index);
append_begin_node(fdt, &cpu_name)?;
append_property_string(fdt, "device_type", "cpu")?;
append_property_string(fdt, "compatible", "arm,arm-v8")?;
for cpu_id in 0..num_cpus {
let cpu_name = format!("cpu@{:x}", cpu_id);
let cpu_node = fdt.begin_node(&cpu_name)?;
fdt.property_string("device_type", "cpu")?;
fdt.property_string("compatible", "arm,arm-v8")?;
if num_cpus > 1 {
// This is required on armv8 64-bit. See aforementioned documentation.
append_property_string(fdt, "enable-method", "psci")?;
fdt.property_string("enable-method", "psci")?;
}
// Set the field to first 24 bits of the MPIDR - Multiprocessor Affinity Register.
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488c/BABHBJCI.html.
append_property_u64(fdt, "reg", mpidr & 0x7FFFFF)?;
append_end_node(fdt)?;
fdt.property_u32("reg", cpu_id as u32)?;
fdt.end_node(cpu_node)?;
}
append_end_node(fdt)?;
fdt.end_node(cpus_node)?;
Ok(())
}
fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemoryMmap) -> Result<()> {
fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> FdtWriterResult<()> {
let mem_size = guest_mem.last_addr().raw_value() - super::layout::RAM_64BIT_START + 1;
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
// for an explanation of this.
let mem_reg_prop = generate_prop64(&[super::layout::RAM_64BIT_START as u64, mem_size as u64]);
let mem_reg_prop = [super::layout::RAM_64BIT_START as u64, mem_size as u64];
let memory_node = fdt.begin_node("memory")?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_prop)?;
fdt.end_node(memory_node)?;
append_begin_node(fdt, "memory")?;
append_property_string(fdt, "device_type", "memory")?;
append_property(fdt, "reg", &mem_reg_prop)?;
append_end_node(fdt)?;
Ok(())
}
fn create_chosen_node(
fdt: &mut Vec<u8>,
cmdline: &CStr,
fdt: &mut FdtWriter,
cmdline: &str,
initrd: &Option<InitramfsConfig>,
) -> Result<()> {
append_begin_node(fdt, "chosen")?;
append_property_cstring(fdt, "bootargs", cmdline)?;
) -> FdtWriterResult<()> {
let chosen_node = fdt.begin_node("chosen")?;
fdt.property_string("bootargs", cmdline)?;
if let Some(initrd_config) = initrd {
append_property_u64(
fdt,
"linux,initrd-start",
initrd_config.address.raw_value() as u64,
)?;
append_property_u64(
fdt,
"linux,initrd-end",
initrd_config.address.raw_value() + initrd_config.size as u64,
)?;
let initrd_start = initrd_config.address.raw_value() as u64;
let initrd_end = initrd_config.address.raw_value() + initrd_config.size as u64;
fdt.property_u64("linux,initrd-start", initrd_start)?;
fdt.property_u64("linux,initrd-end", initrd_end)?;
}
append_end_node(fdt)?;
fdt.end_node(chosen_node)?;
Ok(())
}
fn create_gic_node(fdt: &mut Vec<u8>, gic_device: &dyn GicDevice) -> Result<()> {
let gic_reg_prop = generate_prop64(gic_device.device_properties());
fn create_gic_node(fdt: &mut FdtWriter, gic_device: &dyn GicDevice) -> FdtWriterResult<()> {
let gic_reg_prop = gic_device.device_properties();
append_begin_node(fdt, "intc")?;
append_property_string(fdt, "compatible", gic_device.fdt_compatibility())?;
append_property_null(fdt, "interrupt-controller")?;
let intc_node = fdt.begin_node("intc")?;
fdt.property_string("compatible", gic_device.fdt_compatibility())?;
fdt.property_null("interrupt-controller")?;
// "interrupt-cells" field specifies the number of cells needed to encode an
// interrupt source. The type shall be a <u32> and the value shall be 3 if no PPI affinity description
// is required.
append_property_u32(fdt, "#interrupt-cells", 3)?;
append_property(fdt, "reg", &gic_reg_prop)?;
append_property_u32(fdt, "phandle", GIC_PHANDLE)?;
append_property_u32(fdt, "#address-cells", 2)?;
append_property_u32(fdt, "#size-cells", 2)?;
append_property_null(fdt, "ranges")?;
let gic_intr = [
fdt.property_u32("#interrupt-cells", 3)?;
fdt.property_array_u64("reg", &gic_reg_prop)?;
fdt.property_u32("phandle", GIC_PHANDLE)?;
fdt.property_u32("#address-cells", 2)?;
fdt.property_u32("#size-cells", 2)?;
fdt.property_null("ranges")?;
let gic_intr_prop = [
GIC_FDT_IRQ_TYPE_PPI,
gic_device.fdt_maint_irq(),
IRQ_TYPE_LEVEL_HI,
];
let gic_intr_prop = generate_prop32(&gic_intr);
append_property(fdt, "interrupts", &gic_intr_prop)?;
fdt.property_array_u32("interrupts", &gic_intr_prop)?;
if gic_device.msi_compatible() {
append_begin_node(fdt, "msic")?;
append_property_string(fdt, "compatible", gic_device.msi_compatibility())?;
append_property_null(fdt, "msi-controller")?;
append_property_u32(fdt, "phandle", MSI_PHANDLE)?;
let msi_reg_prop = generate_prop64(gic_device.msi_properties());
append_property(fdt, "reg", &msi_reg_prop)?;
append_end_node(fdt)?;
let msic_node = fdt.begin_node("msic")?;
fdt.property_string("compatible", gic_device.msi_compatibility())?;
fdt.property_null("msi-controller")?;
fdt.property_u32("phandle", MSI_PHANDLE)?;
let msi_reg_prop = gic_device.msi_properties();
fdt.property_array_u64("reg", &msi_reg_prop)?;
fdt.end_node(msic_node)?;
}
append_end_node(fdt)?;
fdt.end_node(intc_node)?;
Ok(())
}
fn create_clock_node(fdt: &mut Vec<u8>) -> Result<()> {
fn create_clock_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
// The Advanced Peripheral Bus (APB) is part of the Advanced Microcontroller Bus Architecture
// (AMBA) protocol family. It defines a low-cost interface that is optimized for minimal power
// consumption and reduced interface complexity.
// PCLK is the clock source and this node defines exactly the clock for the APB.
append_begin_node(fdt, "apb-pclk")?;
append_property_string(fdt, "compatible", "fixed-clock")?;
append_property_u32(fdt, "#clock-cells", 0x0)?;
append_property_u32(fdt, "clock-frequency", 24000000)?;
append_property_string(fdt, "clock-output-names", "clk24mhz")?;
append_property_u32(fdt, "phandle", CLOCK_PHANDLE)?;
append_end_node(fdt)?;
let clock_node = fdt.begin_node("apb-pclk")?;
fdt.property_string("compatible", "fixed-clock")?;
fdt.property_u32("#clock-cells", 0x0)?;
fdt.property_u32("clock-frequency", 24000000)?;
fdt.property_string("clock-output-names", "clk24mhz")?;
fdt.property_u32("phandle", CLOCK_PHANDLE)?;
fdt.end_node(clock_node)?;
Ok(())
}
fn create_timer_node(fdt: &mut Vec<u8>) -> Result<()> {
fn create_timer_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
// See
// https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/interrupt-controller/arch_timer.txt
// These are fixed interrupt numbers for the timer device.
@@ -448,123 +248,136 @@ fn create_timer_node(fdt: &mut Vec<u8>) -> Result<()> {
timer_reg_cells.push(irq);
timer_reg_cells.push(IRQ_TYPE_LEVEL_HI);
}
let timer_reg_prop = generate_prop32(timer_reg_cells.as_slice());
append_begin_node(fdt, "timer")?;
append_property_string(fdt, "compatible", compatible)?;
append_property_null(fdt, "always-on")?;
append_property(fdt, "interrupts", &timer_reg_prop)?;
append_end_node(fdt)?;
let timer_node = fdt.begin_node("timer")?;
fdt.property_string("compatible", compatible)?;
fdt.property_null("always-on")?;
fdt.property_array_u32("interrupts", &timer_reg_cells)?;
fdt.end_node(timer_node)?;
Ok(())
}
fn create_psci_node(fdt: &mut Vec<u8>) -> Result<()> {
fn create_psci_node(fdt: &mut FdtWriter) -> FdtWriterResult<()> {
let compatible = "arm,psci-0.2";
append_begin_node(fdt, "psci")?;
append_property_string(fdt, "compatible", compatible)?;
let psci_node = fdt.begin_node("psci")?;
fdt.property_string("compatible", compatible)?;
// Two methods available: hvc and smc.
// As per documentation, PSCI calls between a guest and hypervisor may use the HVC conduit instead of SMC.
// So, since we are using kvm, we need to use hvc.
append_property_string(fdt, "method", "hvc")?;
append_end_node(fdt)?;
fdt.property_string("method", "hvc")?;
fdt.end_node(psci_node)?;
Ok(())
}
fn create_virtio_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
fdt: &mut FdtWriter,
dev_info: &T,
) -> Result<()> {
let device_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
) -> FdtWriterResult<()> {
let device_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING];
append_begin_node(fdt, &format!("virtio_mmio@{:x}", dev_info.addr()))?;
append_property_string(fdt, "compatible", "virtio,mmio")?;
append_property(fdt, "reg", &device_reg_prop)?;
append_property(fdt, "interrupts", &irq)?;
append_property_u32(fdt, "interrupt-parent", GIC_PHANDLE)?;
append_end_node(fdt)?;
let virtio_node = fdt.begin_node(&format!("virtio_mmio@{:x}", dev_info.addr()))?;
fdt.property_string("compatible", "virtio,mmio")?;
fdt.property_array_u64("reg", &device_reg_prop)?;
fdt.property_array_u32("interrupts", &irq)?;
fdt.property_u32("interrupt-parent", GIC_PHANDLE)?;
fdt.end_node(virtio_node)?;
Ok(())
}
fn create_serial_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
fdt: &mut FdtWriter,
dev_info: &T,
) -> Result<()> {
) -> FdtWriterResult<()> {
let compatible = b"arm,pl011\0arm,primecell\0";
let serial_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
let serial_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_EDGE_RISING,
];
append_begin_node(fdt, &format!("pl011@{:x}", dev_info.addr()))?;
append_property(fdt, "compatible", compatible)?;
append_property(fdt, "reg", &serial_reg_prop)?;
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
append_property_string(fdt, "clock-names", "apb_pclk")?;
append_property(fdt, "interrupts", &irq)?;
append_end_node(fdt)?;
let serial_node = fdt.begin_node(&format!("pl011@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;
fdt.property_array_u64("reg", &serial_reg_prop)?;
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
fdt.property_string("clock-names", "apb_pclk")?;
fdt.property_array_u32("interrupts", &irq)?;
fdt.end_node(serial_node)?;
Ok(())
}
fn create_rtc_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
fdt: &mut FdtWriter,
dev_info: &T,
) -> Result<()> {
) -> FdtWriterResult<()> {
let compatible = b"arm,pl031\0arm,primecell\0";
let rtc_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_LEVEL_HI]);
append_begin_node(fdt, &format!("rtc@{:x}", dev_info.addr()))?;
append_property(fdt, "compatible", compatible)?;
append_property(fdt, "reg", &rtc_reg_prop)?;
append_property(fdt, "interrupts", &irq)?;
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
append_property_string(fdt, "clock-names", "apb_pclk")?;
append_end_node(fdt)?;
let rtc_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_LEVEL_HI,
];
let rtc_node = fdt.begin_node(&format!("rtc@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;
fdt.property_array_u64("reg", &rtc_reg_prop)?;
fdt.property_array_u32("interrupts", &irq)?;
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
fdt.property_string("clock-names", "apb_pclk")?;
fdt.end_node(rtc_node)?;
Ok(())
}
fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
fdt: &mut Vec<u8>,
fdt: &mut FdtWriter,
dev_info: &T,
) -> Result<()> {
) -> FdtWriterResult<()> {
// PL061 GPIO controller node
let compatible = b"arm,pl061\0arm,primecell\0";
let gpio_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
append_begin_node(fdt, &format!("pl061@{:x}", dev_info.addr()))?;
append_property(fdt, "compatible", compatible)?;
append_property(fdt, "reg", &gpio_reg_prop)?;
append_property(fdt, "interrupts", &irq)?;
append_property_null(fdt, "gpio-controller")?;
append_property_u32(fdt, "#gpio-cells", 2)?;
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
append_property_string(fdt, "clock-names", "apb_pclk")?;
append_property_u32(fdt, "phandle", GPIO_PHANDLE)?;
append_end_node(fdt)?;
let gpio_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_EDGE_RISING,
];
let gpio_node = fdt.begin_node(&format!("pl061@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;
fdt.property_array_u64("reg", &gpio_reg_prop)?;
fdt.property_array_u32("interrupts", &irq)?;
fdt.property_null("gpio-controller")?;
fdt.property_u32("#gpio-cells", 2)?;
fdt.property_u32("clocks", CLOCK_PHANDLE)?;
fdt.property_string("clock-names", "apb_pclk")?;
fdt.property_u32("phandle", GPIO_PHANDLE)?;
fdt.end_node(gpio_node)?;
// gpio-keys node
append_begin_node(fdt, "/gpio-keys")?;
append_property_string(fdt, "compatible", "gpio-keys")?;
append_property_u32(fdt, "#size-cells", 0)?;
append_property_u32(fdt, "#address-cells", 1)?;
append_begin_node(fdt, "/gpio-keys/poweroff")?;
append_property_string(fdt, "label", "GPIO Key Poweroff")?;
append_property_u32(fdt, "linux,code", KEY_POWER)?;
let gpios = generate_prop32(&[GPIO_PHANDLE, 3, 0]);
append_property(fdt, "gpios", &gpios)?;
append_end_node(fdt)?;
append_end_node(fdt)?;
let gpio_keys_node = fdt.begin_node("gpio-keys")?;
fdt.property_string("compatible", "gpio-keys")?;
fdt.property_u32("#size-cells", 0)?;
fdt.property_u32("#address-cells", 1)?;
let gpio_keys_poweroff_node = fdt.begin_node("button@1")?;
fdt.property_string("label", "GPIO Key Poweroff")?;
fdt.property_u32("linux,code", KEY_POWER)?;
let gpios = [GPIO_PHANDLE, 3, 0];
fdt.property_array_u32("gpios", &gpios)?;
fdt.end_node(gpio_keys_poweroff_node)?;
fdt.end_node(gpio_keys_node)?;
Ok(())
}
fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
fdt: &mut Vec<u8>,
fdt: &mut FdtWriter,
dev_info: &HashMap<(DeviceType, String), T, S>,
) -> Result<()> {
) -> FdtWriterResult<()> {
// Create one temp Vec to store all virtio devices
let mut ordered_virtio_device: Vec<&T> = Vec::new();
@@ -592,11 +405,40 @@ fn create_devices_node<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Buil
Ok(())
}
fn create_pci_nodes(fdt: &mut Vec<u8>, pci_device_base: u64, pci_device_size: u64) -> Result<()> {
fn create_pci_nodes(
fdt: &mut FdtWriter,
pci_device_base: u64,
pci_device_size: u64,
) -> FdtWriterResult<()> {
// Add node for PCIe controller.
// See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
// and https://elinux.org/Device_Tree_Usage.
let ranges = generate_prop32(&[
// EDK2 requires the PCIe high space above 4G address.
// The actual space in CLH follows the RAM. If the RAM space is small, the PCIe high space
// could fall bellow 4G.
// Here we put it above 512G in FDT to workaround the EDK2 check.
// But the address written in ACPI is not impacted.
let pci_device_base_64bit: u64 = if cfg!(feature = "acpi") {
pci_device_base + PCI_HIGH_BASE
} else {
pci_device_base
};
let pci_device_size_64bit: u64 = if cfg!(feature = "acpi") {
pci_device_size - PCI_HIGH_BASE
} else {
pci_device_size
};
let ranges = [
// io addresses
0x1000000,
0_u32,
0_u32,
(MEM_PCI_IO_START.0 >> 32) as u32,
MEM_PCI_IO_START.0 as u32,
(MEM_PCI_IO_SIZE >> 32) as u32,
MEM_PCI_IO_SIZE as u32,
// mmio addresses
0x2000000, // (ss = 10: 32-bit memory space)
(MEM_32BIT_DEVICES_START.0 >> 32) as u32, // PCI address
@@ -606,31 +448,31 @@ fn create_pci_nodes(fdt: &mut Vec<u8>, pci_device_base: u64, pci_device_size: u6
(MEM_32BIT_DEVICES_SIZE >> 32) as u32, // size
MEM_32BIT_DEVICES_SIZE as u32,
// device addresses
0x3000000, // (ss = 11: 64-bit memory space)
(pci_device_base >> 32) as u32, // PCI address
pci_device_base as u32,
(pci_device_base >> 32) as u32, // CPU address
pci_device_base as u32,
(pci_device_size >> 32) as u32, // size
pci_device_size as u32,
]);
let bus_range = generate_prop32(&[0, 0]); // Only bus 0
let reg = generate_prop64(&[PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE]);
0x3000000, // (ss = 11: 64-bit memory space)
(pci_device_base_64bit >> 32) as u32, // PCI address
pci_device_base_64bit as u32,
(pci_device_base_64bit >> 32) as u32, // CPU address
pci_device_base_64bit as u32,
(pci_device_size_64bit >> 32) as u32, // size
pci_device_size_64bit as u32,
];
let bus_range = [0, 0]; // Only bus 0
let reg = [PCI_MMCONFIG_START.0, PCI_MMCONFIG_SIZE];
append_begin_node(fdt, "pci")?;
append_property_string(fdt, "compatible", "pci-host-ecam-generic")?;
append_property_string(fdt, "device_type", "pci")?;
append_property(fdt, "ranges", &ranges)?;
append_property(fdt, "bus-range", &bus_range)?;
append_property_u32(fdt, "#address-cells", 3)?;
append_property_u32(fdt, "#size-cells", 2)?;
append_property(fdt, "reg", &reg)?;
append_property_u32(fdt, "#interrupt-cells", 1)?;
append_property_null(fdt, "interrupt-map")?;
append_property_null(fdt, "interrupt-map-mask")?;
append_property_null(fdt, "dma-coherent")?;
append_property_u32(fdt, "msi-parent", MSI_PHANDLE)?;
append_end_node(fdt)?;
let pci_node = fdt.begin_node("pci")?;
fdt.property_string("compatible", "pci-host-ecam-generic")?;
fdt.property_string("device_type", "pci")?;
fdt.property_array_u32("ranges", &ranges)?;
fdt.property_array_u32("bus-range", &bus_range)?;
fdt.property_u32("#address-cells", 3)?;
fdt.property_u32("#size-cells", 2)?;
fdt.property_array_u64("reg", &reg)?;
fdt.property_u32("#interrupt-cells", 1)?;
fdt.property_null("interrupt-map")?;
fdt.property_null("interrupt-map-mask")?;
fdt.property_null("dma-coherent")?;
fdt.property_u32("msi-parent", MSI_PHANDLE)?;
fdt.end_node(pci_node)?;
Ok(())
}

View File

@@ -5,17 +5,23 @@ pub mod kvm {
use crate::aarch64::gic::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
use crate::aarch64::gic::icc_regs::{get_icc_regs, set_icc_regs};
use crate::aarch64::gic::kvm::{save_pending_tables, KvmGicDevice};
use crate::aarch64::gic::redist_regs::{get_redist_regs, set_redist_regs};
use crate::aarch64::gic::redist_regs::{
construct_gicr_typers, get_redist_regs, set_redist_regs,
};
use crate::aarch64::gic::GicDevice;
use crate::layout;
use anyhow::anyhow;
use hypervisor::kvm::kvm_bindings;
use hypervisor::CpuState;
use std::any::Any;
use std::convert::TryInto;
use std::sync::Arc;
use std::{boxed::Box, result};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable,
VersionMapped,
};
/// Errors thrown while saving/restoring the GICv3.
@@ -57,7 +63,7 @@ pub mod kvm {
vcpu_count: u64,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
pub struct Gicv3State {
dist: Vec<u32>,
rdist: Vec<u32>,
@@ -66,6 +72,8 @@ pub mod kvm {
gicd_ctlr: u32,
}
impl VersionMapped for Gicv3State {}
impl KvmGicV3 {
// Unfortunately bindgen omits defines that are based on other defines.
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
@@ -160,7 +168,8 @@ pub mod kvm {
self.vcpu_count
}
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>) {
fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]) {
let gicr_typers = construct_gicr_typers(vcpu_states);
self.gicr_typers = gicr_typers;
}
@@ -229,12 +238,12 @@ pub mod kvm {
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let gicr_typers = self.gicr_typers.clone();
Snapshot::new_from_state(&self.id(), &self.state(&gicr_typers).unwrap())
Snapshot::new_from_versioned_state(&self.id(), &self.state(&gicr_typers).unwrap())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
let gicr_typers = self.gicr_typers.clone();
self.set_state(&gicr_typers, &snapshot.to_state(&self.id())?)
self.set_state(&gicr_typers, &snapshot.to_versioned_state(&self.id())?)
.map_err(|e| {
MigratableError::Restore(anyhow!("Could not restore GICv3 state {:?}", e))
})

View File

@@ -10,6 +10,7 @@ pub mod kvm {
use crate::aarch64::gic::kvm::KvmGicDevice;
use crate::aarch64::gic::{Error, GicDevice};
use hypervisor::kvm::kvm_bindings;
use hypervisor::CpuState;
pub struct KvmGicV3Its {
/// The hypervisor agnostic device
@@ -70,7 +71,7 @@ pub mod kvm {
self.vcpu_count
}
fn set_gicr_typers(&mut self, _gicr_typers: Vec<u64>) {}
fn set_gicr_typers(&mut self, _vcpu_states: &[CpuState]) {}
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
self

View File

@@ -10,6 +10,7 @@ pub mod redist_regs;
pub use self::dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
pub use self::icc_regs::{get_icc_regs, set_icc_regs};
pub use self::redist_regs::{get_redist_regs, set_redist_regs};
use hypervisor::CpuState;
use std::any::Any;
use std::result;
use std::sync::Arc;
@@ -58,7 +59,7 @@ pub trait GicDevice: Send {
}
/// Get the values of GICR_TYPER for each vCPU.
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>);
fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]);
/// Downcast the trait object to its concrete type.
fn as_any_concrete_mut(&mut self) -> &mut dyn Any;
@@ -149,7 +150,7 @@ pub mod kvm {
/* We need to tell the kernel how many irqs to support with this vgic.
* See the `layout` module for details.
*/
let nr_irqs: u32 = layout::IRQ_MAX - layout::IRQ_BASE + 1;
let nr_irqs: u32 = layout::IRQ_NUM;
let nr_irqs_ptr = &nr_irqs as *const u32;
Self::set_device_attribute(
gic_device.device(),

View File

@@ -3,6 +3,7 @@
use super::{Error, Result};
use hypervisor::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS};
use hypervisor::CpuState;
use std::sync::Arc;
// Relevant redistributor registers that we want to save/restore.
@@ -177,3 +178,34 @@ pub fn set_redist_regs(
true,
)
}
pub fn construct_gicr_typers(vcpu_states: &[CpuState]) -> Vec<u64> {
/* Pre-construct the GICR_TYPER:
* For our implementation:
* Top 32 bits are the affinity value of the associated CPU
* CommonLPIAff == 01 (redistributors with same Aff3 share LPI table)
* Processor_Number == CPU index starting from 0
* DPGS == 0 (GICR_CTLR.DPG* not supported)
* Last == 1 if this is the last redistributor in a series of
* contiguous redistributor pages
* DirectLPI == 0 (direct injection of LPIs not supported)
* VLPIS == 0 (virtual LPIs not supported)
* PLPIS == 0 (physical LPIs not supported)
*/
let mut gicr_typers: Vec<u64> = Vec::new();
for (index, state) in vcpu_states.iter().enumerate() {
let last = {
if index == vcpu_states.len() - 1 {
1
} else {
0
}
};
//calculate affinity
let mut cpu_affid = state.mpidr & 1095233437695;
cpu_affid = ((cpu_affid & 0xFF00000000) >> 8) | (cpu_affid & 0xFFFFFF);
gicr_typers.push((cpu_affid << 32) | (1 << 24) | (index as u64) << 8 | (last << 4));
}
gicr_typers
}

View File

@@ -36,7 +36,7 @@
// | |
// 144 M +---------------------------------------------------------------|
// | Reserved (now GIC is here) |
// 128 M +---------------------------------------------------------------+
// 64 M +---------------------------------------------------------------+
// | |
// | UEFI space |
// | |
@@ -46,26 +46,23 @@
use vm_memory::GuestAddress;
/// 0x0 ~ 0x800_0000 is reserved to uefi
/// 0x0 ~ 0x400_0000 is reserved to uefi
pub const UEFI_START: u64 = 0x0;
pub const MEM_UEFI_START: GuestAddress = GuestAddress(0);
pub const UEFI_SIZE: u64 = 0x0800_0000;
pub const UEFI_SIZE: u64 = 0x0400_0000;
/// Below this address will reside the GIC, above this address will reside the MMIO devices.
pub const MAPPED_IO_START: u64 = 0x0900_0000;
/// Space 0x0900_0000 ~ 0x1000_0000 is reserved for legacy devices.
/// Space 0x0900_0000 ~ 0x0905_0000 is reserved for legacy devices.
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
/// Space 0x0902_0000 ~ 0x903_0000 is reserved for pcie io address
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0902_0000);
/// Space 0x0905_0000 ~ 0x0906_0000 is reserved for pcie io address
pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0905_0000);
pub const MEM_PCI_IO_SIZE: u64 = 0x10000;
/// Legacy space will be allocated at once whiling setting up legacy devices.
pub const LEGACY_DEVICES_MAPPED_IO_SIZE: u64 = 0x0700_0000;
/// Starting from 0x1000_0000 (256MiB) to 0x3000_0000 (768MiB) is used for PCIE MMIO
pub const MEM_32BIT_DEVICES_START: GuestAddress = GuestAddress(0x1000_0000);
pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x2000_0000;
@@ -81,21 +78,30 @@ pub const RAM_64BIT_START: u64 = 0x4000_0000;
/// As per `arch/arm64/include/uapi/asm/setup.h`.
pub const CMDLINE_MAX_SIZE: usize = 2048;
/// FDT is at the beginning of RAM.
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
pub const FDT_START: u64 = RAM_64BIT_START;
pub const FDT_MAX_SIZE: usize = 0x20_0000;
/// Put ACPI table above dtb
pub const ACPI_START: u64 = RAM_64BIT_START + FDT_MAX_SIZE as u64;
pub const ACPI_MAX_SIZE: usize = 0x20_0000;
pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START);
/// Kernel start after FDT and ACPI
pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
/// Pci high memory base
pub const PCI_HIGH_BASE: u64 = 0x80_0000_0000_u64;
// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need
// the number of interrupts our GIC will support to be:
// * bigger than 32
// * less than 1023 and
// * a multiple of 32.
// We are setting up our interrupt controller to support a maximum of 256 interrupts.
/// First usable interrupt on aarch64.
pub const IRQ_BASE: u32 = 0;
/// First usable interrupt on aarch64
pub const IRQ_BASE: u32 = 32;
/// Last usable interrupt on aarch64.
pub const IRQ_MAX: u32 = 255;
/// Number of supported interrupts
pub const IRQ_NUM: u32 = 256;

View File

@@ -10,25 +10,31 @@ pub mod gic;
pub mod layout;
/// Logic for configuring aarch64 registers.
pub mod regs;
/// Module for loading UEFI binary.
pub mod uefi;
pub use self::fdt::DeviceInfoForFdt;
use crate::DeviceType;
use crate::GuestMemoryMmap;
use crate::RegionType;
use aarch64::gic::GicDevice;
use gic::GicDevice;
use std::collections::HashMap;
use std::convert::TryInto;
use std::ffi::CStr;
use std::fmt::Debug;
use std::sync::Arc;
use vm_memory::{
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
GuestUsize,
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestUsize,
};
/// Errors thrown while configuring aarch64 system.
#[derive(Debug)]
pub enum Error {
/// Failed to create a FDT.
SetupFdt(fdt::Error),
SetupFdt,
/// Failed to write FDT to memory.
WriteFdtToMemory(fdt::Error),
/// Failed to create a GIC.
SetupGic(gic::Error),
@@ -79,64 +85,78 @@ pub fn configure_vcpu(
}
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
// Normally UEFI should be loaded to a flash area at the beginning of memory.
// But now flash memory type is not supported.
// As a workaround, we take 64 MiB memory from the main RAM for UEFI.
// As a result, the RAM that the guest can see is less than what has been
// assigned in command line, when ACPI and UEFI is enabled.
let ram_deduction = if cfg!(feature = "acpi") {
layout::UEFI_SIZE
} else {
0
};
vec![
// 0 ~ 256 MiB: Reserved
// 0 ~ 64 MiB: Reserved for UEFI space
#[cfg(feature = "acpi")]
(GuestAddress(0), layout::UEFI_SIZE as usize, RegionType::Ram),
#[cfg(not(feature = "acpi"))]
(
GuestAddress(0),
layout::MEM_32BIT_DEVICES_START.0 as usize,
layout::UEFI_SIZE as usize,
RegionType::Reserved,
),
// 256 MiB ~ 1 G: MMIO space
// 64 MiB ~ 256 MiB: Gic and legacy devices
(
GuestAddress(layout::UEFI_SIZE),
(layout::MEM_32BIT_DEVICES_START.0 - layout::UEFI_SIZE) as usize,
RegionType::Reserved,
),
// 256 MiB ~ 768 MiB: MMIO space
(
layout::MEM_32BIT_DEVICES_START,
layout::MEM_32BIT_DEVICES_SIZE as usize,
RegionType::SubRegion,
),
// 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space
// 768 MiB ~ 1 GiB: reserved. The leading 256M for PCIe MMCONFIG space
(
layout::PCI_MMCONFIG_START,
(layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize,
layout::PCI_MMCONFIG_SIZE as usize,
RegionType::Reserved,
),
// 1 GiB ~ : Ram
(
GuestAddress(layout::RAM_64BIT_START),
size as usize,
(size - ram_deduction) as usize,
RegionType::Ram,
),
]
}
/// Configures the system and should be called once per vm before starting vcpu threads.
///
/// # Arguments
///
/// * `guest_mem` - The memory to be used by the guest.
/// * `num_cpus` - Number of virtual CPUs the guest will have.
#[allow(clippy::too_many_arguments)]
pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>(
vm: &Arc<dyn hypervisor::Vm>,
guest_mem: &GuestMemoryMmap,
cmdline_cstring: &CStr,
vcpu_count: u64,
vcpu_mpidr: Vec<u64>,
device_info: &HashMap<(DeviceType, String), T, S>,
initrd: &Option<super::InitramfsConfig>,
pci_space_address: &(u64, u64),
) -> super::Result<Box<dyn GicDevice>> {
let gic_device = gic::kvm::create_gic(vm, vcpu_count).map_err(Error::SetupGic)?;
fdt::create_fdt(
gic_device: &dyn GicDevice,
) -> super::Result<()> {
let fdt_final = fdt::create_fdt(
guest_mem,
cmdline_cstring,
vcpu_mpidr,
device_info,
&*gic_device,
gic_device,
initrd,
pci_space_address,
)
.map_err(Error::SetupFdt)?;
.map_err(|_| Error::SetupFdt)?;
Ok(gic_device)
fdt::write_fdt_to_memory(fdt_final, guest_mem).map_err(Error::WriteFdtToMemory)?;
Ok(())
}
/// Returns the memory address where the initramfs could be loaded.
@@ -145,8 +165,9 @@ pub fn initramfs_load_addr(
initramfs_size: usize,
) -> super::Result<u64> {
let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1);
match GuestAddress(get_fdt_addr(&guest_mem))
.checked_sub(round_to_pagesize(initramfs_size) as u64)
match guest_mem
.last_addr()
.checked_sub(round_to_pagesize(initramfs_size) as u64 - 1)
{
Some(offset) => {
if guest_mem.address_in_range(offset) {
@@ -161,41 +182,31 @@ pub fn initramfs_load_addr(
/// Returns the memory address where the kernel could be loaded.
pub fn get_kernel_start() -> u64 {
layout::RAM_64BIT_START
layout::KERNEL_START
}
///Return guest memory address where the uefi should be loaded.
pub fn get_uefi_start() -> u64 {
layout::UEFI_START
}
// Auxiliary function to get the address where the device tree blob is loaded.
fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 {
// If the memory allocated is smaller than the size allocated for the FDT,
// we return the start of the DRAM so that
// we allow the code to try and load the FDT.
if let Some(addr) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) {
if mem.address_in_range(addr) {
return addr.raw_value();
}
}
layout::RAM_64BIT_START
fn get_fdt_addr() -> u64 {
layout::FDT_START
}
pub fn get_host_cpu_phys_bits() -> u8 {
// The value returned here is used to determine the physical address space size
// for a VM (IPA size).
// In recent kernel versions, the maximum IPA size supported by the host can be
// known by querying cap KVM_CAP_ARM_VM_IPA_SIZE. And the IPA size for a
// guest can be configured smaller.
// But in Cloud-Hypervisor we simply use the maximum value for the VM.
// Reference https://lwn.net/Articles/766767/.
//
// The correct way to query KVM_CAP_ARM_VM_IPA_SIZE is via rust-vmm/kvm-ioctls,
// which wraps all IOCTL's and provides easy interface to user hypervisors.
// For now the cap hasn't been supported. A separate patch will be submitted to
// rust-vmm to add it.
// So a hardcoded value is used here as a temporary solution.
// It will be replace once rust-vmm/kvm-ioctls is ready.
//
40
// A dummy hypervisor created only for querying the host IPA size and will
// be freed after the query.
let hv = hypervisor::new().unwrap();
let host_cpu_phys_bits = hv.get_host_ipa_limit().try_into().unwrap();
if host_cpu_phys_bits == 0 {
// Host kernel does not support `get_host_ipa_limit`,
// we return the default value 40 here.
40
} else {
host_cpu_phys_bits
}
}
#[cfg(test)]
@@ -205,38 +216,9 @@ mod tests {
#[test]
fn test_arch_memory_regions_dram() {
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
assert_eq!(4, regions.len());
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[3].0);
assert_eq!(1usize << 32, regions[3].1);
assert_eq!(RegionType::Ram, regions[3].2);
}
#[test]
fn test_get_fdt_addr() {
let mut regions = Vec::new();
regions.push((
GuestAddress(layout::RAM_64BIT_START),
(layout::FDT_MAX_SIZE - 0x1000) as usize,
));
let mem = GuestMemoryMmap::from_ranges(&regions).expect("Cannot initialize memory");
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
regions.clear();
regions.push((
GuestAddress(layout::RAM_64BIT_START),
(layout::FDT_MAX_SIZE) as usize,
));
let mem = GuestMemoryMmap::from_ranges(&regions).expect("Cannot initialize memory");
assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START);
regions.clear();
regions.push((
GuestAddress(layout::RAM_64BIT_START),
(layout::FDT_MAX_SIZE + 0x1000) as usize,
));
let mem = GuestMemoryMmap::from_ranges(&regions).expect("Cannot initialize memory");
assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::RAM_64BIT_START);
regions.clear();
assert_eq!(5, regions.len());
assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[4].0);
assert_eq!(1usize << 32, regions[4].1);
assert_eq!(RegionType::Ram, regions[4].2);
}
}

View File

@@ -6,13 +6,13 @@
// found in the THIRD-PARTY file.
use super::get_fdt_addr;
use crate::GuestMemoryMmap;
use hypervisor::kvm::kvm_bindings::{
kvm_regs, user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
};
use hypervisor::{arm64_core_reg_id, offset__of};
use std::sync::Arc;
use std::{mem, result};
use vm_memory::GuestMemoryMmap;
/// Errors thrown while setting aarch64 registers.
#[derive(Debug)]
@@ -47,7 +47,7 @@ pub fn setup_regs(
vcpu: &Arc<dyn hypervisor::Vcpu>,
cpu_id: u8,
boot_ip: u64,
mem: &GuestMemoryMmap,
_mem: &GuestMemoryMmap,
) -> Result<()> {
let kreg_off = offset__of!(kvm_regs, regs);
@@ -73,7 +73,7 @@ pub fn setup_regs(
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
vcpu.set_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
get_fdt_addr(mem) as u64,
get_fdt_addr() as u64,
)
.map_err(Error::SetCoreRegister)?;
}

43
arch/src/aarch64/uefi.rs Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
use std::io::{Read, Seek, SeekFrom};
use std::result;
use vm_memory::{Bytes, GuestAddress, GuestMemory};
/// Errors thrown while loading UEFI binary
#[derive(Debug)]
pub enum Error {
/// Unable to seek to UEFI image start.
SeekUefiStart,
/// Unable to seek to UEFI image end.
SeekUefiEnd,
/// UEFI image too big.
UefiTooBig,
/// Unable to read UEFI image
ReadUefiImage,
}
type Result<T> = result::Result<T, Error>;
pub fn load_uefi<F, M: GuestMemory>(
guest_mem: &M,
guest_addr: GuestAddress,
uefi_image: &mut F,
) -> Result<()>
where
F: Read + Seek,
{
let uefi_size = uefi_image
.seek(SeekFrom::End(0))
.map_err(|_| Error::SeekUefiEnd)? as usize;
// edk2 image on virtual platform is smaller than 3M
if uefi_size > 0x300000 {
return Err(Error::UefiTooBig);
}
uefi_image
.seek(SeekFrom::Start(0))
.map_err(|_| Error::SeekUefiStart)?;
guest_mem
.read_exact_from(guest_addr, uefi_image, uefi_size)
.map_err(|_| Error::ReadUefiImage)
}

View File

@@ -8,28 +8,14 @@
//! Supported platforms: x86_64, aarch64.
#![allow(clippy::transmute_ptr_to_ptr, clippy::redundant_static_lifetimes)]
extern crate anyhow;
extern crate byteorder;
extern crate hypervisor;
extern crate libc;
#[macro_use]
extern crate log;
#[cfg(feature = "acpi")]
extern crate acpi_tables;
extern crate arch_gen;
extern crate linux_loader;
extern crate serde;
extern crate vm_memory;
extern crate vm_migration;
#[cfg(target_arch = "aarch64")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate thiserror;
use std::fmt;
use std::result;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
/// Type for returning error code.
#[derive(Debug)]
pub enum Error {
@@ -88,8 +74,8 @@ pub mod aarch64;
#[cfg(target_arch = "aarch64")]
pub use aarch64::{
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, get_kernel_start, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, EntryPoint,
get_host_cpu_phys_bits, get_kernel_start, get_uefi_start, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, uefi, EntryPoint,
};
#[cfg(target_arch = "x86_64")]
@@ -98,8 +84,8 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use x86_64::{
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidPatch,
CpuidReg, EntryPoint,
};
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.

View File

@@ -12,12 +12,6 @@ use std::mem;
use std::result;
use std::sync::Arc;
#[derive(Debug)]
pub enum Error {
GetLapic(anyhow::Error),
SetLapic(anyhow::Error),
}
pub type Result<T> = result::Result<T, hypervisor::HypervisorCpuError>;
// Defines poached from apicdef.h kernel header.

View File

@@ -9,40 +9,27 @@
use std::sync::Arc;
pub mod interrupts;
pub mod layout;
mod mpspec;
mod mptable;
pub mod regs;
use crate::GuestMemoryMmap;
use crate::InitramfsConfig;
use crate::RegionType;
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
use linux_loader::loader::bootparam::{boot_params, setup_header};
use linux_loader::loader::bootparam::boot_params;
use linux_loader::loader::elf::start_info::{
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
};
use std::mem;
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryMmap, GuestMemoryRegion, GuestUsize,
GuestMemoryRegion, GuestUsize,
};
mod smbios;
use std::arch::x86_64;
#[cfg(feature = "tdx")]
pub mod tdx;
#[derive(Debug, Copy, Clone)]
pub enum BootProtocol {
LinuxBoot,
PvhBoot,
}
impl ::std::fmt::Display for BootProtocol {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match self {
BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"),
BootProtocol::PvhBoot => write!(f, "PVH boot protocol"),
}
}
}
#[derive(Debug, Copy, Clone)]
/// Specifies the entry point address where the guest must start
/// executing code, as well as which of the supported boot protocols
@@ -50,10 +37,6 @@ impl ::std::fmt::Display for BootProtocol {
pub struct EntryPoint {
/// Address in guest memory where the guest must start execution
pub entry_addr: GuestAddress,
/// Specifies which boot protocol to use
pub protocol: BootProtocol,
/// This field is used for bzImage to fill zero page
pub setup_header: Option<setup_header>,
}
const E820_RAM: u32 = 1;
@@ -140,9 +123,6 @@ unsafe impl ByteValued for BootParamsWrapper {}
#[derive(Debug)]
pub enum Error {
/// Invalid e820 setup params.
E820Configuration,
/// Error writing MP table to memory.
MpTableSetup(mptable::Error),
@@ -351,17 +331,10 @@ pub fn configure_vcpu(
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
if let Some(kernel_entry_point) = kernel_entry_point {
// Safe to unwrap because this method is called after the VM is configured
regs::setup_regs(
fd,
kernel_entry_point.entry_addr.raw_value(),
layout::BOOT_STACK_POINTER.raw_value(),
layout::ZERO_PAGE_START.raw_value(),
kernel_entry_point.protocol,
)
.map_err(Error::RegsConfiguration)?;
regs::setup_regs(fd, kernel_entry_point.entry_addr.raw_value())
.map_err(Error::RegsConfiguration)?;
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
regs::setup_sregs(&vm_memory.memory(), fd, kernel_entry_point.protocol)
.map_err(Error::SregsConfiguration)?;
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
}
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
Ok(())
@@ -426,12 +399,9 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
pub fn configure_system(
guest_mem: &GuestMemoryMmap,
cmdline_addr: GuestAddress,
cmdline_size: usize,
initramfs: &Option<InitramfsConfig>,
_num_cpus: u8,
setup_hdr: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
boot_prot: BootProtocol,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
@@ -448,31 +418,13 @@ pub fn configure_system(
}
}
match boot_prot {
BootProtocol::PvhBoot => {
configure_pvh(
guest_mem,
cmdline_addr,
initramfs,
rsdp_addr,
sgx_epc_region,
)?;
}
BootProtocol::LinuxBoot => {
error!("Using deprecated LinuxBoot protocol: Please configure your kernel with CONFIG_PVH=y and supply the `vmlinux` file to `--kernel`");
configure_64bit_boot(
guest_mem,
cmdline_addr,
cmdline_size,
initramfs,
setup_hdr,
rsdp_addr,
sgx_epc_region,
)?;
}
}
Ok(())
configure_pvh(
guest_mem,
cmdline_addr,
initramfs,
rsdp_addr,
sgx_epc_region,
)
}
fn configure_pvh(
@@ -615,121 +567,6 @@ fn add_memmap_entry(memmap: &mut Vec<hvm_memmap_table_entry>, addr: u64, size: u
});
}
fn configure_64bit_boot(
guest_mem: &GuestMemoryMmap,
cmdline_addr: GuestAddress,
cmdline_size: usize,
initramfs: &Option<InitramfsConfig>,
setup_hdr: Option<setup_header>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
const KERNEL_LOADER_OTHER: u8 = 0xff;
const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x1000000; // Must be non-zero.
let mut params: BootParamsWrapper = BootParamsWrapper(boot_params::default());
if let Some(hdr) = setup_hdr {
// We should use the header if the loader provides one (e.g. from a bzImage).
params.0.hdr = hdr;
} else {
params.0.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
params.0.hdr.header = KERNEL_HDR_MAGIC;
params.0.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
};
// Common bootparams settings
if params.0.hdr.type_of_loader == 0 {
params.0.hdr.type_of_loader = KERNEL_LOADER_OTHER;
}
params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32;
params.0.hdr.cmdline_size = cmdline_size as u32;
if let Some(initramfs_config) = initramfs {
params.0.hdr.ramdisk_image = initramfs_config.address.raw_value() as u32;
params.0.hdr.ramdisk_size = initramfs_config.size as u32;
}
add_e820_entry(&mut params.0, 0, layout::EBDA_START.raw_value(), E820_RAM)?;
let mem_end = guest_mem.last_addr();
if mem_end < layout::MEM_32BIT_RESERVED_START {
add_e820_entry(
&mut params.0,
layout::HIGH_RAM_START.raw_value(),
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
E820_RAM,
)?;
} else {
add_e820_entry(
&mut params.0,
layout::HIGH_RAM_START.raw_value(),
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
E820_RAM,
)?;
if mem_end > layout::RAM_64BIT_START {
add_e820_entry(
&mut params.0,
layout::RAM_64BIT_START.raw_value(),
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
E820_RAM,
)?;
}
}
add_e820_entry(
&mut params.0,
layout::PCI_MMCONFIG_START.0,
layout::PCI_MMCONFIG_SIZE,
E820_RESERVED,
)?;
if let Some(sgx_epc_region) = sgx_epc_region {
add_e820_entry(
&mut params.0,
sgx_epc_region.start().raw_value(),
sgx_epc_region.size() as u64,
E820_RESERVED,
)?;
}
if let Some(rsdp_addr) = rsdp_addr {
params.0.acpi_rsdp_addr = rsdp_addr.0;
}
let zero_page_addr = layout::ZERO_PAGE_START;
guest_mem
.checked_offset(zero_page_addr, mem::size_of::<boot_params>())
.ok_or(super::Error::ZeroPagePastRamEnd)?;
guest_mem
.write_obj(params, zero_page_addr)
.map_err(super::Error::ZeroPageSetup)?;
Ok(())
}
/// Add an e820 region to the e820 map.
/// Returns Ok(()) if successful, or an error if there is no space left in the map.
fn add_e820_entry(
params: &mut boot_params,
addr: u64,
size: u64,
mem_type: u32,
) -> Result<(), Error> {
if params.e820_entries >= params.e820_table.len() as u8 {
return Err(Error::E820Configuration);
}
params.e820_table[params.e820_entries as usize].addr = addr;
params.e820_table[params.e820_entries as usize].size = size;
params.e820_table[params.e820_entries as usize].type_ = mem_type;
params.e820_entries += 1;
Ok(())
}
/// Returns the memory address where the initramfs could be loaded.
pub fn initramfs_load_addr(
guest_mem: &GuestMemoryMmap,
@@ -888,7 +725,6 @@ pub fn update_cpuid_sgx(cpuid: &mut CpuId, epc_sections: Vec<SgxEpcSection>) ->
#[cfg(test)]
mod tests {
use super::*;
use linux_loader::loader::bootparam::boot_e820_entry;
#[test]
fn regions_lt_4gb() {
@@ -913,12 +749,9 @@ mod tests {
let config_err = configure_system(
&gm,
GuestAddress(0),
0,
&None,
1,
None,
Some(layout::RSDP_POINTER),
BootProtocol::LinuxBoot,
None,
);
assert!(config_err.is_err());
@@ -932,31 +765,8 @@ mod tests {
.map(|r| (r.0, r.1))
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
// Now assigning some memory that is equal to the start of the 32bit memory hole.
let mem_size = 3328 << 20;
@@ -967,31 +777,9 @@ mod tests {
.map(|r| (r.0, r.1))
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
// Now assigning some memory that falls after the 32bit memory hole.
let mem_size = 3330 << 20;
@@ -1002,71 +790,9 @@ mod tests {
.map(|r| (r.0, r.1))
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::LinuxBoot,
None,
)
.unwrap();
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
configure_system(
&gm,
GuestAddress(0),
0,
&None,
no_vcpus,
None,
None,
BootProtocol::PvhBoot,
None,
)
.unwrap();
}
#[test]
fn test_add_e820_entry() {
let e820_table = [(boot_e820_entry {
addr: 0x1,
size: 4,
type_: 1,
}); 128];
let expected_params = boot_params {
e820_table,
e820_entries: 1,
..Default::default()
};
let mut params: boot_params = Default::default();
add_e820_entry(
&mut params,
e820_table[0].addr,
e820_table[0].size,
e820_table[0].type_,
)
.unwrap();
assert_eq!(
format!("{:?}", params.e820_table[0]),
format!("{:?}", expected_params.e820_table[0])
);
assert_eq!(params.e820_entries, expected_params.e820_entries);
// Exercise the scenario where the field storing the length of the e820 entry table is
// is bigger than the allocated memory.
params.e820_entries = params.e820_table.len() as u8 + 1;
assert!(add_e820_entry(
&mut params,
e820_table[0].addr,
e820_table[0].size,
e820_table[0].type_
)
.is_err());
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
}
#[test]

112
arch/src/x86_64/mpspec.rs Normal file
View File

@@ -0,0 +1,112 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
pub const MP_PROCESSOR: ::std::os::raw::c_uint = 0;
pub const MP_BUS: ::std::os::raw::c_uint = 1;
pub const MP_IOAPIC: ::std::os::raw::c_uint = 2;
pub const MP_INTSRC: ::std::os::raw::c_uint = 3;
pub const MP_LINTSRC: ::std::os::raw::c_uint = 4;
pub const CPU_ENABLED: ::std::os::raw::c_uint = 1;
pub const CPU_BOOTPROCESSOR: ::std::os::raw::c_uint = 2;
pub const MPC_APIC_USABLE: ::std::os::raw::c_uint = 1;
pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpf_intel {
pub signature: [::std::os::raw::c_char; 4usize],
pub physptr: ::std::os::raw::c_uint,
pub length: ::std::os::raw::c_uchar,
pub specification: ::std::os::raw::c_uchar,
pub checksum: ::std::os::raw::c_uchar,
pub feature1: ::std::os::raw::c_uchar,
pub feature2: ::std::os::raw::c_uchar,
pub feature3: ::std::os::raw::c_uchar,
pub feature4: ::std::os::raw::c_uchar,
pub feature5: ::std::os::raw::c_uchar,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_table {
pub signature: [::std::os::raw::c_char; 4usize],
pub length: ::std::os::raw::c_ushort,
pub spec: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub oem: [::std::os::raw::c_char; 8usize],
pub productid: [::std::os::raw::c_char; 12usize],
pub oemptr: ::std::os::raw::c_uint,
pub oemsize: ::std::os::raw::c_ushort,
pub oemcount: ::std::os::raw::c_ushort,
pub lapic: ::std::os::raw::c_uint,
pub reserved: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_cpu {
pub type_: ::std::os::raw::c_uchar,
pub apicid: ::std::os::raw::c_uchar,
pub apicver: ::std::os::raw::c_uchar,
pub cpuflag: ::std::os::raw::c_uchar,
pub cpufeature: ::std::os::raw::c_uint,
pub featureflag: ::std::os::raw::c_uint,
pub reserved: [::std::os::raw::c_uint; 2usize],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_bus {
pub type_: ::std::os::raw::c_uchar,
pub busid: ::std::os::raw::c_uchar,
pub bustype: [::std::os::raw::c_uchar; 6usize],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_ioapic {
pub type_: ::std::os::raw::c_uchar,
pub apicid: ::std::os::raw::c_uchar,
pub apicver: ::std::os::raw::c_uchar,
pub flags: ::std::os::raw::c_uchar,
pub apicaddr: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_intsrc {
pub type_: ::std::os::raw::c_uchar,
pub irqtype: ::std::os::raw::c_uchar,
pub irqflag: ::std::os::raw::c_ushort,
pub srcbus: ::std::os::raw::c_uchar,
pub srcbusirq: ::std::os::raw::c_uchar,
pub dstapic: ::std::os::raw::c_uchar,
pub dstirq: ::std::os::raw::c_uchar,
}
pub const MP_IRQ_SOURCE_TYPES_MP_INT: ::std::os::raw::c_uint = 0;
pub const MP_IRQ_SOURCE_TYPES_MP_NMI: ::std::os::raw::c_uint = 1;
pub const MP_IRQ_SOURCE_TYPES_MP_EXT_INT: ::std::os::raw::c_uint = 3;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_lintsrc {
pub type_: ::std::os::raw::c_uchar,
pub irqtype: ::std::os::raw::c_uchar,
pub irqflag: ::std::os::raw::c_ushort,
pub srcbusid: ::std::os::raw::c_uchar,
pub srcbusirq: ::std::os::raw::c_uchar,
pub destapic: ::std::os::raw::c_uchar,
pub destapiclint: ::std::os::raw::c_uchar,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct mpc_oemtable {
pub signature: [::std::os::raw::c_char; 4usize],
pub length: ::std::os::raw::c_ushort,
pub rev: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub mpc: [::std::os::raw::c_char; 8usize],
}

View File

@@ -5,18 +5,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::mpspec;
use crate::GuestMemoryMmap;
use libc::c_char;
use std::io;
use std::mem;
use std::result;
use std::slice;
use libc::c_char;
use arch_gen::x86::mpspec;
use layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap,
};
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError};
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `ByteValued`) where:
@@ -222,7 +219,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
let size = mem::size_of::<MpcIntsrcWrapper>();
let mut mpc_intsrc = MpcIntsrcWrapper(mpspec::mpc_intsrc::default());
mpc_intsrc.0.type_ = mpspec::MP_INTSRC as u8;
mpc_intsrc.0.irqtype = mpspec::mp_irq_source_types_mp_INT as u8;
mpc_intsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_INT as u8;
mpc_intsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
mpc_intsrc.0.srcbus = 0;
mpc_intsrc.0.srcbusirq = i;
@@ -237,7 +234,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
let size = mem::size_of::<MpcLintsrcWrapper>();
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
mpc_lintsrc.0.irqtype = mpspec::mp_irq_source_types_mp_ExtINT as u8;
mpc_lintsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_EXT_INT as u8;
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
mpc_lintsrc.0.srcbusid = 0;
mpc_lintsrc.0.srcbusirq = 0;
@@ -252,7 +249,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
let size = mem::size_of::<MpcLintsrcWrapper>();
let mut mpc_lintsrc = MpcLintsrcWrapper(mpspec::mpc_lintsrc::default());
mpc_lintsrc.0.type_ = mpspec::MP_LINTSRC as u8;
mpc_lintsrc.0.irqtype = mpspec::mp_irq_source_types_mp_NMI as u8;
mpc_lintsrc.0.irqtype = mpspec::MP_IRQ_SOURCE_TYPES_MP_NMI as u8;
mpc_lintsrc.0.irqflag = mpspec::MP_IRQDIR_DEFAULT as u16;
mpc_lintsrc.0.srcbusid = 0;
mpc_lintsrc.0.srcbusirq = 0;
@@ -287,7 +284,7 @@ pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8)
#[cfg(test)]
mod tests {
use super::*;
use layout::MPTABLE_START;
use crate::layout::MPTABLE_START;
use vm_memory::{GuestAddress, GuestUsize};
fn table_entry_size(type_: u8) -> usize {

View File

@@ -6,17 +6,14 @@
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use std::sync::Arc;
use std::{mem, result};
use super::BootProtocol;
use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
use crate::GuestMemoryMmap;
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
use hypervisor::arch::x86::regs::*;
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
use layout::{
BOOT_GDT_START, BOOT_IDT_START, PDE_START, PDPTE_START, PML4_START, PML5_START, PVH_INFO_START,
};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
use std::sync::Arc;
use std::{mem, result};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError};
#[derive(Debug)]
pub enum Error {
@@ -81,32 +78,12 @@ pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
/// * `boot_ip` - Starting instruction pointer.
/// * `boot_sp` - Starting stack pointer.
/// * `boot_si` - Must point to zero page address per Linux ABI.
pub fn setup_regs(
vcpu: &Arc<dyn hypervisor::Vcpu>,
boot_ip: u64,
boot_sp: u64,
boot_si: u64,
boot_prot: BootProtocol,
) -> Result<()> {
let regs: StandardRegisters = match boot_prot {
// Configure regs as required by PVH boot protocol.
BootProtocol::PvhBoot => StandardRegisters {
rflags: 0x0000000000000002u64,
rbx: PVH_INFO_START.raw_value(),
rip: boot_ip,
..Default::default()
},
// Configure regs as required by Linux 64-bit boot protocol.
BootProtocol::LinuxBoot => StandardRegisters {
rflags: 0x0000000000000002u64,
rip: boot_ip,
rsp: boot_sp,
rbp: boot_sp,
rsi: boot_si,
..Default::default()
},
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, boot_ip: u64) -> Result<()> {
let regs = StandardRegisters {
rflags: 0x0000000000000002u64,
rbx: PVH_INFO_START.raw_value(),
rip: boot_ip,
..Default::default()
};
vcpu.set_regs(&regs).map_err(Error::SetBaseRegisters)
}
@@ -117,19 +94,9 @@ pub fn setup_regs(
///
/// * `mem` - The memory that will be passed to the guest.
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn setup_sregs(
mem: &GuestMemoryMmap,
vcpu: &Arc<dyn hypervisor::Vcpu>,
boot_prot: BootProtocol,
) -> Result<()> {
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
configure_segments_and_sregs(mem, &mut sregs, boot_prot)?;
if let BootProtocol::LinuxBoot = boot_prot {
setup_page_tables(mem, &mut sregs)?; // TODO(dgreid) - Can this be done once per system instead?
}
configure_segments_and_sregs(mem, &mut sregs)?;
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
}
@@ -156,27 +123,15 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
pub fn configure_segments_and_sregs(
mem: &GuestMemoryMmap,
sregs: &mut SpecialRegisters,
boot_prot: BootProtocol,
) -> Result<()> {
let gdt_table: [u64; BOOT_GDT_MAX as usize] = match boot_prot {
BootProtocol::PvhBoot => {
// Configure GDT entries as specified by PVH boot protocol
[
gdt_entry(0, 0, 0), // NULL
gdt_entry(0xc09b, 0, 0xffffffff), // CODE
gdt_entry(0xc093, 0, 0xffffffff), // DATA
gdt_entry(0x008b, 0, 0x67), // TSS
]
}
BootProtocol::LinuxBoot => {
// Configure GDT entries as specified by Linux 64bit boot protocol
[
gdt_entry(0, 0, 0), // NULL
gdt_entry(0xa09b, 0, 0xfffff), // CODE
gdt_entry(0xc093, 0, 0xfffff), // DATA
gdt_entry(0x808b, 0, 0xfffff), // TSS
]
}
let gdt_table: [u64; BOOT_GDT_MAX as usize] = {
// Configure GDT entries as specified by PVH boot protocol
[
gdt_entry(0, 0, 0), // NULL
gdt_entry(0xc09b, 0, 0xffffffff), // CODE
gdt_entry(0xc093, 0, 0xffffffff), // DATA
gdt_entry(0x008b, 0, 0x67), // TSS
]
};
let code_seg = segment_from_gdt(gdt_table[1], 1);
@@ -200,61 +155,17 @@ pub fn configure_segments_and_sregs(
sregs.ss = data_seg;
sregs.tr = tss_seg;
match boot_prot {
BootProtocol::PvhBoot => {
sregs.cr0 = CR0_PE;
sregs.cr4 = 0;
}
BootProtocol::LinuxBoot => {
/* 64-bit protected mode */
sregs.cr0 |= CR0_PE;
sregs.efer |= EFER_LME | EFER_LMA;
}
}
Ok(())
}
pub fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut SpecialRegisters) -> Result<()> {
// Puts PML5 or PML4 right after zero page but aligned to 4k.
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
// Entry covering VA [0..256TB)
mem.write_obj(PML4_START.raw_value() | 0x03, PML5_START)
.map_err(Error::WritePml5Address)?;
sregs.cr3 = PML5_START.raw_value();
sregs.cr4 |= CR4_LA57;
} else {
sregs.cr3 = PML4_START.raw_value();
}
// Entry covering VA [0..512GB)
mem.write_obj(PDPTE_START.raw_value() | 0x03, PML4_START)
.map_err(Error::WritePml4Address)?;
// Entry covering VA [0..1GB)
mem.write_obj(PDE_START.raw_value() | 0x03, PDPTE_START)
.map_err(Error::WritePdpteAddress)?;
// 512 2MB entries together covering VA [0..1GB). Note we are assuming
// CPU supports 2MB pages (/proc/cpuinfo has 'pse'). All modern CPUs do.
for i in 0..512 {
mem.write_obj((i << 21) + 0x83u64, PDE_START.unchecked_add(i * 8))
.map_err(Error::WritePdeAddress)?;
}
sregs.cr4 |= CR4_PAE;
sregs.cr0 |= CR0_PG;
sregs.cr0 = CR0_PE;
sregs.cr4 = 0;
Ok(())
}
#[cfg(test)]
mod tests {
extern crate vm_memory;
use super::*;
use vm_memory::{GuestAddress, GuestMemoryMmap};
use crate::GuestMemoryMmap;
use vm_memory::GuestAddress;
fn create_guest_mem() -> GuestMemoryMmap {
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap()
@@ -268,36 +179,7 @@ mod tests {
fn segments_and_sregs() {
let mut sregs: SpecialRegisters = Default::default();
let gm = create_guest_mem();
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::LinuxBoot).unwrap();
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
assert_eq!(
0xaf9b000000ffff,
read_u64(&gm, BOOT_GDT_START.unchecked_add(8))
);
assert_eq!(
0xcf93000000ffff,
read_u64(&gm, BOOT_GDT_START.unchecked_add(16))
);
assert_eq!(
0x8f8b000000ffff,
read_u64(&gm, BOOT_GDT_START.unchecked_add(24))
);
assert_eq!(0x0, read_u64(&gm, BOOT_IDT_START));
assert_eq!(0, sregs.cs.base);
assert_eq!(0xffffffff, sregs.ds.limit);
assert_eq!(0x10, sregs.es.selector);
assert_eq!(1, sregs.fs.present);
assert_eq!(1, sregs.gs.g);
assert_eq!(0, sregs.ss.avl);
assert_eq!(0, sregs.tr.base);
assert_eq!(0xffffffff, sregs.tr.limit);
assert_eq!(0, sregs.tr.avl);
assert_eq!(CR0_PE, sregs.cr0);
assert_eq!(EFER_LME | EFER_LMA, sregs.efer);
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::PvhBoot).unwrap();
configure_segments_and_sregs(&gm, &mut sregs).unwrap();
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
assert_eq!(
0xcf9b000000ffff,
@@ -327,31 +209,4 @@ mod tests {
assert_eq!(CR0_PE, sregs.cr0);
assert_eq!(0, sregs.cr4);
}
#[test]
fn page_tables() {
let mut sregs: SpecialRegisters = Default::default();
let gm = create_guest_mem();
setup_page_tables(&gm, &mut sregs).unwrap();
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
assert_eq!(0xa003, read_u64(&gm, PML5_START));
}
assert_eq!(0xb003, read_u64(&gm, PML4_START));
assert_eq!(0xc003, read_u64(&gm, PDPTE_START));
for i in 0..512 {
assert_eq!(
(i << 21) + 0x83u64,
read_u64(&gm, PDE_START.unchecked_add(i * 8))
);
}
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
assert_eq!(PML5_START.raw_value(), sregs.cr3);
} else {
assert_eq!(PML4_START.raw_value(), sregs.cr3);
}
assert_eq!(CR4_PAE, sregs.cr4);
assert_eq!(CR0_PG, sregs.cr0);
}
}

View File

@@ -6,13 +6,14 @@
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use layout::SMBIOS_START;
use crate::layout::SMBIOS_START;
use crate::GuestMemoryMmap;
use std::fmt::{self, Display};
use std::mem;
use std::result;
use std::slice;
use vm_memory::ByteValued;
use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
use vm_memory::{Address, Bytes, GuestAddress};
#[allow(unused_variables)]
#[derive(Debug)]

View File

@@ -1,10 +1,11 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use crate::GuestMemoryMmap;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use thiserror::Error;
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryError, GuestMemoryMmap};
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemoryError};
#[derive(Error, Debug)]
pub enum TdvfError {

6
arch_gen/Cargo.lock generated
View File

@@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "arch_gen"
version = "0.1.0"

View File

@@ -1,7 +0,0 @@
[package]
name = "arch_gen"
version = "0.1.0"
authors = ["Amazon firecracker team <firecracker-devel@amazon.com>"]
[dependencies]

View File

@@ -1,5 +0,0 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod x86;

View File

@@ -1,14 +0,0 @@
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(clippy::unreadable_literal, clippy::redundant_static_lifetimes)]
pub mod mpspec;

View File

@@ -1,832 +0,0 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
/* automatically generated by rust-bindgen */
pub const MPC_SIGNATURE: &'static [u8; 5usize] = b"PCMP\x00";
pub const MP_PROCESSOR: ::std::os::raw::c_uint = 0;
pub const MP_BUS: ::std::os::raw::c_uint = 1;
pub const MP_IOAPIC: ::std::os::raw::c_uint = 2;
pub const MP_INTSRC: ::std::os::raw::c_uint = 3;
pub const MP_LINTSRC: ::std::os::raw::c_uint = 4;
pub const MP_TRANSLATION: ::std::os::raw::c_uint = 192;
pub const CPU_ENABLED: ::std::os::raw::c_uint = 1;
pub const CPU_BOOTPROCESSOR: ::std::os::raw::c_uint = 2;
pub const CPU_STEPPING_MASK: ::std::os::raw::c_uint = 15;
pub const CPU_MODEL_MASK: ::std::os::raw::c_uint = 240;
pub const CPU_FAMILY_MASK: ::std::os::raw::c_uint = 3840;
pub const BUSTYPE_EISA: &'static [u8; 5usize] = b"EISA\x00";
pub const BUSTYPE_ISA: &'static [u8; 4usize] = b"ISA\x00";
pub const BUSTYPE_INTERN: &'static [u8; 7usize] = b"INTERN\x00";
pub const BUSTYPE_MCA: &'static [u8; 4usize] = b"MCA\x00";
pub const BUSTYPE_VL: &'static [u8; 3usize] = b"VL\x00";
pub const BUSTYPE_PCI: &'static [u8; 4usize] = b"PCI\x00";
pub const BUSTYPE_PCMCIA: &'static [u8; 7usize] = b"PCMCIA\x00";
pub const BUSTYPE_CBUS: &'static [u8; 5usize] = b"CBUS\x00";
pub const BUSTYPE_CBUSII: &'static [u8; 7usize] = b"CBUSII\x00";
pub const BUSTYPE_FUTURE: &'static [u8; 7usize] = b"FUTURE\x00";
pub const BUSTYPE_MBI: &'static [u8; 4usize] = b"MBI\x00";
pub const BUSTYPE_MBII: &'static [u8; 5usize] = b"MBII\x00";
pub const BUSTYPE_MPI: &'static [u8; 4usize] = b"MPI\x00";
pub const BUSTYPE_MPSA: &'static [u8; 5usize] = b"MPSA\x00";
pub const BUSTYPE_NUBUS: &'static [u8; 6usize] = b"NUBUS\x00";
pub const BUSTYPE_TC: &'static [u8; 3usize] = b"TC\x00";
pub const BUSTYPE_VME: &'static [u8; 4usize] = b"VME\x00";
pub const BUSTYPE_XPRESS: &'static [u8; 7usize] = b"XPRESS\x00";
pub const MPC_APIC_USABLE: ::std::os::raw::c_uint = 1;
pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
pub const MP_IRQDIR_HIGH: ::std::os::raw::c_uint = 1;
pub const MP_IRQDIR_LOW: ::std::os::raw::c_uint = 3;
pub const MP_APIC_ALL: ::std::os::raw::c_uint = 255;
pub const MPC_OEM_SIGNATURE: &'static [u8; 5usize] = b"_OEM\x00";
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpf_intel {
pub signature: [::std::os::raw::c_char; 4usize],
pub physptr: ::std::os::raw::c_uint,
pub length: ::std::os::raw::c_uchar,
pub specification: ::std::os::raw::c_uchar,
pub checksum: ::std::os::raw::c_uchar,
pub feature1: ::std::os::raw::c_uchar,
pub feature2: ::std::os::raw::c_uchar,
pub feature3: ::std::os::raw::c_uchar,
pub feature4: ::std::os::raw::c_uchar,
pub feature5: ::std::os::raw::c_uchar,
}
#[test]
fn bindgen_test_layout_mpf_intel() {
assert_eq!(
::std::mem::size_of::<mpf_intel>(),
16usize,
concat!("Size of: ", stringify!(mpf_intel))
);
assert_eq!(
::std::mem::align_of::<mpf_intel>(),
4usize,
concat!("Alignment of ", stringify!(mpf_intel))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(signature)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).physptr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(physptr)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).length as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(length)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).specification as *const _ as usize },
9usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(specification)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).checksum as *const _ as usize },
10usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(checksum)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).feature1 as *const _ as usize },
11usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(feature1)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).feature2 as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(feature2)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).feature3 as *const _ as usize },
13usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(feature3)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).feature4 as *const _ as usize },
14usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(feature4)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpf_intel>()).feature5 as *const _ as usize },
15usize,
concat!(
"Alignment of field: ",
stringify!(mpf_intel),
"::",
stringify!(feature5)
)
);
}
impl Clone for mpf_intel {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_table {
pub signature: [::std::os::raw::c_char; 4usize],
pub length: ::std::os::raw::c_ushort,
pub spec: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub oem: [::std::os::raw::c_char; 8usize],
pub productid: [::std::os::raw::c_char; 12usize],
pub oemptr: ::std::os::raw::c_uint,
pub oemsize: ::std::os::raw::c_ushort,
pub oemcount: ::std::os::raw::c_ushort,
pub lapic: ::std::os::raw::c_uint,
pub reserved: ::std::os::raw::c_uint,
}
#[test]
fn bindgen_test_layout_mpc_table() {
assert_eq!(
::std::mem::size_of::<mpc_table>(),
44usize,
concat!("Size of: ", stringify!(mpc_table))
);
assert_eq!(
::std::mem::align_of::<mpc_table>(),
4usize,
concat!("Alignment of ", stringify!(mpc_table))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(signature)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).length as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(length)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).spec as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(spec)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).checksum as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(checksum)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).oem as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(oem)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).productid as *const _ as usize },
16usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(productid)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).oemptr as *const _ as usize },
28usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(oemptr)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).oemsize as *const _ as usize },
32usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(oemsize)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).oemcount as *const _ as usize },
34usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(oemcount)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).lapic as *const _ as usize },
36usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(lapic)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_table>()).reserved as *const _ as usize },
40usize,
concat!(
"Alignment of field: ",
stringify!(mpc_table),
"::",
stringify!(reserved)
)
);
}
impl Clone for mpc_table {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_cpu {
pub type_: ::std::os::raw::c_uchar,
pub apicid: ::std::os::raw::c_uchar,
pub apicver: ::std::os::raw::c_uchar,
pub cpuflag: ::std::os::raw::c_uchar,
pub cpufeature: ::std::os::raw::c_uint,
pub featureflag: ::std::os::raw::c_uint,
pub reserved: [::std::os::raw::c_uint; 2usize],
}
#[test]
fn bindgen_test_layout_mpc_cpu() {
assert_eq!(
::std::mem::size_of::<mpc_cpu>(),
20usize,
concat!("Size of: ", stringify!(mpc_cpu))
);
assert_eq!(
::std::mem::align_of::<mpc_cpu>(),
4usize,
concat!("Alignment of ", stringify!(mpc_cpu))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(apicid)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).apicver as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(apicver)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpuflag as *const _ as usize },
3usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(cpuflag)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).cpufeature as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(cpufeature)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).featureflag as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(featureflag)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_cpu>()).reserved as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
stringify!(mpc_cpu),
"::",
stringify!(reserved)
)
);
}
impl Clone for mpc_cpu {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_bus {
pub type_: ::std::os::raw::c_uchar,
pub busid: ::std::os::raw::c_uchar,
pub bustype: [::std::os::raw::c_uchar; 6usize],
}
#[test]
fn bindgen_test_layout_mpc_bus() {
assert_eq!(
::std::mem::size_of::<mpc_bus>(),
8usize,
concat!("Size of: ", stringify!(mpc_bus))
);
assert_eq!(
::std::mem::align_of::<mpc_bus>(),
1usize,
concat!("Alignment of ", stringify!(mpc_bus))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_bus>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_bus),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_bus>()).busid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
stringify!(mpc_bus),
"::",
stringify!(busid)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_bus>()).bustype as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(mpc_bus),
"::",
stringify!(bustype)
)
);
}
impl Clone for mpc_bus {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_ioapic {
pub type_: ::std::os::raw::c_uchar,
pub apicid: ::std::os::raw::c_uchar,
pub apicver: ::std::os::raw::c_uchar,
pub flags: ::std::os::raw::c_uchar,
pub apicaddr: ::std::os::raw::c_uint,
}
#[test]
fn bindgen_test_layout_mpc_ioapic() {
assert_eq!(
::std::mem::size_of::<mpc_ioapic>(),
8usize,
concat!("Size of: ", stringify!(mpc_ioapic))
);
assert_eq!(
::std::mem::align_of::<mpc_ioapic>(),
4usize,
concat!("Alignment of ", stringify!(mpc_ioapic))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_ioapic>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_ioapic),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicid as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
stringify!(mpc_ioapic),
"::",
stringify!(apicid)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicver as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(mpc_ioapic),
"::",
stringify!(apicver)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_ioapic>()).flags as *const _ as usize },
3usize,
concat!(
"Alignment of field: ",
stringify!(mpc_ioapic),
"::",
stringify!(flags)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_ioapic>()).apicaddr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_ioapic),
"::",
stringify!(apicaddr)
)
);
}
impl Clone for mpc_ioapic {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_intsrc {
pub type_: ::std::os::raw::c_uchar,
pub irqtype: ::std::os::raw::c_uchar,
pub irqflag: ::std::os::raw::c_ushort,
pub srcbus: ::std::os::raw::c_uchar,
pub srcbusirq: ::std::os::raw::c_uchar,
pub dstapic: ::std::os::raw::c_uchar,
pub dstirq: ::std::os::raw::c_uchar,
}
#[test]
fn bindgen_test_layout_mpc_intsrc() {
assert_eq!(
::std::mem::size_of::<mpc_intsrc>(),
8usize,
concat!("Size of: ", stringify!(mpc_intsrc))
);
assert_eq!(
::std::mem::align_of::<mpc_intsrc>(),
2usize,
concat!("Alignment of ", stringify!(mpc_intsrc))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqtype as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(irqtype)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).irqflag as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(irqflag)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbus as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(srcbus)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).srcbusirq as *const _ as usize },
5usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(srcbusirq)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstapic as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(dstapic)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_intsrc>()).dstirq as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
stringify!(mpc_intsrc),
"::",
stringify!(dstirq)
)
);
}
impl Clone for mpc_intsrc {
fn clone(&self) -> Self {
*self
}
}
pub const mp_irq_source_types_mp_INT: mp_irq_source_types = 0;
pub const mp_irq_source_types_mp_NMI: mp_irq_source_types = 1;
pub const mp_irq_source_types_mp_SMI: mp_irq_source_types = 2;
pub const mp_irq_source_types_mp_ExtINT: mp_irq_source_types = 3;
pub type mp_irq_source_types = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_lintsrc {
pub type_: ::std::os::raw::c_uchar,
pub irqtype: ::std::os::raw::c_uchar,
pub irqflag: ::std::os::raw::c_ushort,
pub srcbusid: ::std::os::raw::c_uchar,
pub srcbusirq: ::std::os::raw::c_uchar,
pub destapic: ::std::os::raw::c_uchar,
pub destapiclint: ::std::os::raw::c_uchar,
}
#[test]
fn bindgen_test_layout_mpc_lintsrc() {
assert_eq!(
::std::mem::size_of::<mpc_lintsrc>(),
8usize,
concat!("Size of: ", stringify!(mpc_lintsrc))
);
assert_eq!(
::std::mem::align_of::<mpc_lintsrc>(),
2usize,
concat!("Alignment of ", stringify!(mpc_lintsrc))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).type_ as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqtype as *const _ as usize },
1usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(irqtype)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).irqflag as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(irqflag)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusid as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(srcbusid)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).srcbusirq as *const _ as usize },
5usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(srcbusirq)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapic as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(destapic)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_lintsrc>()).destapiclint as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
stringify!(mpc_lintsrc),
"::",
stringify!(destapiclint)
)
);
}
impl Clone for mpc_lintsrc {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct mpc_oemtable {
pub signature: [::std::os::raw::c_char; 4usize],
pub length: ::std::os::raw::c_ushort,
pub rev: ::std::os::raw::c_char,
pub checksum: ::std::os::raw::c_char,
pub mpc: [::std::os::raw::c_char; 8usize],
}
#[test]
fn bindgen_test_layout_mpc_oemtable() {
assert_eq!(
::std::mem::size_of::<mpc_oemtable>(),
16usize,
concat!("Size of: ", stringify!(mpc_oemtable))
);
assert_eq!(
::std::mem::align_of::<mpc_oemtable>(),
2usize,
concat!("Alignment of ", stringify!(mpc_oemtable))
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_oemtable>()).signature as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(mpc_oemtable),
"::",
stringify!(signature)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_oemtable>()).length as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(mpc_oemtable),
"::",
stringify!(length)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_oemtable>()).rev as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
stringify!(mpc_oemtable),
"::",
stringify!(rev)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_oemtable>()).checksum as *const _ as usize },
7usize,
concat!(
"Alignment of field: ",
stringify!(mpc_oemtable),
"::",
stringify!(checksum)
)
);
assert_eq!(
unsafe { &(*std::ptr::null::<mpc_oemtable>()).mpc as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(mpc_oemtable),
"::",
stringify!(mpc)
)
);
}
impl Clone for mpc_oemtable {
fn clone(&self) -> Self {
*self
}
}
pub const mp_bustype_MP_BUS_ISA: mp_bustype = 1;
pub const mp_bustype_MP_BUS_EISA: mp_bustype = 2;
pub const mp_bustype_MP_BUS_PCI: mp_bustype = 3;
pub type mp_bustype = ::std::os::raw::c_uint;

View File

@@ -10,15 +10,14 @@ io_uring = []
[dependencies]
io-uring = ">=0.4.0"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
qcow = { path = "../qcow" }
serde = ">=1.0.27"
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
thiserror = "1.0"
versionize = "0.1.6"
versionize_derive = "0.1.4"
virtio-bindings = { version = "0.1", features = ["virtio-v5_0_0"]}
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = ">=0.3.1"

View File

@@ -10,8 +10,6 @@
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
pub mod async_io;
pub mod fixed_vhd_async;
@@ -34,11 +32,18 @@ use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::result;
use std::sync::{Arc, Mutex};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::bindings::virtio_blk::*;
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
use vm_memory::{
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
GuestMemoryError,
};
use vm_virtio::DescriptorChain;
use vmm_sys_util::eventfd::EventFd;
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
const SECTOR_SHIFT: u8 = 9;
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
@@ -331,6 +336,12 @@ impl Request {
// Queue operations expected to be submitted.
match request_type {
RequestType::In => {
for (data_addr, data_len) in &self.data_descriptors {
mem.get_slice(*data_addr, *data_len as usize)
.map_err(ExecuteError::GetHostAddress)?
.bitmap()
.mark_dirty(0, *data_len as usize);
}
disk_image
.read_vectored(offset, iovecs, user_data)
.map_err(ExecuteError::AsyncRead)?;
@@ -369,7 +380,7 @@ impl Request {
}
}
#[derive(Copy, Clone, Debug, Default, Deserialize, Serialize)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[repr(C, packed)]
pub struct VirtioBlockConfig {
pub capacity: u64,
@@ -394,7 +405,7 @@ pub struct VirtioBlockConfig {
}
unsafe impl ByteValued for VirtioBlockConfig {}
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
#[repr(C, packed)]
pub struct VirtioBlockGeometry {
pub cylinders: u16,

View File

@@ -2,19 +2,20 @@
name = "devices"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
[dependencies]
acpi_tables = { path = "../acpi_tables", optional = true }
anyhow = "1.0"
arch = { path = "../arch" }
bitflags = ">=1.2.1"
byteorder = "1.4.3"
epoll = ">=4.0.1"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
versionize = "0.1.6"
versionize_derive = "0.1.4"
vm-device = { path = "../vm-device" }
acpi_tables = { path = "../acpi_tables", optional = true }
vm-memory = "0.5.0"
vm-migration = { path = "../vm-migration" }
vmm-sys-util = ">=0.3.1"

View File

@@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use super::AcpiNotificationFlags;
use acpi_tables::{aml, aml::Aml};
use std::sync::{Arc, Barrier};
use std::time::Instant;
@@ -10,7 +11,6 @@ use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_memory::GuestAddress;
use vmm_sys_util::eventfd::EventFd;
use AcpiNotificationFlags;
pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
@@ -52,7 +52,6 @@ impl BusDevice for AcpiShutdownDevice {
const SLEEP_VALUE_BIT: u8 = 2;
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
debug!("ACPI Shutdown signalled");
extern crate bitflags;
if let Err(e) = self.exit_evt.write(1) {
error!("Error triggering ACPI shutdown event: {}", e);
}

View File

@@ -3,8 +3,10 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use super::interrupt_controller::{Error, InterruptController};
extern crate arch;
use arch::aarch64::gic::GicDevice;
use std::result;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
LegacyIrqSourceConfig, MsiIrqGroupConfig,
@@ -14,7 +16,7 @@ use vmm_sys_util::eventfd::EventFd;
type Result<T> = result::Result<T, Error>;
// Reserve 32 IRQs for legacy device.
pub const IRQ_LEGACY_BASE: usize = 0;
pub const IRQ_LEGACY_BASE: usize = arch::layout::IRQ_BASE as usize;
pub const IRQ_LEGACY_COUNT: usize = 32;
// This Gic struct implements InterruptController to provide interrupt delivery service.
@@ -25,6 +27,7 @@ pub const IRQ_LEGACY_COUNT: usize = 32;
// 2. Move this file and ioapic.rs to arch/, as they are architecture specific.
pub struct Gic {
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
gic_device: Option<Arc<Mutex<Box<dyn GicDevice>>>>,
}
impl Gic {
@@ -41,8 +44,17 @@ impl Gic {
Ok(Gic {
interrupt_source_group,
gic_device: None,
})
}
pub fn set_gic_device(&mut self, gic_device: Arc<Mutex<Box<dyn GicDevice>>>) {
self.gic_device = Some(gic_device);
}
pub fn get_gic_device(&self) -> Option<&Arc<Mutex<Box<dyn GicDevice>>>> {
self.gic_device.as_ref()
}
}
impl InterruptController for Gic {
@@ -58,7 +70,7 @@ impl InterruptController for Gic {
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
let config = LegacyIrqSourceConfig {
irqchip: 0,
pin: i as u32,
pin: (i - IRQ_LEGACY_BASE) as u32,
};
self.interrupt_source_group
.update(

View File

@@ -14,13 +14,17 @@ use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use std::result;
use std::sync::{Arc, Barrier};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
MsiIrqGroupConfig, MsiIrqSourceConfig,
};
use vm_device::BusDevice;
use vm_memory::GuestAddress;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vmm_sys_util::eventfd::EventFd;
type Result<T> = result::Result<T, Error>;
@@ -133,7 +137,7 @@ pub struct Ioapic {
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
pub struct IoapicState {
id_reg: u32,
reg_sel: u32,
@@ -141,6 +145,7 @@ pub struct IoapicState {
used_entries: [bool; NUM_IOAPIC_PINS],
apic_address: u64,
}
impl VersionMapped for IoapicState {}
impl BusDevice for Ioapic {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
@@ -410,13 +415,18 @@ impl Snapshottable for Ioapic {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id, &self.state())
Snapshot::new_from_versioned_state(&self.id, &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id)?).map_err(|e| {
MigratableError::Restore(anyhow!("Could not restore state for {}: {:?}", self.id, e))
})
self.set_state(&snapshot.to_versioned_state(&self.id)?)
.map_err(|e| {
MigratableError::Restore(anyhow!(
"Could not restore state for {}: {:?}",
self.id,
e
))
})
}
}

View File

@@ -11,9 +11,13 @@ use crate::{read_le_u32, write_le_u32};
use std::result;
use std::sync::{Arc, Barrier};
use std::{fmt, io};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
const OFS_DATA: u64 = 0x400; // Data Register
const GPIODIR: u64 = 0x400; // Direction Register
@@ -85,7 +89,7 @@ pub struct Gpio {
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
pub struct GpioState {
data: u32,
old_in_data: u32,
@@ -98,6 +102,8 @@ pub struct GpioState {
afsel: u32,
}
impl VersionMapped for GpioState {}
impl Gpio {
/// Constructs an PL061 GPIO device.
pub fn new(id: String, interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Self {
@@ -313,11 +319,11 @@ impl Snapshottable for Gpio {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id, &self.state())
Snapshot::new_from_versioned_state(&self.id, &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id)?);
self.set_state(&snapshot.to_versioned_state(&self.id)?);
Ok(())
}
}

View File

@@ -8,9 +8,13 @@
use std::collections::VecDeque;
use std::sync::{Arc, Barrier};
use std::{io, result};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
use vmm_sys_util::errno::Result;
const LOOP_SIZE: usize = 0x40;
@@ -70,7 +74,7 @@ pub struct Serial {
out: Option<Box<dyn io::Write + Send>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
pub struct SerialState {
interrupt_enable: u8,
interrupt_identification: u8,
@@ -82,6 +86,7 @@ pub struct SerialState {
baud_divisor: u16,
in_buffer: Vec<u8>,
}
impl VersionMapped for SerialState {}
impl Serial {
pub fn new(
@@ -288,11 +293,11 @@ impl Snapshottable for Serial {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id, &self.state())
Snapshot::new_from_versioned_state(&self.id, &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id)?);
self.set_state(&snapshot.to_versioned_state(&self.id)?);
Ok(())
}
}

View File

@@ -11,9 +11,13 @@ use std::collections::VecDeque;
use std::fmt;
use std::sync::{Arc, Barrier};
use std::{io, result};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_migration::{
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
};
/* Registers */
const UARTDR: u64 = 0;
@@ -86,7 +90,7 @@ pub struct Pl011 {
out: Option<Box<dyn io::Write + Send>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
pub struct Pl011State {
flags: u32,
lcr: u32,
@@ -104,6 +108,8 @@ pub struct Pl011State {
read_trigger: u32,
}
impl VersionMapped for Pl011State {}
impl Pl011 {
/// Constructs an AMBA PL011 UART device.
pub fn new(
@@ -357,11 +363,11 @@ impl Snapshottable for Pl011 {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id, &self.state())
Snapshot::new_from_versioned_state(&self.id, &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id)?);
self.set_state(&snapshot.to_versioned_state(&self.id)?);
Ok(())
}
}

View File

@@ -6,24 +6,11 @@
// found in the LICENSE-BSD-3-Clause file.
//! Emulates virtual and hardware devices.
extern crate anyhow;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate epoll;
extern crate libc;
#[macro_use]
extern crate log;
#[cfg(feature = "acpi")]
extern crate acpi_tables;
extern crate serde;
extern crate vm_device;
extern crate vm_memory;
extern crate vm_migration;
extern crate vmm_sys_util;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "acpi")]
pub mod acpi;

View File

@@ -78,7 +78,7 @@ Ubuntu distributions.
```bash
apt update
apt install fio iperf iperf3 socat
apt install fio iperf iperf3 socat stress
```
### Remove counterproductive packages

View File

@@ -31,7 +31,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
$ popd
```
Notice the addition of `--api-socket=/tmp/ch-socket` and a `max` parameter on `--cpus boot=4.max=8`.
Notice the addition of `--api-socket=/tmp/ch-socket` and a `max` parameter on `--cpus boot=4,max=8`.
To ask the VMM to add additional vCPUs then use the resize API:

View File

@@ -19,7 +19,7 @@ following [instructions](https://github.com/intel/linux-sgx).
## Cloud-Hypervisor support
Assuming the host exposes `/dev/sgx_virt_epc`, we can pass SGX enclaves through
Assuming the host exposes `/dev/sgx_vepc`, we can pass SGX enclaves through
the guest.
In order to use SGX enclaves within a Cloud-Hypervisor VM, we must define one
@@ -43,7 +43,7 @@ have been correctly created under `/dev/sgx`:
```bash
ls /dev/sgx*
/dev/sgx_enclave /dev/sgx_provision /dev/sgx_virt_epc
/dev/sgx_enclave /dev/sgx_provision /dev/sgx_vepc
```
From this point, it is possible to run any SGX application from the guest, as
@@ -51,5 +51,5 @@ it will access `/dev/sgx_enclave` device to create dedicated SGX enclaves.
Note: There is only one contiguous SGX EPC region, which contains all SGX EPC
sections. This region is exposed through ACPI and marked as reserved through
the e820 table. It is treated yet as another device, which means it should
the e820 table. It is treated as yet another device, which means it should
appear at the end of the guest address space.

139
docs/live_migration.md Normal file
View File

@@ -0,0 +1,139 @@
# Live Migration
This document gives two examples of how to use the live migration
support in Cloud Hypervisor:
1. local migration - migrating between two VMs running on the same
machine;
1. nested-vm migration - migrating between two nested VMs whose host VMs
are running on the same machine.
## Local Migration
Launch the source VM (on the host machine):
```bash
$ target/release/cloud-hypervisor
--kernel ~/workloads/vmlinux \
--disk path=~/workloads/focal.raw \
--cpus boot=1 --memory size=1G \
--cmdline "root=/dev/vda1 console=ttyS0" \
--serial tty --console off --api-socket=/tmp/api1
```
Launch the destination VM from the same directory (on the host machine):
```bash
$ target/release/cloud-hypervisor --api-socket=/tmp/api2
```
Get ready for receiving migration for the destination VM (on the host machine):
```bash
$ target/release/ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/sock
```
Start to send migration for the source VM (on the host machine):
```bash
$ target/release/ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/sock
```
When the above commands completed, the source VM should be successfully
migrated to the destination VM. Now the destination VM is running while
the source VM is paused.
## Nested-VM Migration
Launch VM 1 (on the host machine) with an extra virtio-blk device for
exposing a guest image for the nested source VM:
> Note: the example below also attached an additional virtio-blk device
> with a dummy image for testing purpose (which is optional).
```bash
$ head -c 1M < /dev/urandom > tmp.img # create a dummy image for testing
$ sudo /target/release/cloud-hypervisor \
--serial tty --console off \
--cpus boot=1 --memory size=512M \
--kernel vmlinux \
--cmdline "root=/dev/vda1 console=ttyS0" \
--disk path=focal-1.raw path=focal-nested.raw path=tmp.img\
--net ip=192.168.101.1
```
Launch VM 2 (on the host machine) with an extra virtio-blk device for
exposing the same guest image for the nested destination VM:
```bash
$ sudo /target/release/cloud-hypervisor \
--serial tty --console off \
--cpus boot=1 --memory size=512M \
--kernel vmlinux \
--cmdline "root=/dev/vda1 console=ttyS0" \
--disk path=focal-2.raw path=focal-nested.raw path=tmp.img\
--net ip=192.168.102.1
```
Launch the nested source VM (inside the guest OS of the VM 1) :
```bash
vm-1:~$ sudo ./cloud-hypervisor \
--serial tty --console off \
--memory size=128M \
--kernel vmlinux \
--cmdline "console=ttyS0 root=/dev/vda1" \
--disk path=/dev/vdb path=/dev/vdc \
--api-socket=/tmp/api1 \
--net ip=192.168.100.1
vm-1:~$ # setup the guest network if needed
vm-1:~$ sudo ip addr add 192.168.101.2/24 dev ens4
vm-1:~$ sudo ip link set up dev ens4
vm-1:~$ sudo ip r add default via 192.168.101.1
```
Optional: Run the guest workload below (on the guest OS of the nested source VM),
which performs intensive virtio-blk operations. Now the console of the nested
source VM should repeatedly print `"equal"`, and our goal is migrating
this VM and the running workload without interruption.
```bash
#/bin/bash
# On the guest OS of the nested source VM
input="/dev/vdb"
result=$(md5sum $input)
tmp=$(md5sum $input)
while [[ "$result" == "$tmp" ]]
do
echo "equal"
tmp=$(md5sum $input)
done
echo "not equal"
echo "result = $result"
echo "tmp = $tmp"
```
Launch the nested destination VM (inside the guest OS of the VM 2):
```bash
vm-2:~$ sudo ./cloud-hypervisor --api-socket=/tmp/api2
vm-2:~$ # setup the guest network with the following commands if needed
vm-2:~$ sudo ip addr add 192.168.102.2/24 dev ens4
vm-2:~$ sudo ip link set up dev ens4
vm-2:~$ sudo ip r add default via 192.168.102.1
vm-2:~$ ping 192.168.101.2 # This should succeed
```
> Note: If the above ping failed, please check the iptables rule on the
> host machine, e.g. whether the policy for the `FORWARD` chain is set
> to `DROP` (which is the default setting configured by Docker).
Get ready for receiving migration for the nested destination VM (inside
the guest OS of the VM 2):
```bash
vm-2:~$ sudo ./ch-remote --api-socket=/tmp/api2 receive-migration unix:/tmp/sock2
vm-2:~$ sudo socat TCP-LISTEN:6000,reuseaddr UNIX-CLIENT:/tmp/sock2
```
Start to send migration for the nested source VM (inside the guest OS of
the VM 1):
```bash
vm-1:~$ sudo socat UNIX-LISTEN:/tmp/sock1,reuseaddr TCP:192.168.102.2:6000
vm-1:~$ sudo ./ch-remote --api-socket=/tmp/api1 send-migration unix:/tmp/sock1
```
When the above commands completed, the source VM should be successfully
migrated to the destination VM without interrupting our testing guest
workload. Now the destination VM is running the testing guest workload
while the source VM is paused.

View File

@@ -1,6 +1,6 @@
# Using MACVTAP to Bridge onto Host Network
Cloud Hypervisor supports using a MACVTAP device which is derived from a MACVLAN. Full details of configuring MACVLAN or MACVTAP is out of scope of this document. However the example below indicates how to bridge the guest directly onto the the network the host is on. Due to the lack of hairpin mode it not usually possible to reach the guest directly from the host.
Cloud Hypervisor supports using a MACVTAP device which is derived from a MACVLAN. Full details of configuring MACVLAN or MACVTAP is out of scope of this document. However the example below indicates how to bridge the guest directly onto the network the host is on. Due to the lack of hairpin mode it not usually possible to reach the guest directly from the host.
```bash
# The MAC address must be attached to the macvtap and be used inside the guest

View File

@@ -1,6 +1,6 @@
# Profiling
`perf` can be used to profile the `cloud-hypervisor` binary but it is necessary to make some modifications to the the build in order to produce a binary that gives useful results.
`perf` can be used to profile the `cloud-hypervisor` binary but it is necessary to make some modifications to the build in order to produce a binary that gives useful results.
## Building a suitable binary

View File

@@ -11,7 +11,7 @@ by the VFIO kernel drivers. However, by default, a host device will be bound to
its native driver, which is not the VFIO one.
As a consequence, a device must be unbound from its native driver before passing
it to `cloud-hypervisor` for assigning it to a guess.
it to `cloud-hypervisor` for assigning it to a guest.
### Example

View File

@@ -35,38 +35,52 @@ Here are some good references for detailing them.
## Test environment
The below test environment is based on ubuntu release(16.04.1 LTS), as for other system, please check related document.
The test runs with multiple queue (MQ) support enabled, using 4 queues defined for both SPDK and the virtual machine.
Here are the details on how the test can be run.
The below test environment is based on Ubuntu release (20.04.1 LTS), as for other system, please check related documents.
This test runs with multiple queue (MQ) support enabled, using 4 queues defined for both SPDK and the virtual machine.
Here are the detailed instructions.
### The hugepages settings in host linux
Add "default_hugepagesz=1G hugepagesz=1G hugepages=2" into host linux cmdline.
As for how to change Ubuntu linux cmdline in grub file, please ref below link:
https://www.ostechnix.com/configure-grub-2-boot-loader-settings-ubuntu-16-04/
reboot Ubuntu
sudo mount -t hugetlbfs -o pagesize=1G none /dev/hugepages
### The hugepages settings on the host
Allocate enough persistent huge pages (e.g. 2GiB) on the host:
```bash
# Assume the default hugepage size is 2MiB
echo 1024 | sudo tee /proc/sys/vm/nr_hugepages
# Confirm the value of "Hugepagesize" and "HugePages_Total"
cat /proc/meminfo | grep -i huge
```
### Download the SPDK code
```bash
git clone https://github.com/spdk/spdk
cd spdk
git submodule update --init
```
### Create the build dep
./scripts/pkgdep.sh
### Build spdk
```bash
./scripts/pkgdep.sh
```
### Build SPDK
```bash
./configure
make
```
### Set the SPDk environment
### Set the SPDK environment
```bash
sudo HUGEMEM=2048 scripts/setup.sh
sudo ./app/vhost/vhost -S /var/tmp -s 1024 -m 0x3 &
sudo ./build/bin/vhost -S /var/tmp -s 1024 -m 0x3 &
```
### Create 512M block device
```bash
sudo scripts/rpc.py bdev_malloc_create 512 512 -b Malloc0
sudo scripts/rpc.py vhost_create_blk_controller --cpumask 0x1 vhost.1 Malloc0
```
_Launch the VM_
### Launch the VM
VMs run in client mode. They connect to the socket created by the `dpdkvhostuser` in the SPDK backend.
```bash
@@ -89,9 +103,9 @@ login in guest
# Use lsblk command to find out vhost-user-blk device
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 252:0 0 2.2G 0 disk
vda 252:0 0 2.2G 0 disk
├─vda1 252:1 0 2.1G 0 part /
├─vda14 252:14 0 4M 0 part
├─vda14 252:14 0 4M 0 part
└─vda15 252:15 0 106M 0 part /boot/efi
vdb 253:16 0 512M 0 disk

View File

@@ -1,27 +1,30 @@
# How to test Vhost-user net with OpenVSwitch/DPDK
The purpose of this document is to illustrate how to test vhost-user-net in cloud-hypervisor with OVS/DPDK as the backend.
The purpose of this document is to illustrate how to test vhost-user-net
in cloud-hypervisor with OVS/DPDK as the backend. This document was
tested with Open vSwitch v2.13.1, DPDK v19.11.3, and Cloud Hypervisor
v15.0 on Ubuntu 20.04.1 (host kernel v5.4.0).
## Framework
It's a simple test to validate the communication between two virtual machine, connecting them to vhost-user ports respectively provided by `OVS/DPDK`.
```
+----+----------+ +-------------+-----------+-------------+ +----------+----+
| | | | | | | | | |
| |vhost-user|----------| vhost-user | ovs | vhost-user |----------|vhost-user| |
| |net device| | port 1 | | port 2 | |net device| |
| | | | | | | | | |
| +----------+ +-------------+-----------+-------------+ +----------+ |
| | | | | |
|vm1 | | dpdk | | vm2 |
| | | | | |
+--+---------------------------------------------------------------------------------------------+--+
| | hugepages | |
| +---------------------------------------------------------------------------------------------+ |
| |
| host |
| |
+---------------------------------------------------------------------------------------------------+
+----+----------+ +-------------+-----------+-------------+ +----------+----+
| | | | | | | | | |
| |vhost-user|----------| vhost-user | ovs | vhost-user |----------|vhost-user| |
| |net device| | port 1 | | port 2 | |net device| |
| | | | | | | | | |
| +----------+ +-------------+-----------+-------------+ +----------+ |
| | | | | |
|vm1 | | dpdk | | vm2 |
| | | | | |
+--+---------------------------------------------------------------------------------------------+--+
| | hugepages | |
| +---------------------------------------------------------------------------------------------+ |
| |
| host |
| |
+---------------------------------------------------------------------------------------------------+
```
## Prerequisites
@@ -30,44 +33,54 @@ Prior to running the test, the following steps need to be performed.
- Install DPDK
- Install OVS
Here are some good references for detailing them.
- Red Hat
* https://wiki.qemu.org/Documentation/vhost-user-ovs-dpdk
- Ubuntu server
* https://help.ubuntu.com/lts/serverguide/DPDK.html
* https://software.intel.com/en-us/articles/set-up-open-vswitch-with-dpdk-on-ubuntu-server
Here is a good reference for setting up OVS with DPDK from scratch:
https://docs.openvswitch.org/en/latest/intro/install/dpdk/.
On Ubuntu systems (18.04 or newer), the OpenVswitch-DPDK package can be
easily installed with:
```bash
sudo apt-get update
sudo apt-get install openvswitch-switch-dpdk
sudo update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
```
## Test
The test runs with multiple queue (MQ) support enabled, using 2 pairs of TX/RX queues defined for both OVS and the virtual machine. Here are the details on how the test can be run.
The test runs with multiple queue (MQ) support enabled, using 2 pairs of
TX/RX queues defined for both OVS and the virtual machine. Here are the
detailed instructions.
_Setup OVS_
`ovs_test.sh` is created to setup and start OVS. OVS will provide the `dpdkvhostuser` backend running in server mode.
Here is an example how to configure a basic OpenVswitch using DPDK:
```bash
mkdir -p /var/run/openvswitch
# load the ovs kernel module
modprobe openvswitch
killall ovsdb-server ovs-vswitchd
rm -f /var/run/openvswitch/vhost-user*
rm -f /etc/openvswitch/conf.db
export DB_SOCK=/var/run/openvswitch/db.sock
ovsdb-tool create /etc/openvswitch/conf.db /usr/share/openvswitch/vswitch.ovsschema
ovsdb-server --remote=punix:$DB_SOCK --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach
ovs-vsctl --no-wait init
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0xf
ovs-vswitchd unix:$DB_SOCK --pidfile --detach --log-file=/var/log/openvswitch/ovs-vswitchd.log
sudo service openvswitch-switch start
ovs-vsctl init
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
# run on core 0-3 only
ovs-vsctl set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
# allocate 2G huge pages (to NUMA 0 only)
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024
# run PMD (Pull Mode Driver) threads on core 0-3 only
ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0xf
sudo service openvswitch-switch restart
# double check the configurations
ovs-vsctl list Open_vSwitch
```
Here is an example how to create a bridge and add two DPDK ports to it
(for later use via Cloud Hypervisor):
```bash
# create a bridge
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
# create two DPDK ports and add them to the bridge
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2
type=dpdkvhostuser
# set the number of rx queues
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
```
_Run ovs_test.sh_
```bash
./ovs_test.sh
```
_Launch the VMs_
@@ -89,19 +102,21 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
--kernel vmlinux \
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
--disk path=focal-server-cloudimg-amd64.raw \
--net "mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4"
--net mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4
```
_Setup VM1_
```bash
# From inside the guest
sudo ip addr add 172.100.0.1/24 dev enp0s3
sudo ip addr add 172.100.0.1/24 dev ens2
sudo ip link set up dev ens2
```
_Setup VM2_
```bash
# From inside the guest
sudo ip addr add 172.100.0.2/24 dev enp0s3
sudo ip addr add 172.100.0.2/24 dev ens2
sudo ip link set up dev ens2
```
_Ping VM1 from VM2_
@@ -129,4 +144,3 @@ _Run VM2 as client_
# From inside the guest
iperf3 -c 172.100.0.1 -t 30 -p 4444 &
```

View File

@@ -192,6 +192,8 @@ RAM hotplug is supported. Note, that while the `pnpmem.sys` driver in use suppor
Network device hotplug and hot-remove are supported.
Disk hotplug and hot-remove are supported. After the device has been hotplugged, it will need to be onlined from within the guest. Among other tools, powershell applets `Get-Disk` and `Set-Disk` can be used for the disk configuration and activation.
## Debugging
The Windows guest debugging process relies heavily on QEMU and [socat](http://www.dest-unreach.org/socat/). The procedure requires two Windows VMs:

View File

@@ -5,7 +5,7 @@ authors = ["The Cloud Hypervisor Authors"]
edition = "2018"
[dependencies]
libc = "0.2.94"
libc = "0.2.96"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"

174
fuzz/Cargo.lock generated
View File

@@ -30,15 +30,15 @@ version = "0.1.0"
[[package]]
name = "arbitrary"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b"
checksum = "237430fd6ed3740afe94eefcc278ae21e050285be882804e0d6e8695f0c94691"
[[package]]
name = "arc-swap"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
checksum = "e906254e445520903e7fc9da4f709886c84ae4bc4ddaf0e093188d66df4dc820"
[[package]]
name = "arch"
@@ -46,24 +46,20 @@ version = "0.1.0"
dependencies = [
"acpi_tables",
"anyhow",
"arch_gen",
"byteorder",
"hypervisor",
"libc",
"linux-loader",
"log",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"vm-fdt",
"vm-memory",
"vm-migration",
]
[[package]]
name = "arch_gen"
version = "0.1.0"
[[package]]
name = "atty"
version = "0.2.14"
@@ -75,6 +71,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.2.1"
@@ -89,10 +94,9 @@ dependencies = [
"libc",
"log",
"qcow",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"virtio-bindings",
"vm-memory",
"vm-virtio",
@@ -107,9 +111,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.67"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "cfg-if"
@@ -135,7 +139,7 @@ dependencies = [
[[package]]
name = "cloud-hypervisor"
version = "0.14.0"
version = "15.0.0"
dependencies = [
"anyhow",
"api_client",
@@ -171,20 +175,26 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "crc64"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
[[package]]
name = "devices"
version = "0.1.0"
dependencies = [
"acpi_tables",
"anyhow",
"arch",
"bitflags",
"byteorder",
"epoll",
"libc",
"log",
"serde",
"serde_derive",
"serde_json",
"versionize",
"versionize_derive",
"vm-device",
"vm-memory",
"vm-migration",
@@ -241,9 +251,9 @@ dependencies = [
[[package]]
name = "iced-x86"
version = "1.11.1"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b85a147f5dcb22ece887da5b99187954cc046939f22416e953dd7c336e85a1"
checksum = "6d907dfc273d9ed0da940e8145ceb77759056a1fb2110b44b83d1b203cddb906"
dependencies = [
"lazy_static",
"static_assertions",
@@ -277,9 +287,9 @@ dependencies = [
[[package]]
name = "kvm-ioctls"
version = "0.8.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74058b16912c6723db02d4ca3ec919b73cd41512ccd3b6202cf91ae8d6c9dce5"
checksum = "f2924454e22895c738e43331ae310459c74a11ded9c97dc250129ee10d2f9ca2"
dependencies = [
"kvm-bindings",
"libc",
@@ -294,18 +304,19 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.94"
version = "0.2.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc"
[[package]]
name = "libfuzzer-sys"
version = "0.4.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86c975d637bc2a2f99440932b731491fc34c7f785d239e38af3addd3c2fd0e46"
checksum = "36a9a84a6e8b55dfefb04235e55edb2b9a2a18488fcae777a6bdaa6f06f1deb3"
dependencies = [
"arbitrary",
"cc",
"once_cell",
]
[[package]]
@@ -352,12 +363,20 @@ dependencies = [
"net_gen",
"rate_limiter",
"serde",
"versionize",
"versionize_derive",
"virtio-bindings",
"vm-memory",
"vm-virtio",
"vmm-sys-util",
]
[[package]]
name = "once_cell"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "option_parser"
version = "0.1.0"
@@ -371,9 +390,8 @@ dependencies = [
"hypervisor",
"libc",
"log",
"serde",
"serde_derive",
"serde_json",
"versionize",
"versionize_derive",
"vfio-bindings",
"vfio-ioctls",
"vm-allocator",
@@ -385,9 +403,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
dependencies = [
"unicode-xid",
]
@@ -441,22 +459,22 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "seccomp"
version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/firecracker?tag=v0.24.2#5ba819d7b7a684107f5434bcbd1617bc94565478"
source = "git+https://github.com/firecracker-microvm/firecracker?tag=v0.24.4#8f44986a0e956a77f2b2324c12f73bec16130c82"
dependencies = [
"libc",
]
[[package]]
name = "serde"
version = "1.0.125"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
[[package]]
name = "serde_derive"
version = "1.0.125"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote",
@@ -476,9 +494,9 @@ dependencies = [
[[package]]
name = "signal-hook"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39"
dependencies = [
"libc",
"signal-hook-registry",
@@ -486,9 +504,9 @@ dependencies = [
[[package]]
name = "signal-hook-registry"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
@@ -507,9 +525,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.71"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
dependencies = [
"proc-macro2",
"quote",
@@ -538,18 +556,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
dependencies = [
"proc-macro2",
"quote",
@@ -564,9 +582,15 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "vec_map"
@@ -574,6 +598,34 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "versionize"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7429cf68de8f091b667d27323ed323afd39584a56d533995b12ddd748e5e6ca9"
dependencies = [
"bincode",
"crc64",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn",
"versionize_derive",
"vmm-sys-util",
]
[[package]]
name = "versionize_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "140aa9fd298f667ea50fa1cb0d8530076924079285c623b18b8f8a1c28386b4a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "vfio-bindings"
version = "0.2.0"
@@ -586,7 +638,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=master#a87b13bdec026e8144b91f30f35451a966d8c1ca"
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=master#5cb8550556620546e74b9fe6d1174e0d1fc83888"
dependencies = [
"byteorder",
"kvm-bindings",
@@ -600,7 +652,7 @@ dependencies = [
[[package]]
name = "vhost"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vhost?branch=master#ee3e8722706c984b3dfe12d3a130e92101b78e8f"
source = "git+https://github.com/rust-vmm/vhost?branch=master#e5b930b73a47cbdd79858e2e68bcb57123d1c1f3"
dependencies = [
"bitflags",
"libc",
@@ -634,6 +686,8 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"versionize",
"versionize_derive",
"vhost",
"virtio-bindings",
"vm-allocator",
@@ -667,11 +721,15 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "vm-fdt"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vm-fdt?branch=master#13ab882e2f8387753064351c69fbe35c422b448b"
[[package]]
name = "vm-memory"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625f401b1b8b3ac3d43f53903cd138cfe840bd985f8581e553027b31d2bb8ae8"
source = "git+https://github.com/rust-vmm/vm-memory?rev=5bd7138758183a73ac0da27ce40c004d95f1a7e9#5bd7138758183a73ac0da27ce40c004d95f1a7e9"
dependencies = [
"arc-swap",
"libc",
@@ -687,6 +745,8 @@ dependencies = [
"serde_derive",
"serde_json",
"thiserror",
"versionize",
"versionize_derive",
"vm-memory",
]
@@ -695,9 +755,6 @@ name = "vm-virtio"
version = "0.1.0"
dependencies = [
"log",
"serde",
"serde_derive",
"serde_json",
"virtio-bindings",
"vm-memory",
]
@@ -732,6 +789,9 @@ dependencies = [
"serde_json",
"signal-hook",
"thiserror",
"uuid",
"versionize",
"versionize_derive",
"vfio-ioctls",
"virtio-devices",
"vm-allocator",

View File

@@ -10,21 +10,22 @@ cargo-fuzz = true
[dependencies]
block_util = { path = "../block_util" }
libc = "0.2.94"
libfuzzer-sys = "0.4"
libc = "0.2.96"
libfuzzer-sys = "0.4.2"
qcow = { path = "../qcow" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.2" }
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.24.4" }
virtio-devices = { path = "../virtio-devices" }
vmm-sys-util = "0.8.0"
vm-virtio = { path = "../vm-virtio" }
vm-memory = "0.5.0"
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
[dependencies.cloud-hypervisor]
path = ".."
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"] }
vm-memory = { git = "https://github.com/rust-vmm/vm-memory", rev = "5bd7138758183a73ac0da27ce40c004d95f1a7e9"}
# Prevent this from interfering with workspaces
[workspace]
members = ["."]

View File

@@ -14,9 +14,9 @@ tdx = []
anyhow = "1.0"
epoll = ">=4.0.1"
thiserror = "1.0"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
kvm-ioctls = { version = "0.8.0", optional = true }
kvm-ioctls = { version = "0.9.0", optional = true }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.4.0", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-bindings = {git = "https://github.com/cloud-hypervisor/mshv", branch = "master", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-ioctls = { git = "https://github.com/cloud-hypervisor/mshv", branch = "master", optional = true}

View File

@@ -4,8 +4,6 @@
// SPDX-License-Identifier: Apache-2.0
//
extern crate thiserror;
use core::fmt::Debug;
use std::fmt::{self, Display};
use thiserror::Error;

View File

@@ -10,8 +10,6 @@
// CMP-Compare Two Operands
//
extern crate iced_x86;
use crate::arch::emulator::{EmulationError, PlatformEmulator};
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::*;

View File

@@ -4,8 +4,6 @@
// SPDX-License-Identifier: Apache-2.0
//
extern crate iced_x86;
use crate::arch::emulator::{EmulationError, PlatformEmulator, PlatformError};
use crate::arch::x86::emulator::CpuStateManager;
use crate::arch::x86::Exception;
@@ -14,6 +12,7 @@ use iced_x86::*;
pub mod cmp;
pub mod mov;
pub mod movs;
pub mod or;
fn get_op<T: CpuStateManager>(
insn: &Instruction,

View File

@@ -12,8 +12,6 @@
// Copies the second operand (source operand) to the first operand (destination operand).
//
extern crate iced_x86;
use crate::arch::emulator::{EmulationError, PlatformEmulator};
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::Exception;

View File

@@ -10,8 +10,6 @@
// MOVS - Move Data from String to String
//
extern crate iced_x86;
use crate::arch::emulator::{EmulationError, PlatformEmulator};
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::DF;

View File

@@ -0,0 +1,83 @@
//
// Copyright © 2021 Microsoft
//
// SPDX-License-Identifier: Apache-2.0
//
#![allow(non_camel_case_types)]
//
// OR - Logical inclusive OR
//
use crate::arch::emulator::{EmulationError, PlatformEmulator};
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::Exception;
macro_rules! or_rm_r {
($bound:ty) => {
fn emulate(
&self,
insn: &Instruction,
state: &mut T,
platform: &mut dyn PlatformEmulator<CpuState = T>,
) -> Result<(), EmulationError<Exception>> {
let src_reg_value = get_op(&insn, 1, std::mem::size_of::<$bound>(), state, platform)
.map_err(EmulationError::PlatformEmulationError)?;
let dst_value = get_op(&insn, 0, std::mem::size_of::<$bound>(), state, platform)
.map_err(EmulationError::PlatformEmulationError)?;
let result = src_reg_value | dst_value;
set_op(
&insn,
0,
std::mem::size_of::<$bound>(),
state,
platform,
result,
)
.map_err(EmulationError::PlatformEmulationError)?;
Ok(())
}
};
}
pub struct Or_rm8_r8;
impl<T: CpuStateManager> InstructionHandler<T> for Or_rm8_r8 {
or_rm_r!(u8);
}
#[cfg(test)]
mod tests {
#![allow(unused_mut)]
use super::*;
use crate::arch::x86::emulator::mock_vmm::*;
#[test]
// or byte ptr [rax+1h], sil
fn test_or_rm8_r8() {
let rax = 0;
let insn = [0x40, 0x08, 0x70, 0x1];
let cpu_id = 0;
let ip: u64 = 0x1000;
let sil = 0xaa;
let memory = [0x0, 0x55];
let mut vmm = MockVmm::new(
ip,
vec![(Register::SIL, sil), (Register::RAX, rax)],
Some((0, &memory)),
);
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
let mut out: [u8; 1] = [0; 1];
vmm.read_memory(rax + 1, &mut out).unwrap();
assert_eq!(u8::from_le_bytes(out), 0xff);
}
}

View File

@@ -4,8 +4,6 @@
// SPDX-License-Identifier: Apache-2.0
//
extern crate iced_x86;
use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::*;
@@ -526,7 +524,9 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
(mov, Movzx_r32_rm16),
(mov, Movzx_r64_rm16),
// MOVS
(movs, Movsd_m32_m32)
(movs, Movsd_m32_m32),
// OR
(or, Or_rm8_r8)
);
handler
@@ -640,8 +640,6 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
mod mock_vmm {
#![allow(unused_mut)]
extern crate env_logger;
use super::*;
use crate::arch::emulator::{EmulationError, PlatformEmulator};
use crate::arch::x86::emulator::{Emulator, EmulatorCpuState as CpuState};
@@ -718,7 +716,7 @@ mod mock_vmm {
"Memory read {} bytes from [{:#x} -> {:#x}]",
data.len(),
gva,
gva
gva + data.len() as u64 - 1
);
data.copy_from_slice(&self.memory[gva as usize..gva as usize + data.len()]);
Ok(())
@@ -729,7 +727,7 @@ mod mock_vmm {
"Memory write {} bytes at [{:#x} -> {:#x}]",
data.len(),
gva,
gva
gva + data.len() as u64 - 1
);
self.memory[gva as usize..gva as usize + data.len()].copy_from_slice(data);

View File

@@ -12,8 +12,6 @@ use crate::vm::Vm;
use crate::x86_64::CpuId;
#[cfg(target_arch = "x86_64")]
use crate::x86_64::MsrList;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
use kvm_ioctls::Cap;
use std::sync::Arc;
use thiserror::Error;
@@ -42,16 +40,6 @@ pub enum HypervisorError {
#[error("Failed to get API Version: {0}")]
GetApiVersion(#[source] anyhow::Error),
///
/// Vcpu mmap error
///
#[error("Failed to get Vcpu Mmap: {0}")]
GetVcpuMmap(#[source] anyhow::Error),
///
/// Max Vcpu error
///
#[error("Failed to get number of max vcpus: {0}")]
GetMaxVcpu(#[source] anyhow::Error),
///
/// CpuId error
///
#[error("Failed to get cpuid: {0}")]
@@ -66,6 +54,11 @@ pub enum HypervisorError {
///
#[error("Incompatible API version")]
IncompatibleApiVersion,
///
/// Checking extensions failed
///
#[error("Checking extensions:{0}")]
CheckExtensions(#[source] anyhow::Error),
}
///
@@ -84,45 +77,32 @@ pub trait Hypervisor: Send + Sync {
/// Return a hypervisor-agnostic Vm trait object
///
fn create_vm(&self) -> Result<Arc<dyn Vm>>;
#[cfg(feature = "kvm")]
///
/// Create a Vm of a specific type using the underlying hypervisor
/// Return a hypervisor-agnostic Vm trait object
///
fn create_vm_with_type(&self, vm_type: u64) -> Result<Arc<dyn Vm>>;
#[cfg(feature = "kvm")]
///
/// Returns the size of the memory mapping required to use the vcpu's structures
///
fn get_vcpu_mmap_size(&self) -> Result<usize>;
#[cfg(feature = "kvm")]
///
/// Gets the recommended maximum number of VCPUs per VM.
///
fn get_max_vcpus(&self) -> Result<usize>;
#[cfg(feature = "kvm")]
///
/// Gets the recommended number of VCPUs per VM.
///
fn get_nr_vcpus(&self) -> Result<usize>;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
///
/// Checks if a particular `Cap` is available.
///
fn check_capability(&self, c: Cap) -> bool;
fn create_vm_with_type(&self, _vm_type: u64) -> Result<Arc<dyn Vm>> {
unreachable!()
}
#[cfg(target_arch = "x86_64")]
///
/// Get the supported CpuID
///
fn get_cpuid(&self) -> Result<CpuId>;
#[cfg(not(feature = "mshv"))]
///
/// Check particular extensions if any
///
fn check_required_extensions(&self) -> Result<()>;
fn check_required_extensions(&self) -> Result<()> {
Ok(())
}
#[cfg(target_arch = "x86_64")]
///
/// Retrieve the list of MSRs supported by the hypervisor.
///
fn get_msr_list(&self) -> Result<MsrList>;
#[cfg(target_arch = "aarch64")]
///
/// Retrieve AArch64 host maximum IPA size supported by KVM.
///
fn get_host_ipa_limit(&self) -> i32;
}

View File

@@ -32,19 +32,17 @@ pub use {kvm_ioctls::Cap, kvm_ioctls::Kvm};
// This macro gets the offset of a structure (i.e `str`) member (i.e `field`) without having
// an instance of that structure.
// It uses a null pointer to retrieve the offset to the field.
// Inspired by C solution: `#define offsetof(str, f) ((size_t)(&((str *)0)->f))`.
// Doing `offset__of!(user_pt_regs, pstate)` in our rust code will trigger the following:
// unsafe { &(*(0 as *const user_pt_regs)).pstate as *const _ as usize }
// The dereference expression produces an lvalue, but that lvalue is not actually read from,
// we're just doing pointer math on it, so in theory, it should safe.
#[macro_export]
macro_rules! offset__of {
($str:ty, $field:ident) => {
unsafe { &(*std::ptr::null::<$str>()).$field as *const _ as usize }
};
}
($str:ty, $($field:ident)+) => ({
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
let tmp = unsafe { tmp.assume_init() };
let base = &tmp as *const _ as usize;
let member = &tmp.$($field)* as *const _ as usize;
member - base
});
}
// Get the ID of a core register
#[macro_export]
macro_rules! arm64_core_reg_id {

View File

@@ -22,6 +22,8 @@ use crate::vm::{self, VmmOps};
use crate::{arm64_core_reg_id, offset__of};
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
use serde_derive::{Deserialize, Serialize};
#[cfg(target_arch = "aarch64")]
use std::convert::TryInto;
use std::os::unix::io::{AsRawFd, RawFd};
use std::result;
#[cfg(target_arch = "x86_64")]
@@ -70,9 +72,9 @@ pub use kvm_ioctls;
pub use kvm_ioctls::{Cap, Kvm};
#[cfg(target_arch = "aarch64")]
use std::mem;
use thiserror::Error;
#[cfg(feature = "tdx")]
use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_expr, ioctl_ioc_nr, ioctl_iowr_nr};
///
/// Export generically-named wrappers of kvm-bindings for Unix-based platforms
///
@@ -373,7 +375,7 @@ impl vm::Vm for KvmVm {
let data = TdxInitVm {
max_vcpus,
reserved: 0,
attributes: 0,
attributes: 1, // TDX1_TD_ATTRIBUTE_DEBUG,
cpuid: cpuid.as_fam_struct_ptr() as u64,
};
@@ -465,8 +467,9 @@ pub struct KvmHypervisor {
kvm: Kvm,
}
/// Enum for KVM related error
#[derive(Debug)]
#[derive(Debug, Error)]
pub enum KvmError {
#[error("Capability missing: {0:?}")]
CapabilityMissing(Cap),
}
pub type KvmResult<T> = result::Result<T, KvmError>;
@@ -557,41 +560,25 @@ impl hypervisor::Hypervisor for KvmHypervisor {
/// let vm = hypervisor.create_vm().unwrap()
///
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
self.create_vm_with_type(0) // Create with default platform type
#[allow(unused_mut)]
let mut vm_type: u64 = 0; // Create with default platform type
// When KVM supports Cap::ArmVmIPASize, it is better to get the IPA
// size from the host and use that when creating the VM, which may
// avoid unnecessary VM creation failures.
#[cfg(target_arch = "aarch64")]
if self.kvm.check_extension(Cap::ArmVmIPASize) {
vm_type = self.kvm.get_host_ipa_limit().try_into().unwrap();
}
self.create_vm_with_type(vm_type)
}
fn check_required_extensions(&self) -> hypervisor::Result<()> {
check_required_kvm_extensions(&self.kvm).expect("Missing KVM capabilities");
Ok(())
check_required_kvm_extensions(&self.kvm)
.map_err(|e| hypervisor::HypervisorError::CheckExtensions(e.into()))
}
///
/// Returns the size of the memory mapping required to use the vcpu's `kvm_run` structure.
///
fn get_vcpu_mmap_size(&self) -> hypervisor::Result<usize> {
self.kvm
.get_vcpu_mmap_size()
.map_err(|e| hypervisor::HypervisorError::GetVcpuMmap(e.into()))
}
///
/// Gets the recommended maximum number of VCPUs per VM.
///
fn get_max_vcpus(&self) -> hypervisor::Result<usize> {
Ok(self.kvm.get_max_vcpus())
}
///
/// Gets the recommended number of VCPUs per VM.
///
fn get_nr_vcpus(&self) -> hypervisor::Result<usize> {
Ok(self.kvm.get_nr_vcpus())
}
#[cfg(target_arch = "x86_64")]
///
/// Checks if a particular `Cap` is available.
///
fn check_capability(&self, c: Cap) -> bool {
self.kvm.check_extension(c)
}
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to get the system supported CPUID values.
@@ -601,6 +588,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
.get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
.map_err(|e| hypervisor::HypervisorError::GetCpuId(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
/// Retrieve the list of MSRs supported by KVM.
@@ -610,6 +598,13 @@ impl hypervisor::Hypervisor for KvmHypervisor {
.get_msr_index_list()
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))
}
#[cfg(target_arch = "aarch64")]
///
/// Retrieve AArch64 host maximum IPA size supported by KVM.
///
fn get_host_ipa_limit(&self) -> i32 {
self.kvm.get_host_ipa_limit()
}
}
/// Vcpu struct for KVM
pub struct KvmVcpu {

View File

@@ -23,10 +23,6 @@ extern crate anyhow;
#[cfg(target_arch = "x86_64")]
#[macro_use]
extern crate log;
extern crate serde;
extern crate serde_derive;
extern crate serde_json;
extern crate thiserror;
/// Architecture specific definitions
#[macro_use]

View File

@@ -473,7 +473,7 @@ impl cpu::Vcpu for MshvVcpu {
///
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
self.fd
.set_xsave(*xsave)
.set_xsave(xsave)
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
}
///

View File

@@ -2,6 +2,7 @@
name = "net_gen"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
[dependencies]
vmm-sys-util = ">=0.3.1"

View File

@@ -1,24 +1,27 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
/* automatically generated by rust-bindgen */
// bindgen /usr/include/linux/if_tun.h --no-layout-tests
/* automatically generated by rust-bindgen 0.58.1 */
#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
impl<T> __IncompleteArrayField<T> {
#[inline]
pub fn new() -> Self {
__IncompleteArrayField(::std::marker::PhantomData)
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,191 +33,203 @@ impl<T> __IncompleteArrayField<T> {
}
}
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_str("__IncompleteArrayField")
}
}
impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
#[inline]
fn clone(&self) -> Self {
Self::new()
}
}
impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {}
pub const __BITS_PER_LONG: ::std::os::raw::c_uint = 64;
pub const __FD_SETSIZE: ::std::os::raw::c_uint = 1024;
pub const ETH_ALEN: ::std::os::raw::c_uint = 6;
pub const ETH_HLEN: ::std::os::raw::c_uint = 14;
pub const ETH_ZLEN: ::std::os::raw::c_uint = 60;
pub const ETH_DATA_LEN: ::std::os::raw::c_uint = 1500;
pub const ETH_FRAME_LEN: ::std::os::raw::c_uint = 1514;
pub const ETH_FCS_LEN: ::std::os::raw::c_uint = 4;
pub const ETH_P_LOOP: ::std::os::raw::c_uint = 96;
pub const ETH_P_PUP: ::std::os::raw::c_uint = 512;
pub const ETH_P_PUPAT: ::std::os::raw::c_uint = 513;
pub const ETH_P_TSN: ::std::os::raw::c_uint = 8944;
pub const ETH_P_IP: ::std::os::raw::c_uint = 2048;
pub const ETH_P_X25: ::std::os::raw::c_uint = 2053;
pub const ETH_P_ARP: ::std::os::raw::c_uint = 2054;
pub const ETH_P_BPQ: ::std::os::raw::c_uint = 2303;
pub const ETH_P_IEEEPUP: ::std::os::raw::c_uint = 2560;
pub const ETH_P_IEEEPUPAT: ::std::os::raw::c_uint = 2561;
pub const ETH_P_BATMAN: ::std::os::raw::c_uint = 17157;
pub const ETH_P_DEC: ::std::os::raw::c_uint = 24576;
pub const ETH_P_DNA_DL: ::std::os::raw::c_uint = 24577;
pub const ETH_P_DNA_RC: ::std::os::raw::c_uint = 24578;
pub const ETH_P_DNA_RT: ::std::os::raw::c_uint = 24579;
pub const ETH_P_LAT: ::std::os::raw::c_uint = 24580;
pub const ETH_P_DIAG: ::std::os::raw::c_uint = 24581;
pub const ETH_P_CUST: ::std::os::raw::c_uint = 24582;
pub const ETH_P_SCA: ::std::os::raw::c_uint = 24583;
pub const ETH_P_TEB: ::std::os::raw::c_uint = 25944;
pub const ETH_P_RARP: ::std::os::raw::c_uint = 32821;
pub const ETH_P_ATALK: ::std::os::raw::c_uint = 32923;
pub const ETH_P_AARP: ::std::os::raw::c_uint = 33011;
pub const ETH_P_8021Q: ::std::os::raw::c_uint = 33024;
pub const ETH_P_IPX: ::std::os::raw::c_uint = 33079;
pub const ETH_P_IPV6: ::std::os::raw::c_uint = 34525;
pub const ETH_P_PAUSE: ::std::os::raw::c_uint = 34824;
pub const ETH_P_SLOW: ::std::os::raw::c_uint = 34825;
pub const ETH_P_WCCP: ::std::os::raw::c_uint = 34878;
pub const ETH_P_MPLS_UC: ::std::os::raw::c_uint = 34887;
pub const ETH_P_MPLS_MC: ::std::os::raw::c_uint = 34888;
pub const ETH_P_ATMMPOA: ::std::os::raw::c_uint = 34892;
pub const ETH_P_PPP_DISC: ::std::os::raw::c_uint = 34915;
pub const ETH_P_PPP_SES: ::std::os::raw::c_uint = 34916;
pub const ETH_P_LINK_CTL: ::std::os::raw::c_uint = 34924;
pub const ETH_P_ATMFATE: ::std::os::raw::c_uint = 34948;
pub const ETH_P_PAE: ::std::os::raw::c_uint = 34958;
pub const ETH_P_AOE: ::std::os::raw::c_uint = 34978;
pub const ETH_P_8021AD: ::std::os::raw::c_uint = 34984;
pub const ETH_P_802_EX1: ::std::os::raw::c_uint = 34997;
pub const ETH_P_TIPC: ::std::os::raw::c_uint = 35018;
pub const ETH_P_8021AH: ::std::os::raw::c_uint = 35047;
pub const ETH_P_MVRP: ::std::os::raw::c_uint = 35061;
pub const ETH_P_1588: ::std::os::raw::c_uint = 35063;
pub const ETH_P_PRP: ::std::os::raw::c_uint = 35067;
pub const ETH_P_FCOE: ::std::os::raw::c_uint = 35078;
pub const ETH_P_TDLS: ::std::os::raw::c_uint = 35085;
pub const ETH_P_FIP: ::std::os::raw::c_uint = 35092;
pub const ETH_P_80221: ::std::os::raw::c_uint = 35095;
pub const ETH_P_LOOPBACK: ::std::os::raw::c_uint = 36864;
pub const ETH_P_QINQ1: ::std::os::raw::c_uint = 37120;
pub const ETH_P_QINQ2: ::std::os::raw::c_uint = 37376;
pub const ETH_P_QINQ3: ::std::os::raw::c_uint = 37632;
pub const ETH_P_EDSA: ::std::os::raw::c_uint = 56026;
pub const ETH_P_AF_IUCV: ::std::os::raw::c_uint = 64507;
pub const ETH_P_802_3_MIN: ::std::os::raw::c_uint = 1536;
pub const ETH_P_802_3: ::std::os::raw::c_uint = 1;
pub const ETH_P_AX25: ::std::os::raw::c_uint = 2;
pub const ETH_P_ALL: ::std::os::raw::c_uint = 3;
pub const ETH_P_802_2: ::std::os::raw::c_uint = 4;
pub const ETH_P_SNAP: ::std::os::raw::c_uint = 5;
pub const ETH_P_DDCMP: ::std::os::raw::c_uint = 6;
pub const ETH_P_WAN_PPP: ::std::os::raw::c_uint = 7;
pub const ETH_P_PPP_MP: ::std::os::raw::c_uint = 8;
pub const ETH_P_LOCALTALK: ::std::os::raw::c_uint = 9;
pub const ETH_P_CAN: ::std::os::raw::c_uint = 12;
pub const ETH_P_CANFD: ::std::os::raw::c_uint = 13;
pub const ETH_P_PPPTALK: ::std::os::raw::c_uint = 16;
pub const ETH_P_TR_802_2: ::std::os::raw::c_uint = 17;
pub const ETH_P_MOBITEX: ::std::os::raw::c_uint = 21;
pub const ETH_P_CONTROL: ::std::os::raw::c_uint = 22;
pub const ETH_P_IRDA: ::std::os::raw::c_uint = 23;
pub const ETH_P_ECONET: ::std::os::raw::c_uint = 24;
pub const ETH_P_HDLC: ::std::os::raw::c_uint = 25;
pub const ETH_P_ARCNET: ::std::os::raw::c_uint = 26;
pub const ETH_P_DSA: ::std::os::raw::c_uint = 27;
pub const ETH_P_TRAILER: ::std::os::raw::c_uint = 28;
pub const ETH_P_PHONET: ::std::os::raw::c_uint = 245;
pub const ETH_P_IEEE802154: ::std::os::raw::c_uint = 246;
pub const ETH_P_CAIF: ::std::os::raw::c_uint = 247;
pub const ETH_P_XDSA: ::std::os::raw::c_uint = 248;
pub const BPF_LD: ::std::os::raw::c_uint = 0;
pub const BPF_LDX: ::std::os::raw::c_uint = 1;
pub const BPF_ST: ::std::os::raw::c_uint = 2;
pub const BPF_STX: ::std::os::raw::c_uint = 3;
pub const BPF_ALU: ::std::os::raw::c_uint = 4;
pub const BPF_JMP: ::std::os::raw::c_uint = 5;
pub const BPF_RET: ::std::os::raw::c_uint = 6;
pub const BPF_MISC: ::std::os::raw::c_uint = 7;
pub const BPF_W: ::std::os::raw::c_uint = 0;
pub const BPF_H: ::std::os::raw::c_uint = 8;
pub const BPF_B: ::std::os::raw::c_uint = 16;
pub const BPF_IMM: ::std::os::raw::c_uint = 0;
pub const BPF_ABS: ::std::os::raw::c_uint = 32;
pub const BPF_IND: ::std::os::raw::c_uint = 64;
pub const BPF_MEM: ::std::os::raw::c_uint = 96;
pub const BPF_LEN: ::std::os::raw::c_uint = 128;
pub const BPF_MSH: ::std::os::raw::c_uint = 160;
pub const BPF_ADD: ::std::os::raw::c_uint = 0;
pub const BPF_SUB: ::std::os::raw::c_uint = 16;
pub const BPF_MUL: ::std::os::raw::c_uint = 32;
pub const BPF_DIV: ::std::os::raw::c_uint = 48;
pub const BPF_OR: ::std::os::raw::c_uint = 64;
pub const BPF_AND: ::std::os::raw::c_uint = 80;
pub const BPF_LSH: ::std::os::raw::c_uint = 96;
pub const BPF_RSH: ::std::os::raw::c_uint = 112;
pub const BPF_NEG: ::std::os::raw::c_uint = 128;
pub const BPF_MOD: ::std::os::raw::c_uint = 144;
pub const BPF_XOR: ::std::os::raw::c_uint = 160;
pub const BPF_JA: ::std::os::raw::c_uint = 0;
pub const BPF_JEQ: ::std::os::raw::c_uint = 16;
pub const BPF_JGT: ::std::os::raw::c_uint = 32;
pub const BPF_JGE: ::std::os::raw::c_uint = 48;
pub const BPF_JSET: ::std::os::raw::c_uint = 64;
pub const BPF_K: ::std::os::raw::c_uint = 0;
pub const BPF_X: ::std::os::raw::c_uint = 8;
pub const BPF_MAXINSNS: ::std::os::raw::c_uint = 4096;
pub const BPF_MAJOR_VERSION: ::std::os::raw::c_uint = 1;
pub const BPF_MINOR_VERSION: ::std::os::raw::c_uint = 1;
pub const BPF_A: ::std::os::raw::c_uint = 16;
pub const BPF_TAX: ::std::os::raw::c_uint = 0;
pub const BPF_TXA: ::std::os::raw::c_uint = 128;
pub const BPF_MEMWORDS: ::std::os::raw::c_uint = 16;
pub const SKF_AD_OFF: ::std::os::raw::c_int = -4096;
pub const SKF_AD_PROTOCOL: ::std::os::raw::c_uint = 0;
pub const SKF_AD_PKTTYPE: ::std::os::raw::c_uint = 4;
pub const SKF_AD_IFINDEX: ::std::os::raw::c_uint = 8;
pub const SKF_AD_NLATTR: ::std::os::raw::c_uint = 12;
pub const SKF_AD_NLATTR_NEST: ::std::os::raw::c_uint = 16;
pub const SKF_AD_MARK: ::std::os::raw::c_uint = 20;
pub const SKF_AD_QUEUE: ::std::os::raw::c_uint = 24;
pub const SKF_AD_HATYPE: ::std::os::raw::c_uint = 28;
pub const SKF_AD_RXHASH: ::std::os::raw::c_uint = 32;
pub const SKF_AD_CPU: ::std::os::raw::c_uint = 36;
pub const SKF_AD_ALU_XOR_X: ::std::os::raw::c_uint = 40;
pub const SKF_AD_VLAN_TAG: ::std::os::raw::c_uint = 44;
pub const SKF_AD_VLAN_TAG_PRESENT: ::std::os::raw::c_uint = 48;
pub const SKF_AD_PAY_OFFSET: ::std::os::raw::c_uint = 52;
pub const SKF_AD_RANDOM: ::std::os::raw::c_uint = 56;
pub const SKF_AD_VLAN_TPID: ::std::os::raw::c_uint = 60;
pub const SKF_AD_MAX: ::std::os::raw::c_uint = 64;
pub const SKF_NET_OFF: ::std::os::raw::c_int = -1048576;
pub const SKF_LL_OFF: ::std::os::raw::c_int = -2097152;
pub const BPF_NET_OFF: ::std::os::raw::c_int = -1048576;
pub const BPF_LL_OFF: ::std::os::raw::c_int = -2097152;
pub const TUN_READQ_SIZE: ::std::os::raw::c_uint = 500;
pub const TUN_TYPE_MASK: ::std::os::raw::c_uint = 15;
pub const IFF_TUN: ::std::os::raw::c_uint = 1;
pub const IFF_TAP: ::std::os::raw::c_uint = 2;
pub const IFF_NO_PI: ::std::os::raw::c_uint = 4096;
pub const IFF_ONE_QUEUE: ::std::os::raw::c_uint = 8192;
pub const IFF_VNET_HDR: ::std::os::raw::c_uint = 16384;
pub const IFF_TUN_EXCL: ::std::os::raw::c_uint = 32768;
pub const IFF_MULTI_QUEUE: ::std::os::raw::c_uint = 256;
pub const IFF_ATTACH_QUEUE: ::std::os::raw::c_uint = 512;
pub const IFF_DETACH_QUEUE: ::std::os::raw::c_uint = 1024;
pub const IFF_PERSIST: ::std::os::raw::c_uint = 2048;
pub const IFF_NOFILTER: ::std::os::raw::c_uint = 4096;
pub const TUN_TX_TIMESTAMP: ::std::os::raw::c_uint = 1;
pub const TUN_F_CSUM: ::std::os::raw::c_uint = 1;
pub const TUN_F_TSO4: ::std::os::raw::c_uint = 2;
pub const TUN_F_TSO6: ::std::os::raw::c_uint = 4;
pub const TUN_F_TSO_ECN: ::std::os::raw::c_uint = 8;
pub const TUN_F_UFO: ::std::os::raw::c_uint = 16;
pub const TUN_PKT_STRIP: ::std::os::raw::c_uint = 1;
pub const TUN_FLT_ALLMULTI: ::std::os::raw::c_uint = 1;
pub const __BITS_PER_LONG: u32 = 64;
pub const __FD_SETSIZE: u32 = 1024;
pub const ETH_ALEN: u32 = 6;
pub const ETH_TLEN: u32 = 2;
pub const ETH_HLEN: u32 = 14;
pub const ETH_ZLEN: u32 = 60;
pub const ETH_DATA_LEN: u32 = 1500;
pub const ETH_FRAME_LEN: u32 = 1514;
pub const ETH_FCS_LEN: u32 = 4;
pub const ETH_MIN_MTU: u32 = 68;
pub const ETH_MAX_MTU: u32 = 65535;
pub const ETH_P_LOOP: u32 = 96;
pub const ETH_P_PUP: u32 = 512;
pub const ETH_P_PUPAT: u32 = 513;
pub const ETH_P_TSN: u32 = 8944;
pub const ETH_P_ERSPAN2: u32 = 8939;
pub const ETH_P_IP: u32 = 2048;
pub const ETH_P_X25: u32 = 2053;
pub const ETH_P_ARP: u32 = 2054;
pub const ETH_P_BPQ: u32 = 2303;
pub const ETH_P_IEEEPUP: u32 = 2560;
pub const ETH_P_IEEEPUPAT: u32 = 2561;
pub const ETH_P_BATMAN: u32 = 17157;
pub const ETH_P_DEC: u32 = 24576;
pub const ETH_P_DNA_DL: u32 = 24577;
pub const ETH_P_DNA_RC: u32 = 24578;
pub const ETH_P_DNA_RT: u32 = 24579;
pub const ETH_P_LAT: u32 = 24580;
pub const ETH_P_DIAG: u32 = 24581;
pub const ETH_P_CUST: u32 = 24582;
pub const ETH_P_SCA: u32 = 24583;
pub const ETH_P_TEB: u32 = 25944;
pub const ETH_P_RARP: u32 = 32821;
pub const ETH_P_ATALK: u32 = 32923;
pub const ETH_P_AARP: u32 = 33011;
pub const ETH_P_8021Q: u32 = 33024;
pub const ETH_P_ERSPAN: u32 = 35006;
pub const ETH_P_IPX: u32 = 33079;
pub const ETH_P_IPV6: u32 = 34525;
pub const ETH_P_PAUSE: u32 = 34824;
pub const ETH_P_SLOW: u32 = 34825;
pub const ETH_P_WCCP: u32 = 34878;
pub const ETH_P_MPLS_UC: u32 = 34887;
pub const ETH_P_MPLS_MC: u32 = 34888;
pub const ETH_P_ATMMPOA: u32 = 34892;
pub const ETH_P_PPP_DISC: u32 = 34915;
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_AOE: u32 = 34978;
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_FCOE: u32 = 35078;
pub const ETH_P_IBOE: u32 = 35093;
pub const ETH_P_TDLS: u32 = 35085;
pub const ETH_P_FIP: u32 = 35092;
pub const ETH_P_80221: u32 = 35095;
pub const ETH_P_HSR: u32 = 35119;
pub const ETH_P_NSH: u32 = 35151;
pub const ETH_P_LOOPBACK: u32 = 36864;
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;
pub const ETH_P_802_3: u32 = 1;
pub const ETH_P_AX25: u32 = 2;
pub const ETH_P_ALL: u32 = 3;
pub const ETH_P_802_2: u32 = 4;
pub const ETH_P_SNAP: u32 = 5;
pub const ETH_P_DDCMP: u32 = 6;
pub const ETH_P_WAN_PPP: u32 = 7;
pub const ETH_P_PPP_MP: u32 = 8;
pub const ETH_P_LOCALTALK: u32 = 9;
pub const ETH_P_CAN: u32 = 12;
pub const ETH_P_CANFD: u32 = 13;
pub const ETH_P_PPPTALK: u32 = 16;
pub const ETH_P_TR_802_2: u32 = 17;
pub const ETH_P_MOBITEX: u32 = 21;
pub const ETH_P_CONTROL: u32 = 22;
pub const ETH_P_IRDA: u32 = 23;
pub const ETH_P_ECONET: u32 = 24;
pub const ETH_P_HDLC: u32 = 25;
pub const ETH_P_ARCNET: u32 = 26;
pub const ETH_P_DSA: u32 = 27;
pub const ETH_P_TRAILER: u32 = 28;
pub const ETH_P_PHONET: u32 = 245;
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 __UAPI_DEF_ETHHDR: u32 = 1;
pub const BPF_LD: u32 = 0;
pub const BPF_LDX: u32 = 1;
pub const BPF_ST: u32 = 2;
pub const BPF_STX: u32 = 3;
pub const BPF_ALU: u32 = 4;
pub const BPF_JMP: u32 = 5;
pub const BPF_RET: u32 = 6;
pub const BPF_MISC: u32 = 7;
pub const BPF_W: u32 = 0;
pub const BPF_H: u32 = 8;
pub const BPF_B: u32 = 16;
pub const BPF_IMM: u32 = 0;
pub const BPF_ABS: u32 = 32;
pub const BPF_IND: u32 = 64;
pub const BPF_MEM: u32 = 96;
pub const BPF_LEN: u32 = 128;
pub const BPF_MSH: u32 = 160;
pub const BPF_ADD: u32 = 0;
pub const BPF_SUB: u32 = 16;
pub const BPF_MUL: u32 = 32;
pub const BPF_DIV: u32 = 48;
pub const BPF_OR: u32 = 64;
pub const BPF_AND: u32 = 80;
pub const BPF_LSH: u32 = 96;
pub const BPF_RSH: u32 = 112;
pub const BPF_NEG: u32 = 128;
pub const BPF_MOD: u32 = 144;
pub const BPF_XOR: u32 = 160;
pub const BPF_JA: u32 = 0;
pub const BPF_JEQ: u32 = 16;
pub const BPF_JGT: u32 = 32;
pub const BPF_JGE: u32 = 48;
pub const BPF_JSET: u32 = 64;
pub const BPF_K: u32 = 0;
pub const BPF_X: u32 = 8;
pub const BPF_MAXINSNS: u32 = 4096;
pub const BPF_MAJOR_VERSION: u32 = 1;
pub const BPF_MINOR_VERSION: u32 = 1;
pub const BPF_A: u32 = 16;
pub const BPF_TAX: u32 = 0;
pub const BPF_TXA: u32 = 128;
pub const BPF_MEMWORDS: u32 = 16;
pub const SKF_AD_OFF: i32 = -4096;
pub const SKF_AD_PROTOCOL: u32 = 0;
pub const SKF_AD_PKTTYPE: u32 = 4;
pub const SKF_AD_IFINDEX: u32 = 8;
pub const SKF_AD_NLATTR: u32 = 12;
pub const SKF_AD_NLATTR_NEST: u32 = 16;
pub const SKF_AD_MARK: u32 = 20;
pub const SKF_AD_QUEUE: u32 = 24;
pub const SKF_AD_HATYPE: u32 = 28;
pub const SKF_AD_RXHASH: u32 = 32;
pub const SKF_AD_CPU: u32 = 36;
pub const SKF_AD_ALU_XOR_X: u32 = 40;
pub const SKF_AD_VLAN_TAG: u32 = 44;
pub const SKF_AD_VLAN_TAG_PRESENT: u32 = 48;
pub const SKF_AD_PAY_OFFSET: u32 = 52;
pub const SKF_AD_RANDOM: u32 = 56;
pub const SKF_AD_VLAN_TPID: u32 = 60;
pub const SKF_AD_MAX: u32 = 64;
pub const SKF_NET_OFF: i32 = -1048576;
pub const SKF_LL_OFF: i32 = -2097152;
pub const BPF_NET_OFF: i32 = -1048576;
pub const BPF_LL_OFF: i32 = -2097152;
pub const TUN_READQ_SIZE: u32 = 500;
pub const TUN_TYPE_MASK: u32 = 15;
pub const IFF_TUN: u32 = 1;
pub const IFF_TAP: u32 = 2;
pub const IFF_NAPI: u32 = 16;
pub const IFF_NAPI_FRAGS: u32 = 32;
pub const IFF_NO_PI: u32 = 4096;
pub const IFF_ONE_QUEUE: u32 = 8192;
pub const IFF_VNET_HDR: u32 = 16384;
pub const IFF_TUN_EXCL: u32 = 32768;
pub const IFF_MULTI_QUEUE: u32 = 256;
pub const IFF_ATTACH_QUEUE: u32 = 512;
pub const IFF_DETACH_QUEUE: u32 = 1024;
pub const IFF_PERSIST: u32 = 2048;
pub const IFF_NOFILTER: u32 = 4096;
pub const TUN_TX_TIMESTAMP: u32 = 1;
pub const TUN_F_CSUM: u32 = 1;
pub const TUN_F_TSO4: u32 = 2;
pub const TUN_F_TSO6: u32 = 4;
pub const TUN_F_TSO_ECN: u32 = 8;
pub const TUN_F_UFO: u32 = 16;
pub const TUN_PKT_STRIP: u32 = 1;
pub const TUN_FLT_ALLMULTI: u32 = 1;
pub type __s8 = ::std::os::raw::c_schar;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
@@ -224,38 +239,10 @@ 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)]
#[derive(Debug, Copy, Clone)]
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))
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_fd_set)).fds_bits as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_fd_set),
"::",
stringify!(fds_bits)
)
);
}
impl Clone for __kernel_fd_set {
fn clone(&self) -> Self {
*self
}
}
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;
@@ -279,41 +266,15 @@ 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)]
#[derive(Debug, Copy, Clone)]
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))
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_fsid_t)).val as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_fsid_t),
"::",
stringify!(val)
)
);
}
impl Clone for __kernel_fsid_t {
fn clone(&self) -> Self {
*self
}
}
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;
@@ -328,272 +289,38 @@ 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;
#[repr(C, packed)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct ethhdr {
pub h_dest: [::std::os::raw::c_uchar; 6usize],
pub h_source: [::std::os::raw::c_uchar; 6usize],
pub h_proto: __be16,
}
#[test]
fn bindgen_test_layout_ethhdr() {
assert_eq!(
::std::mem::size_of::<ethhdr>(),
14usize,
concat!("Size of: ", stringify!(ethhdr))
);
assert_eq!(
::std::mem::align_of::<ethhdr>(),
1usize,
concat!("Alignment of ", stringify!(ethhdr))
);
assert_eq!(
unsafe { &(*(0 as *const ethhdr)).h_dest as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(ethhdr),
"::",
stringify!(h_dest)
)
);
assert_eq!(
unsafe { &(*(0 as *const ethhdr)).h_source as *const _ as usize },
6usize,
concat!(
"Alignment of field: ",
stringify!(ethhdr),
"::",
stringify!(h_source)
)
);
assert_eq!(
unsafe { &(*(0 as *const ethhdr)).h_proto as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
stringify!(ethhdr),
"::",
stringify!(h_proto)
)
);
}
impl Clone for ethhdr {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct sock_filter {
pub code: __u16,
pub jt: __u8,
pub jf: __u8,
pub k: __u32,
}
#[test]
fn bindgen_test_layout_sock_filter() {
assert_eq!(
::std::mem::size_of::<sock_filter>(),
8usize,
concat!("Size of: ", stringify!(sock_filter))
);
assert_eq!(
::std::mem::align_of::<sock_filter>(),
4usize,
concat!("Alignment of ", stringify!(sock_filter))
);
assert_eq!(
unsafe { &(*(0 as *const sock_filter)).code as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(sock_filter),
"::",
stringify!(code)
)
);
assert_eq!(
unsafe { &(*(0 as *const sock_filter)).jt as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(sock_filter),
"::",
stringify!(jt)
)
);
assert_eq!(
unsafe { &(*(0 as *const sock_filter)).jf as *const _ as usize },
3usize,
concat!(
"Alignment of field: ",
stringify!(sock_filter),
"::",
stringify!(jf)
)
);
assert_eq!(
unsafe { &(*(0 as *const sock_filter)).k as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(sock_filter),
"::",
stringify!(k)
)
);
}
impl Clone for sock_filter {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct sock_fprog {
pub len: ::std::os::raw::c_ushort,
pub filter: *mut sock_filter,
}
#[test]
fn bindgen_test_layout_sock_fprog() {
assert_eq!(
::std::mem::size_of::<sock_fprog>(),
16usize,
concat!("Size of: ", stringify!(sock_fprog))
);
assert_eq!(
::std::mem::align_of::<sock_fprog>(),
8usize,
concat!("Alignment of ", stringify!(sock_fprog))
);
assert_eq!(
unsafe { &(*(0 as *const sock_fprog)).len as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(sock_fprog),
"::",
stringify!(len)
)
);
assert_eq!(
unsafe { &(*(0 as *const sock_fprog)).filter as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(sock_fprog),
"::",
stringify!(filter)
)
);
}
impl Clone for sock_fprog {
fn clone(&self) -> Self {
*self
}
}
impl Default for sock_fprog {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct tun_pi {
pub flags: __u16,
pub proto: __be16,
}
#[test]
fn bindgen_test_layout_tun_pi() {
assert_eq!(
::std::mem::size_of::<tun_pi>(),
4usize,
concat!("Size of: ", stringify!(tun_pi))
);
assert_eq!(
::std::mem::align_of::<tun_pi>(),
2usize,
concat!("Alignment of ", stringify!(tun_pi))
);
assert_eq!(
unsafe { &(*(0 as *const tun_pi)).flags as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(tun_pi),
"::",
stringify!(flags)
)
);
assert_eq!(
unsafe { &(*(0 as *const tun_pi)).proto as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(tun_pi),
"::",
stringify!(proto)
)
);
}
impl Clone for tun_pi {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug)]
pub struct tun_filter {
pub flags: __u16,
pub count: __u16,
pub addr: __IncompleteArrayField<[__u8; 6usize]>,
}
#[test]
fn bindgen_test_layout_tun_filter() {
assert_eq!(
::std::mem::size_of::<tun_filter>(),
4usize,
concat!("Size of: ", stringify!(tun_filter))
);
assert_eq!(
::std::mem::align_of::<tun_filter>(),
2usize,
concat!("Alignment of ", stringify!(tun_filter))
);
assert_eq!(
unsafe { &(*(0 as *const tun_filter)).flags as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(tun_filter),
"::",
stringify!(flags)
)
);
assert_eq!(
unsafe { &(*(0 as *const tun_filter)).count as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(tun_filter),
"::",
stringify!(count)
)
);
assert_eq!(
unsafe { &(*(0 as *const tun_filter)).addr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(tun_filter),
"::",
stringify!(addr)
)
);
}
impl Clone for tun_filter {
fn clone(&self) -> Self {
*self
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,103 +1,119 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
/* automatically generated by rust-bindgen */
// bindgen /usr/include/linux/in.h --no-layout-tests
pub const __BITS_PER_LONG: ::std::os::raw::c_uint = 64;
pub const __FD_SETSIZE: ::std::os::raw::c_uint = 1024;
pub const __UAPI_DEF_IN_ADDR: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN_IPPROTO: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN_PKTINFO: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IP_MREQ: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_SOCKADDR_IN: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN_CLASS: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN6_ADDR: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN6_ADDR_ALT: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_SOCKADDR_IN6: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IPV6_MREQ: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IPPROTO_V6: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IPV6_OPTIONS: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IN6_PKTINFO: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_IP6_MTUINFO: ::std::os::raw::c_uint = 1;
pub const __UAPI_DEF_XATTR: ::std::os::raw::c_uint = 1;
pub const _K_SS_MAXSIZE: ::std::os::raw::c_uint = 128;
pub const IP_TOS: ::std::os::raw::c_uint = 1;
pub const IP_TTL: ::std::os::raw::c_uint = 2;
pub const IP_HDRINCL: ::std::os::raw::c_uint = 3;
pub const IP_OPTIONS: ::std::os::raw::c_uint = 4;
pub const IP_ROUTER_ALERT: ::std::os::raw::c_uint = 5;
pub const IP_RECVOPTS: ::std::os::raw::c_uint = 6;
pub const IP_RETOPTS: ::std::os::raw::c_uint = 7;
pub const IP_PKTINFO: ::std::os::raw::c_uint = 8;
pub const IP_PKTOPTIONS: ::std::os::raw::c_uint = 9;
pub const IP_MTU_DISCOVER: ::std::os::raw::c_uint = 10;
pub const IP_RECVERR: ::std::os::raw::c_uint = 11;
pub const IP_RECVTTL: ::std::os::raw::c_uint = 12;
pub const IP_RECVTOS: ::std::os::raw::c_uint = 13;
pub const IP_MTU: ::std::os::raw::c_uint = 14;
pub const IP_FREEBIND: ::std::os::raw::c_uint = 15;
pub const IP_IPSEC_POLICY: ::std::os::raw::c_uint = 16;
pub const IP_XFRM_POLICY: ::std::os::raw::c_uint = 17;
pub const IP_PASSSEC: ::std::os::raw::c_uint = 18;
pub const IP_TRANSPARENT: ::std::os::raw::c_uint = 19;
pub const IP_RECVRETOPTS: ::std::os::raw::c_uint = 7;
pub const IP_ORIGDSTADDR: ::std::os::raw::c_uint = 20;
pub const IP_RECVORIGDSTADDR: ::std::os::raw::c_uint = 20;
pub const IP_MINTTL: ::std::os::raw::c_uint = 21;
pub const IP_NODEFRAG: ::std::os::raw::c_uint = 22;
pub const IP_CHECKSUM: ::std::os::raw::c_uint = 23;
pub const IP_BIND_ADDRESS_NO_PORT: ::std::os::raw::c_uint = 24;
pub const IP_RECVFRAGSIZE: ::std::os::raw::c_uint = 25;
pub const IP_PMTUDISC_DONT: ::std::os::raw::c_uint = 0;
pub const IP_PMTUDISC_WANT: ::std::os::raw::c_uint = 1;
pub const IP_PMTUDISC_DO: ::std::os::raw::c_uint = 2;
pub const IP_PMTUDISC_PROBE: ::std::os::raw::c_uint = 3;
pub const IP_PMTUDISC_INTERFACE: ::std::os::raw::c_uint = 4;
pub const IP_PMTUDISC_OMIT: ::std::os::raw::c_uint = 5;
pub const IP_MULTICAST_IF: ::std::os::raw::c_uint = 32;
pub const IP_MULTICAST_TTL: ::std::os::raw::c_uint = 33;
pub const IP_MULTICAST_LOOP: ::std::os::raw::c_uint = 34;
pub const IP_ADD_MEMBERSHIP: ::std::os::raw::c_uint = 35;
pub const IP_DROP_MEMBERSHIP: ::std::os::raw::c_uint = 36;
pub const IP_UNBLOCK_SOURCE: ::std::os::raw::c_uint = 37;
pub const IP_BLOCK_SOURCE: ::std::os::raw::c_uint = 38;
pub const IP_ADD_SOURCE_MEMBERSHIP: ::std::os::raw::c_uint = 39;
pub const IP_DROP_SOURCE_MEMBERSHIP: ::std::os::raw::c_uint = 40;
pub const IP_MSFILTER: ::std::os::raw::c_uint = 41;
pub const MCAST_JOIN_GROUP: ::std::os::raw::c_uint = 42;
pub const MCAST_BLOCK_SOURCE: ::std::os::raw::c_uint = 43;
pub const MCAST_UNBLOCK_SOURCE: ::std::os::raw::c_uint = 44;
pub const MCAST_LEAVE_GROUP: ::std::os::raw::c_uint = 45;
pub const MCAST_JOIN_SOURCE_GROUP: ::std::os::raw::c_uint = 46;
pub const MCAST_LEAVE_SOURCE_GROUP: ::std::os::raw::c_uint = 47;
pub const MCAST_MSFILTER: ::std::os::raw::c_uint = 48;
pub const IP_MULTICAST_ALL: ::std::os::raw::c_uint = 49;
pub const IP_UNICAST_IF: ::std::os::raw::c_uint = 50;
pub const MCAST_EXCLUDE: ::std::os::raw::c_uint = 0;
pub const MCAST_INCLUDE: ::std::os::raw::c_uint = 1;
pub const IP_DEFAULT_MULTICAST_TTL: ::std::os::raw::c_uint = 1;
pub const IP_DEFAULT_MULTICAST_LOOP: ::std::os::raw::c_uint = 1;
pub const __SOCK_SIZE__: ::std::os::raw::c_uint = 16;
pub const IN_CLASSA_NET: ::std::os::raw::c_uint = 4278190080;
pub const IN_CLASSA_NSHIFT: ::std::os::raw::c_uint = 24;
pub const IN_CLASSA_HOST: ::std::os::raw::c_uint = 16777215;
pub const IN_CLASSA_MAX: ::std::os::raw::c_uint = 128;
pub const IN_CLASSB_NET: ::std::os::raw::c_uint = 4294901760;
pub const IN_CLASSB_NSHIFT: ::std::os::raw::c_uint = 16;
pub const IN_CLASSB_HOST: ::std::os::raw::c_uint = 65535;
pub const IN_CLASSB_MAX: ::std::os::raw::c_uint = 65536;
pub const IN_CLASSC_NET: ::std::os::raw::c_uint = 4294967040;
pub const IN_CLASSC_NSHIFT: ::std::os::raw::c_uint = 8;
pub const IN_CLASSC_HOST: ::std::os::raw::c_uint = 255;
pub const IN_MULTICAST_NET: ::std::os::raw::c_uint = 4026531840;
pub const IN_LOOPBACKNET: ::std::os::raw::c_uint = 127;
pub const INADDR_LOOPBACK: ::std::os::raw::c_uint = 2130706433;
pub const INADDR_UNSPEC_GROUP: ::std::os::raw::c_uint = 3758096384;
pub const INADDR_ALLHOSTS_GROUP: ::std::os::raw::c_uint = 3758096385;
pub const INADDR_ALLRTRS_GROUP: ::std::os::raw::c_uint = 3758096386;
pub const INADDR_MAX_LOCAL_GROUP: ::std::os::raw::c_uint = 3758096639;
pub const __LITTLE_ENDIAN: ::std::os::raw::c_uint = 1234;
/* automatically generated by rust-bindgen 0.58.1 */
pub const __BITS_PER_LONG: u32 = 64;
pub const __FD_SETSIZE: u32 = 1024;
pub const __UAPI_DEF_IF_IFCONF: u32 = 1;
pub const __UAPI_DEF_IF_IFMAP: u32 = 1;
pub const __UAPI_DEF_IF_IFNAMSIZ: u32 = 1;
pub const __UAPI_DEF_IF_IFREQ: u32 = 1;
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS: u32 = 1;
pub const __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO: u32 = 1;
pub const __UAPI_DEF_IN_ADDR: u32 = 1;
pub const __UAPI_DEF_IN_IPPROTO: u32 = 1;
pub const __UAPI_DEF_IN_PKTINFO: u32 = 1;
pub const __UAPI_DEF_IP_MREQ: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IN: u32 = 1;
pub const __UAPI_DEF_IN_CLASS: u32 = 1;
pub const __UAPI_DEF_IN6_ADDR: u32 = 1;
pub const __UAPI_DEF_IN6_ADDR_ALT: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IN6: u32 = 1;
pub const __UAPI_DEF_IPV6_MREQ: u32 = 1;
pub const __UAPI_DEF_IPPROTO_V6: u32 = 1;
pub const __UAPI_DEF_IPV6_OPTIONS: u32 = 1;
pub const __UAPI_DEF_IN6_PKTINFO: u32 = 1;
pub const __UAPI_DEF_IP6_MTUINFO: u32 = 1;
pub const __UAPI_DEF_SOCKADDR_IPX: u32 = 1;
pub const __UAPI_DEF_IPX_ROUTE_DEFINITION: u32 = 1;
pub const __UAPI_DEF_IPX_INTERFACE_DEFINITION: u32 = 1;
pub const __UAPI_DEF_IPX_CONFIG_DATA: u32 = 1;
pub const __UAPI_DEF_IPX_ROUTE_DEF: u32 = 1;
pub const __UAPI_DEF_XATTR: u32 = 1;
pub const _K_SS_MAXSIZE: u32 = 128;
pub const IP_TOS: u32 = 1;
pub const IP_TTL: u32 = 2;
pub const IP_HDRINCL: u32 = 3;
pub const IP_OPTIONS: u32 = 4;
pub const IP_ROUTER_ALERT: u32 = 5;
pub const IP_RECVOPTS: u32 = 6;
pub const IP_RETOPTS: u32 = 7;
pub const IP_PKTINFO: u32 = 8;
pub const IP_PKTOPTIONS: u32 = 9;
pub const IP_MTU_DISCOVER: u32 = 10;
pub const IP_RECVERR: u32 = 11;
pub const IP_RECVTTL: u32 = 12;
pub const IP_RECVTOS: u32 = 13;
pub const IP_MTU: u32 = 14;
pub const IP_FREEBIND: u32 = 15;
pub const IP_IPSEC_POLICY: u32 = 16;
pub const IP_XFRM_POLICY: u32 = 17;
pub const IP_PASSSEC: u32 = 18;
pub const IP_TRANSPARENT: u32 = 19;
pub const IP_RECVRETOPTS: u32 = 7;
pub const IP_ORIGDSTADDR: u32 = 20;
pub const IP_RECVORIGDSTADDR: u32 = 20;
pub const IP_MINTTL: u32 = 21;
pub const IP_NODEFRAG: u32 = 22;
pub const IP_CHECKSUM: u32 = 23;
pub const IP_BIND_ADDRESS_NO_PORT: u32 = 24;
pub const IP_RECVFRAGSIZE: u32 = 25;
pub const IP_PMTUDISC_DONT: u32 = 0;
pub const IP_PMTUDISC_WANT: u32 = 1;
pub const IP_PMTUDISC_DO: u32 = 2;
pub const IP_PMTUDISC_PROBE: u32 = 3;
pub const IP_PMTUDISC_INTERFACE: u32 = 4;
pub const IP_PMTUDISC_OMIT: u32 = 5;
pub const IP_MULTICAST_IF: u32 = 32;
pub const IP_MULTICAST_TTL: u32 = 33;
pub const IP_MULTICAST_LOOP: u32 = 34;
pub const IP_ADD_MEMBERSHIP: u32 = 35;
pub const IP_DROP_MEMBERSHIP: u32 = 36;
pub const IP_UNBLOCK_SOURCE: u32 = 37;
pub const IP_BLOCK_SOURCE: u32 = 38;
pub const IP_ADD_SOURCE_MEMBERSHIP: u32 = 39;
pub const IP_DROP_SOURCE_MEMBERSHIP: u32 = 40;
pub const IP_MSFILTER: u32 = 41;
pub const MCAST_JOIN_GROUP: u32 = 42;
pub const MCAST_BLOCK_SOURCE: u32 = 43;
pub const MCAST_UNBLOCK_SOURCE: u32 = 44;
pub const MCAST_LEAVE_GROUP: u32 = 45;
pub const MCAST_JOIN_SOURCE_GROUP: u32 = 46;
pub const MCAST_LEAVE_SOURCE_GROUP: u32 = 47;
pub const MCAST_MSFILTER: u32 = 48;
pub const IP_MULTICAST_ALL: u32 = 49;
pub const IP_UNICAST_IF: u32 = 50;
pub const MCAST_EXCLUDE: u32 = 0;
pub const MCAST_INCLUDE: u32 = 1;
pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1;
pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1;
pub const __SOCK_SIZE__: u32 = 16;
pub const IN_CLASSA_NET: u32 = 4278190080;
pub const IN_CLASSA_NSHIFT: u32 = 24;
pub const IN_CLASSA_HOST: u32 = 16777215;
pub const IN_CLASSA_MAX: u32 = 128;
pub const IN_CLASSB_NET: u32 = 4294901760;
pub const IN_CLASSB_NSHIFT: u32 = 16;
pub const IN_CLASSB_HOST: u32 = 65535;
pub const IN_CLASSB_MAX: u32 = 65536;
pub const IN_CLASSC_NET: u32 = 4294967040;
pub const IN_CLASSC_NSHIFT: u32 = 8;
pub const IN_CLASSC_HOST: u32 = 255;
pub const IN_MULTICAST_NET: u32 = 3758096384;
pub const IN_CLASSE_NET: u32 = 4294967295;
pub const IN_CLASSE_NSHIFT: u32 = 0;
pub const IN_LOOPBACKNET: u32 = 127;
pub const INADDR_LOOPBACK: u32 = 2130706433;
pub const INADDR_UNSPEC_GROUP: u32 = 3758096384;
pub const INADDR_ALLHOSTS_GROUP: u32 = 3758096385;
pub const INADDR_ALLRTRS_GROUP: u32 = 3758096386;
pub const INADDR_ALLSNOOPERS_GROUP: u32 = 3758096490;
pub const INADDR_MAX_LOCAL_GROUP: u32 = 3758096639;
pub const __LITTLE_ENDIAN: u32 = 1234;
pub type __s8 = ::std::os::raw::c_schar;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
@@ -107,38 +123,10 @@ 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)]
#[derive(Debug, Copy, Clone)]
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))
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_fd_set)).fds_bits as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_fd_set),
"::",
stringify!(fds_bits)
)
);
}
impl Clone for __kernel_fd_set {
fn clone(&self) -> Self {
*self
}
}
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;
@@ -162,41 +150,15 @@ 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)]
#[derive(Debug, Copy, Clone)]
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))
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_fsid_t)).val as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_fsid_t),
"::",
stringify!(val)
)
);
}
impl Clone for __kernel_fsid_t {
fn clone(&self) -> Self {
*self
}
}
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;
@@ -211,267 +173,81 @@ 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 type __kernel_sa_family_t = ::std::os::raw::c_ushort;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct __kernel_sockaddr_storage {
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union __kernel_sockaddr_storage__bindgen_ty_1 {
pub __bindgen_anon_1: __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1,
pub __align: *mut ::std::os::raw::c_void,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct __kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
pub ss_family: __kernel_sa_family_t,
pub __data: [::std::os::raw::c_char; 126usize],
pub __bindgen_align: [u64; 0usize],
}
#[test]
fn bindgen_test_layout___kernel_sockaddr_storage() {
assert_eq!(
::std::mem::size_of::<__kernel_sockaddr_storage>(),
128usize,
concat!("Size of: ", stringify!(__kernel_sockaddr_storage))
);
assert_eq!(
::std::mem::align_of::<__kernel_sockaddr_storage>(),
8usize,
concat!("Alignment of ", stringify!(__kernel_sockaddr_storage))
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_sockaddr_storage)).ss_family as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_sockaddr_storage),
"::",
stringify!(ss_family)
)
);
assert_eq!(
unsafe { &(*(0 as *const __kernel_sockaddr_storage)).__data as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(__kernel_sockaddr_storage),
"::",
stringify!(__data)
)
);
}
impl Default for __kernel_sockaddr_storage {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
pub const IPPROTO_IP: _bindgen_ty_1 = 0;
pub const IPPROTO_ICMP: _bindgen_ty_1 = 1;
pub const IPPROTO_IGMP: _bindgen_ty_1 = 2;
pub const IPPROTO_IPIP: _bindgen_ty_1 = 4;
pub const IPPROTO_TCP: _bindgen_ty_1 = 6;
pub const IPPROTO_EGP: _bindgen_ty_1 = 8;
pub const IPPROTO_PUP: _bindgen_ty_1 = 12;
pub const IPPROTO_UDP: _bindgen_ty_1 = 17;
pub const IPPROTO_IDP: _bindgen_ty_1 = 22;
pub const IPPROTO_TP: _bindgen_ty_1 = 29;
pub const IPPROTO_DCCP: _bindgen_ty_1 = 33;
pub const IPPROTO_IPV6: _bindgen_ty_1 = 41;
pub const IPPROTO_RSVP: _bindgen_ty_1 = 46;
pub const IPPROTO_GRE: _bindgen_ty_1 = 47;
pub const IPPROTO_ESP: _bindgen_ty_1 = 50;
pub const IPPROTO_AH: _bindgen_ty_1 = 51;
pub const IPPROTO_MTP: _bindgen_ty_1 = 92;
pub const IPPROTO_BEETPH: _bindgen_ty_1 = 94;
pub const IPPROTO_ENCAP: _bindgen_ty_1 = 98;
pub const IPPROTO_PIM: _bindgen_ty_1 = 103;
pub const IPPROTO_COMP: _bindgen_ty_1 = 108;
pub const IPPROTO_SCTP: _bindgen_ty_1 = 132;
pub const IPPROTO_UDPLITE: _bindgen_ty_1 = 136;
pub const IPPROTO_MPLS: _bindgen_ty_1 = 137;
pub const IPPROTO_RAW: _bindgen_ty_1 = 255;
pub const IPPROTO_MAX: _bindgen_ty_1 = 256;
pub const IPPROTO_IP: ::std::os::raw::c_uint = 0;
pub const IPPROTO_ICMP: ::std::os::raw::c_uint = 1;
pub const IPPROTO_IGMP: ::std::os::raw::c_uint = 2;
pub const IPPROTO_IPIP: ::std::os::raw::c_uint = 4;
pub const IPPROTO_TCP: ::std::os::raw::c_uint = 6;
pub const IPPROTO_EGP: ::std::os::raw::c_uint = 8;
pub const IPPROTO_PUP: ::std::os::raw::c_uint = 12;
pub const IPPROTO_UDP: ::std::os::raw::c_uint = 17;
pub const IPPROTO_IDP: ::std::os::raw::c_uint = 22;
pub const IPPROTO_TP: ::std::os::raw::c_uint = 29;
pub const IPPROTO_DCCP: ::std::os::raw::c_uint = 33;
pub const IPPROTO_IPV6: ::std::os::raw::c_uint = 41;
pub const IPPROTO_RSVP: ::std::os::raw::c_uint = 46;
pub const IPPROTO_GRE: ::std::os::raw::c_uint = 47;
pub const IPPROTO_ESP: ::std::os::raw::c_uint = 50;
pub const IPPROTO_AH: ::std::os::raw::c_uint = 51;
pub const IPPROTO_MTP: ::std::os::raw::c_uint = 92;
pub const IPPROTO_BEETPH: ::std::os::raw::c_uint = 94;
pub const IPPROTO_ENCAP: ::std::os::raw::c_uint = 98;
pub const IPPROTO_PIM: ::std::os::raw::c_uint = 103;
pub const IPPROTO_COMP: ::std::os::raw::c_uint = 108;
pub const IPPROTO_SCTP: ::std::os::raw::c_uint = 132;
pub const IPPROTO_UDPLITE: ::std::os::raw::c_uint = 136;
pub const IPPROTO_MPLS: ::std::os::raw::c_uint = 137;
pub const IPPROTO_ETHERNET: ::std::os::raw::c_uint = 143;
pub const IPPROTO_RAW: ::std::os::raw::c_uint = 255;
pub const IPPROTO_MPTCP: ::std::os::raw::c_uint = 262;
pub const IPPROTO_MAX: ::std::os::raw::c_uint = 263;
pub type _bindgen_ty_1 = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct in_addr {
pub s_addr: __be32,
}
#[test]
fn bindgen_test_layout_in_addr() {
assert_eq!(
::std::mem::size_of::<in_addr>(),
4usize,
concat!("Size of: ", stringify!(in_addr))
);
assert_eq!(
::std::mem::align_of::<in_addr>(),
4usize,
concat!("Alignment of ", stringify!(in_addr))
);
assert_eq!(
unsafe { &(*(0 as *const in_addr)).s_addr as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(in_addr),
"::",
stringify!(s_addr)
)
);
}
impl Clone for in_addr {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[test]
fn bindgen_test_layout_ip_mreq() {
assert_eq!(
::std::mem::size_of::<ip_mreq>(),
8usize,
concat!("Size of: ", stringify!(ip_mreq))
);
assert_eq!(
::std::mem::align_of::<ip_mreq>(),
4usize,
concat!("Alignment of ", stringify!(ip_mreq))
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreq)).imr_multiaddr as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreq),
"::",
stringify!(imr_multiaddr)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreq)).imr_interface as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreq),
"::",
stringify!(imr_interface)
)
);
}
impl Clone for ip_mreq {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreqn {
pub imr_multiaddr: in_addr,
pub imr_address: in_addr,
pub imr_ifindex: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_ip_mreqn() {
assert_eq!(
::std::mem::size_of::<ip_mreqn>(),
12usize,
concat!("Size of: ", stringify!(ip_mreqn))
);
assert_eq!(
::std::mem::align_of::<ip_mreqn>(),
4usize,
concat!("Alignment of ", stringify!(ip_mreqn))
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreqn)).imr_multiaddr as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreqn),
"::",
stringify!(imr_multiaddr)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreqn)).imr_address as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreqn),
"::",
stringify!(imr_address)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreqn)).imr_ifindex as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreqn),
"::",
stringify!(imr_ifindex)
)
);
}
impl Clone for ip_mreqn {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct ip_mreq_source {
pub imr_multiaddr: __be32,
pub imr_interface: __be32,
pub imr_sourceaddr: __be32,
}
#[test]
fn bindgen_test_layout_ip_mreq_source() {
assert_eq!(
::std::mem::size_of::<ip_mreq_source>(),
12usize,
concat!("Size of: ", stringify!(ip_mreq_source))
);
assert_eq!(
::std::mem::align_of::<ip_mreq_source>(),
4usize,
concat!("Alignment of ", stringify!(ip_mreq_source))
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreq_source)).imr_multiaddr as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreq_source),
"::",
stringify!(imr_multiaddr)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreq_source)).imr_interface as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreq_source),
"::",
stringify!(imr_interface)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_mreq_source)).imr_sourceaddr as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(ip_mreq_source),
"::",
stringify!(imr_sourceaddr)
)
);
}
impl Clone for ip_mreq_source {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct ip_msfilter {
pub imsf_multiaddr: __be32,
pub imsf_interface: __be32,
@@ -479,172 +255,21 @@ pub struct ip_msfilter {
pub imsf_numsrc: __u32,
pub imsf_slist: [__be32; 1usize],
}
#[test]
fn bindgen_test_layout_ip_msfilter() {
assert_eq!(
::std::mem::size_of::<ip_msfilter>(),
20usize,
concat!("Size of: ", stringify!(ip_msfilter))
);
assert_eq!(
::std::mem::align_of::<ip_msfilter>(),
4usize,
concat!("Alignment of ", stringify!(ip_msfilter))
);
assert_eq!(
unsafe { &(*(0 as *const ip_msfilter)).imsf_multiaddr as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(ip_msfilter),
"::",
stringify!(imsf_multiaddr)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_msfilter)).imsf_interface as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(ip_msfilter),
"::",
stringify!(imsf_interface)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_msfilter)).imsf_fmode as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(ip_msfilter),
"::",
stringify!(imsf_fmode)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_msfilter)).imsf_numsrc as *const _ as usize },
12usize,
concat!(
"Alignment of field: ",
stringify!(ip_msfilter),
"::",
stringify!(imsf_numsrc)
)
);
assert_eq!(
unsafe { &(*(0 as *const ip_msfilter)).imsf_slist as *const _ as usize },
16usize,
concat!(
"Alignment of field: ",
stringify!(ip_msfilter),
"::",
stringify!(imsf_slist)
)
);
}
impl Clone for ip_msfilter {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_req {
pub gr_interface: __u32,
pub gr_group: __kernel_sockaddr_storage,
}
#[test]
fn bindgen_test_layout_group_req() {
assert_eq!(
::std::mem::size_of::<group_req>(),
136usize,
concat!("Size of: ", stringify!(group_req))
);
assert_eq!(
::std::mem::align_of::<group_req>(),
8usize,
concat!("Alignment of ", stringify!(group_req))
);
assert_eq!(
unsafe { &(*(0 as *const group_req)).gr_interface as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(group_req),
"::",
stringify!(gr_interface)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_req)).gr_group as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(group_req),
"::",
stringify!(gr_group)
)
);
}
impl Default for group_req {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_source_req {
pub gsr_interface: __u32,
pub gsr_group: __kernel_sockaddr_storage,
pub gsr_source: __kernel_sockaddr_storage,
}
#[test]
fn bindgen_test_layout_group_source_req() {
assert_eq!(
::std::mem::size_of::<group_source_req>(),
264usize,
concat!("Size of: ", stringify!(group_source_req))
);
assert_eq!(
::std::mem::align_of::<group_source_req>(),
8usize,
concat!("Alignment of ", stringify!(group_source_req))
);
assert_eq!(
unsafe { &(*(0 as *const group_source_req)).gsr_interface as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(group_source_req),
"::",
stringify!(gsr_interface)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_source_req)).gsr_group as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(group_source_req),
"::",
stringify!(gsr_group)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_source_req)).gsr_source as *const _ as usize },
136usize,
concat!(
"Alignment of field: ",
stringify!(group_source_req),
"::",
stringify!(gsr_source)
)
);
}
impl Default for group_source_req {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct group_filter {
pub gf_interface: __u32,
pub gf_group: __kernel_sockaddr_storage,
@@ -652,192 +277,18 @@ pub struct group_filter {
pub gf_numsrc: __u32,
pub gf_slist: [__kernel_sockaddr_storage; 1usize],
}
#[test]
fn bindgen_test_layout_group_filter() {
assert_eq!(
::std::mem::size_of::<group_filter>(),
272usize,
concat!("Size of: ", stringify!(group_filter))
);
assert_eq!(
::std::mem::align_of::<group_filter>(),
8usize,
concat!("Alignment of ", stringify!(group_filter))
);
assert_eq!(
unsafe { &(*(0 as *const group_filter)).gf_interface as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(group_filter),
"::",
stringify!(gf_interface)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_filter)).gf_group as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(group_filter),
"::",
stringify!(gf_group)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_filter)).gf_fmode as *const _ as usize },
136usize,
concat!(
"Alignment of field: ",
stringify!(group_filter),
"::",
stringify!(gf_fmode)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_filter)).gf_numsrc as *const _ as usize },
140usize,
concat!(
"Alignment of field: ",
stringify!(group_filter),
"::",
stringify!(gf_numsrc)
)
);
assert_eq!(
unsafe { &(*(0 as *const group_filter)).gf_slist as *const _ as usize },
144usize,
concat!(
"Alignment of field: ",
stringify!(group_filter),
"::",
stringify!(gf_slist)
)
);
}
impl Default for group_filter {
fn default() -> Self {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct in_pktinfo {
pub ipi_ifindex: ::std::os::raw::c_int,
pub ipi_spec_dst: in_addr,
pub ipi_addr: in_addr,
}
#[test]
fn bindgen_test_layout_in_pktinfo() {
assert_eq!(
::std::mem::size_of::<in_pktinfo>(),
12usize,
concat!("Size of: ", stringify!(in_pktinfo))
);
assert_eq!(
::std::mem::align_of::<in_pktinfo>(),
4usize,
concat!("Alignment of ", stringify!(in_pktinfo))
);
assert_eq!(
unsafe { &(*(0 as *const in_pktinfo)).ipi_ifindex as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(in_pktinfo),
"::",
stringify!(ipi_ifindex)
)
);
assert_eq!(
unsafe { &(*(0 as *const in_pktinfo)).ipi_spec_dst as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(in_pktinfo),
"::",
stringify!(ipi_spec_dst)
)
);
assert_eq!(
unsafe { &(*(0 as *const in_pktinfo)).ipi_addr as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(in_pktinfo),
"::",
stringify!(ipi_addr)
)
);
}
impl Clone for in_pktinfo {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
#[derive(Debug, Copy, Clone)]
pub struct sockaddr_in {
pub sin_family: __kernel_sa_family_t,
pub sin_port: __be16,
pub sin_addr: in_addr,
pub __pad: [::std::os::raw::c_uchar; 8usize],
}
#[test]
fn bindgen_test_layout_sockaddr_in() {
assert_eq!(
::std::mem::size_of::<sockaddr_in>(),
16usize,
concat!("Size of: ", stringify!(sockaddr_in))
);
assert_eq!(
::std::mem::align_of::<sockaddr_in>(),
4usize,
concat!("Alignment of ", stringify!(sockaddr_in))
);
assert_eq!(
unsafe { &(*(0 as *const sockaddr_in)).sin_family as *const _ as usize },
0usize,
concat!(
"Alignment of field: ",
stringify!(sockaddr_in),
"::",
stringify!(sin_family)
)
);
assert_eq!(
unsafe { &(*(0 as *const sockaddr_in)).sin_port as *const _ as usize },
2usize,
concat!(
"Alignment of field: ",
stringify!(sockaddr_in),
"::",
stringify!(sin_port)
)
);
assert_eq!(
unsafe { &(*(0 as *const sockaddr_in)).sin_addr as *const _ as usize },
4usize,
concat!(
"Alignment of field: ",
stringify!(sockaddr_in),
"::",
stringify!(sin_addr)
)
);
assert_eq!(
unsafe { &(*(0 as *const sockaddr_in)).__pad as *const _ as usize },
8usize,
concat!(
"Alignment of field: ",
stringify!(sockaddr_in),
"::",
stringify!(__pad)
)
);
}
impl Clone for sockaddr_in {
fn clone(&self) -> Self {
*self
}
}

View File

@@ -1,89 +1,95 @@
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
/* automatically generated by rust-bindgen */
// bindgen /usr/include/linux/sockios.h --no-layout-tests
pub const FIOSETOWN: ::std::os::raw::c_uint = 35073;
pub const SIOCSPGRP: ::std::os::raw::c_uint = 35074;
pub const FIOGETOWN: ::std::os::raw::c_uint = 35075;
pub const SIOCGPGRP: ::std::os::raw::c_uint = 35076;
pub const SIOCATMARK: ::std::os::raw::c_uint = 35077;
pub const SIOCGSTAMP: ::std::os::raw::c_uint = 35078;
pub const SIOCGSTAMPNS: ::std::os::raw::c_uint = 35079;
pub const SOCK_IOC_TYPE: ::std::os::raw::c_uint = 137;
pub const SIOCADDRT: ::std::os::raw::c_uint = 35083;
pub const SIOCDELRT: ::std::os::raw::c_uint = 35084;
pub const SIOCRTMSG: ::std::os::raw::c_uint = 35085;
pub const SIOCGIFNAME: ::std::os::raw::c_uint = 35088;
pub const SIOCSIFLINK: ::std::os::raw::c_uint = 35089;
pub const SIOCGIFCONF: ::std::os::raw::c_uint = 35090;
pub const SIOCGIFFLAGS: ::std::os::raw::c_uint = 35091;
pub const SIOCSIFFLAGS: ::std::os::raw::c_uint = 35092;
pub const SIOCGIFADDR: ::std::os::raw::c_uint = 35093;
pub const SIOCSIFADDR: ::std::os::raw::c_uint = 35094;
pub const SIOCGIFDSTADDR: ::std::os::raw::c_uint = 35095;
pub const SIOCSIFDSTADDR: ::std::os::raw::c_uint = 35096;
pub const SIOCGIFBRDADDR: ::std::os::raw::c_uint = 35097;
pub const SIOCSIFBRDADDR: ::std::os::raw::c_uint = 35098;
pub const SIOCGIFNETMASK: ::std::os::raw::c_uint = 35099;
pub const SIOCSIFNETMASK: ::std::os::raw::c_uint = 35100;
pub const SIOCGIFMETRIC: ::std::os::raw::c_uint = 35101;
pub const SIOCSIFMETRIC: ::std::os::raw::c_uint = 35102;
pub const SIOCGIFMEM: ::std::os::raw::c_uint = 35103;
pub const SIOCSIFMEM: ::std::os::raw::c_uint = 35104;
pub const SIOCGIFMTU: ::std::os::raw::c_uint = 35105;
pub const SIOCSIFMTU: ::std::os::raw::c_uint = 35106;
pub const SIOCSIFNAME: ::std::os::raw::c_uint = 35107;
pub const SIOCSIFHWADDR: ::std::os::raw::c_uint = 35108;
pub const SIOCGIFENCAP: ::std::os::raw::c_uint = 35109;
pub const SIOCSIFENCAP: ::std::os::raw::c_uint = 35110;
pub const SIOCGIFHWADDR: ::std::os::raw::c_uint = 35111;
pub const SIOCGIFSLAVE: ::std::os::raw::c_uint = 35113;
pub const SIOCSIFSLAVE: ::std::os::raw::c_uint = 35120;
pub const SIOCADDMULTI: ::std::os::raw::c_uint = 35121;
pub const SIOCDELMULTI: ::std::os::raw::c_uint = 35122;
pub const SIOCGIFINDEX: ::std::os::raw::c_uint = 35123;
pub const SIOGIFINDEX: ::std::os::raw::c_uint = 35123;
pub const SIOCSIFPFLAGS: ::std::os::raw::c_uint = 35124;
pub const SIOCGIFPFLAGS: ::std::os::raw::c_uint = 35125;
pub const SIOCDIFADDR: ::std::os::raw::c_uint = 35126;
pub const SIOCSIFHWBROADCAST: ::std::os::raw::c_uint = 35127;
pub const SIOCGIFCOUNT: ::std::os::raw::c_uint = 35128;
pub const SIOCGIFBR: ::std::os::raw::c_uint = 35136;
pub const SIOCSIFBR: ::std::os::raw::c_uint = 35137;
pub const SIOCGIFTXQLEN: ::std::os::raw::c_uint = 35138;
pub const SIOCSIFTXQLEN: ::std::os::raw::c_uint = 35139;
pub const SIOCETHTOOL: ::std::os::raw::c_uint = 35142;
pub const SIOCGMIIPHY: ::std::os::raw::c_uint = 35143;
pub const SIOCGMIIREG: ::std::os::raw::c_uint = 35144;
pub const SIOCSMIIREG: ::std::os::raw::c_uint = 35145;
pub const SIOCWANDEV: ::std::os::raw::c_uint = 35146;
pub const SIOCOUTQNSD: ::std::os::raw::c_uint = 35147;
pub const SIOCGSKNS: ::std::os::raw::c_uint = 35148;
pub const SIOCDARP: ::std::os::raw::c_uint = 35155;
pub const SIOCGARP: ::std::os::raw::c_uint = 35156;
pub const SIOCSARP: ::std::os::raw::c_uint = 35157;
pub const SIOCDRARP: ::std::os::raw::c_uint = 35168;
pub const SIOCGRARP: ::std::os::raw::c_uint = 35169;
pub const SIOCSRARP: ::std::os::raw::c_uint = 35170;
pub const SIOCGIFMAP: ::std::os::raw::c_uint = 35184;
pub const SIOCSIFMAP: ::std::os::raw::c_uint = 35185;
pub const SIOCADDDLCI: ::std::os::raw::c_uint = 35200;
pub const SIOCDELDLCI: ::std::os::raw::c_uint = 35201;
pub const SIOCGIFVLAN: ::std::os::raw::c_uint = 35202;
pub const SIOCSIFVLAN: ::std::os::raw::c_uint = 35203;
pub const SIOCBONDENSLAVE: ::std::os::raw::c_uint = 35216;
pub const SIOCBONDRELEASE: ::std::os::raw::c_uint = 35217;
pub const SIOCBONDSETHWADDR: ::std::os::raw::c_uint = 35218;
pub const SIOCBONDSLAVEINFOQUERY: ::std::os::raw::c_uint = 35219;
pub const SIOCBONDINFOQUERY: ::std::os::raw::c_uint = 35220;
pub const SIOCBONDCHANGEACTIVE: ::std::os::raw::c_uint = 35221;
pub const SIOCBRADDBR: ::std::os::raw::c_uint = 35232;
pub const SIOCBRDELBR: ::std::os::raw::c_uint = 35233;
pub const SIOCBRADDIF: ::std::os::raw::c_uint = 35234;
pub const SIOCBRDELIF: ::std::os::raw::c_uint = 35235;
pub const SIOCSHWTSTAMP: ::std::os::raw::c_uint = 35248;
pub const SIOCGHWTSTAMP: ::std::os::raw::c_uint = 35249;
pub const SIOCDEVPRIVATE: ::std::os::raw::c_uint = 35312;
pub const SIOCPROTOPRIVATE: ::std::os::raw::c_uint = 35296;
/* automatically generated by rust-bindgen 0.58.1 */
pub const __BITS_PER_LONG: u32 = 64;
pub const FIOSETOWN: u32 = 35073;
pub const SIOCSPGRP: u32 = 35074;
pub const FIOGETOWN: u32 = 35075;
pub const SIOCGPGRP: u32 = 35076;
pub const SIOCATMARK: u32 = 35077;
pub const SIOCGSTAMP_OLD: u32 = 35078;
pub const SIOCGSTAMPNS_OLD: u32 = 35079;
pub const SOCK_IOC_TYPE: u32 = 137;
pub const SIOCGSTAMP: u32 = 35078;
pub const SIOCGSTAMPNS: u32 = 35079;
pub const SIOCADDRT: u32 = 35083;
pub const SIOCDELRT: u32 = 35084;
pub const SIOCRTMSG: u32 = 35085;
pub const SIOCGIFNAME: u32 = 35088;
pub const SIOCSIFLINK: u32 = 35089;
pub const SIOCGIFCONF: u32 = 35090;
pub const SIOCGIFFLAGS: u32 = 35091;
pub const SIOCSIFFLAGS: u32 = 35092;
pub const SIOCGIFADDR: u32 = 35093;
pub const SIOCSIFADDR: u32 = 35094;
pub const SIOCGIFDSTADDR: u32 = 35095;
pub const SIOCSIFDSTADDR: u32 = 35096;
pub const SIOCGIFBRDADDR: u32 = 35097;
pub const SIOCSIFBRDADDR: u32 = 35098;
pub const SIOCGIFNETMASK: u32 = 35099;
pub const SIOCSIFNETMASK: u32 = 35100;
pub const SIOCGIFMETRIC: u32 = 35101;
pub const SIOCSIFMETRIC: u32 = 35102;
pub const SIOCGIFMEM: u32 = 35103;
pub const SIOCSIFMEM: u32 = 35104;
pub const SIOCGIFMTU: u32 = 35105;
pub const SIOCSIFMTU: u32 = 35106;
pub const SIOCSIFNAME: u32 = 35107;
pub const SIOCSIFHWADDR: u32 = 35108;
pub const SIOCGIFENCAP: u32 = 35109;
pub const SIOCSIFENCAP: u32 = 35110;
pub const SIOCGIFHWADDR: u32 = 35111;
pub const SIOCGIFSLAVE: u32 = 35113;
pub const SIOCSIFSLAVE: u32 = 35120;
pub const SIOCADDMULTI: u32 = 35121;
pub const SIOCDELMULTI: u32 = 35122;
pub const SIOCGIFINDEX: u32 = 35123;
pub const SIOGIFINDEX: u32 = 35123;
pub const SIOCSIFPFLAGS: u32 = 35124;
pub const SIOCGIFPFLAGS: u32 = 35125;
pub const SIOCDIFADDR: u32 = 35126;
pub const SIOCSIFHWBROADCAST: u32 = 35127;
pub const SIOCGIFCOUNT: u32 = 35128;
pub const SIOCGIFBR: u32 = 35136;
pub const SIOCSIFBR: u32 = 35137;
pub const SIOCGIFTXQLEN: u32 = 35138;
pub const SIOCSIFTXQLEN: u32 = 35139;
pub const SIOCETHTOOL: u32 = 35142;
pub const SIOCGMIIPHY: u32 = 35143;
pub const SIOCGMIIREG: u32 = 35144;
pub const SIOCSMIIREG: u32 = 35145;
pub const SIOCWANDEV: u32 = 35146;
pub const SIOCOUTQNSD: u32 = 35147;
pub const SIOCGSKNS: u32 = 35148;
pub const SIOCDARP: u32 = 35155;
pub const SIOCGARP: u32 = 35156;
pub const SIOCSARP: u32 = 35157;
pub const SIOCDRARP: u32 = 35168;
pub const SIOCGRARP: u32 = 35169;
pub const SIOCSRARP: u32 = 35170;
pub const SIOCGIFMAP: u32 = 35184;
pub const SIOCSIFMAP: u32 = 35185;
pub const SIOCADDDLCI: u32 = 35200;
pub const SIOCDELDLCI: u32 = 35201;
pub const SIOCGIFVLAN: u32 = 35202;
pub const SIOCSIFVLAN: u32 = 35203;
pub const SIOCBONDENSLAVE: u32 = 35216;
pub const SIOCBONDRELEASE: u32 = 35217;
pub const SIOCBONDSETHWADDR: u32 = 35218;
pub const SIOCBONDSLAVEINFOQUERY: u32 = 35219;
pub const SIOCBONDINFOQUERY: u32 = 35220;
pub const SIOCBONDCHANGEACTIVE: u32 = 35221;
pub const SIOCBRADDBR: u32 = 35232;
pub const SIOCBRDELBR: u32 = 35233;
pub const SIOCBRADDIF: u32 = 35234;
pub const SIOCBRDELIF: u32 = 35235;
pub const SIOCSHWTSTAMP: u32 = 35248;
pub const SIOCGHWTSTAMP: u32 = 35249;
pub const SIOCDEVPRIVATE: u32 = 35312;
pub const SIOCPROTOPRIVATE: u32 = 35296;

View File

@@ -2,20 +2,23 @@
name = "net_util"
version = "0.1.0"
authors = ["The Chromium OS Authors"]
edition = "2018"
[dependencies]
epoll = ">=4.0.1"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = "1.0.125"
serde = "1.0.126"
versionize = "0.1.6"
versionize_derive = "0.1.4"
virtio-bindings = "0.1.0"
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = ">=0.3.1"
[dev-dependencies]
lazy_static = "1.3.0"
pnet = "0.27.2"
pnet = "0.28.0"
serde_json = "1.0.64"

141
net_util/src/ctrl_queue.rs Normal file
View File

@@ -0,0 +1,141 @@
// Copyright (c) 2021 Intel Corporation. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use crate::GuestMemoryMmap;
use crate::Tap;
use libc::c_uint;
use virtio_bindings::bindings::virtio_net::{
VIRTIO_NET_CTRL_GUEST_OFFLOADS, VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, VIRTIO_NET_CTRL_MQ,
VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, VIRTIO_NET_ERR, VIRTIO_NET_F_GUEST_CSUM,
VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_OK,
};
use vm_memory::{ByteValued, Bytes, GuestMemoryError};
use vm_virtio::Queue;
#[derive(Debug)]
pub enum Error {
/// Read queue failed.
GuestMemory(GuestMemoryError),
/// No queue pairs number.
NoQueuePairsDescriptor,
/// No status descriptor
NoStatusDescriptor,
}
type Result<T> = std::result::Result<T, Error>;
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, Default)]
pub struct ControlHeader {
pub class: u8,
pub cmd: u8,
}
unsafe impl ByteValued for ControlHeader {}
pub struct CtrlQueue {
pub taps: Vec<Tap>,
}
impl CtrlQueue {
pub fn new(taps: Vec<Tap>) -> Self {
CtrlQueue { taps }
}
pub fn process(&mut self, mem: &GuestMemoryMmap, queue: &mut Queue) -> Result<bool> {
let mut used_desc_heads = Vec::new();
for avail_desc in queue.iter(&mem) {
let ctrl_hdr: ControlHeader =
mem.read_obj(avail_desc.addr).map_err(Error::GuestMemory)?;
let data_desc = avail_desc
.next_descriptor()
.ok_or(Error::NoQueuePairsDescriptor)?;
let status_desc = data_desc
.next_descriptor()
.ok_or(Error::NoStatusDescriptor)?;
let ok = match u32::from(ctrl_hdr.class) {
VIRTIO_NET_CTRL_MQ => {
let queue_pairs = mem
.read_obj::<u16>(data_desc.addr)
.map_err(Error::GuestMemory)?;
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET {
warn!("Unsupported command: {}", ctrl_hdr.cmd);
false
} else if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
|| (queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
{
warn!("Number of MQ pairs out of range: {}", queue_pairs);
false
} else {
info!("Number of MQ pairs requested: {}", queue_pairs);
true
}
}
VIRTIO_NET_CTRL_GUEST_OFFLOADS => {
let features = mem
.read_obj::<u64>(data_desc.addr)
.map_err(Error::GuestMemory)?;
if u32::from(ctrl_hdr.cmd) != VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET {
warn!("Unsupported command: {}", ctrl_hdr.cmd);
false
} else {
let mut ok = true;
for tap in self.taps.iter_mut() {
info!("Reprogramming tap offload with features: {}", features);
tap.set_offload(virtio_features_to_tap_offload(features))
.map_err(|e| {
error!("Error programming tap offload: {:?}", e);
ok = false
})
.ok();
}
ok
}
}
_ => {
warn!("Unsupported command {:?}", ctrl_hdr);
false
}
};
mem.write_obj(
if ok { VIRTIO_NET_OK } else { VIRTIO_NET_ERR } as u8,
status_desc.addr,
)
.map_err(Error::GuestMemory)?;
used_desc_heads.push((avail_desc.index, avail_desc.len));
}
for (desc_index, len) in used_desc_heads.iter() {
queue.add_used(&mem, *desc_index, *len);
queue.update_avail_event(&mem);
}
Ok(!used_desc_heads.is_empty())
}
}
pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
let mut tap_offloads: c_uint = 0;
if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 {
tap_offloads |= net_gen::TUN_F_CSUM;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 {
tap_offloads |= net_gen::TUN_F_TSO4;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 {
tap_offloads |= net_gen::TUN_F_TSO6;
}
if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 {
tap_offloads |= net_gen::TUN_F_TSO_ECN;
}
if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 {
tap_offloads |= net_gen::TUN_F_UFO;
}
tap_offloads
}

View File

@@ -10,26 +10,31 @@
#[cfg(test)]
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate net_gen;
extern crate rate_limiter;
extern crate serde;
extern crate virtio_bindings;
extern crate vm_memory;
extern crate vm_virtio;
extern crate vmm_sys_util;
mod ctrl_queue;
mod mac;
mod open_tap;
mod queue_pair;
mod tap;
use std::io::Error as IoError;
use std::os::raw::c_uint;
use std::os::unix::io::{FromRawFd, RawFd};
use std::{io, mem, net};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::bindings::virtio_net::{
virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4,
VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MQ,
};
use vm_memory::{bitmap::AtomicBitmap, ByteValued};
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
pub use ctrl_queue::{CtrlQueue, Error as CtrlQueueError};
pub use mac::{MacAddr, MAC_ADDR_LEN};
pub use open_tap::{open_tap, Error as OpenTapError};
pub use queue_pair::{NetCounters, NetQueuePair, NetQueuePairError, RxVirtio, TxVirtio};
@@ -43,6 +48,20 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
#[repr(C, packed)]
#[derive(Copy, Clone, Debug, Default, Versionize)]
pub struct VirtioNetConfig {
pub mac: [u8; 6],
pub status: u16,
pub max_virtqueue_pairs: u16,
pub mtu: u16,
pub speed: u32,
pub duplex: u8,
}
// Safe because it only has data and has no implicit padding.
unsafe impl ByteValued for VirtioNetConfig {}
/// Create a sockaddr_in from an IPv4 address, and expose it as
/// an opaque sockaddr suitable for usage by socket ioctls.
fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_gen::sockaddr {
@@ -70,7 +89,6 @@ fn create_socket() -> Result<net::UdpSocket> {
}
fn vnet_hdr_len() -> usize {
use virtio_bindings::bindings::virtio_net::virtio_net_hdr_v1;
std::mem::size_of::<virtio_net_hdr_v1>()
}
@@ -102,6 +120,53 @@ pub fn unregister_listener(
)
}
pub fn build_net_config_space(
mut config: &mut VirtioNetConfig,
mac: MacAddr,
num_queues: usize,
avail_features: &mut u64,
) {
config.mac.copy_from_slice(mac.get_bytes());
*avail_features |= 1 << VIRTIO_NET_F_MAC;
build_net_config_space_with_mq(&mut config, num_queues, avail_features);
}
pub fn build_net_config_space_with_mq(
config: &mut VirtioNetConfig,
num_queues: usize,
avail_features: &mut u64,
) {
let num_queue_pairs = (num_queues / 2) as u16;
if (num_queue_pairs >= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN as u16)
&& (num_queue_pairs <= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX as u16)
{
config.max_virtqueue_pairs = num_queue_pairs;
*avail_features |= 1 << VIRTIO_NET_F_MQ;
}
}
pub fn virtio_features_to_tap_offload(features: u64) -> c_uint {
let mut tap_offloads: c_uint = 0;
if features & (1 << VIRTIO_NET_F_GUEST_CSUM) != 0 {
tap_offloads |= net_gen::TUN_F_CSUM;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO4) != 0 {
tap_offloads |= net_gen::TUN_F_TSO4;
}
if features & (1 << VIRTIO_NET_F_GUEST_TSO6) != 0 {
tap_offloads |= net_gen::TUN_F_TSO6;
}
if features & (1 << VIRTIO_NET_F_GUEST_ECN) != 0 {
tap_offloads |= net_gen::TUN_F_TSO_ECN;
}
if features & (1 << VIRTIO_NET_F_GUEST_UFO) != 0 {
tap_offloads |= net_gen::TUN_F_UFO;
}
tap_offloads
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -152,8 +152,6 @@ impl FromStr for MacAddr {
#[cfg(test)]
mod tests {
extern crate serde_json;
use super::*;
#[test]

View File

@@ -27,8 +27,6 @@ pub enum Error {
TapSetMac(TapError),
/// Getting MAC address failed
TapGetMac(TapError),
/// Setting tap interface offload flags failed.
TapSetOffload(TapError),
/// Setting vnet header size failed.
TapSetVnetHdrSize(TapError),
/// Enabling tap interface failed.

View File

@@ -3,13 +3,14 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use super::{unregister_listener, vnet_hdr_len, Tap};
use crate::GuestMemoryMmap;
use rate_limiter::{RateLimiter, TokenType};
use std::io;
use std::num::Wrapping;
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use vm_memory::{Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap};
use vm_memory::{Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic};
use vm_virtio::Queue;
#[derive(Clone)]

View File

@@ -6,8 +6,7 @@
// found in the THIRD-PARTY file.
use super::{create_sockaddr, create_socket, vnet_hdr_len, Error as NetUtilError, MacAddr};
use mac::MAC_ADDR_LEN;
use net_gen;
use crate::mac::MAC_ADDR_LEN;
use std::fs::File;
use std::io::{Error as IoError, Read, Result as IoResult, Write};
use std::net;
@@ -121,13 +120,12 @@ impl Tap {
let mut ifreq: net_gen::ifreq = Default::default();
unsafe {
let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
let name_slice = &mut ifrn_name[..terminated_if_name.len()];
name_slice.copy_from_slice(terminated_if_name.as_slice());
*ifru_flags =
ifreq.ifr_ifru.ifru_flags =
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
if num_queue_pairs > 1 {
*ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
}
}
@@ -138,8 +136,7 @@ impl Tap {
return Err(Error::ConfigureTap(IoError::last_os_error()));
}
let if_name_temp = unsafe { *ifreq.ifr_ifrn.ifrn_name.as_ref() };
let mut if_name = if_name_temp.to_vec();
let mut if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
if_name.truncate(terminated_if_name.len() - 1);
// Safe since only the name is accessed, and it's cloned out.
Ok(Tap {
@@ -173,16 +170,16 @@ impl Tap {
if ret < 0 {
return Err(Error::IoctlError(IoError::last_os_error()));
}
let if_name = unsafe { *ifreq.ifr_ifrn.ifrn_name.as_ref() }.to_vec();
// We only access one field of the ifru union, hence this is safe.
let if_name = unsafe { ifreq.ifr_ifrn.ifrn_name }.to_vec();
// Try and update flags. Depending on how the tap was created (macvtap
// or via open_named()) this might return -EEXIST so we just ignore that.
unsafe {
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
*ifru_flags =
ifreq.ifr_ifru.ifru_flags =
(net_gen::IFF_TAP | net_gen::IFF_NO_PI | net_gen::IFF_VNET_HDR) as c_short;
if num_queue_pairs > 1 {
*ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
ifreq.ifr_ifru.ifru_flags |= net_gen::IFF_MULTI_QUEUE as c_short;
}
}
let ret = unsafe { ioctl_with_mut_ref(&tap_file, net_gen::TUNSETIFF(), &mut ifreq) };
@@ -204,11 +201,7 @@ impl Tap {
let mut ifreq = self.get_ifreq();
// We only access one field of the ifru union, hence this is safe.
unsafe {
let ifru_addr = ifreq.ifr_ifru.ifru_addr.as_mut();
*ifru_addr = addr;
}
ifreq.ifr_ifru.ifru_addr = addr;
// ioctl is safe. Called with a valid sock fd, and we check the return.
#[allow(clippy::cast_lossless)]
@@ -245,9 +238,9 @@ impl Tap {
}
// We only access one field of the ifru union, hence this is safe.
unsafe {
let ifru_hwaddr = ifreq.ifr_ifru.ifru_hwaddr.as_mut();
let ifru_hwaddr = &mut ifreq.ifr_ifru.ifru_hwaddr;
for (i, v) in addr.get_bytes().iter().enumerate() {
ifru_hwaddr.sa_data[i] = *v as c_char;
ifru_hwaddr.sa_data[i] = *v as c_uchar;
}
}
@@ -278,11 +271,8 @@ impl Tap {
// We only access one field of the ifru union, hence this is safe.
let addr = unsafe {
let ifru_hwaddr = ifreq.ifr_ifru.ifru_hwaddr.as_ref();
MacAddr::from_bytes(
&*(&ifru_hwaddr.sa_data[0..MAC_ADDR_LEN] as *const _ as *const [u8]),
)
.map_err(Error::MacParsing)?
MacAddr::from_bytes(&ifreq.ifr_ifru.ifru_hwaddr.sa_data[0..MAC_ADDR_LEN])
.map_err(Error::MacParsing)?
};
Ok(addr)
}
@@ -294,11 +284,7 @@ impl Tap {
let mut ifreq = self.get_ifreq();
// We only access one field of the ifru union, hence this is safe.
unsafe {
let ifru_addr = ifreq.ifr_ifru.ifru_addr.as_mut();
*ifru_addr = addr;
}
ifreq.ifr_ifru.ifru_addr = addr;
// ioctl is safe. Called with a valid sock fd, and we check the return.
#[allow(clippy::cast_lossless)]
@@ -338,7 +324,7 @@ impl Tap {
}
// If TAP device is already up don't try and enable it
let ifru_flags = unsafe { ifreq.ifr_ifru.ifru_flags.as_ref() };
let ifru_flags = unsafe { ifreq.ifr_ifru.ifru_flags };
if ifru_flags
& (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
== (net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16
@@ -346,13 +332,8 @@ impl Tap {
return Ok(());
}
// We only access one field of the ifru union, hence this is safe.
unsafe {
let ifru_flags = ifreq.ifr_ifru.ifru_flags.as_mut();
*ifru_flags =
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
}
ifreq.ifr_ifru.ifru_flags =
(net_gen::net_device_flags_IFF_UP | net_gen::net_device_flags_IFF_RUNNING) as i16;
// ioctl is safe. Called with a valid sock fd, and we check the return.
#[allow(clippy::cast_lossless)]
@@ -631,18 +612,6 @@ mod tests {
assert!(ret.is_ok());
}
#[test]
fn test_tap_get_ifreq() {
let _tap_ip_guard = TAP_IP_LOCK.lock().unwrap();
let tap = Tap::new(1).unwrap();
let ret = tap.get_ifreq();
assert_eq!(
"__BindgenUnionField",
format!("{:?}", ret.ifr_ifrn.ifrn_name)
);
}
#[test]
fn test_raw_fd() {
let _tap_ip_guard = TAP_IP_LOCK.lock().unwrap();

View File

@@ -10,11 +10,10 @@ byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "master" }
vmm-sys-util = ">=0.3.1"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
serde = {version = ">=1.0.27", features = ["rc"] }
serde_derive = ">=1.0.27"
serde_json = ">=1.0.9"
versionize = "0.1.6"
versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = "0.5.0"

View File

@@ -7,7 +7,9 @@ use crate::{MsixConfig, PciInterruptPin};
use byteorder::{ByteOrder, LittleEndian};
use std::fmt::{self, Display};
use std::sync::{Arc, Mutex};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
use versionize_derive::Versionize;
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
// The number of 32bit registers in the config space, 4096 bytes.
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
@@ -276,7 +278,7 @@ fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> {
None
}
#[derive(Serialize, Deserialize, Default, Clone, Copy)]
#[derive(Default, Clone, Copy, Versionize)]
struct PciBar {
addr: u32,
size: u32,
@@ -284,7 +286,7 @@ struct PciBar {
r#type: Option<PciBarRegionType>,
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
struct PciConfigurationState {
registers: Vec<u32>,
writable_bits: Vec<u32>,
@@ -296,6 +298,8 @@ struct PciConfigurationState {
msix_cap_reg_idx: Option<usize>,
}
impl VersionMapped for PciConfigurationState {}
/// Contains the configuration space of a PCI node.
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
/// The configuration space is accessed with DWORD reads and writes from the guest.
@@ -313,7 +317,7 @@ pub struct PciConfiguration {
}
/// See pci_regs.h in kernel
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Copy, Clone, PartialEq, Versionize)]
pub enum PciBarRegionType {
Memory32BitRegion = 0,
IoRegion = 0x01,
@@ -881,11 +885,11 @@ impl Snapshottable for PciConfiguration {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id(), &self.state())
Snapshot::new_from_versioned_state(&self.id(), &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id())?);
self.set_state(&snapshot.to_versioned_state(&self.id())?);
Ok(())
}
}

View File

@@ -5,12 +5,6 @@
//! Implements pci devices and busses.
#[macro_use]
extern crate log;
extern crate hypervisor;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate vm_memory;
mod bus;
mod configuration;

View File

@@ -3,9 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
extern crate byteorder;
extern crate vm_memory;
use byteorder::{ByteOrder, LittleEndian};
use std::sync::Arc;
use vm_device::interrupt::{

View File

@@ -3,20 +3,19 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
extern crate byteorder;
extern crate vm_memory;
use crate::{PciCapability, PciCapabilityId};
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use std::io;
use std::result;
use std::sync::Arc;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use vm_device::interrupt::{
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
};
use vm_memory::ByteValued;
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
@@ -36,7 +35,7 @@ enum Error {
UpdateInterruptRoute(io::Error),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Versionize)]
pub struct MsixTableEntry {
pub msg_addr_lo: u32,
pub msg_addr_hi: u32,
@@ -61,7 +60,7 @@ impl Default for MsixTableEntry {
}
}
#[derive(Serialize, Deserialize)]
#[derive(Versionize)]
struct MsixConfigState {
table_entries: Vec<MsixTableEntry>,
pba_entries: Vec<u64>,
@@ -69,6 +68,8 @@ struct MsixConfigState {
enabled: bool,
}
impl VersionMapped for MsixConfigState {}
pub struct MsixConfig {
pub table_entries: Vec<MsixTableEntry>,
pub pba_entries: Vec<u64>,
@@ -432,11 +433,11 @@ impl Snapshottable for MsixConfig {
}
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
Snapshot::new_from_state(&self.id(), &self.state())
Snapshot::new_from_versioned_state(&self.id(), &self.state())
}
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.set_state(&snapshot.to_state(&self.id())?)
self.set_state(&snapshot.to_versioned_state(&self.id())?)
.map_err(|e| {
MigratableError::Restore(anyhow!(
"Could not restore state for {}: {:?}",

View File

@@ -3,8 +3,6 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//
extern crate vm_allocator;
use crate::{
msi_num_enabled_vectors, BarReprogrammingParams, MsiConfig, MsixCap, MsixConfig,
PciBarConfiguration, PciBarRegionType, PciCapabilityId, PciClassCode, PciConfiguration,

View File

@@ -10,7 +10,7 @@ path = "src/qcow.rs"
[dependencies]
byteorder = "1.4.3"
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
remain = "0.2.2"
vmm-sys-util = ">=0.3.1"

View File

@@ -4,6 +4,6 @@ version = "0.1.0"
edition = "2018"
[dependencies]
libc = "0.2.94"
libc = "0.2.96"
log = "0.4.14"
vmm-sys-util = "0.8.0"

View File

@@ -1,3 +1,10 @@
- [v16.0](#v160)
- [Improved live migration support](#improved-live-migration-support)
- [Improved `vhost-user` support](#improved-vhost-user-support)
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
- [Notable bug fixes](#notable-bug-fixes)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@@ -5,7 +12,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations)
- [Contributors](#contributors)
- [Contributors](#contributors-1)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@@ -15,7 +22,7 @@
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
- [Block device rate limiting](#block-device-rate-limiting)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-1)
- [Contributors](#contributors-2)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@@ -23,13 +30,13 @@
- [VHD disk image support](#vhd-disk-image-support)
- [Improved Virtio device threading](#improved-virtio-device-threading)
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
- [Contributors](#contributors-2)
- [Contributors](#contributors-3)
- [v0.12.0](#v0120)
- [ARM64 enhancements](#arm64-enhancements)
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
- [Enhanced "info" API](#enhanced-info-api)
- [Contributors](#contributors-3)
- [Contributors](#contributors-4)
- [v0.11.0](#v0110)
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
- [Windows Guest Support](#windows-guest-support)
@@ -41,15 +48,15 @@
- [Default Log Level Changed](#default-log-level-changed)
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors-4)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-5)
- [v0.10.0](#v0100)
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
- [Memory Zones](#memory-zones)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-5)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-6)
- [v0.9.0](#v090)
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
- [Block and Network Device Statistics](#block-and-network-device-statistics)
@@ -62,17 +69,17 @@
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
- [Intel SGX Support](#intel-sgx-support)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-6)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-7)
- [v0.8.0](#v080)
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
- [Experimental ARM64 Support](#experimental-arm64-support)
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-7)
- [Contributors](#contributors-8)
- [v0.7.0](#v070)
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
- [Alternative `libc` Support](#alternative-libc-support)
@@ -82,14 +89,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-8)
- [Contributors](#contributors-9)
- [v0.6.0](#v060)
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
- [Command Line Interface](#command-line-interface)
- [PVH Boot](#pvh-boot)
- [Contributors](#contributors-9)
- [Contributors](#contributors-10)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -97,7 +104,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-10)
- [Contributors](#contributors-11)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -106,7 +113,7 @@
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
- [PCI BAR reprogramming](#pci-bar-reprogramming)
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
- [Contributors](#contributors-11)
- [Contributors](#contributors-12)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@@ -133,6 +140,55 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# v16.0
This release has been tracked through the [v16.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/19).
### Improved live migration support
The live migration support inside Cloud Hypervisor has been improved with the addition of the tracking of dirty pages written by the VMM to complement the tracking of dirty pages made by the guest itself. Further the internal state of the VMM now is versioned which allows the safe migration of VMs from one version of the VMM to a newer one. However further testing is required so this should be done with care. See the [live migration documentation](docs/live_migration.md) for more details.
### Improved `vhost-user` support
When using `vhost-user` to access devices implemented in different processes there is now support for reconnection of those devices in the case of a restart of the backend. In addition it is now possible to operate with the direction of the `vhost-user-net` connection reversed with the server in the VMM and the client in the backend. This is aligns with the default approach recommended by Open vSwitch.
### ARM64 ACPI and UEFI support
Cloud Hypervisor now supports using ACPI and booting from a UEFI image on ARM64. This allows the use of stock OS images without direct kernel boot.
### Notable bug fixes
* Activating fewer `virtio-net` queues than advertised is now supported. This appeared when using OVMF with an MQ enabled device (#2578).
* When using MQ with `virtio` devices Cloud Hypervisor now enforces a minimum vCPU count which ensures that the user will not see adverse guest performance (#2563).
* The KVM clock is now correctly handled during live migration / snapshot & restore.
### Removed functionality
The following formerly deprecated features have been removed:
* Support for booting with the "LinuxBoot" protocol for ELF and `bzImage`
binaries has been deprecated. When using direct boot users should configure
their kernel with `CONFIG_PVH=y`.
### Contributors
Many thanks to everyone who has contributed to our release including some new faces.
* Anatol Belski <anbelski@linux.microsoft.com>
* Bo Chen <chen.bo@intel.com>
* Dayu Liu <liu.dayu@zte.com.cn>
* Henry Wang <Henry.Wang@arm.com>
* Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
* Jianyong Wu <jianyong.wu@arm.com>
* Michael Zhao <michael.zhao@arm.com>
* Mikko Ylinen <mikko.ylinen@intel.com>
* Muminul Islam <muislam@microsoft.com>
* Ren Lei <ren.lei4@zte.com.cn>
* Rob Bradford <robert.bradford@intel.com>
* Sebastien Boeuf <sebastien.boeuf@intel.com>
* Wei Liu <liuwe@microsoft.com>
* Yi Wang <wang.yi59@zte.com.cn>
# v15.0
This release has been tracked through the [v15.0 project](https://github.com/cloud-hypervisor/cloud-hypervisor/projects/18).

View File

@@ -1,7 +1,7 @@
FROM ubuntu:20.04 as dev
ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.51.0"
ARG RUST_TOOLCHAIN="1.52.1"
ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
@@ -37,11 +37,18 @@ RUN apt-get update \
socat \
dosfstools \
cpio \
libfdt-dev \
python \
python3 \
python3-setuptools \
ntfs-3g \
openvswitch-switch-dpdk \
python3-distutils \
uuid-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
RUN if [ "$TARGETARCH" = "amd64" ]; then \
apt-get update \
&& apt-get -yq upgrade \
@@ -56,14 +63,7 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \
&& apt-get -yq upgrade \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq libcap2-bin \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
# Build and install the musl-gcc version of libfdt. This is to ensure
# the cloud-hypervisor binary can be built and linked using musl toolchain.
&& git clone https://github.com/dgibson/dtc.git && cd dtc \
&& sed -i 's/$(LIBFDT_archive) $(LIBFDT_lib)/$(LIBFDT_archive)/g' Makefile \
&& export CC=musl-gcc && make libfdt \
&& cp libfdt/libfdt.a /usr/lib/aarch64-linux-musl \
&& rm -rf /dtc; fi
&& rm -rf /var/lib/apt/lists/*; fi
# Fix the libssl-dev install
RUN export ARCH="$(uname -m)" \

View File

@@ -1,6 +1,6 @@
Name: cloud-hypervisor
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
Version: 0.13.0
Version: 15.0
Release: 0%{?dist}
License: ASL 2.0 or BSD-3-clause
Group: Applications/System
@@ -88,5 +88,8 @@ setcap cap_net_admin+ep %{_libdir}/cloud-hypervisor/static/vhost_user_net
%changelog
* Fri May 28 2021 Muminul Islam <muislam@microsoft.com> 15.0-0
- Update version to 15.0
* Wed Jul 22 2020 Muminul Islam <muislam@microsoft.com> 0.8.0-0
- Initial version

View File

@@ -8,9 +8,73 @@ export BUILD_TARGET=${BUILD_TARGET-aarch64-unknown-linux-gnu}
WORKLOADS_DIR="$HOME/workloads"
WORKLOADS_LOCK="$WORKLOADS_DIR/integration_test.lock"
EDK2_BUILD_DIR="$WORKLOADS_DIR/edk2_build"
mkdir -p "$WORKLOADS_DIR"
build_edk2() {
EDK2_REPO="https://github.com/cloud-hypervisor/edk2.git"
EDK2_DIR="edk2"
EDK2_BRANCH="ch-aarch64"
EDK2_PLAT_REPO="https://github.com/tianocore/edk2-platforms.git"
EDK2_PLAT_DIR="edk2-platforms"
ACPICA_REPO="https://github.com/acpica/acpica.git"
ACPICA_DIR="acpica"
export WORKSPACE="$EDK2_BUILD_DIR"
export PACKAGES_PATH="$WORKSPACE/$EDK2_DIR:$WORKSPACE/$EDK2_PLAT_DIR"
export IASL_PREFIX="$WORKSPACE/acpica/generate/unix/bin/"
cd "$WORKLOADS_DIR"
if [ ! -d "$WORKSPACE" ]; then
mkdir -p "$WORKSPACE"
fi
pushd "$WORKSPACE"
# Check whether the local HEAD commit same as the remote HEAD or not. Remove the folder if they are different.
if [ -d "$EDK2_DIR" ]; then
pushd $EDK2_DIR
git fetch
EDK2_LOCAL_HEAD=$(git rev-parse HEAD)
EDK2_REMOTE_HEAD=$(git rev-parse remotes/origin/$EDK2_BRANCH)
popd
if [ "$EDK2_LOCAL_HEAD" != "$EDK2_REMOTE_HEAD" ]; then
# If EDK2 code is out of date, remove and rebuild all
rm -rf "$EDK2_DIR"
rm -rf "$EDK2_PLAT_DIR"
rm -rf "$ACPICA_DIR"
fi
fi
if [ ! -d "$EDK2_DIR" ]; then
time git clone --depth 1 "$EDK2_REPO" -b "$EDK2_BRANCH" "$EDK2_DIR"
pushd $EDK2_DIR
git submodule update --init
popd
fi
if [ ! -d "$EDK2_PLAT_DIR" ]; then
time git clone --depth 1 "$EDK2_PLAT_REPO" -b master "$EDK2_PLAT_DIR"
fi
if [ ! -d "$ACPICA_DIR" ]; then
time git clone --depth 1 "$ACPICA_REPO" -b master "$ACPICA_DIR"
fi
make -C "$ACPICA_DIR"/
source edk2/edksetup.sh
make -C edk2/BaseTools
build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtCloudHv.dsc -b RELEASE
cp Build/ArmVirtCloudHv-AARCH64/RELEASE_GCC5/FV/CLOUDHV_EFI.fd "$WORKLOADS_DIR"
echo "Info: build UEFI successfully"
popd
}
update_workloads() {
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
@@ -176,6 +240,9 @@ update_workloads() {
echo "foo" > "$SHARED_DIR/file1"
echo "bar" > "$SHARED_DIR/file3" || exit 1
fi
# Check and build EDK2 binary
build_edk2
}
process_common_args "$@"
@@ -186,8 +253,10 @@ if [[ "$hypervisor" = "mshv" ]]; then
exit 1
fi
features_build="--no-default-features --features $hypervisor "
features_test="--no-default-features --features integration_tests,$hypervisor"
features_build_fdt="--no-default-features --features $hypervisor"
features_build_acpi="--no-default-features --features $hypervisor,acpi"
features_test_fdt="--no-default-features --features integration_tests,$hypervisor"
features_test_acpi="--no-default-features --features integration_tests,$hypervisor,acpi"
# lock the workloads folder to avoid parallel updating by different containers
(
@@ -211,7 +280,10 @@ TARGET_CC="musl-gcc"
CFLAGS="-I /usr/include/aarch64-linux-musl/ -idirafter /usr/include/"
fi
cargo build --all --release $features_build --target $BUILD_TARGET
export RUST_BACKTRACE=1
# Test without ACPI
cargo build --all --release $features_build_fdt --target $BUILD_TARGET
strip target/$BUILD_TARGET/release/cloud-hypervisor
strip target/$BUILD_TARGET/release/vhost_user_net
strip target/$BUILD_TARGET/release/ch-remote
@@ -222,8 +294,27 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
export RUST_BACKTRACE=1
time cargo test $features_test "tests::parallel::$test_filter"
# Setup ovs-dpdk
echo 2048 | sudo tee /proc/sys/vm/nr_hugepages
service openvswitch-switch start
ovs-vsctl init
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
service openvswitch-switch restart
time cargo test $features_test_fdt "tests::parallel::$test_filter"
RES=$?
echo "Integration test on FDT finished with result $RES."
if [ $RES -eq 0 ]; then
# Test with EDK2 + ACPI
cargo build --all --release $features_build_acpi --target $BUILD_TARGET
strip target/$BUILD_TARGET/release/cloud-hypervisor
strip target/$BUILD_TARGET/release/vhost_user_net
strip target/$BUILD_TARGET/release/ch-remote
time cargo test $features_test_acpi "tests::parallel::test_edk2_acpi_launch"
RES=$?
echo "Integration test on UEFI & ACPI finished with result $RES."
fi
exit $RES

View File

@@ -22,7 +22,7 @@ strip target/$BUILD_TARGET/release/cloud-hypervisor
export RUST_BACKTRACE=1
time cargo test $features_test "tests::vfio::$test_filter"
time cargo test $features_test "tests::vfio::$test_filter" -- --test-threads=1
RES=$?
exit $RES

View File

@@ -44,7 +44,7 @@ export RUST_BACKTRACE=1
# Only run with 1 thread to avoid tests interfering with one another because
# Windows has a static IP configured
time cargo test $features_test "tests::windows::$test_filter" -- --test-threads=1
time cargo test $features_test "tests::windows::$test_filter"
RES=$?
dmsetup remove_all -f

View File

@@ -43,7 +43,7 @@ if [ ! -f "$BIONIC_OS_RAW_IMAGE" ]; then
fi
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210407-0.qcow2"
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
FOCAL_OS_IMAGE_URL="https://cloudhypervisorstorage.blob.core.windows.net/images/$FOCAL_OS_IMAGE_NAME"
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_IMAGE" ]; then
@@ -52,7 +52,7 @@ if [ ! -f "$FOCAL_OS_IMAGE" ]; then
popd
fi
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210407-0.raw"
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.raw"
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR
@@ -96,7 +96,6 @@ popd
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
BZIMAGE_IMAGE="$WORKLOADS_DIR/bzImage"
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
@@ -112,7 +111,6 @@ if [ ! -f "$VMLINUX_IMAGE" ]; then
pushd $LINUX_CUSTOM_DIR
time make bzImage -j `nproc`
cp vmlinux $VMLINUX_IMAGE || exit 1
cp arch/x86/boot/bzImage $BZIMAGE_IMAGE || exit 1
popd
fi
@@ -200,10 +198,16 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan"
sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
# test_vfio relies on hugepages
echo 4096 | sudo tee /proc/sys/vm/nr_hugepages
# Both test_vfio and ovs-dpdk rely on hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
# Setup ovs-dpdk
service openvswitch-switch start
ovs-vsctl init
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
service openvswitch-switch restart
export RUST_BACKTRACE=1
time cargo test $features_test "tests::parallel::$test_filter"
RES=$?

View File

@@ -1,6 +1,6 @@
6fee67adbfed8db7a225be23ee9d90b5bd7f19e6 bionic-server-cloudimg-arm64.img
786fe1c33588334e92b35c65e414da068df180bc bionic-server-cloudimg-arm64.raw
34039f2fc4242acff0d42af82fbee91070978da3 bionic-server-cloudimg-arm64.qcow2
6e66f9f4b01adc72c884c1c1111e60afadc9c871 bionic-server-cloudimg-arm64.qcow2
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
063d1a9f32db641138e6e0c53f58e6545a3d48e6 focal-server-cloudimg-arm64-custom.raw
013837926872f1c7d1b3a1a95305e4a31c8600ab focal-server-cloudimg-arm64-custom.qcow2

View File

@@ -1,5 +1,5 @@
27f3b17962ace69b51f0ddc2012095e3109e6ed8 bionic-server-cloudimg-amd64.qcow2
8db9cc58b01452ce2d06c313177e6e74d8582d93 bionic-server-cloudimg-amd64.raw
d4a44acc6014d5f83dea1c625c43d677a95fa75f alpine-minirootfs-x86_64.tar.gz
f2f88ab4c08e36a4b6747a1aac4f94065952cadd focal-server-cloudimg-amd64-custom-20210407-0.qcow2
6c5770ebd34c0dd53987bc9deae43690ef02ffc5 focal-server-cloudimg-amd64-custom-20210407-0.raw
f1eccdc5e1b515dbad294426ab081b47ebfb97c0 focal-server-cloudimg-amd64-custom-20210609-0.qcow2
7f5a8358243a96adf61f5c20139b29f308f2c0e3 focal-server-cloudimg-amd64-custom-20210609-0.raw

View File

@@ -5,9 +5,6 @@
#[macro_use(crate_authors)]
extern crate clap;
extern crate api_client;
extern crate serde_json;
extern crate vmm;
use api_client::simple_api_command;
use api_client::Error as ApiClientError;

View File

@@ -3,14 +3,8 @@
// SPDX-License-Identifier: Apache-2.0
//
extern crate anyhow;
extern crate signal_hook;
extern crate vmm;
extern crate vmm_sys_util;
#[macro_use(crate_authors)]
extern crate clap;
#[macro_use]
extern crate event_monitor;
@@ -194,7 +188,7 @@ fn create_app<'a, 'b>(
.long("kernel")
.help(
"Path to loaded kernel. This may be a kernel or firmware that supports a PVH \
entry point, a vmlinux ELF file or a Linux bzImage or achitecture equivalent",
entry point (e.g. vmlinux) or architecture equivalent",
)
.takes_value(true)
.group("vm-config"),
@@ -984,11 +978,13 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--cpus", "boot=2",
"--net",
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4",
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
"net": [
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4}
]
@@ -998,11 +994,13 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--cpus", "boot=2",
"--net",
"mac=12:34:56:78:90:ab,host_mac=34:56:78:90:ab:cd,tap=tap0,ip=1.2.3.4,mask=5.6.7.8,num_queues=4,queue_size=128",
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"cpus": {"boot_vcpus": 2, "max_vcpus": 2},
"net": [
{"mac": "12:34:56:78:90:ab", "host_mac": "34:56:78:90:ab:cd", "tap": "tap0", "ip": "1.2.3.4", "mask": "5.6.7.8", "num_queues": 4, "queue_size": 128}
]
@@ -1163,13 +1161,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4",
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4}
]
@@ -1179,13 +1178,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
]
@@ -1195,13 +1195,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
]
@@ -1211,13 +1212,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,dax=on"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
]
@@ -1227,13 +1229,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "dax": true}
]
@@ -1243,13 +1246,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=8589934592"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
]
@@ -1259,13 +1263,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true", "--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 8589934592}
]
@@ -1275,13 +1280,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true","--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128, "cache_size": 4294967296}
]
@@ -1291,13 +1297,14 @@ mod unit_tests {
(
vec![
"cloud-hypervisor", "--kernel", "/path/to/kernel",
"--memory", "shared=true",
"--memory", "shared=true","--cpus", "boot=4",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1,num_queues=4,queue_size=128,cache_size=4294967296"
],
r#"{
"kernel": {"path": "/path/to/kernel"},
"memory" : { "shared": true, "size": 536870912 },
"cpus": {"boot_vcpus": 4, "max_vcpus": 4},
"fs": [
{"tag": "virtiofs1", "socket": "/path/to/sock1", "num_queues": 4, "queue_size": 128}
]

View File

@@ -44,7 +44,7 @@ write_files:
# 1G ram requires 512 pages
echo 512 | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210407-0.qcow2 path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:06.0/ path=/sys/bus/pci/devices/0000:00:07.0/ --api-socket /tmp/ch_api.sock
/mnt/cloud-hypervisor --kernel /mnt/vmlinux --cmdline "console=hvc0 reboot=k panic=1 nomodules root=/dev/vda1 VFIOTAG" --disk path=/mnt/focal-server-cloudimg-amd64-custom-20210609-0.qcow2 path=/mnt/cloudinit.img --cpus boot=1 --memory size=512M,hotplug_size=1G,hugepages=on --device path=/sys/bus/pci/devices/0000:00:06.0/ path=/sys/bus/pci/devices/0000:00:07.0/ --api-socket /tmp/ch_api.sock
-
path: /etc/systemd/system/notify-booted.service

View File

@@ -11,6 +11,7 @@ use std::net::TcpListener;
use std::net::TcpStream;
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::process::{ExitStatus, Output};
use std::str::FromStr;
use std::thread;
use vmm_sys_util::tempdir::TempDir;
@@ -503,6 +504,8 @@ pub enum SshCommandError {
Authentication(ssh2::Error),
ChannelSession(ssh2::Error),
Command(ssh2::Error),
ExitStatus(ssh2::Error),
NonZeroExitStatus(i32),
}
pub fn ssh_command_ip_with_auth(
@@ -537,7 +540,14 @@ pub fn ssh_command_ip_with_auth(
let _ = channel.read_to_string(&mut s);
let _ = channel.close();
let _ = channel.wait_close();
Ok(())
let status = channel.exit_status().map_err(SshCommandError::ExitStatus)?;
if status != 0 {
Err(SshCommandError::NonZeroExitStatus(status))
} else {
Ok(())
}
})() {
Ok(_) => break,
Err(e) => {
@@ -580,3 +590,17 @@ pub fn ssh_command_ip(
timeout,
)
}
pub fn exec_host_command_status(command: &str) -> ExitStatus {
std::process::Command::new("bash")
.args(&["-c", command])
.status()
.expect(&format!("Expected '{}' to run", command))
}
pub fn exec_host_command_output(command: &str) -> Output {
std::process::Command::new("bash")
.args(&["-c", command])
.output()
.expect(&format!("Expected '{}' to run", command))
}

Some files were not shown because too many files have changed in this diff Show More