Compare commits

..

278 Commits

Author SHA1 Message Date
Bo Chen
3a63fa2613 build: Release v31.2 (bug fix release)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-07-06 14:55:05 -07:00
Bo Chen
3a63143f33 misc: Address clippy beta issues
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-07-05 09:36:08 -07:00
Rob Bradford
064c1e2c8b virtio-devices: Avoid clashing names in imports
Don't import via glob to avoid (unused) objects colliding in the
namespace. This fixes a beta clippy issue.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-07-05 09:36:08 -07:00
Rob Bradford
15b9d14876 net_gen: Avoid clashing names in imports
Remove use of glob imports to fix an issue detected by clippy.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-07-05 09:36:08 -07:00
Alyssa Ross
9da363e79b vmm: ignore and warn TAP FDs send in vm.create
This does the same thing as df2a7c17 ("vmm: Ignore and warn TAP FDs
sent via the HTTP request body"), but for the vm.create endpoint,
which also previously would accept file descriptors in the body, and
try to use whatever fd occupied that number as a TAP device.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-07-05 09:36:08 -07:00
Alyssa Ross
bbfd810c3b vmm: allow restart_syscall() in PTY process
This can be triggered by debugging cloud-hypervisor using gdb, or
probably if the process is suspended and restarted.

Fixes: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/5489
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-07-05 09:36:08 -07:00
Jianyong Wu
8fb86d2284 vfio: fix vfio device fail to initialize issue for 64k page size
Currently, vfio device fails to initialize as the msix-cap region in BAR
is mapped as RW region.

To resolve the initialization issue, this commit avoids mapping the
msix-cap region in the BAR. However, this solution introduces another
problem where aligning the msix table offset in the BAR to the page
size may cause overlap with the MMIO RW region, leading to reduced
performance. By enlarging the entire region in the BAR and relocating
the msix table to achieve page size alignment, this problem can be
overcomed effectively.

Fixes: #5292
Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2023-07-05 09:36:08 -07:00
Jianyong Wu
797110cca1 vm-allocator: Add page size related functions
To avoid code duplication extract page related functions to their
own module and add utility functions for manipulating addresses
related to page sizes

Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2023-07-05 09:36:08 -07:00
Bo Chen
19ca5c0b84 vmm: Clarify memory regions are required to be page-size aligned
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-07-05 09:36:08 -07:00
Bo Chen
9fe9b8504d arch: Refactor the way of creating memory mapping
This patch clarifies the assumptions we have regarding the guest address
space layout while creating memory mapping in E820 on x86_64 and fdt on
aarch64. It also explicitly checks on these assumptions and report
errors if these assumptions do not hold.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-07-05 09:36:08 -07:00
Yu Li
4fc3dd5004 vmm: memory_manager: align down the rest space of ram_region
This commit renames `ram_region_sub_size` to `ram_region_available_size`
and make its value align down to the default page size or hugepage
size of the current memory zone, which can prevent the memory zone from
being split into misaligned parts.  And if the available size of ram
region is zero, this region will be marked as consumed even it has
unused space.

Note that there is two methods to use hugepages.

1. Specify `hugepages` for `memory` or `memory-zone`, if the
   `hugepage_size` is not specified, the value can be got by `statfs`
   for `/dev/hugepages`.
2. Specify a `file` in hugetlbfs for `memory-zone`, the hugepage size
   can also be got by `statfs` for the file.

The value for alignment will be the hugepage size if this memory zone
is using hugepages, otherwise the value will be default page size of
system.

Fixes: #5463

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-07-05 09:36:08 -07:00
Yu Li
6bc6365c35 arch: let arch_memory_regions return all available regions
The previous `arch_memory_regions` function will provide some memory
regions with the specified memory size and fill all the previous
regions before using the next one, but sometimes there may be no need
to fill up the previous one, e.g., the previous one should be aligned
with hugepage size.

This commit make `arch_memory_regions` function not take any
parameters and return the max available regions, the memory manager
can use them on demand.

Fixes: #5463

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-07-05 09:36:08 -07:00
Yu Li
e139cdfd69 arch: create memory mapping by the actual memory info
The original codes did not consider that the previous memory region
might not be full and always set it to the maximum size.

This commit fixes this problem by creating memory mappings based on
the actual memory details in both E820 on x86_64 and fdt on aarch64.

Fixes: #5463

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-07-05 09:36:08 -07:00
Yu Li
541de8b757 logger: use write with \r\n instead of writeln
The device manager will set tty or pty to raw mode, all the `\n` will
be LF without CR, which makes the output difficult to read.

This commit solves it by using `write` with `\r\n` instead of
`writeln`, which can print CR and LF explicitly.

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-07-05 09:36:08 -07:00
Yu Li
184dac70a0 vmm: use unwrap_or instead of match for prefault
Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-07-05 09:36:08 -07:00
Jianyong Wu
022b489e7b arch: x86_64: Populate the APIC Id
Program the APIC ID (CPUID leaf 0x1 EBX) with the CPU id. This resolves
an issue where the EDKII firmware expects the APIC ID to vary per-CPU.

Fixes: #5475
Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2023-07-05 09:36:08 -07:00
Alyssa Ross
399e2f9f7d vmm, virtio-devices: allow mremap for consoles
SerialBuffer uses VecDeque::extend, which calls realloc, which a
maximum buffer size of 1 MiB.  Starting at allocation sizes of
128 KiB, musl's mallocng allocator will use mremap for the allocation.
Since this was not permitted by the seccomp rules, heavy write load
could crash cloud-hypervisor with a seccomp failure.  (Encountered
using virtio-console, but I don't see any reason it wouldn't happen
for the legacy serial device too.)

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-07-05 09:36:08 -07:00
Rafael Mendonca
22cc96494f main: Fix error propagation if starting the VM fails
Commit 21d40d7 ("main: reset tty if starting the VM fails") changed
start_vmm() to join the vmm thread if an error happens after the vmm
thread is started. The implementation put all the error-prone code that
is run after the vmm is started in a closure, to be able to always join
the vmm thread, regardless of any error happening. However, it missed
propagating the error that might happen inside the closure back to the
main function, after joining the vmm thread.

For some cmd line options, the above issue inhibits proper error
reporting when starting a VM with invalid commands, as many parameters
are parsed after the vmm is started, thus if such parsing fails, no
error will be reported back to the user.

See: #5435
Fixes: 21d40d7 ("main: reset tty if starting the VM fails")
Signed-off-by: Rafael Mendonca <rafaelmendsr@gmail.com>
2023-07-05 09:36:08 -07:00
Bo Chen
f98402ec15 vmm: Allocate guest memory address space before TDX initialization
The refactoring on deferring address space allocation (#5169) broke TDX,
as TDX initialization needs to access guest memory for encryption and
measurement of guest pages.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-07-05 09:36:08 -07:00
Jianyong Wu
acc54ade7b vfio: align memory region size and address to PAGE_SIZE
In current implementation, memory region used in vfio is assumed to
align to 4k which may cause error when the PAGE_SIZE is not 4k, like on
Arm, it can be 16k and 64k.

Remove this assumption and align memory resource used by vfio to
PAGE_SIZE then vfio can run on host with 64k PAGE_SIZE.

Fixes: #5292
Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
2023-07-05 09:36:08 -07:00
Alyssa Ross
0ebbb3f8a2 vmm: allow getdents64 in seccomp filter
This is used on older kernels where close_range() is not available.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Fixes: 505f4dfa ("vmm: close all unused fds in sigwinch listener")
2023-07-05 09:36:08 -07:00
Anatol Belski
95511287ec tests: Enable topology integration tests under mshv
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2023-07-05 09:36:08 -07:00
Anatol Belski
5a3af30e6a seccomp: Add filter entry for MSHV_VP_REGISTER_INTERCEPT_RESULT
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2023-07-05 09:36:08 -07:00
Anatol Belski
034b48faf7 mshv: Pass topology explicitly while constructing cpuid
Unlike KVM, there's no internal handling for topoolgy under MSHV. Thus,
if no topology has been passed during the CH launch, use the boot CPUs
count to construct the topology struct.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2023-07-05 09:36:08 -07:00
Anatol Belski
ba3e02ce86 hypervisor: mshv: Implement set_cpuid2 call
Passing the CPUID leafs with the topology is integrated into the common
mechanism of setting and patching CPUID in Cloud Hypervisor. All the
CPUID values will be passed to the hypervisor through the register
intercept call.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2023-07-05 09:36:08 -07:00
Alyssa Ross
5492259af9 main: reset tty if starting the VM fails
When I refactored this to centralise resetting the tty into
DeviceManager::drop, I tested that the tty was reset if an error
happened on the vmm thread, but not on the main thread.  It turns out
that if an error happened on the main thread, the process would just
exit, so drop handlers on other threads wouldn't get run.

To fix this, I've changed start_vmm() to write to the VMM's exit
eventfd and then join the thread if an error happens after the vmm
thread is started.

Fixes: b6feae0a ("vmm: only touch the tty flags if it's being used")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-07-05 09:36:08 -07:00
Alyssa Ross
cc1254d5e1 vmm: reset to the original termios
Previously, we used two different functions for configuring ttys.
vmm_sys_util::terminal::Terminal::set_raw_mode() was used to configure
stdio ttys, and cfmakeraw() was used to configure ptys created by
cloud-hypervisor.  When I centralized the stdio tty cleanup, I also
switched to using cfmakeraw() everywhere, to avoid duplication.

cfmakeraw sets the OPOST flag, but when we later reset the ttys, we
used vmm_sys_util::terminal::Terminal::set_canon_mode(), which does
not unset this flag.  This meant that the terminal was getting mostly,
but not fully, reset.

To fix this without depending on the implementation of cfmakeraw(),
let's just store the original termios for stdio terminals, and restore
them to exactly the state we found them in when cloud-hypervisor exits.

Fixes: b6feae0a ("vmm: only touch the tty flags if it's being used")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-07-05 09:36:08 -07:00
Rob Bradford
34bb3319d4 hypervisor, vmm: Limit max number of vCPUs to hypervisor maximum
On KVM this is provided by an ioctl, on MSHV this is constant. Although
there is a HV_MAXIMUM_PROCESSORS constant the MSHV ioctl API is limited
to u8.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-07-05 09:36:08 -07:00
Bo Chen
d530569ac2 build: Release v31.1 (bug fix release)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 16:41:02 -07:00
Bo Chen
75956e64ec tests: Extend '_test_macvtap()' with reboot
In this way, we can cover the scenario where a VM with hotplugged net
device using FDs can work properly with reboot.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
ae646c2a00 vmm: Add valid FDs for TAP devices to 'VmConfig::preserved_fds'
In this way, valid FDs for TAP devices will be closed when the holding
VmConfig instance is destroyed.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
04d3e5bbf5 vmm: Add unit test for 'VmConfig::preserved_fds'
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
cbe972659c vmm: Implement Clone and Drop for VmConfig
The custom 'clone' duplicates 'preserved_fds' so that the validation
logic can be safely carried out on the clone of the VmConfig.

The custom 'drop' ensures 'preserved_fds' are safely closed when the
holding VmConfig instance is destroyed.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
1e4e03d110 vmm: config: Extend 'VmConfig' with 'preserved_fds'
Preserved FDs are the ones that share the same life-time as its holding
VmConfig instance, such as FDs for creating TAP devices.

Preserved FDs will stay open as long as the holding VmConfig instance is
valid, and will be closed when the holding VmConfig instance is destroyed.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
4876f7550d Revert "vmm: config: Implement Clone for NetConfig"
This reverts commit ea4a95c4f6.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
c0146e3ef1 Revert "vmm: config: Close FDs for TAP devices that are provided to VM"
This reverts commit b14427540b.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
77a205881b Revert "vmm: config: Don't close reserved FDs from NetConfig::drop()"
This reverts commit 0110fb4edc.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
321421c53e Revert "vmm: config: Avoid closing invalid FDs from 'test_net_parsing()'"
This reverts commit 0567def931.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Bo Chen
48a87e699d Revert "vmm: config: Replace use of memfd_create with fd pointing to /dev/null"
This reverts commit 46066d6ae1.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Alyssa Ross
147a800d5d vmm: only touch the tty flags if it's being used
When neither serial nor console are connected to the tty,
cloud-hypervisor shouldn't touch the tty at all.  One way in which
this is annoying is that if I am running cloud-hypervisor without it
using my terminal, I expect to be able to suspend it with ^Z like any
other process, but that doesn't work if it's put the terminal into raw
mode.

Instead of putting the tty into raw mode when a VM is created or
restored, do it when a serial or console device is created.  Since we
now know it can't be put into raw mode until the Vm object is created,
we can move setting it back to canon mode into the drop handler for
that object, which should always be run in normal operation.  We still
also put the tty into canon mode in the SIGTERM / SIGINT handler, but
check whether the tty was actually used, rather than whether stdin is
a tty.  This requires passing on_tty around as an atomic boolean.

I explored more of an abstraction over the tty — having an object that
encapsulated stdout and put the tty into raw mode when initialized and
into canon mode when dropped — but it wasn't practical, mostly due to
the special requirements of the signal handler.  I also investigated
whether the SIGWINCH listener process could be used here, which I
think would have worked but I'm hesitant to involve it in serial
handling as well as conosle handling.

There's no longer a check for whether the file descriptor is a tty
before setting it into canon mode — it's redundant, because if it's
not a tty it just won't respond to the ioctl.

Tested by shutting down through the API, SIGTERM, and an error
injected after setting raw mode.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-18 10:47:33 -07:00
Alyssa Ross
eaf8cbd47d vmm: don't redundantly set the TTY to canon mode
If the VM is shut down, either it's going to be started again, in
which case we still want to be in raw mode, or the process is about to
exit, in which case canon mode will be set at the end of main.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-18 10:47:33 -07:00
Alyssa Ross
9d24e862eb vmm: only use KVM_ARM_VCPU_PMU_V3 if available
Having PMU in guests isn't critical, and not all hardware supports
it (e.g. Apple Silicon).

CpuManager::init_pmu already has a fallback for if PMU is not
supported by the VCPU, but we weren't getting that far, because we
would always try to initialise the VCPU with KVM_ARM_VCPU_PMU_V3, and
then bail when it returned with EINVAL.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-18 10:47:33 -07:00
Alyssa Ross
11324ac21c virtio-devices: seccomp: add vhost-user syscalls
Cloud Hypervisor's vhost-user implementation will reconnect if it gets
disconnected from the backend.  That means connections happen inside
the vhost-user seccomp sandbox, so all syscalls used in reconnecting
have to be allowed in that sandbox.

clock_nanosleep is used by Glibc, and nanosleep is used by musl.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-18 10:47:33 -07:00
Bo Chen
ce75865e2c vmm: Ignore and warn TAP FDs sent via the HTTP request body
Valid FDs can only be sent from another process via `SCM_RIGHTS`.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-18 10:47:33 -07:00
Michael Zhao
f3522e85fc build: Release v31.0
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2023-04-06 07:05:11 -07:00
dependabot[bot]
d3ac6a85e0 build: Bump serde_with from 2.3.1 to 2.3.2 in /fuzz
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v2.3.1...v2.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-06 00:11:31 +00:00
Alyssa Ross
38a1b45783 vmm: use the SIGWINCH listener for TTYs too
Previously, we were only using it for PTYs, because for PTYs there's
no alternative.  But since we have to have it for PTYs anyway, if we
also use it for TTYs, we can eliminate all of the code that handled
SIGWINCH for TTYs.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:23:06 +01:00
Alyssa Ross
e9841db486 vmm: don't ignore errors from SIGWINCH listener
Now that the SIGWINCH listener has fallbacks for older kernels, we
don't expect it to routinely fail, so if there's an error setting it
up, we want to know about it.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:23:06 +01:00
Alyssa Ross
c1f555cde3 vmm: fall back if CLONE_CLEAR_SIGHAND unsupported
This will allow the SIGWINCH listener to run on kernels older than
5.5, although on those kernels it will have to make 64 syscalls to
reset all the signal handlers.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:23:06 +01:00
Alyssa Ross
505f4dfa53 vmm: close all unused fds in sigwinch listener
The PTY main file descriptor had to be introduced as a parameter to
start_sigwinch_listener, so that it could be closed in the child.
Really the SIGWINCH listener process should not have any file
descriptors open, except for the ones it needs to function, so let's
make it more robust by having it close all other file descriptors.

For recent kernels, we can do this very conveniently with
close_range(2), but for older kernels, we have to fall back to closing
open file descriptors one at a time.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:23:06 +01:00
Alyssa Ross
67ad3ff1ba scripts: run doc tests
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:22:47 +01:00
Alyssa Ross
755cabea4c hypervisor: use proper doc tests for examples
It seems like these examples were always intended to be doctests,
since there are lines marked with "#" so that they are excluded from
the generated documentation, but they were not recognised as doc tests
because they were not formatted correctly.

The code needed some adjustments so that it would actually compile and
run as doctests.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:22:47 +01:00
Alyssa Ross
1ed4898d28 hypervisor: fix building doctests
When doctests are built, the crate is built with itself as a
dependency via --extern.  This causes a compiler error if using a
module with the name same as the crate, because it's ambiguous whether
it's referring to the module, or the extern version of the crate, so
it's necessary to disambiguate when using the hypervisor module here.

Fixes running cargo test --doc --workspace.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-05 11:22:47 +01:00
Alyssa Ross
a807b91f86 virtio-devices: fix accidental HTML in doc comments
Doc comments are Markdown, and can include HTML tags.  Anything in
angle brackets will therefore be inserted as an HTML tag into
rustdoc's output.  If that's not intentional, the left angle bracket
needs to be escaped.

I haven't fixed the doc comments in src/main.rs, because argh doesn't
understand the escaping, so the backslashes would show up in the
--help output.  I've opened https://github.com/google/argh/issues/159
about that.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-04 17:38:21 -07:00
Alyssa Ross
f6236087d8 virtio-devices: fix broken vsock doc comments
These need to be //! comments, because they apply to the module as a
whole, not to whatever directly follows the comment.  Using ///
comments here resulted in documentation being attached to the wrong
thing, or not rendered at all.

I've also checked the Markdown formatting of these comments as
rendered by rustdoc, and fixed it where appropriate.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-04 17:38:21 -07:00
Alyssa Ross
95f83320b1 arch: use a non-doc comment for diagram
This doesn't need to be rendered in the HTML API documentation, and
wouldn't be formatted correctly if it was.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-04 17:38:21 -07:00
dependabot[bot]
dcc858a403 build: Bump libc from 0.2.139 to 0.2.141 in /fuzz
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.139 to 0.2.141.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.139...0.2.141)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-05 00:27:44 +00:00
Alyssa Ross
57ea412c64 hypervisor: make buildable independently
It was not possible to build just hypervisor with Cargo's -p flag,
because it was not properly specifying the features it requires from
vfio-ioctls.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2023-04-04 09:57:19 -07:00
Muminul Islam
e32c9525c0 tests: disable virtio_balloon_free_page_reporting on mshv
balloon_free_page_reporting test case should not
work as expected. The reason is that MSHV pins
all the pages during the memory map for the guest.
Those pages can not be altered without unpinning the pages.
MSHV does not support modifying the pages during the guest
life cycle. This test case can be enabled once we add
VA backed VM support.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2023-04-04 07:41:04 -07:00
Bo Chen
2b4f60e57b docs: Remove directory support from MemoryZoneConfig::file
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-04 06:49:18 -07:00
Bo Chen
5736205cf0 tests: Use native support of shared memory
This replaces the deprecated way of allocating anonymous shared memory
explicitly from '/dev/shm'.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-04-04 06:49:18 -07:00
Ravi kumar Veeramally
a8d1849485 vmm: Remove directory support from MemoryZoneConfig::file
Fixes: #5082

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-04-04 06:49:18 -07:00
dependabot[bot]
55937f63bc build: Bump serde_json from 1.0.93 to 1.0.95
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.93 to 1.0.95.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.93...v1.0.95)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-04 00:41:41 +00:00
dependabot[bot]
426d5d6dd0 build: Bump proc-macro2 from 1.0.54 to 1.0.56 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.54 to 1.0.56.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.54...1.0.56)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-04 00:12:40 +00:00
dependabot[bot]
3f3d07b3dc build: Bump openssl-sys from 0.9.81 to 0.9.83
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.81 to 0.9.83.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.81...openssl-sys-v0.9.83)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 13:29:11 -07:00
dependabot[bot]
296cb909f4 build: Bump serde_json from 1.0.94 to 1.0.95 in /fuzz
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.94 to 1.0.95.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.94...v1.0.95)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-01 00:26:03 +00:00
Omer Faruk Bayram
e7d52fc736 docs: api: document receive-migration and send-migration
Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
2023-03-31 10:02:34 -07:00
dependabot[bot]
a598b935f2 build: Bump regex-syntax from 0.6.28 to 0.6.29
Bumps [regex-syntax](https://github.com/rust-lang/regex) from 0.6.28 to 0.6.29.
- [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/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-31 00:41:13 +00:00
dependabot[bot]
1c0b6f1090 build: Bump remain from 0.2.7 to 0.2.8 in /fuzz
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.7 to 0.2.8.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.7...0.2.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-31 00:15:56 +00:00
Omer Faruk Bayram
1b12790c13 ch-remote: fixed ShutdownVmm and Shutdown commands
Fixed `ShutdownVmm` and `Shutdown` commands to call the correct API
endpoint.

Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
2023-03-30 09:37:02 -07:00
dependabot[bot]
bd307dcab5 build: Bump anyhow from 1.0.69 to 1.0.70 in /fuzz
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.69 to 1.0.70.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.69...1.0.70)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-30 00:16:07 +00:00
Daniel Farina
83d757d89a Fix typo in README.md
Signed-off-by: Daniel Farina <daniel@fdr.io>
2023-03-29 09:08:26 +01:00
dependabot[bot]
1b8e7ac06c build: Bump vm-fdt from 3709ca6 to ad21ede
Bumps [vm-fdt](https://github.com/rust-vmm/vm-fdt) from `3709ca6` to `ad21ede`.
- [Release notes](https://github.com/rust-vmm/vm-fdt/releases)
- [Commits](3709ca6336...ad21ede0dd)

---
updated-dependencies:
- dependency-name: vm-fdt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 00:41:17 +00:00
dependabot[bot]
389e4fe8be build: Bump serde from 1.0.158 to 1.0.159 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.158 to 1.0.159.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.158...v1.0.159)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 00:19:16 +00:00
Omer Faruk Bayram
06a9c3b839 scripts: dev_cli: mention the --local flag in the help string
Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
2023-03-28 12:37:35 +01:00
Omer Faruk Bayram
36cf46e381 docs: document that vmcoredump is conditionally compiled
Fixes #5311.

Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
2023-03-28 11:16:13 +01:00
dependabot[bot]
1efdea7466 build: Bump semver from 1.0.16 to 1.0.17
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.16 to 1.0.17.
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.16...1.0.17)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-28 00:40:43 +00:00
dependabot[bot]
e662a2e12c build: Bump proc-macro2 from 1.0.53 to 1.0.54 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.53 to 1.0.54.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.53...1.0.54)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-28 00:20:45 +00:00
Ravi kumar Veeramally
5496bd5dfb tests: Replace use of "curl" with direct HTTP API calls
Fixes: #5128

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-03-27 10:02:22 -07:00
dependabot[bot]
e655de1e39 build: Bump windows-targets from 0.42.1 to 0.42.2
Bumps [windows-targets](https://github.com/microsoft/windows-rs) from 0.42.1 to 0.42.2.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-25 00:41:54 +00:00
dependabot[bot]
a55a642b70 build: Bump proc-macro2 from 1.0.52 to 1.0.53 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.52 to 1.0.53.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.52...1.0.53)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-25 00:17:24 +00:00
dependabot[bot]
ded8959b9a build: Bump versionize from 0.1.9 to 0.1.10
Bumps [versionize](https://github.com/firecracker-microvm/versionize) from 0.1.9 to 0.1.10.
- [Release notes](https://github.com/firecracker-microvm/versionize/releases)
- [Changelog](https://github.com/firecracker-microvm/versionize/blob/main/CHANGELOG.md)
- [Commits](https://github.com/firecracker-microvm/versionize/compare/v0.1.9...v0.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 23:46:46 +00:00
dependabot[bot]
53e49636ca build: Bump versionize from 0.1.9 to 0.1.10 in /fuzz
Bumps [versionize](https://github.com/firecracker-microvm/versionize) from 0.1.9 to 0.1.10.
- [Release notes](https://github.com/firecracker-microvm/versionize/releases)
- [Changelog](https://github.com/firecracker-microvm/versionize/blob/main/CHANGELOG.md)
- [Commits](https://github.com/firecracker-microvm/versionize/compare/v0.1.9...v0.1.10)

---
updated-dependencies:
- dependency-name: versionize
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 22:55:42 +00:00
dependabot[bot]
0b0f3c69f0 build: Bump windows_x86_64_gnu from 0.42.1 to 0.42.2
Bumps [windows_x86_64_gnu](https://github.com/microsoft/windows-rs) from 0.42.1 to 0.42.2.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 00:39:19 +00:00
dependabot[bot]
6650f553bd build: Bump semver from 1.0.16 to 1.0.17 in /fuzz
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.16 to 1.0.17.
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.16...1.0.17)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 00:23:44 +00:00
dependabot[bot]
c5bca514b9 build: Bump serde from 1.0.156 to 1.0.158 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.156 to 1.0.158.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.156...v1.0.158)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 19:38:30 +00:00
Bo Chen
c4106c0592 fuzz: Fix building error with 'versionize_derive'
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-23 12:18:21 -07:00
dependabot[bot]
61f89e7dcc build: Bump windows_i686_gnu from 0.42.1 to 0.42.2
Bumps [windows_i686_gnu](https://github.com/microsoft/windows-rs) from 0.42.1 to 0.42.2.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-22 17:57:39 -07:00
dependabot[bot]
7a4be1534f build: Bump serde_with from 2.2.0 to 2.3.1
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 2.2.0 to 2.3.1.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v2.2.0...v2.3.1)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-22 00:39:59 +00:00
dependabot[bot]
cf0c4e07b6 build: Bump thiserror from 1.0.39 to 1.0.40 in /fuzz
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.39 to 1.0.40.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.39...1.0.40)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-22 00:13:14 +00:00
dependabot[bot]
36ec53c4a0 build: Bump is-terminal from 0.4.4 to 0.4.5
Bumps [is-terminal](https://github.com/sunfishcode/is-terminal) from 0.4.4 to 0.4.5.
- [Release notes](https://github.com/sunfishcode/is-terminal/releases)
- [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.4...v0.4.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-21 00:39:09 +00:00
dependabot[bot]
c7997ea4e5 build: Bump serde_json from 1.0.93 to 1.0.94 in /fuzz
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.93 to 1.0.94.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.93...v1.0.94)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-21 00:21:19 +00:00
dependabot[bot]
b2d3aba19c build: Bump proc-macro2 from 1.0.51 to 1.0.52
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.51 to 1.0.52.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.51...1.0.52)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-18 01:00:38 +00:00
dependabot[bot]
9cd97bb64e build: Bump remain from 0.2.6 to 0.2.7 in /fuzz
Bumps [remain](https://github.com/dtolnay/remain) from 0.2.6 to 0.2.7.
- [Release notes](https://github.com/dtolnay/remain/releases)
- [Commits](https://github.com/dtolnay/remain/compare/0.2.6...0.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-18 00:15:31 +00:00
dependabot[bot]
868fdf9dfe build: Bump paste from 1.0.11 to 1.0.12
Bumps [paste](https://github.com/dtolnay/paste) from 1.0.11 to 1.0.12.
- [Release notes](https://github.com/dtolnay/paste/releases)
- [Commits](https://github.com/dtolnay/paste/compare/1.0.11...1.0.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 17:22:53 +00:00
dependabot[bot]
12729eb034 build: Bump darling from 0.14.3 to 0.14.4 in /fuzz
Bumps [darling](https://github.com/TedDriggs/darling) from 0.14.3 to 0.14.4.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/compare/v0.14.3...v0.14.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 17:18:14 +00:00
Rob Bradford
a062401be6 scripts: dev_cli: Bump container version
Unfortunately the build had a transient error and so needed to be
restarted which generated a build with a different date tag.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-03-16 08:36:25 +00:00
dependabot[bot]
09cc139b53 build: Bump openssl-sys from 0.9.80 to 0.9.81
Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.80 to 0.9.81.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.80...openssl-sys-v0.9.81)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-16 00:46:10 +00:00
dependabot[bot]
4635ebd4b2 build: Bump arbitrary from 1.2.3 to 1.3.0 in /fuzz
Bumps [arbitrary](https://github.com/rust-fuzz/arbitrary) from 1.2.3 to 1.3.0.
- [Release notes](https://github.com/rust-fuzz/arbitrary/releases)
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/compare/v1.2.3...v1.3.0)

---
updated-dependencies:
- dependency-name: arbitrary
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-16 00:23:59 +00:00
Rob Bradford
ca96ff601b build: Migrate from DockerHub to ghcr
It is necessary to transition away from DockerHub as the small
organisation plan in being EOLed.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-03-15 22:41:23 +00:00
Bo Chen
feb523ef78 README: Fix typo and trailing white-space
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-15 10:13:27 -07:00
smit-gardhariya
7e47464a48 tests: performance-metrics: Add timeout parameter as runtime argument
This commit will add timeout parameter to performance metrics
testcases as runtime argument. Testcases are facing the timeout
sometimes when we run with MSHV hypervisor. This change will
provide mechanism to pass the timeout as per the need while
running the testcases. If nothing is passed, default timeout or
timeout set as per the testcase will be followed.

Signed-off-by: smit-gardhariya <gardhariya.smit@gmail.com>
2023-03-14 22:05:55 -07:00
dependabot[bot]
4c4f79c831 build: Bump windows_x86_64_gnullvm from 0.42.1 to 0.42.2
Bumps [windows_x86_64_gnullvm](https://github.com/microsoft/windows-rs) from 0.42.1 to 0.42.2.
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-15 00:39:47 +00:00
dependabot[bot]
0fd701ac75 build: Bump serde from 1.0.154 to 1.0.156 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.154 to 1.0.156.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.154...v1.0.156)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-15 00:20:16 +00:00
dependabot[bot]
64924d5c2b build: Bump signal-hook from 0.3.14 to 0.3.15
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.14 to 0.3.15.
- [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.14...v0.3.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-14 00:40:33 +00:00
dependabot[bot]
9c11927305 build: Bump proc-macro2 from 1.0.51 to 1.0.52 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.51 to 1.0.52.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.51...1.0.52)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-14 00:21:55 +00:00
Yang
b13d0e53c5 README: Add slack channel for community activity
Signed-off-by: Yang <ailin.yang@intel.com>
2023-03-13 12:27:32 -07:00
Ruslan Mstoi
6001240ca1 tests: Fix typo vitio-blk to virtio-blk
Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
2023-03-13 11:59:39 -07:00
dependabot[bot]
9534604ef3 build: Bump thiserror-impl from 1.0.38 to 1.0.39 in /fuzz
Bumps [thiserror-impl](https://github.com/dtolnay/thiserror) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.38...1.0.39)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-11 10:03:06 +00:00
Bo Chen
c152f9f6bc mics: Update reference kernel to 6.2
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-11 09:55:34 +00:00
Bo Chen
325e62372d scripts: Ensure to rebuild custom kernel for bare-metal tests
Tests of rate-limiter and vfio are running on bare-metal, so we need to
ensure the custom kernel is updated and rebuilt for them.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-11 09:55:34 +00:00
Bo Chen
9421884334 scripts: Use 'build_custom_linux' if possible
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-11 09:55:34 +00:00
dependabot[bot]
fcd09946b7 build: Bump darling from 0.14.3 to 0.14.4
Bumps [darling](https://github.com/TedDriggs/darling) from 0.14.3 to 0.14.4.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/compare/v0.14.3...v0.14.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-11 00:40:18 +00:00
dependabot[bot]
a20e481abe build: Bump thiserror from 1.0.38 to 1.0.39
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.38...1.0.39)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-10 00:39:45 +00:00
dependabot[bot]
6e4374c392 build: Bump ryu from 1.0.12 to 1.0.13 in /fuzz
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.12 to 1.0.13.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.12...1.0.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-10 00:18:00 +00:00
Ravi kumar Veeramally
44452cbe22 doc: Fix broken link for micro_http website
Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-03-09 09:58:46 -08:00
dependabot[bot]
7b2ebd2fa5 build: Bump itoa from 1.0.5 to 1.0.6
Bumps [itoa](https://github.com/dtolnay/itoa) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.5...1.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 00:39:36 +00:00
dependabot[bot]
8a0f6014ce build: Bump serde from 1.0.153 to 1.0.154 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.153 to 1.0.154.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.153...v1.0.154)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 00:15:46 +00:00
Bo Chen
d78da5d252 tests: Enable live-upgrade tests based on v30.0
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-08 13:02:38 +00:00
Dom
b35a94d83c tests: integration: Use hugepage size to calculate the number of pages
The tests require a fixed amount of huge page memory to run, rather than
encode that as fixed number of huge pages it should be calculated from
the size of memory required and the huge page size

Signed-off-by: Dom <peng6662001@163.com>
2023-03-08 10:18:28 +00:00
dependabot[bot]
961319d8ad build: Bump vfio-ioctls from 43439e0 to ea8f710
Bumps [vfio-ioctls](https://github.com/rust-vmm/vfio) from `43439e0` to `ea8f710`.
- [Release notes](https://github.com/rust-vmm/vfio/releases)
- [Commits](43439e056d...ea8f710464)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-08 02:11:45 +00:00
dependabot[bot]
b97f929706 build: Bump serde from 1.0.152 to 1.0.153 in /fuzz
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.152 to 1.0.153.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.152...v1.0.153)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-08 01:32:23 +00:00
Bo Chen
b71564f284 vmm: Remove unnecessary parentheses (beta 1.69 clippy check)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-07 17:02:35 -08:00
dependabot[bot]
f2be30f699 build: Bump mshv-bindings from 0b2af25 to 66531ba
Bumps [mshv-bindings](https://github.com/rust-vmm/mshv) from `0b2af25` to `66531ba`.
- [Release notes](https://github.com/rust-vmm/mshv/releases)
- [Commits](0b2af25128...66531ba242)

---
updated-dependencies:
- dependency-name: mshv-bindings
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-07 00:38:07 +00:00
dependabot[bot]
b14216e854 build: Bump unicode-ident from 1.0.6 to 1.0.8 in /fuzz
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.6 to 1.0.8.
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.6...1.0.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-07 00:22:05 +00:00
dependabot[bot]
3498e67bda build: Bump ryu from 1.0.12 to 1.0.13
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.12 to 1.0.13.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.12...1.0.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-04 00:37:43 +00:00
dependabot[bot]
24d163b244 build: Bump itoa from 1.0.5 to 1.0.6 in /fuzz
Bumps [itoa](https://github.com/dtolnay/itoa) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.5...1.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-04 00:24:21 +00:00
dependabot[bot]
90697d4ae0 build: Bump io-uring from 0.5.12 to 0.5.13
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.12 to 0.5.13.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-03 18:04:21 +00:00
Rob Bradford
73c4156775 vmm, devices: Update to latest acpi_tables crate API
Significant API changes have occured, most significantly is the switch
to an approach which does not require vm-memory and can run no_std.

Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
2023-03-03 13:08:36 +00:00
dependabot[bot]
02f774824b build: Bump gdbstub from 0.6.3 to 0.6.4
Bumps [gdbstub](https://github.com/daniel5151/gdbstub) from 0.6.3 to 0.6.4.
- [Release notes](https://github.com/daniel5151/gdbstub/releases)
- [Changelog](https://github.com/daniel5151/gdbstub/blob/master/CHANGELOG.md)
- [Commits](https://github.com/daniel5151/gdbstub/compare/0.6.3...0.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-02 00:39:01 +00:00
Hao Xu
74cd3d0dc2 virtio-devices: Reset offset properly upon unmap for virtio-fs.
We should reset the offset to 0, when asked to remove the whole dax
mapping.

Signed-off-by: Hao Xu <howeyxu@tencent.com>
2023-03-01 09:45:26 -08:00
Bo Chen
85962099c7 build: Update development container and release action to Rust 1.67
This latest stable Rust toolchain can help reduce the final binary size
around ~300k when comparing with building with Rust 1.62. Specifically,
the binary size now is 3.3M (previously 3.6M) with default feature, and
4.0M (previously 4.2M) with "kvm+mshv" feature (e.g. our release action
build) .

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-03-01 15:16:23 +00:00
dependabot[bot]
04ee1efa70 build: Bump virtio-queue from 0.7.0 to 0.7.1
Bumps [virtio-queue](https://github.com/rust-vmm/vm-virtio) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/rust-vmm/vm-virtio/releases)
- [Commits](https://github.com/rust-vmm/vm-virtio/compare/virtio-queue-v0.7.0...virtio-queue-v0.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-01 00:37:27 +00:00
dependabot[bot]
5258a870e0 build: Bump jobserver from 0.1.25 to 0.1.26 in /fuzz
Bumps [jobserver](https://github.com/alexcrichton/jobserver-rs) from 0.1.25 to 0.1.26.
- [Release notes](https://github.com/alexcrichton/jobserver-rs/releases)
- [Commits](https://github.com/alexcrichton/jobserver-rs/compare/0.1.25...0.1.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-01 00:14:52 +00:00
Yong He
76d6d28f3e vmm: do not start signal thread to resize console if no need
Now cloud hypervisor will start signal thread to catch
SIGWINCH signal, cloud hypervisor then will resize the
guest console via vconsole.

This patch skip starting signal thread when there is no
need to resize guest console, such as console is not
configured.

Signed-off-by: Yong He <alexyonghe@tencent.com>
2023-02-28 09:40:07 -08:00
dependabot[bot]
5132e3b907 build: Bump is-terminal from 0.4.3 to 0.4.4
Bumps [is-terminal](https://github.com/sunfishcode/is-terminal) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/sunfishcode/is-terminal/releases)
- [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.3...v0.4.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 00:40:40 +00:00
dependabot[bot]
599c5280ed build: Bump vm-fdt from c5a99ab to 3709ca6
Bumps [vm-fdt](https://github.com/rust-vmm/vm-fdt) from `c5a99ab` to `3709ca6`.
- [Release notes](https://github.com/rust-vmm/vm-fdt/releases)
- [Commits](c5a99ab71b...3709ca6336)

---
updated-dependencies:
- dependency-name: vm-fdt
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-25 00:36:09 +00:00
dependabot[bot]
2f649bb6ad build: Bump syn from 1.0.108 to 1.0.109 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.108 to 1.0.109.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.108...1.0.109)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-25 00:18:44 +00:00
Bo Chen
ece0e6fa92 build: Release v30.0
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-23 16:46:00 -08:00
Bo Chen
2593b67864 misc: Remove tailing whitespaces from release notes and cargo.toml
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-23 16:46:00 -08:00
dependabot[bot]
191e865261 build: Bump once_cell from 1.17.0 to 1.17.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.17.0 to 1.17.1.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.17.0...v1.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-24 00:36:14 +00:00
dependabot[bot]
ca3a441c49 build: Bump syn from 1.0.107 to 1.0.108 in /fuzz
Bumps [syn](https://github.com/dtolnay/syn) from 1.0.107 to 1.0.108.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.107...1.0.108)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-24 00:16:53 +00:00
Wei Liu
de3ca97095 hypervisor: rename get_cpuid to get_supported_cpuid
To better reflect its nature and avoid confusion with get_cpuid2.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-02-23 13:03:12 +00:00
Yu Li
74dcb37ec3 vmm: config: fix incorrect values of error
The PR #2333 added I/O rate limiter on block device, with some options
in `DiskConfig`.  And the PR #2401 added rate limiter on virtio-net
device with same options, but it still throws `Error::ParseDisk`.

This commit fixes it with correct values.

Fixes: #2401

Signed-off-by: Yu Li <liyu.yukiteru@bytedance.com>
2023-02-23 09:57:48 +00:00
dependabot[bot]
1d55de9c74 build: Bump virtio-bindings from 0.1.0 to 0.2.0
Bumps [virtio-bindings](https://github.com/rust-vmm/vm-virtio) from 0.1.0 to 0.2.0.
- [Release notes](https://github.com/rust-vmm/vm-virtio/releases)
- [Commits](https://github.com/rust-vmm/vm-virtio/compare/virtio-queue-v0.1.0...virtio-bindings-v0.2.0)

---
updated-dependencies:
- dependency-name: virtio-bindings
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-23 00:59:32 +00:00
Ruslan Mstoi
2e94a86b31 scripts: dev_cli.sh: print help if command unspecified
To improve user friendliness, print help text when no command is given.

Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
2023-02-22 11:29:54 -08:00
Rob Bradford
996bdc6e08 vfio_user: Use new Rust-VMM crate
This contains the same code as was included in tree.

Fixes: #5123

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-22 15:13:12 +00:00
dependabot[bot]
9d18012c52 build: Bump io-uring from 0.5.12 to 0.5.13 in /fuzz
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.12 to 0.5.13.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-22 00:18:07 +00:00
dependabot[bot]
6a8bd8e8c5 build: Bump signal-hook-registry from 1.4.0 to 1.4.1
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.0 to 1.4.1.
- [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.4.0...registry-v1.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-21 00:37:30 +00:00
dependabot[bot]
d9184e5256 build: Bump virtio-queue from 0.7.0 to 0.7.1 in /fuzz
Bumps [virtio-queue](https://github.com/rust-vmm/vm-virtio) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/rust-vmm/vm-virtio/releases)
- [Commits](https://github.com/rust-vmm/vm-virtio/compare/virtio-queue-v0.7.0...virtio-queue-v0.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-21 00:21:31 +00:00
dependabot[bot]
5e475e70e6 build: Bump acpi_tables from 4fd38dd to 12bb6d7
Bumps [acpi_tables](https://github.com/rust-vmm/acpi_tables) from `4fd38dd` to `12bb6d7`.
- [Release notes](https://github.com/rust-vmm/acpi_tables/releases)
- [Commits](4fd38dd5f7...12bb6d7b25)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-18 00:37:26 +00:00
Ruslan Mstoi
bd1e1677bd scripts: ch-trace-visualiser.py: remove unused import 'xml'
Unused import 'xml' is redefined at:

> xml = ET.ElementTree(element=svg)

Hence, remove unused xml import.

Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
2023-02-17 11:48:37 -08:00
dependabot[bot]
595c9d13a9 build: Bump proc-macro2 from 1.0.50 to 1.0.51
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.50 to 1.0.51.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.50...1.0.51)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-17 05:29:34 +00:00
dependabot[bot]
c2616f3f4f build: Bump signal-hook from 0.3.14 to 0.3.15 in /fuzz
Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.14 to 0.3.15.
- [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.14...v0.3.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-17 00:14:37 +00:00
Rob Bradford
7ceb126184 github: Build examples as well as tests in quality workflow
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
879411e70f build: Ensure pci crate uses vm-memory with required features
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
1181fd21fd vfio_user: Make GPIO device more interesting
Every third read on the GPIO pin will return 1 and also trigger an
interrupt in the guest.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
c8967fcc37 vfio_user: Add command line parsing for socket option
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
19e893fa53 vfio_user: Reject SET_IRQS with VFIO_IRQ_SET_DATA_BOOL
This is unsupported.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
aa502b3e41 vfio_user: Add TODOs for missing functionality
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
10531f052b vfio_user: Always generate an error for commands
Any error from the backend or from the protocol handling code will now
result in an error reply being sent. This is cleanly achieved by
splitting the command handling out into its own method and using the
Rust Result<> based error handling to trigger the generation of the
error reply.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
b072eb454e vfio_user: Add a simple sample device
This implements a similar GPIO device to that found in the libvfio-user
source code.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
b7c2a0f23f vfio_user: Add basic server side support
This allows the implementation of PCI devices in a different process
using the vfio-user protocol.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
874d524a13 vfio_user: Add flags for DMA_UNMAP command
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Rob Bradford
91e2601523 vfio_user: Improve flags for DMA_MAP command
Replace the use of an enum with a bitfield representation which means
that is now possible to logical OR flags together.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-16 09:59:14 -08:00
Yong He
01900e3c2b vmm: properly set vcpu state when thread exited
Once error occur, vcpu thread may exit, this should
be critical event for the whole VM, we should fire
exit event and set vcpu state.

If we don't set vcpu state, the shutdown process
will hang at signal_thread, which is waiting the
vcpu state to change.

Signed-off-by: Yong He <alexyonghe@tencent.com>
2023-02-16 14:40:04 +00:00
dependabot[bot]
e35ef40029 build: Bump fdt from 0.1.4 to 0.1.5
Bumps [fdt](https://github.com/repnop/fdt) from 0.1.4 to 0.1.5.
- [Release notes](https://github.com/repnop/fdt/releases)
- [Commits](https://github.com/repnop/fdt/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 00:36:48 +00:00
dependabot[bot]
aa0af5f8d7 build: Bump proc-macro2 from 1.0.50 to 1.0.51 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.50 to 1.0.51.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.50...1.0.51)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 00:14:39 +00:00
Rob Bradford
46066d6ae1 vmm: config: Replace use of memfd_create with fd pointing to /dev/null
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-15 11:10:00 -08:00
Rob Bradford
51c1738d55 tests: Disable test_vfio test
This test (which relies on nesting) is failing on the VFIO worker. The tests that use the
dedicated hardware pass fine.

See: #5190

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-15 12:30:34 +00:00
Bo Chen
0567def931 vmm: config: Avoid closing invalid FDs from 'test_net_parsing()'
We need to provide valid FDs while creating 'NetConfig' instances even
for unit tests. Closing invalid FDs would cause random unit test
failures.

Also, two identical 'NetConfig' instances are not allowed any more,
because it would lead to close the same FD twice. This is consistent
with the fact that a clone of a "NetConfig" instance is no
longer *equal* to the instance itself.

Fixes: #5203

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-15 12:30:09 +00:00
Bo Chen
0110fb4edc vmm: config: Don't close reserved FDs from NetConfig::drop()
Fixes: #5203

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-15 12:30:09 +00:00
dependabot[bot]
4f945743cb build: Bump is-terminal from 0.4.2 to 0.4.3
Bumps [is-terminal](https://github.com/sunfishcode/is-terminal) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/sunfishcode/is-terminal/releases)
- [Commits](https://github.com/sunfishcode/is-terminal/compare/v0.4.2...v0.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 11:27:27 +00:00
dependabot[bot]
8f6afec520 build: Bump once_cell from 1.17.0 to 1.17.1 in /fuzz
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.17.0 to 1.17.1.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.17.0...v1.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 00:14:51 +00:00
Rob Bradford
b14427540b vmm: config: Close FDs for TAP devices that are provided to VM
These are owned by the config (and are duplicated before being used to
create the `Tap` for the virtio-net device.)

By implementing Drop on NetConfig we have issues with moving out of
members that don't implement the Copy trait. This requires a small
adjustment to the unit tests that use the Default::default() function.

Fixes: #5197

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-14 12:37:50 +01:00
Rob Bradford
ea4a95c4f6 vmm: config: Implement Clone for NetConfig
The custom version duplicates any FDs that have been provided so that
the validation logic used on hotplug, which takes a clone of the config,
can be safely carried out.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-14 12:37:50 +01:00
dependabot[bot]
f5084f7c65 build: Bump uuid from 1.2.2 to 1.3.0
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.2.2...1.3.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-14 00:37:27 +00:00
dependabot[bot]
45ab9f77b7 build: Bump signal-hook-registry from 1.4.0 to 1.4.1 in /fuzz
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.0 to 1.4.1.
- [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.4.0...registry-v1.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-14 00:24:21 +00:00
dependabot[bot]
f0ea8eb70b build: Bump serde_json from 1.0.91 to 1.0.93
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.93.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 14:09:46 +01:00
Bo Chen
3377e0e983 docs: hotplug: Fix link to booting with uefi on aarch64
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-12 14:40:04 +08:00
dependabot[bot]
e9435b1327 build: Bump serde_json from 1.0.92 to 1.0.93 in /fuzz
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.92 to 1.0.93.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.92...v1.0.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-11 00:17:12 +00:00
Rob Bradford
09fca4a5dd build: Move to rust-vmm acpi_tables crate
This code is indentical to what is in this repository. When a release
gets made we can then switch to that.

Fixes: #5122

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-10 18:58:12 +01:00
Praveen K Paladugu
1143d54ee0 tpm: Add recv timeout while running recvmsg
If swtpm becomes unresponsive, guest gets blocked at "recvmsg" on tpm's
data FD. This change adds a timeout to the data fd socket. If swtpm
becomes unresponsive guest waits for "timeout" (secs) and continues to
run after returning an I/O error to tpm commands.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2023-02-10 17:49:03 +01:00
Anatol Belski
934b20a77a ci: Switch to Windows Server 2022
The updated image is configured in a same way as the previously used
2019, it has same

- Credentials
- Services configured, like SAC, SSH, RDP
- Size

All the Windows updates are applied so the state is current to the date.
Also, the latest stable version 0.1.229 of the VirtIO Windows drivers
is installed.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2023-02-10 17:48:46 +01:00
Jinank Jain
b54ce6c3db vmm: Defer address space allocation
We can ideally defer the address space allocation till we start the
vCPUs for the very first time. Because the VM will not access the memory
until the CPUs start running. Thus there is no need to allocate the
address space eagerly and wait till the time we are going to start the
vCPUs for the first time.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2023-02-10 11:52:20 +01:00
Kaihang Zhang
3dd01443d5 openapi: Make 'vcpu' and 'host_cpus' required in CpuAffinity
Signed-off-by: Kaihang Zhang <kaihang.zhang@smartx.com>
2023-02-10 10:06:43 +01:00
dependabot[bot]
43227cd5c4 build: Bump anyhow from 1.0.68 to 1.0.69
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.68 to 1.0.69.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.68...1.0.69)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-10 00:55:05 +00:00
dependabot[bot]
176e438d17 build: Bump anyhow from 1.0.68 to 1.0.69 in /fuzz
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.68 to 1.0.69.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.68...1.0.69)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-10 00:13:38 +00:00
Rob Bradford
c22c4675b3 arch, hypervisor: Populate CPUID leaf 0x4000_0010 (TSC frequency)
This hypervisor leaf includes details of the TSC frequency if that is
available from KVM. This can be used to efficiently calculate time
passed when there is an invariant TSC.

TEST=Run `cpuid` in the guest and observe the frequency populated.

Fixes: #5178

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-09 18:32:21 +01:00
Rob Bradford
7ccf58a019 Revert "build: Temporarily disable bare metal x86-64 workers"
This reverts commit 496f932276.

The systems are back online and reachable.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-09 16:30:07 +01:00
dependabot[bot]
48e1af7d3c build: Bump fdt from 0.1.4 to 0.1.5 in /fuzz
Bumps [fdt](https://github.com/repnop/fdt) from 0.1.4 to 0.1.5.
- [Release notes](https://github.com/repnop/fdt/releases)
- [Commits](https://github.com/repnop/fdt/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-08 23:20:11 +00:00
dependabot[bot]
341a69c39c build: Bump openssl-src from 111.24.0+1.1.1s to 111.25.0+1.1.1t
Bumps [openssl-src](https://github.com/alexcrichton/openssl-src-rs) from 111.24.0+1.1.1s to 111.25.0+1.1.1t.
- [Release notes](https://github.com/alexcrichton/openssl-src-rs/releases)
- [Commits](https://github.com/alexcrichton/openssl-src-rs/commits)

---
updated-dependencies:
- dependency-name: openssl-src
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-08 23:09:51 +00:00
dependabot[bot]
5d34d85b92 build: Bump darling from 0.14.2 to 0.14.3
Bumps [darling](https://github.com/TedDriggs/darling) from 0.14.2 to 0.14.3.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/compare/v0.14.2...v0.14.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-07 23:40:55 +00:00
dependabot[bot]
bcd46906ec build: Bump serde_json from 1.0.91 to 1.0.92 in /fuzz
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.92.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.92)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-07 23:17:44 +00:00
Bo Chen
bc59ca72f3 docs: Update the intel_tdx documentation
Updates include:
- Add references to 'TDX Tools'
- Expand instructions on buidling and using TDShim
- Add version information of guest/host kernel, TDVF, TDShim being tested

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-07 06:30:38 -08:00
dependabot[bot]
995945dd25 build: Bump rustix from 0.36.7 to 0.36.8
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.36.7 to 0.36.8.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.36.7...v0.36.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 23:42:06 +00:00
dependabot[bot]
8edd81ec82 build: Bump darling from 0.14.2 to 0.14.3 in /fuzz
Bumps [darling](https://github.com/TedDriggs/darling) from 0.14.2 to 0.14.3.
- [Release notes](https://github.com/TedDriggs/darling/releases)
- [Changelog](https://github.com/TedDriggs/darling/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TedDriggs/darling/compare/v0.14.2...v0.14.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 23:21:38 +00:00
dependabot[bot]
726cfa41f4 build: Bump pnet and pnet_datalink from 0.31.0 to 0.33.0
Bumps [pnet](https://github.com/libpnet/libpnet) from 0.31.0 to 0.33.0.
- [Release notes](https://github.com/libpnet/libpnet/releases)
- [Commits](https://github.com/libpnet/libpnet/compare/v0.31.0...v0.33.0)

---
updated-dependencies:
- dependency-name: pnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: Bo Chen <chen.bo@intel.com>
Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 19:26:36 +00:00
dependabot[bot]
d19a5d5356 build: Bump mshv-bindings from 48b389a to 0b2af25
Bumps [mshv-bindings](https://github.com/rust-vmm/mshv) from `48b389a` to `0b2af25`.
- [Release notes](https://github.com/rust-vmm/mshv/releases)
- [Commits](48b389af1f...0b2af25128)

---
updated-dependencies:
- dependency-name: mshv-bindings
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 23:42:08 +00:00
Rob Bradford
69e8f60b91 tdx: Set the SEPT_VE_DISABLE attribute
This is required for booting Linux:

From: https://lore.kernel.org/all/20221028141220.29217-3-kirill.shutemov@linux.intel.com/

"""

Virtualization Exceptions (#VE) are delivered to TDX guests due to
specific guest actions such as using specific instructions or accessing
a specific MSR.

Notable reason for #VE is access to specific guest physical addresses.
It requires special security considerations as it is not fully in
control of the guest kernel. VMM can remove a page from EPT page table
and trigger #VE on access.

The primary use-case for #VE on a memory access is MMIO: VMM removes
page from EPT to trigger exception in the guest which allows guest to
emulate MMIO with hypercalls.

MMIO only happens on shared memory. All conventional kernel memory is
private. This includes everything from kernel stacks to kernel text.

Handling exceptions on arbitrary accesses to kernel memory is
essentially impossible as handling #VE may require access to memory
that also triggers the exception.

TDX module provides mechanism to disable #VE delivery on access to
private memory. If SEPT_VE_DISABLE TD attribute is set, private EPT
violation will not be reflected to the guest as #VE, but will trigger
exit to VMM.

Make sure the attribute is set by VMM. Panic otherwise.

There's small window during the boot before the check where kernel has
early #VE handler. But the handler is only for port I/O and panic as
soon as it sees any other #VE reason.

SEPT_VE_DISABLE makes SEPT violation unrecoverable and terminating the
TD is the only option.

Kernel has no legitimate use-cases for #VE on private memory. It is
either a guest kernel bug (like access of unaccepted memory) or
malicious/buggy VMM that removes guest page that is still in use.

In both cases terminating TD is the right thing to do.

"""

With this change Cloud Hypervisor can boot the current Linux guest
kernel.

Reported-By: Jiaqi Gao <jiaqi.gao@intel.com
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-02 14:53:59 +00:00
dependabot[bot]
c6eb69caba build: Bump miniz_oxide from 0.6.2 to 0.6.4
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.6.2 to 0.6.4.
- [Release notes](https://github.com/Frommi/miniz_oxide/releases)
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.6.2...0.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 23:44:16 +00:00
dependabot[bot]
e4ed9bc557 build: Bump uuid from 1.2.2 to 1.3.0 in /fuzz
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.2.2...1.3.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 23:27:32 +00:00
dependabot[bot]
f4509c3611 build: Bump kvm-ioctls from 0.12.0 to 0.13.0
Bumps [kvm-ioctls](https://github.com/rust-vmm/kvm-ioctls) from 0.12.0 to 0.13.0.
- [Release notes](https://github.com/rust-vmm/kvm-ioctls/releases)
- [Changelog](https://github.com/rust-vmm/kvm-ioctls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/kvm-ioctls/commits)

---
updated-dependencies:
- dependency-name: kvm-ioctls
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-02-01 12:23:00 +00:00
Bo Chen
ecbb8ab282 docs: Add @likebreath to MAINTAINERS.md
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-02-01 12:19:07 +00:00
Wei Liu
29ebecccb0 tpm: be more consistent when converting responses
Do the following:

1. Use from_be_bytes to drop mutable slices.
2. Check for the exact buffer size throughout.
3. Simplify ptm_to_request where possible.
4. Make error messages style consistent.

Fix a typo in code comment while at it.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-31 18:09:28 +00:00
Wei Liu
5646a917ff tpm: handle short write
There is no guarantee that the write can send the whole buffer at once.

In those rare occasions, we should return a sensible error.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-31 18:09:28 +00:00
Wei Liu
6e22f23831 tpm: save almost 8KB stack space
The largest possible PTM response is only 16 bytes. Size the output
buffer correctly.

In the socket read function, rely on the caller to provide a
sufficiently large buffer. That eliminates another large stack variable.

In total this saves almost 8KB stack space.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-31 18:09:28 +00:00
Wei Liu
8e996ff2fe tpm: drop unnecessary cast
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-31 18:09:28 +00:00
Wei Liu
2d2f356d94 devices: tpm: failure to deliver request is considered fatal
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-31 18:09:18 +00:00
dependabot[bot]
938c16f2b2 build: Bump cc from 1.0.78 to 1.0.79
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.78 to 1.0.79.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.78...1.0.79)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-31 13:51:07 +00:00
dependabot[bot]
105a7dd7aa build: Bump cc from 1.0.78 to 1.0.79 in /fuzz
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.78 to 1.0.79.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.78...1.0.79)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 23:21:59 +00:00
Wei Liu
11ef495e6b performance-metrics: share build.rs from project root
No need to duplicate the same content in two places.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-30 21:10:02 +00:00
Wei Liu
34b3170680 vmm: fix two typos
Change "thead" to "thread".

Also make sure the two messages are distinguishable by adding "vmm" and
"vm" prefix.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-30 21:10:02 +00:00
Wei Liu
427a2bacf5 block_util: convert aligned_operations to SmallVec
The number of aligned operations can not be larger than the number of
descriptors. Initializing the capacity to 1 is good enough per the
observation that most of time there is only one data descriptor in a
given request.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-30 08:13:40 +00:00
Wei Liu
1325c76525 block_util: use SmallVec in async adaptor
Also fix a comment while at it.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-30 08:13:40 +00:00
Michael Zhao
4a51a6615f arch: Fix AArch64 socket setting in CPU topology
Before Linux v6.0, AArch64 didn't support "socket" in "cpu-map"
(CPU topology) of FDT.

We found that clusters can be used in the same way of sockets. That is
the way we implemented the socket settings in Cloud Hypervisor. But in
fact it was a bug.

Linux commit 26a2b7 fixed the mistake. So the cluster nodes can no
longer act as sockets. And in a following commit dea8c0, sockets were
supported.

This patch fixed the way to configure sockets. In each socket, a default
cluster was added to contain all the cores, because cluster layer is
mandatory in CPU topology on AArch64.

This fix will break the socket settings on the guests where the kernel
version is lower than v6.0. In that case, if socket number is set to
more than 1, the kernel will treat that as FDT mistake and all the CPUs
will be put in single cluster of single socket.

The patch only impacts the case of using FDT, not ACPI.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
2023-01-30 08:12:56 +00:00
Rob Bradford
d5ce855649 misc: Update reference kernel to 6.1.6
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-30 08:12:56 +00:00
Bo Chen
496f932276 build: Temporarily disable bare metal x86-64 workers
These machines are unreachable.

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-01-28 09:27:27 +00:00
dependabot[bot]
c33efe294a build: Bump micro_http from fbef706 to b538bf8
Bumps [micro_http](https://github.com/firecracker-microvm/micro-http) from `fbef706` to `b538bf8`.
- [Release notes](https://github.com/firecracker-microvm/micro-http/releases)
- [Commits](fbef706e28...b538bf89e5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-27 23:59:35 +00:00
dependabot[bot]
2d022d0c85 build: Bump micro_http from fbef706 to b538bf8 in /fuzz
Bumps [micro_http](https://github.com/firecracker-microvm/micro-http) from `fbef706` to `b538bf8`.
- [Release notes](https://github.com/firecracker-microvm/micro-http/releases)
- [Commits](fbef706e28...b538bf89e5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-27 23:19:16 +00:00
Praveen K Paladugu
5b31b19530 tests: enable tpm tests for mshv
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2023-01-27 21:14:38 +00:00
Praveen K Paladugu
ad202f9b7a hypervisor: x86: emulate MOVSB
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2023-01-27 21:14:38 +00:00
Wei Liu
3a225aaa23 hypervisor: x86: emulate MOVSW
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-27 21:14:38 +00:00
Wei Liu
1bfa07f48e hypervisor: x86: use a macro to generate emulate function for movs
No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-27 21:14:38 +00:00
Ravi kumar Veeramally
8e682bcb00 scripts: Avoid warning from mkdosfs command
Fix lowercase label to avoid "mkfs.fat: Warning: lowercase labels
might not work properly on some systems".

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-01-27 08:12:38 -08:00
Bo Chen
1ee2922dbc Jenkinsfile: Enforce global execution timeout
This patch adds a global execution timeout to the Jenkinsfile to avoid
infinite pending Jenkins pipelines, such as when certain worker nodes
are not available. The global execution timeout is now set to 4 hours
which is derived from total timeout of our longest stage (e.g. the
`Worker build`).

Fixes: #5148

Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-01-27 08:04:40 +00:00
dependabot[bot]
2ce503f457 build: Bump libfuzzer-sys from 0.4.5 to 0.4.6 in /fuzz
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.4.5 to 0.4.6.
- [Release notes](https://github.com/rust-fuzz/libfuzzer/releases)
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.5...0.4.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-26 23:17:41 +00:00
Bo Chen
574576c8e9 misc: Automatically fix cargo clippy issues added in 1.68 (beta)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-01-26 08:58:37 -08:00
Ravi kumar Veeramally
aaf67c9ae4 doc: Add musl-tools to instructions for build
As a first time user of cloud-hypervisor and Rust environment
you get build errors with out this.

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
2023-01-26 08:09:46 -08:00
Rob Bradford
8b9da4e286 build: Bump MSRV to 1.62
Needed for #[derive(Default)] on enums which is now clippy checked in
1.68.

Fixes: #5140

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-26 13:05:23 +00:00
dependabot[bot]
271f11d9ec build: Bump ssh2 from 0.9.3 to 0.9.4
Bumps [ssh2](https://github.com/alexcrichton/ssh2-rs) from 0.9.3 to 0.9.4.
- [Release notes](https://github.com/alexcrichton/ssh2-rs/releases)
- [Commits](https://github.com/alexcrichton/ssh2-rs/compare/0.9.3...0.9.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-26 07:59:11 +00:00
Muminul Islam
e436b382cc scripts: check if /dev/{mshv,kvm} exists before test run
Right now integration test fails during the test run if
/dev/mshv or /dev/kvm does not exist. We should not
progress and exit early if not present.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2023-01-26 07:58:13 +00:00
Wei Liu
1ce1fe7334 tpm: rework set_buffer_size
Make the code more idiomatic by wrapping the actual size configured in
the returning Result type. This further allows simplifying
get_buffer_size.

The debug message in startup_tpm is more useful if it prints out the
actual size than the wanted size.

No functional change.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
73af65f417 tpm: drop unused fields in BackendCmd struct
They are never used.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
cffde0ff65 devices: avoid unnecessary allocations in TPM code
Use the data buffer in the TPM device directly.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
e41b7d90d5 tpm: drop cmd from Emulator struct
The command is not done asynchronously. And there is no way to propagate
this error anywhere.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
60425471dd tpm: get_buffer_size always succeeds
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
2b76e1d7ba devices: simplify TPM handling
The error is never propagated anywhere. Drop it.

Avoid unwrapping unconditionally.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
15ace525be devices: drop cmd field from TPM struct
There is no need to hold on to it. It is only used locally in a
function.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-26 07:57:48 +00:00
Wei Liu
8db630763a devices: clean up two comments in TPM code
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-25 18:40:57 +00:00
Wei Liu
cd1470e289 devices: rework TPM register and field look-up
Match against enums instead.

This then drops the need to import phf.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-25 18:40:57 +00:00
Wei Liu
99d8c34861 devices: change TPM_CRB_R_MAX from u32 to usize
This simplifies the code a bit.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-25 18:40:57 +00:00
Philipp Schuster
6725771dc3 virtio-devices: typo fixes
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
2023-01-25 10:38:31 +00:00
dependabot[bot]
0e8fd0bc17 build: Bump object from 0.30.2 to 0.30.3
Bumps [object](https://github.com/gimli-rs/object) from 0.30.2 to 0.30.3.
- [Release notes](https://github.com/gimli-rs/object/releases)
- [Changelog](https://github.com/gimli-rs/object/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/object/compare/0.30.2...0.30.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 23:41:13 +00:00
dependabot[bot]
0ef1e668a5 build: Bump quote from 1.0.21 to 1.0.23 in /fuzz
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.21 to 1.0.23.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.21...1.0.23)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 23:21:28 +00:00
dependabot[bot]
477332a94a build: Bump arbitrary from 1.2.0 to 1.2.3 in /fuzz
Bumps [arbitrary](https://github.com/rust-fuzz/arbitrary) from 1.2.0 to 1.2.3.
- [Release notes](https://github.com/rust-fuzz/arbitrary/releases)
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/compare/v1.2.0...v1.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 00:26:33 +00:00
dependabot[bot]
7b102c4fa3 build: Bump gimli from 0.27.0 to 0.27.1
Bumps [gimli](https://github.com/gimli-rs/gimli) from 0.27.0 to 0.27.1.
- [Release notes](https://github.com/gimli-rs/gimli/releases)
- [Changelog](https://github.com/gimli-rs/gimli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/gimli/compare/0.27.0...0.27.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 23:43:21 +00:00
Praveen K Paladugu
1e159dbefb tests: Add a test for tpm driver
Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2023-01-23 10:10:19 -08:00
Praveen K Paladugu
a4ef6e57a7 ci: install swtpm in Docker container
Add steps to build and install swtpm and its dependencies in
ci docker container.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
2023-01-23 10:10:19 -08:00
Bo Chen
ec45daac19 docs: Use the TDVF firmware from the edk2 repository
Signed-off-by: Bo Chen <chen.bo@intel.com>
2023-01-23 10:25:27 +01:00
dependabot[bot]
c773330a65 build: Bump arc-swap from 1.5.1 to 1.6.0 in /fuzz
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.5.1 to 1.6.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.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: arc-swap
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 23:17:10 +00:00
Sebastien Boeuf
e4ae668bcd tdx: Update support based on kvm-upstream v5.19
In order to comply with latest TDX version, we rely onto the branch
kvm-upstream-2022.08.07-v5.19-rc8 from https://github.com/intel/tdx
repository. Updates are based on changes that happened in
arch/x86/include/uapi/asm/kvm.h headers file.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2023-01-20 09:59:56 +00:00
Rob Bradford
f6c058da56 .github: Don't try and create releases for created branches
Dependabot will create a branch on the repo for it's updates this
triggers the release action (because it's the same event as a tag) which
will then fail leading to dependabot PRs not being automerged. Instead
only run the release check test on PRs or tag creation.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-20 09:58:53 +00:00
dependabot[bot]
089dffcb49 build: Bump io-uring from 0.5.11 to 0.5.12
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.11 to 0.5.12.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 09:24:06 +00:00
dependabot[bot]
9d7034b9c6 build: Bump io-uring from 0.5.11 to 0.5.12 in /fuzz
Bumps [io-uring](https://github.com/tokio-rs/io-uring) from 0.5.11 to 0.5.12.
- [Release notes](https://github.com/tokio-rs/io-uring/releases)
- [Commits](https://github.com/tokio-rs/io-uring/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 09:44:48 +01:00
Rob Bradford
a86edd3032 tests: Add tpm2-tools to custom jammy image
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-19 19:19:52 +00:00
Anirudh Rayabharam
7805fe58e2 tests: disable test_memory_mergeable_on for mshv
KSM doesn't work with MSHV stack since guest memory is pinned
(`pin_user_pages`) and pinned pages cannot be merged.

So, don't run the test for mshv.

Signed-off-by: Anirudh Rayabharam <anrayabh@linux.microsoft.com>
2023-01-19 13:25:40 +00:00
dependabot[bot]
e66ffffd43 build: Bump rustix from 0.36.6 to 0.36.7
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.36.6 to 0.36.7.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.36.6...v0.36.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-19 07:36:35 +00:00
dependabot[bot]
843c8ad51c build: Bump proc-macro2 from 1.0.49 to 1.0.50 in /fuzz
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.49 to 1.0.50.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.49...1.0.50)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-19 07:36:23 +00:00
dependabot[bot]
a334831d54 build: Bump vmm-sys-util from 0.11.0 to 0.11.1 in /fuzz
Bumps [vmm-sys-util](https://github.com/rust-vmm/vmm-sys-util) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/rust-vmm/vmm-sys-util/releases)
- [Changelog](https://github.com/rust-vmm/vmm-sys-util/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-vmm/vmm-sys-util/compare/v0.11.0...v0.11.1)

---
updated-dependencies:
- dependency-name: vmm-sys-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 11:30:04 +00:00
Rob Bradford
dab9f1cf30 docs: Add instructions for heap profiling
Fixes: #5074

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-17 14:02:01 +00:00
Rob Bradford
3a81f9328f build: Add optional dhat heap profiling
Add new "dhat-heap" build feature which enables dhat heap profiling.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-17 14:02:01 +00:00
Rob Bradford
e2886a4b1f docs: Update instructions to point to new profiling target
This removes the need for the user to manually change the Cargo.toml
file for profiling.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-17 14:02:01 +00:00
Rob Bradford
c6d3f61a42 build: Add new profiling target
This makes it much more convenient to build binaries for profiling
without having to modify the Cargo.toml file.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-17 14:02:01 +00:00
dependabot[bot]
4689abd9f4 build: Bump argh_derive from 0.1.9 to 0.1.10
Bumps [argh_derive](https://github.com/google/argh) from 0.1.9 to 0.1.10.
- [Release notes](https://github.com/google/argh/releases)
- [Commits](https://github.com/google/argh/compare/0.1.9...0.1.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 09:11:48 +01:00
dependabot[bot]
f479f0605d build: Bump serde_with from 2.1.0 to 2.2.0 in /fuzz
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v2.1.0...v2.2.0)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 09:11:36 +01:00
Rob Bradford
5034bea8c4 Docker: Update Rust toolchain in dev container
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
2023-01-16 16:43:49 +00:00
Wei Liu
b8172408f8 vhost_user_net: add --version
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
b0a2ce0598 vhost_user_block: add --version
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
a0922930b1 docs: update command line options
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
d1ec65873e vhost_user_net: switch to argh
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
54e9ed9932 vhost_user_blk: switch to argh
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
111225a2a5 main: switch to argh
A few breaking changes:

1. `-vvv` needs to be written as `-v -v -v`.
2. `--disk D1 D2` and others need to be written as `--disk D1 --disk D2`.
3. `--option=value` needs to be written as `--option value`

Change integration tests to adapt to the breaking changes.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
fe49056129 main: split out a few functions
Switching to `argh` requires individual default functions.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
d5558aea2a ch-remote: switch to argh
Since argh does not support `--option=value`, we need to change the
integration test code to become `--option value`.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
Wei Liu
1ba995d952 performance-metrics: switch to argh
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2023-01-16 16:39:03 +00:00
dependabot[bot]
c6c081099f build: Bump proc-macro2 from 1.0.47 to 1.0.49
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.47 to 1.0.49.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.47...1.0.49)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 09:22:06 +01:00
dependabot[bot]
3a1254a9b2 build: Bump clap from 4.0.32 to 4.1.0 in /fuzz
Bumps [clap](https://github.com/clap-rs/clap) from 4.0.32 to 4.1.0.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.0.32...clap_complete-v4.1.0)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 09:21:57 +01:00
142 changed files with 5112 additions and 6693 deletions

View File

@@ -13,7 +13,7 @@ jobs:
- stable
- beta
- nightly
- "1.60"
- "1.62"
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl

View File

@@ -7,6 +7,10 @@ on:
pull_request:
paths: resources/Dockerfile
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
main:
runs-on: ubuntu-latest
@@ -20,19 +24,19 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v1
- name: Login to ghcr
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: cloudhypervisor/dev
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value={{date 'YYYYMMDD'}}-0

View File

@@ -51,7 +51,7 @@ jobs:
run: |
set -e
commits=$(git rev-list origin/${{ github.base_ref }}..${{ github.sha }})
for commit in $commits; do git checkout $commit; cargo check --tests --all --target=${{ matrix.target }}; done
for commit in $commits; do git checkout $commit; cargo check --tests --examples --all --target=${{ matrix.target }}; done
git checkout ${{ github.sha }}
- name: Formatting (rustfmt)
@@ -62,28 +62,28 @@ jobs:
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (default features)
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --tests -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (default features + guest_debug)
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples --features "guest_debug" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (default features + tracing)
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --features "tracing" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples --features "tracing" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (mshv)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
@@ -91,7 +91,7 @@ jobs:
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (mshv + kvm)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
@@ -99,7 +99,7 @@ jobs:
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (kvm + tdx)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
@@ -107,7 +107,7 @@ jobs:
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --features "tdx,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "tdx,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Check build did not modify any files
run: test -z "$(git status --porcelain)"

View File

@@ -3,6 +3,7 @@ on: [pull_request, create]
jobs:
release:
if: (github.event_name == 'create' && github.event.ref_type == 'tag') || github.event_name == 'pull_request'
name: Release
runs-on: ubuntu-latest
steps:
@@ -15,29 +16,29 @@ jobs:
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.62"
toolchain: "1.67.1"
target: x86_64-unknown-linux-gnu
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.62"
toolchain: "1.67.1"
target: x86_64-unknown-linux-musl
- name: Build
uses: actions-rs/cargo@v1
with:
toolchain: "1.62"
toolchain: "1.67.1"
command: build
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-gnu
- name: Static Build
uses: actions-rs/cargo@v1
with:
toolchain: "1.62"
toolchain: "1.67.1"
command: build
args: --all --release --no-default-features --features "kvm,mshv" --target=x86_64-unknown-linux-musl
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
uses: actions-rs/toolchain@v1
with:
toolchain: "1.62"
toolchain: "1.67.1"
target: aarch64-unknown-linux-musl
override: true
- name: Create Release

592
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "cloud-hypervisor"
version = "29.0.0"
version = "31.2.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
default-run = "cloud-hypervisor"
@@ -12,10 +12,10 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
# Keep in sync with version in .github/workflows/build.yaml
# Policy on MSRV (see #4318):
# Can only be bumped by:
# a.) A dependency requires it,
# a.) A dependency requires it,
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
# c.) There is a security issue that is addressed by the toolchain update.
rust-version = "1.60"
rust-version = "1.62"
[profile.release]
lto = true
@@ -23,10 +23,16 @@ codegen-units = 1
opt-level = "s"
strip = true
[profile.profiling]
inherits = "release"
strip = false
debug = true
[dependencies]
anyhow = "1.0.68"
anyhow = "1.0.69"
api_client = { path = "api_client" }
clap = { version = "4.0.32", features = ["wrap_help","cargo","string"] }
argh = "0.1.9"
dhat = { version = "0.3.2", optional = true }
epoll = "4.3.1"
event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" }
@@ -34,9 +40,9 @@ libc = "0.2.139"
log = { version = "0.4.17", features = ["std"] }
option_parser = { path = "option_parser" }
seccompiler = "0.3.0"
serde_json = "1.0.89"
signal-hook = "0.3.14"
thiserror = "1.0.38"
serde_json = "1.0.95"
signal-hook = "0.3.15"
thiserror = "1.0.39"
tpm = { path = "tpm"}
tracer = { path = "tracer" }
vmm = { path = "vmm" }
@@ -46,18 +52,20 @@ vm-memory = "0.10.0"
# List of patched crates
[patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
[dev-dependencies]
dirs = "4.0.0"
net_util = { path = "net_util" }
once_cell = "1.16.0"
serde_json = "1.0.89"
once_cell = "1.17.1"
serde_json = "1.0.95"
test_infra = { path = "test_infra" }
wait-timeout = "0.2.0"
[features]
default = ["kvm"]
dhat-heap = ["dhat"] # For heap profiling
guest_debug = ["vmm/guest_debug"]
kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"]
@@ -66,7 +74,6 @@ tracing = ["vmm/tracing", "tracer/tracing"]
[workspace]
members = [
"acpi_tables",
"api_client",
"arch",
"block_util",
@@ -83,7 +90,6 @@ members = [
"serial_buffer",
"test_infra",
"tracer",
"vfio_user",
"vhdx",
"vhost_user_block",
"vhost_user_net",

5
Jenkinsfile vendored
View File

@@ -1,6 +1,9 @@
def runWorkers = true
pipeline {
agent none
options {
timeout(time: 4, unit: 'HOURS')
}
stages {
stage('Early checks') {
agent { node { label 'built-in' } }
@@ -214,7 +217,7 @@ pipeline {
stage('Download assets') {
steps {
sh "mkdir ${env.HOME}/workloads"
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2019.raw" --name windows-server-2019.raw --connection-string "$AZURE_CONNECTION_STRING"'
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2022-amd64-2.raw" --name windows-server-2022-amd64-2.raw --connection-string "$AZURE_CONNECTION_STRING"'
}
}
stage('Run Windows guest integration tests') {

View File

@@ -2,6 +2,7 @@
- Sebastien Boeuf - @sboeuf
- Robert Bradford - @rbradford
- Bo Chen - @likebreath
- Samuel Ortiz - @sameo
- Wei Liu - @liuw
- Michael Zhao - @michael2012z

View File

@@ -113,7 +113,7 @@ Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware) or an
edk2 UEFI firmware called `CLOUDHV` / `CLOUDHV_EFI`.)
Binary builds of the firmware files are available for the latest release of
[Rust Hyperivor
[Rust Hypervisor
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware/releases/latest)
and [our edk2
repository](https://github.com/cloud-hypervisor/edk2/releases/latest)
@@ -124,7 +124,7 @@ may be required.
### Firmware Booting
Cloud Hypervisor supports booting disk images containing all needed components
to run cloud workloads, a.k.a. cloud images.
to run cloud workloads, a.k.a. cloud images.
The following sample commands will download an Ubuntu Cloud image, converting
it into a format that Cloud Hypervisor can use and a firmware to boot the image
@@ -147,7 +147,7 @@ $ sudo setcap cap_net_admin+ep ./cloud-hypervisor
$ ./create-cloud-init.sh
$ ./cloud-hypervisor \
--kernel ./hypervisor-fw \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--disk path=focal-server-cloudimg-amd64.raw --disk path=/tmp/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask="
@@ -160,7 +160,7 @@ GRUB) is required then it necessary to switch to the serial console instead of
```shell
$ ./cloud-hypervisor \
--kernel ./hypervisor-fw \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--disk path=focal-server-cloudimg-amd64.raw --disk path=/tmp/ubuntu-cloudinit.img \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
@@ -178,7 +178,7 @@ To build the kernel:
```shell
# Clone the Cloud Hypervisor Linux branch
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-5.15.12 linux-cloud-hypervisor
$ git clone --depth 1 https://github.com/cloud-hypervisor/linux.git -b ch-6.2 linux-cloud-hypervisor
$ pushd linux-cloud-hypervisor
# Use the x86-64 cloud-hypervisor kernel config to build your kernel for x86-64
$ wget https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/main/resources/linux-config-x86_64
@@ -222,7 +222,7 @@ $ sudo setcap cap_net_admin+ep ./cloud-hypervisor
$ ./create-cloud-init.sh
$ ./cloud-hypervisor \
--kernel ./linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin \
--disk path=focal-server-cloudimg-amd64.raw path=/tmp/ubuntu-cloudinit.img \
--disk path=focal-server-cloudimg-amd64.raw --disk path=/tmp/ubuntu-cloudinit.img \
--cmdline "console=hvc0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
@@ -236,7 +236,7 @@ $ sudo setcap cap_net_admin+ep ./cloud-hypervisor
$ ./create-cloud-init.sh
$ ./cloud-hypervisor \
--kernel ./linux-cloud-hypervisor/arch/arm64/boot/Image \
--disk path=focal-server-cloudimg-arm64.raw path=/tmp/ubuntu-cloudinit.img \
--disk path=focal-server-cloudimg-arm64.raw --disk path=/tmp/ubuntu-cloudinit.img \
--cmdline "console=hvc0 root=/dev/vda1 rw" \
--cpus boot=4 \
--memory size=1024M \
@@ -372,8 +372,8 @@ are all equal and welcome means of contribution. See the
## Slack
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI)
and [join us on Slack](https://cloud-hypervisor.slack.com/).
Get an [invite to our Slack channel](https://join.slack.com/t/cloud-hypervisor/shared_invite/enQtNjY3MTE3MDkwNDQ4LWQ1MTA1ZDVmODkwMWQ1MTRhYzk4ZGNlN2UwNTI3ZmFlODU0OTcwOWZjMTkwZDExYWE3YjFmNzgzY2FmNDAyMjI),
[join us on Slack](https://cloud-hypervisor.slack.com/), and [participate in our community activities](https://cloud-hypervisor.slack.com/archives/C04R5DUQVBN).
## Mailing list

View File

@@ -1,8 +0,0 @@
[package]
name = "acpi_tables"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
[dependencies]
vm-memory = "0.10.0"

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +0,0 @@
// Copyright © 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
pub mod aml;
pub mod rsdp;
pub mod sdt;
fn generate_checksum(data: &[u8]) -> u8 {
(255 - data.iter().fold(0u8, |acc, x| acc.wrapping_add(*x))).wrapping_add(1)
}

View File

@@ -1,68 +0,0 @@
// Copyright © 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
use vm_memory::ByteValued;
#[repr(packed)]
#[derive(Clone, Copy, Default)]
pub struct Rsdp {
pub signature: [u8; 8],
pub checksum: u8,
pub oem_id: [u8; 6],
pub revision: u8,
_rsdt_addr: u32,
pub length: u32,
pub xsdt_addr: u64,
pub extended_checksum: u8,
_reserved: [u8; 3],
}
// SAFETY: Rsdp only contains a series of integers
unsafe impl ByteValued for Rsdp {}
impl Rsdp {
pub fn new(oem_id: [u8; 6], xsdt_addr: u64) -> Self {
let mut rsdp = Rsdp {
signature: *b"RSD PTR ",
checksum: 0,
oem_id,
revision: 2,
_rsdt_addr: 0,
length: std::mem::size_of::<Rsdp>() as u32,
xsdt_addr,
extended_checksum: 0,
_reserved: [0; 3],
};
rsdp.checksum = super::generate_checksum(&rsdp.as_slice()[0..19]);
rsdp.extended_checksum = super::generate_checksum(rsdp.as_slice());
rsdp
}
pub fn len() -> usize {
std::mem::size_of::<Rsdp>()
}
}
#[cfg(test)]
mod tests {
use super::Rsdp;
use vm_memory::bytes::ByteValued;
#[test]
fn test_rsdp() {
let rsdp = Rsdp::new(*b"CHYPER", 0xdead_beef);
let sum = rsdp
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
let sum: u8 = rsdp
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
}
}

View File

@@ -1,151 +0,0 @@
// Copyright © 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
#[repr(packed)]
#[derive(Clone, Copy)]
pub struct GenericAddress {
pub address_space_id: u8,
pub register_bit_width: u8,
pub register_bit_offset: u8,
pub access_size: u8,
pub address: u64,
}
impl GenericAddress {
pub fn io_port_address<T>(address: u16) -> Self {
GenericAddress {
address_space_id: 1,
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: 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 {
data: Vec<u8>,
}
impl Sdt {
pub fn new(
signature: [u8; 4],
length: u32,
revision: u8,
oem_id: [u8; 6],
oem_table: [u8; 8],
oem_revision: u32,
) -> Self {
assert!(length >= 36);
let mut data = Vec::with_capacity(length as usize);
data.extend_from_slice(&signature);
data.extend_from_slice(&length.to_le_bytes());
data.push(revision);
data.push(0); // checksum
data.extend_from_slice(&oem_id);
data.extend_from_slice(&oem_table);
data.extend_from_slice(&oem_revision.to_le_bytes());
data.extend_from_slice(b"CLDH");
data.extend_from_slice(&0u32.to_le_bytes());
assert_eq!(data.len(), 36);
data.resize(length as usize, 0);
let mut sdt = Sdt { data };
sdt.update_checksum();
sdt
}
pub fn update_checksum(&mut self) {
self.data[9] = 0;
let checksum = super::generate_checksum(self.data.as_slice());
self.data[9] = checksum
}
pub fn as_slice(&self) -> &[u8] {
self.data.as_slice()
}
pub fn append<T>(&mut self, value: T) {
let orig_length = self.data.len();
let new_length = orig_length + std::mem::size_of::<T>();
self.data.resize(new_length, 0);
self.write_u32(4, new_length as u32);
self.write(orig_length, value);
}
pub fn append_slice(&mut self, data: &[u8]) {
let orig_length = self.data.len();
let new_length = orig_length + data.len();
self.write_u32(4, new_length as u32);
self.data.extend_from_slice(data);
self.update_checksum();
}
/// Write a value at the given offset
pub fn write<T>(&mut self, offset: usize, value: T) {
assert!((offset + (std::mem::size_of::<T>() - 1)) < self.data.len());
// SAFETY: The assertion above makes sure we don't do out of bounds write.
unsafe {
*(((self.data.as_mut_ptr() as usize) + offset) as *mut T) = value;
}
self.update_checksum();
}
pub fn write_u8(&mut self, offset: usize, val: u8) {
self.write(offset, val);
}
pub fn write_u16(&mut self, offset: usize, val: u16) {
self.write(offset, val);
}
pub fn write_u32(&mut self, offset: usize, val: u32) {
self.write(offset, val);
}
pub fn write_u64(&mut self, offset: usize, val: u64) {
self.write(offset, val);
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::Sdt;
#[test]
fn test_sdt() {
let mut sdt = Sdt::new(*b"TEST", 40, 1, *b"CLOUDH", *b"TESTTEST", 1);
let sum: u8 = sdt
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
sdt.write_u32(36, 0x12345678);
let sum: u8 = sdt
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
}
}

View File

@@ -9,16 +9,16 @@ default = []
tdx = []
[dependencies]
anyhow = "1.0.68"
anyhow = "1.0.69"
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
libc = "0.2.139"
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
log = "0.4.17"
serde = { version = "1.0.151", features = ["rc", "derive"] }
thiserror = "1.0.38"
uuid = "1.2.2"
versionize = "0.1.9"
thiserror = "1.0.39"
uuid = "1.3.0"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }

View File

@@ -191,9 +191,13 @@ fn create_cpu_nodes(
let cpu_map_node = fdt.begin_node("cpu-map")?;
// Create device tree nodes with regard of above mapping.
for cluster_idx in 0..packages {
let cluster_name = format!("cluster{cluster_idx:x}");
let cluster_node = fdt.begin_node(&cluster_name)?;
for package_idx in 0..packages {
let package_name = format!("socket{package_idx:x}");
let package_node = fdt.begin_node(&package_name)?;
// Cluster is the container of cores, and it is mandatory in the CPU topology.
// Add a default "cluster0" in each socket/package.
let cluster_node = fdt.begin_node("cluster0")?;
for core_idx in 0..cores_per_package {
let core_name = format!("core{core_idx:x}");
@@ -202,7 +206,7 @@ fn create_cpu_nodes(
for thread_idx in 0..threads_per_core {
let thread_name = format!("thread{thread_idx:x}");
let thread_node = fdt.begin_node(&thread_name)?;
let cpu_idx = threads_per_core * cores_per_package * cluster_idx
let cpu_idx = threads_per_core * cores_per_package * package_idx
+ threads_per_core * core_idx
+ thread_idx;
fdt.property_u32("cpu", cpu_idx as u32 + FIRST_VCPU_PHANDLE)?;
@@ -212,6 +216,7 @@ fn create_cpu_nodes(
fdt.end_node(core_node)?;
}
fdt.end_node(cluster_node)?;
fdt.end_node(package_node)?;
}
fdt.end_node(cpu_map_node)?;
} else {
@@ -255,32 +260,86 @@ fn create_memory_node(
fdt.end_node(memory_node)?;
}
} else {
let last_addr = guest_mem.last_addr().raw_value();
if last_addr < super::layout::MEM_32BIT_RESERVED_START.raw_value() {
// Case 1: all RAM is under the hole
let mem_size = last_addr - super::layout::RAM_START.raw_value() + 1;
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
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)?;
} else {
// Case 2: RAM is split by the hole
// Region 1: RAM before the hole
let mem_size = super::layout::MEM_32BIT_RESERVED_START.raw_value()
- super::layout::RAM_START.raw_value();
let mem_reg_prop = [super::layout::RAM_START.raw_value(), mem_size];
let memory_node_name = format!("memory@{:x}", super::layout::RAM_START.raw_value());
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
let ram_regions = {
let mut ram_regions = Vec::new();
let mut current_start = guest_mem
.iter()
.next()
.map(GuestMemoryRegion::start_addr)
.expect("GuestMemory must have one memory region at least")
.raw_value();
let mut current_end = current_start;
for (start, size) in guest_mem
.iter()
.map(|m| (m.start_addr().raw_value(), m.len()))
{
if current_end == start {
// This zone is continuous with the previous one.
current_end += size;
} else {
ram_regions.push((current_start, current_end));
current_start = start;
current_end = start + size;
}
}
ram_regions.push((current_start, current_end));
ram_regions
};
if ram_regions.len() > 2 {
panic!(
"There should be up to two non-continuous regions, devidided by the
gap at the end of 32bit address space."
);
}
// Create the memory node for memory region before the gap
{
let (first_region_start, first_region_end) = ram_regions
.first()
.expect("There should be at last one memory region");
let ram_start = super::layout::RAM_START.raw_value();
let mem_32bit_reserved_start = super::layout::MEM_32BIT_RESERVED_START.raw_value();
if !((first_region_start <= &ram_start)
&& (first_region_end > &ram_start)
&& (first_region_end <= &mem_32bit_reserved_start))
{
panic!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, ram_start, mem_32bit_reserved_start
);
}
let mem_size = first_region_end - ram_start;
let mem_reg_prop = [ram_start, mem_size];
let memory_node_name = format!("memory@{:x}", ram_start);
let memory_node = fdt.begin_node(&memory_node_name)?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_prop)?;
fdt.end_node(memory_node)?;
}
// Region 2: RAM after the hole
let mem_size = last_addr - super::layout::RAM_64BIT_START.raw_value() + 1;
let mem_reg_prop = [super::layout::RAM_64BIT_START.raw_value(), mem_size];
let memory_node_name =
format!("memory@{:x}", super::layout::RAM_64BIT_START.raw_value());
// Create the memory map entry for memory region after the gap if any
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
let ram_64bit_start = super::layout::RAM_64BIT_START.raw_value();
if second_region_start != &ram_64bit_start {
panic!(
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
second_region_start, ram_64bit_start
);
}
let mem_size = second_region_end - ram_64bit_start;
let mem_reg_prop = [ram_64bit_start, mem_size];
let memory_node_name = format!("memory@{:x}", ram_64bit_start);
let memory_node = fdt.begin_node(&memory_node_name)?;
fdt.property_string("device_type", "memory")?;
fdt.property_array_u64("reg", &mem_reg_prop)?;

View File

@@ -19,7 +19,9 @@ use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic, GuestUsize};
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
pub const _NSIG: i32 = 65;
/// Errors thrown while configuring aarch64 system.
#[derive(Debug)]
@@ -81,8 +83,8 @@ pub fn configure_vcpu(
Ok(mpidr)
}
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
let mut regions = vec![
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
vec![
// 0 MiB ~ 256 MiB: UEFI, GIC and legacy devices
(
GuestAddress(0),
@@ -101,39 +103,21 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
layout::PCI_MMCONFIG_SIZE as usize,
RegionType::Reserved,
),
];
let ram_32bit_space_size =
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START);
// RAM space
// Case1: guest memory fits before the gap
if size <= ram_32bit_space_size {
regions.push((layout::RAM_START, size as usize, RegionType::Ram));
// Case2: guest memory extends beyond the gap
} else {
// Push memory before the gap
regions.push((
// 1GiB ~ 4032 MiB: RAM before the gap
(
layout::RAM_START,
ram_32bit_space_size as usize,
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize,
RegionType::Ram,
));
// Other memory is placed after 4GiB
regions.push((
layout::RAM_64BIT_START,
(size - ram_32bit_space_size) as usize,
RegionType::Ram,
));
}
// Add the 32-bit reserved memory hole as a reserved region
regions.push((
layout::MEM_32BIT_RESERVED_START,
layout::MEM_32BIT_RESERVED_SIZE as usize,
RegionType::Reserved,
));
regions
),
// 4GiB ~ inf: RAM after the gap
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
// Add the 32-bit reserved memory hole as a reserved region
(
layout::MEM_32BIT_RESERVED_START,
layout::MEM_32BIT_RESERVED_SIZE as usize,
RegionType::Reserved,
),
]
}
/// Configures the system and should be called once per vm before starting vcpu threads.
@@ -215,26 +199,12 @@ mod tests {
use super::*;
#[test]
fn test_arch_memory_regions_dram_2gb() {
let regions = arch_memory_regions((1usize << 31) as u64); //2GB
assert_eq!(5, regions.len());
assert_eq!(layout::RAM_START, regions[3].0);
assert_eq!((1usize << 31), regions[3].1);
assert_eq!(RegionType::Ram, regions[3].2);
assert_eq!(RegionType::Reserved, regions[4].2);
}
#[test]
fn test_arch_memory_regions_dram_4gb() {
let regions = arch_memory_regions((1usize << 32) as u64); //4GB
let ram_32bit_space_size =
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::RAM_START) as usize;
fn test_arch_memory_regions_dram() {
let regions = arch_memory_regions();
assert_eq!(6, regions.len());
assert_eq!(layout::RAM_START, regions[3].0);
assert_eq!(ram_32bit_space_size, regions[3].1);
assert_eq!(RegionType::Ram, regions[3].2);
assert_eq!(RegionType::Reserved, regions[5].2);
assert_eq!(RegionType::Ram, regions[4].2);
assert_eq!(((1usize << 32) - ram_32bit_space_size), regions[4].1);
}
}

View File

@@ -1,18 +1,17 @@
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
// SPDX-License-Identifier: Apache-2.0
///
/// AArch64 system register encoding:
/// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
///
/// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
/// +----------+---+-----+-----+-----+-----+-----+----+
/// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
/// +----------+---+-----+-----+-----+-----+-----+----+
///
/// Notes:
/// - L and Rt are reserved as implementation defined fields, ignored.
///
// AArch64 system register encoding:
// See https://developer.arm.com/documentation/ddi0487 (chapter D12)
//
// 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
// +----------+---+-----+-----+-----+-----+-----+----+
// |1101010100| L | op0 | op1 | CRn | CRm | op2 | Rt |
// +----------+---+-----+-----+-----+-----+-----+----+
//
// Notes:
// - L and Rt are reserved as implementation defined fields, ignored.
const SYSREG_HEAD: u32 = 0b1101010100u32 << 22;
const SYSREG_OP0_SHIFT: u32 = 19;
const SYSREG_OP0_MASK: u32 = 0b11u32 << 19;

View File

@@ -82,7 +82,7 @@ pub mod aarch64;
pub use aarch64::{
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::IRQ_BASE, uefi, EntryPoint,
layout::IRQ_BASE, uefi, EntryPoint, _NSIG,
};
#[cfg(target_arch = "x86_64")]
@@ -92,7 +92,7 @@ pub mod x86_64;
pub use x86_64::{
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint,
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, _NSIG,
};
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.

View File

@@ -16,7 +16,7 @@ use crate::GuestMemoryMmap;
use crate::InitramfsConfig;
use crate::RegionType;
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
use hypervisor::HypervisorError;
use hypervisor::{HypervisorCpuError, HypervisorError};
use linux_loader::loader::bootparam::boot_params;
use linux_loader::loader::elf::start_info::{
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
@@ -36,6 +36,7 @@ pub mod tdx;
const TSC_DEADLINE_TIMER_ECX_BIT: u8 = 24; // tsc deadline timer ecx bit.
const HYPERVISOR_ECX_BIT: u8 = 31; // Hypervisor ecx bit.
const MTRR_EDX_BIT: u8 = 12; // Hypervisor ecx bit.
const INVARIANT_TSC_EDX_BIT: u8 = 8; // Invariant TSC bit on 0x8000_0007 EDX
// KVM feature bits
const KVM_FEATURE_ASYNC_PF_INT_BIT: u8 = 14;
@@ -52,6 +53,8 @@ const KVM_FEATURE_ASYNC_PF_VMEXIT_BIT: u8 = 10;
#[cfg(feature = "tdx")]
const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5;
pub const _NSIG: i32 = 65;
#[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
@@ -193,6 +196,9 @@ pub enum Error {
// Error writing EBDA address
EbdaSetup(vm_memory::GuestMemoryError),
// Error getting CPU TSC frequency
GetTscFrequency(HypervisorCpuError),
/// Error retrieving TDX capabilities through the hypervisor (kvm/mshv) API
#[cfg(feature = "tdx")]
TdxCapabilities(HypervisorError),
@@ -605,7 +611,9 @@ pub fn generate_common_cpuid(
];
// Supported CPUID
let mut cpuid = hypervisor.get_cpuid().map_err(Error::CpuidGetSupported)?;
let mut cpuid = hypervisor
.get_supported_cpuid()
.map_err(Error::CpuidGetSupported)?;
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
@@ -768,6 +776,41 @@ pub fn configure_vcpu(
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
// Set ApicId in cpuid for each vcpu
// SAFETY: get host cpuid when eax=1
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx;
cpu_ebx &= 0xffffff;
cpu_ebx |= (id as u32) << 24;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation
if !kvm_hyperv {
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
// Need to check that the TSC doesn't vary with dynamic frequency
// SAFETY: cpuid called with valid leaves
if unsafe { std::arch::x86_64::__cpuid(0x8000_0007) }.edx
& (1u32 << INVARIANT_TSC_EDX_BIT)
> 0
{
CpuidPatch::set_cpuid_reg(
&mut cpuid,
0x4000_0000,
None,
CpuidReg::EAX,
0x4000_0010,
);
cpuid.retain(|c| c.function != 0x4000_0010);
cpuid.push(CpuIdEntry {
function: 0x4000_0010,
eax: tsc_khz,
ebx: 1000000, /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's
* APIC_BUS_CYCLE_NS */
..Default::default()
});
};
}
}
vcpu.set_cpuid2(&cpuid)
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
@@ -792,47 +835,29 @@ pub fn configure_vcpu(
/// These should be used to configure the GuestMemory structure for the platform.
/// For x86_64 all addresses are valid from the start of the kernel except a
/// carve out at the end of 32bit address space.
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
let reserved_memory_gap_start = layout::MEM_32BIT_RESERVED_START
.checked_add(layout::MEM_32BIT_DEVICES_SIZE)
.expect("32-bit reserved region is too large");
let requested_memory_size = GuestAddress(size);
let mut regions = Vec::new();
// case1: guest memory fits before the gap
if size <= layout::MEM_32BIT_RESERVED_START.raw_value() {
regions.push((GuestAddress(0), size as usize, RegionType::Ram));
// case2: guest memory extends beyond the gap
} else {
// push memory before the gap
regions.push((
pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
vec![
// 0 GiB ~ 3GiB: memory before the gap
(
GuestAddress(0),
layout::MEM_32BIT_RESERVED_START.raw_value() as usize,
RegionType::Ram,
));
regions.push((
layout::RAM_64BIT_START,
requested_memory_size.unchecked_offset_from(layout::MEM_32BIT_RESERVED_START) as usize,
RegionType::Ram,
));
}
// Add the 32-bit device memory hole as a sub region.
regions.push((
layout::MEM_32BIT_RESERVED_START,
layout::MEM_32BIT_DEVICES_SIZE as usize,
RegionType::SubRegion,
));
// Add the 32-bit reserved memory hole as a sub region.
regions.push((
reserved_memory_gap_start,
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_SIZE) as usize,
RegionType::Reserved,
));
regions
),
// 4 GiB ~ inf: memory after the gap
(layout::RAM_64BIT_START, usize::MAX, RegionType::Ram),
// 3 GiB ~ 3712 MiB: 32-bit device memory hole
(
layout::MEM_32BIT_RESERVED_START,
layout::MEM_32BIT_DEVICES_SIZE as usize,
RegionType::SubRegion,
),
// 3712 MiB ~ 3968 MiB: 32-bit reserved memory hole
(
layout::MEM_32BIT_RESERVED_START.unchecked_add(layout::MEM_32BIT_DEVICES_SIZE),
(layout::MEM_32BIT_RESERVED_SIZE - layout::MEM_32BIT_DEVICES_SIZE) as usize,
RegionType::Reserved,
),
]
}
/// Configures the system and should be called once per vm before starting vcpu threads.
@@ -930,30 +955,102 @@ fn configure_pvh(
// Create the memory map entries.
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
let mem_end = guest_mem.last_addr();
// Merge continuous memory regions into one region.
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
let ram_regions = {
let mut ram_regions = Vec::new();
let mut current_start = guest_mem
.iter()
.next()
.map(GuestMemoryRegion::start_addr)
.expect("GuestMemory must have one memory region at least")
.raw_value();
let mut current_end = current_start;
if mem_end < layout::MEM_32BIT_RESERVED_START {
add_memmap_entry(
&mut memmap,
layout::HIGH_RAM_START.raw_value(),
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
E820_RAM,
);
} else {
add_memmap_entry(
&mut memmap,
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_memmap_entry(
&mut memmap,
layout::RAM_64BIT_START.raw_value(),
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
E820_RAM,
);
for (start, size) in guest_mem
.iter()
.map(|m| (m.start_addr().raw_value(), m.len()))
{
if current_end == start {
// This zone is continuous with the previous one.
current_end += size;
} else {
ram_regions.push((current_start, current_end));
current_start = start;
current_end = start + size;
}
}
ram_regions.push((current_start, current_end));
ram_regions
};
if ram_regions.len() > 2 {
error!(
"There should be up to two non-continuous regions, devidided by the
gap at the end of 32bit address space (e.g. between 3G and 4G)."
);
return Err(super::Error::MemmapTableSetup);
}
// Create the memory map entry for memory region before the gap
{
let (first_region_start, first_region_end) =
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
let high_ram_start = layout::HIGH_RAM_START.raw_value();
let mem_32bit_reserved_start = layout::MEM_32BIT_RESERVED_START.raw_value();
if !((first_region_start <= &high_ram_start)
&& (first_region_end > &high_ram_start)
&& (first_region_end <= &mem_32bit_reserved_start))
{
error!(
"Unexpected first memory region layout: (start: 0x{:08x}, end: 0x{:08x}).
high_ram_start: 0x{:08x}, mem_32bit_reserved_start: 0x{:08x}",
first_region_start, first_region_end, high_ram_start, mem_32bit_reserved_start
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x})",
high_ram_start, first_region_end
);
add_memmap_entry(
&mut memmap,
high_ram_start,
first_region_end - high_ram_start,
E820_RAM,
);
}
// Create the memory map entry for memory region after the gap if any
if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
if second_region_start != &ram_64bit_start {
error!(
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
second_region_start, ram_64bit_start
);
return Err(super::Error::MemmapTableSetup);
}
info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x})",
ram_64bit_start, second_region_end
);
add_memmap_entry(
&mut memmap,
ram_64bit_start,
second_region_end - ram_64bit_start,
E820_RAM,
);
}
add_memmap_entry(
@@ -1189,16 +1286,8 @@ mod tests {
use super::*;
#[test]
fn regions_lt_4gb() {
let regions = arch_memory_regions(1 << 29);
assert_eq!(3, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(1usize << 29, regions[0].1);
}
#[test]
fn regions_gt_4gb() {
let regions = arch_memory_regions((1 << 32) + 0x8000);
fn regions_base_addr() {
let regions = arch_memory_regions();
assert_eq!(4, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(GuestAddress(1 << 32), regions[1].0);
@@ -1222,11 +1311,10 @@ mod tests {
assert!(config_err.is_err());
// Now assigning some memory that falls before the 32bit memory hole.
let mem_size = 128 << 20;
let arch_mem_regions = arch_memory_regions(mem_size);
let arch_mem_regions = arch_memory_regions();
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
.iter()
.filter(|r| r.2 == RegionType::Ram)
.filter(|r| r.2 == RegionType::Ram && r.1 != usize::MAX)
.map(|r| (r.0, r.1))
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
@@ -1244,48 +1332,18 @@ mod tests {
)
.unwrap();
// Now assigning some memory that is equal to the start of the 32bit memory hole.
let mem_size = 3328 << 20;
let arch_mem_regions = arch_memory_regions(mem_size);
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
.iter()
.filter(|r| r.2 == RegionType::Ram)
.map(|r| (r.0, r.1))
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
configure_system(
&gm,
GuestAddress(0),
&None,
no_vcpus,
None,
None,
None,
None,
None,
)
.unwrap();
configure_system(
&gm,
GuestAddress(0),
&None,
no_vcpus,
None,
None,
None,
None,
None,
)
.unwrap();
// Now assigning some memory that falls after the 32bit memory hole.
let mem_size = 3330 << 20;
let arch_mem_regions = arch_memory_regions(mem_size);
let arch_mem_regions = arch_memory_regions();
let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions
.iter()
.filter(|r| r.2 == RegionType::Ram)
.map(|r| (r.0, r.1))
.map(|r| {
if r.1 == usize::MAX {
(r.0, 128 << 20)
} else {
(r.0, r.1)
}
})
.collect();
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
configure_system(

View File

@@ -55,7 +55,7 @@ pub struct TdvfSection {
}
#[repr(u32)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default)]
pub enum TdvfSectionType {
Bfv,
Cfv,
@@ -64,15 +64,10 @@ pub enum TdvfSectionType {
PermMem,
Payload,
PayloadParam,
#[default]
Reserved = 0xffffffff,
}
impl Default for TdvfSectionType {
fn default() -> Self {
TdvfSectionType::Reserved
}
}
fn tdvf_descriptor_offset(file: &mut File) -> Result<(SeekFrom, bool), TdvfError> {
// Let's first try to identify the presence of the table footer GUID
file.seek(SeekFrom::End(-0x30))
@@ -202,21 +197,16 @@ pub fn parse_tdvf_sections(file: &mut File) -> Result<(Vec<TdvfSection>, bool),
}
#[repr(u16)]
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Default)]
enum HobType {
Handoff = 0x1,
ResourceDescriptor = 0x3,
GuidExtension = 0x4,
#[default]
Unused = 0xfffe,
EndOfHobList = 0xffff,
}
impl Default for HobType {
fn default() -> Self {
HobType::Unused
}
}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
struct HobHeader {
@@ -266,19 +256,14 @@ struct HobGuidType {
}
#[repr(u32)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default)]
pub enum PayloadImageType {
#[default]
ExecutablePayload,
BzImage,
RawVmLinux,
}
impl Default for PayloadImageType {
fn default() -> Self {
PayloadImageType::ExecutablePayload
}
}
#[repr(C)]
#[derive(Copy, Clone, Default, Debug)]
pub struct PayloadInfo {

View File

@@ -8,17 +8,17 @@ edition = "2021"
default = []
[dependencies]
io-uring = "0.5.11"
io-uring = "0.5.13"
libc = "0.2.139"
log = "0.4.17"
qcow = { path = "../qcow" }
smallvec = "1.10.0"
thiserror = "1.0.38"
versionize = "0.1.9"
thiserror = "1.0.39"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vhdx = { path = "../vhdx" }
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.7.0"
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.7.1"
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.11.0"

View File

@@ -38,7 +38,7 @@ use std::time::Instant;
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::bindings::virtio_blk::*;
use virtio_bindings::virtio_blk::*;
use virtio_queue::DescriptorChain;
use vm_memory::{
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
@@ -201,7 +201,7 @@ pub struct Request {
pub data_descriptors: SmallVec<[(GuestAddress, u32); 1]>,
pub status_addr: GuestAddress,
pub writeback: bool,
pub aligned_operations: Vec<AlignedOperation>,
pub aligned_operations: SmallVec<[AlignedOperation; 1]>,
pub start: Instant,
}
@@ -233,7 +233,7 @@ impl Request {
data_descriptors: SmallVec::with_capacity(1),
status_addr: GuestAddress(0),
writeback: true,
aligned_operations: Vec::new(),
aligned_operations: SmallVec::with_capacity(1),
start: Instant::now(),
};
@@ -602,7 +602,7 @@ where
completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> {
// Convert libc::iovec into IoSliceMut
let mut slices = Vec::new();
let mut slices: SmallVec<[IoSliceMut; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSliceMut wraps around libc::iovec
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
@@ -635,9 +635,9 @@ where
completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> {
// Convert libc::iovec into IoSlice
let mut slices = Vec::new();
let mut slices: SmallVec<[IoSlice; 1]> = SmallVec::with_capacity(iovecs.len());
for iovec in iovecs.iter() {
// SAFETY: on Linux IoSliceMut wraps around libc::iovec
// SAFETY: on Linux IoSlice wraps around libc::iovec
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
}

View File

@@ -5,18 +5,17 @@ authors = ["The Chromium OS Authors"]
edition = "2021"
[dependencies]
acpi_tables = { path = "../acpi_tables" }
anyhow = "1.0.68"
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
anyhow = "1.0.69"
arch = { path = "../arch" }
bitflags = "1.3.2"
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
libc = "0.2.139"
log = "0.4.17"
phf = { version = "0.11.1", features = ["macros"] }
thiserror = "1.0.38"
thiserror = "1.0.39"
tpm = { path = "../tpm" }
versionize = "0.1.9"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-device = { path = "../vm-device" }
vm-memory = "0.10.0"

View File

@@ -4,7 +4,7 @@
//
use super::AcpiNotificationFlags;
use acpi_tables::{aml, aml::Aml};
use acpi_tables::{aml, Aml, AmlSink};
use std::sync::{Arc, Barrier};
use std::time::Instant;
use vm_device::interrupt::InterruptSourceGroup;
@@ -103,11 +103,11 @@ impl BusDevice for AcpiGedDevice {
}
impl Aml for AcpiGedDevice {
fn append_aml_bytes(&self, bytes: &mut Vec<u8>) {
fn to_aml_bytes(&self, sink: &mut dyn AmlSink) {
aml::Device::new(
"_SB_.GEC_".into(),
vec![
&aml::Name::new("_HID".into(), &aml::EisaName::new("PNP0A06")),
&aml::Name::new("_HID".into(), &aml::EISAName::new("PNP0A06")),
&aml::Name::new("_UID".into(), &"Generic Event Controller"),
&aml::Name::new(
"_CRS".into(),
@@ -121,12 +121,13 @@ impl Aml for AcpiGedDevice {
&aml::OpRegion::new(
"GDST".into(),
aml::OpRegionSpace::SystemMemory,
self.address.0 as usize,
GED_DEVICE_ACPI_SIZE,
&(self.address.0 as usize),
&GED_DEVICE_ACPI_SIZE,
),
&aml::Field::new(
"GDST".into(),
aml::FieldAccessType::Byte,
aml::FieldLockRule::NoLock,
aml::FieldUpdateRule::WriteAsZeroes,
vec![aml::FieldEntry::Named(*b"GDAT", 8)],
),
@@ -163,7 +164,7 @@ impl Aml for AcpiGedDevice {
),
],
)
.append_aml_bytes(bytes);
.to_aml_bytes(sink);
aml::Device::new(
"_SB_.GED_".into(),
vec![
@@ -187,7 +188,7 @@ impl Aml for AcpiGedDevice {
),
],
)
.append_aml_bytes(bytes)
.to_aml_bytes(sink)
}
}

View File

@@ -8,13 +8,11 @@ use anyhow::anyhow;
use arch::aarch64::layout::{TPM_SIZE, TPM_START};
#[cfg(target_arch = "x86_64")]
use arch::x86_64::layout::{TPM_SIZE, TPM_START};
use phf::phf_map;
use std::cmp;
use std::sync::{Arc, Barrier};
use thiserror::Error;
use tpm::emulator::{BackendCmd, Emulator};
use tpm::TPM_CRB_BUFFER_MAX;
use tpm::TPM_SUCCESS;
use vm_device::BusDevice;
#[derive(Error, Debug)]
@@ -23,62 +21,135 @@ pub enum Error {
CheckCaps(#[source] anyhow::Error),
#[error("Failed to initialize tpm: {0}")]
Init(#[source] anyhow::Error),
#[error("Failed to deliver tpm Command: {0}")]
DeliverRequest(#[source] anyhow::Error),
}
type Result<T> = anyhow::Result<T, Error>;
#[allow(dead_code)]
enum LocStateFields {
TpmEstablished,
LocAssigned,
ActiveLocality,
Reserved,
TpmRegValidSts,
}
enum LocStsFields {
Granted,
BeenSeized,
}
#[allow(dead_code)]
enum IntfIdFields {
InterfaceType,
InterfaceVersion,
CapLocality,
CapCRBIdleBypass,
Reserved1,
CapDataXferSizeSupport,
CapFIFO,
CapCRB,
CapIFRes,
InterfaceSelector,
IntfSelLock,
Reserved2,
Rid,
}
#[allow(dead_code)]
enum IntfId2Fields {
Vid,
Did,
}
enum CtrlStsFields {
TpmSts,
TpmIdle,
}
enum CrbRegister {
LocState(LocStateFields),
LocSts(LocStsFields),
IntfId(IntfIdFields),
IntfId2(IntfId2Fields),
CtrlSts(CtrlStsFields),
}
/* crb 32-bit registers */
const CRB_LOC_STATE: u32 = 0x0;
//Register Fields
// Field => (start, length)
// start: lowest bit in the bit field numbered from 0
// Field => (base, offset, length)
// base: starting position of the register
// offset: lowest bit in the bit field numbered from 0
// length: length of the bit field
const CRB_LOC_STATE_FIELDS: phf::Map<&str, [u32; 2]> = phf_map! {
"tpmEstablished" => [0, 1],
"locAssigned" => [1,1],
"activeLocality"=> [2, 3],
"reserved" => [5, 2],
"tpmRegValidSts" => [7, 1]
};
const fn get_crb_loc_state_field(f: LocStateFields) -> (u32, u32, u32) {
let (offset, len) = match f {
LocStateFields::TpmEstablished => (0, 1),
LocStateFields::LocAssigned => (1, 1),
LocStateFields::ActiveLocality => (2, 3),
LocStateFields::Reserved => (5, 2),
LocStateFields::TpmRegValidSts => (7, 1),
};
(CRB_LOC_STATE, offset, len)
}
const CRB_LOC_CTRL: u32 = 0x08;
const CRB_LOC_CTRL_REQUEST_ACCESS: u32 = 1 << 0;
const CRB_LOC_CTRL_RELINQUISH: u32 = 1 << 1;
const CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT: u32 = 1 << 3;
const CRB_LOC_STS: u32 = 0x0C;
const CRB_LOC_STS_FIELDS: phf::Map<&str, [u32; 2]> = phf_map! {
"Granted" => [0, 1],
"beenSeized" => [1,1]
};
const fn get_crb_loc_sts_field(f: LocStsFields) -> (u32, u32, u32) {
let (offset, len) = match f {
LocStsFields::Granted => (0, 1),
LocStsFields::BeenSeized => (1, 1),
};
(CRB_LOC_STS, offset, len)
}
const CRB_INTF_ID: u32 = 0x30;
const CRB_INTF_ID_FIELDS: phf::Map<&str, [u32; 2]> = phf_map! {
"InterfaceType" => [0, 4],
"InterfaceVersion" => [4, 4],
"CapLocality" => [8, 1],
"CapCRBIdleBypass" => [9, 1],
"Reserved1" => [10, 1],
"CapDataXferSizeSupport" => [11, 2],
"CapFIFO" => [13, 1],
"CapCRB" => [14, 1],
"CapIFRes" => [15, 2],
"InterfaceSelector" => [17, 2],
"IntfSelLock" => [19, 1],
"Reserved2" => [20, 4],
"RID" => [24, 8]
};
const fn get_crb_intf_id_field(f: IntfIdFields) -> (u32, u32, u32) {
let (offset, len) = match f {
IntfIdFields::InterfaceType => (0, 4),
IntfIdFields::InterfaceVersion => (4, 4),
IntfIdFields::CapLocality => (8, 1),
IntfIdFields::CapCRBIdleBypass => (9, 1),
IntfIdFields::Reserved1 => (10, 1),
IntfIdFields::CapDataXferSizeSupport => (11, 2),
IntfIdFields::CapFIFO => (13, 1),
IntfIdFields::CapCRB => (14, 1),
IntfIdFields::CapIFRes => (15, 2),
IntfIdFields::InterfaceSelector => (17, 2),
IntfIdFields::IntfSelLock => (19, 1),
IntfIdFields::Reserved2 => (20, 4),
IntfIdFields::Rid => (24, 8),
};
(CRB_INTF_ID, offset, len)
}
const CRB_INTF_ID2: u32 = 0x34;
const CRB_INTF_ID2_FIELDS: phf::Map<&str, [u32; 2]> = phf_map! {
"VID" => [0, 16],
"DID" => [16, 16]
};
const fn get_crb_intf_id2_field(f: IntfId2Fields) -> (u32, u32, u32) {
let (offset, len) = match f {
IntfId2Fields::Vid => (0, 16),
IntfId2Fields::Did => (16, 16),
};
(CRB_INTF_ID2, offset, len)
}
const CRB_CTRL_REQ: u32 = 0x40;
const CRB_CTRL_REQ_CMD_READY: u32 = 1 << 0;
const CRB_CTRL_REQ_GO_IDLE: u32 = 1 << 1;
const CRB_CTRL_STS: u32 = 0x44;
const CRB_CTRL_STS_FIELDS: phf::Map<&str, [u32; 2]> = phf_map! {
"tpmSts" => [0, 1],
"tpmIdle" => [1, 1]
};
const fn get_crb_ctrl_sts_field(f: CtrlStsFields) -> (u32, u32, u32) {
let (offset, len) = match f {
CtrlStsFields::TpmSts => (0, 1),
CtrlStsFields::TpmIdle => (1, 1),
};
(CRB_CTRL_STS, offset, len)
}
const CRB_CTRL_CANCEL: u32 = 0x48;
const CRB_CANCEL_INVOKE: u32 = 1 << 0;
const CRB_CTRL_START: u32 = 0x4C;
@@ -94,7 +165,7 @@ const TPM_CRB_NO_LOCALITY: u32 = 0xff;
const TPM_CRB_ADDR_BASE: u32 = TPM_START.0 as u32;
const TPM_CRB_ADDR_SIZE: usize = TPM_SIZE as usize;
const TPM_CRB_R_MAX: u32 = CRB_DATA_BUFFER;
const TPM_CRB_R_MAX: usize = CRB_DATA_BUFFER as usize;
// CRB Protocol details
const CRB_INTF_TYPE_CRB_ACTIVE: u32 = 0b1;
@@ -109,47 +180,29 @@ const PCI_VENDOR_ID_IBM: u32 = 0x1014;
const CRB_CTRL_CMD_SIZE_REG: u32 = 0x58;
const CRB_CTRL_CMD_SIZE: usize = TPM_CRB_ADDR_SIZE - CRB_DATA_BUFFER as usize;
fn get_fields_map(reg: u32) -> phf::Map<&'static str, [u32; 2]> {
// Returns (register base, offset, len)
const fn get_field(reg: CrbRegister) -> (u32, u32, u32) {
match reg {
CRB_LOC_STATE => CRB_LOC_STATE_FIELDS,
CRB_LOC_STS => CRB_LOC_STS_FIELDS,
CRB_INTF_ID => CRB_INTF_ID_FIELDS,
CRB_INTF_ID2 => CRB_INTF_ID2_FIELDS,
CRB_CTRL_STS => CRB_CTRL_STS_FIELDS,
_ => {
panic!("Fields in '{reg:?}' register were accessed which are Invalid");
}
CrbRegister::LocState(f) => get_crb_loc_state_field(f),
CrbRegister::LocSts(f) => get_crb_loc_sts_field(f),
CrbRegister::IntfId(f) => get_crb_intf_id_field(f),
CrbRegister::IntfId2(f) => get_crb_intf_id2_field(f),
CrbRegister::CtrlSts(f) => get_crb_ctrl_sts_field(f),
}
}
/// Set a particular field in a Register
fn set_reg_field(regs: &mut [u32; TPM_CRB_R_MAX as usize], reg: u32, field: &str, value: u32) {
let reg_fields = get_fields_map(reg);
if reg_fields.contains_key(field) {
let start = reg_fields.get(field).unwrap()[0];
let len = reg_fields.get(field).unwrap()[1];
let mask = (!(0_u32) >> (32 - len)) << start;
regs[reg as usize] = (regs[reg as usize] & !mask) | ((value << start) & mask);
} else {
error!(
"Failed to tpm Register. {:?} is not a valid field in Reg {:#X}",
field, reg
)
}
// Set a particular field in a Register
fn set_reg_field(regs: &mut [u32; TPM_CRB_R_MAX], reg: CrbRegister, value: u32) {
let (base, offset, len) = get_field(reg);
let mask = (!(0_u32) >> (32 - len)) << offset;
regs[base as usize] = (regs[base as usize] & !mask) | ((value << offset) & mask);
}
/// Get the value of a particular field in a Register
fn get_reg_field(regs: &[u32; TPM_CRB_R_MAX as usize], reg: u32, field: &str) -> u32 {
let reg_fields = get_fields_map(reg);
if reg_fields.contains_key(field) {
let start = reg_fields.get(field).unwrap()[0];
let len = reg_fields.get(field).unwrap()[1];
let mask = (!(0_u32) >> (32 - len)) << start;
(regs[reg as usize] & mask) >> start
} else {
// TODO: Sensible return value if fields do not exist
0x0
}
// Get the value of a particular field in a Register
const fn get_reg_field(regs: &[u32; TPM_CRB_R_MAX], reg: CrbRegister) -> u32 {
let (base, offset, len) = get_field(reg);
let mask = (!(0_u32) >> (32 - len)) << offset;
(regs[base as usize] & mask) >> offset
}
fn locality_from_addr(addr: u32) -> u8 {
@@ -158,8 +211,7 @@ fn locality_from_addr(addr: u32) -> u8 {
pub struct Tpm {
emulator: Emulator,
cmd: Option<BackendCmd>,
regs: [u32; TPM_CRB_R_MAX as usize],
regs: [u32; TPM_CRB_R_MAX],
backend_buff_size: usize,
data_buff: [u8; TPM_CRB_BUFFER_MAX],
data_buff_len: usize,
@@ -171,8 +223,7 @@ impl Tpm {
.map_err(|e| Error::Init(anyhow!("Failed while initializing tpm Emulator: {:?}", e)))?;
let mut tpm = Tpm {
emulator,
cmd: None,
regs: [0; TPM_CRB_R_MAX as usize],
regs: [0; TPM_CRB_R_MAX],
backend_buff_size: TPM_CRB_BUFFER_MAX,
data_buff: [0; TPM_CRB_BUFFER_MAX],
data_buff_len: 0,
@@ -182,74 +233,93 @@ impl Tpm {
}
fn get_active_locality(&mut self) -> u32 {
if get_reg_field(&self.regs, CRB_LOC_STATE, "locAssigned") == 0 {
if get_reg_field(
&self.regs,
CrbRegister::LocState(LocStateFields::LocAssigned),
) == 0
{
return TPM_CRB_NO_LOCALITY;
}
get_reg_field(&self.regs, CRB_LOC_STATE, "activeLocality")
get_reg_field(
&self.regs,
CrbRegister::LocState(LocStateFields::ActiveLocality),
)
}
fn request_completed(&mut self, result: isize) {
fn request_completed(&mut self, success: bool) {
self.regs[CRB_CTRL_START as usize] = !CRB_START_INVOKE;
if result != 0 {
set_reg_field(&mut self.regs, CRB_CTRL_STS, "tpmSts", 1);
if !success {
set_reg_field(
&mut self.regs,
CrbRegister::CtrlSts(CtrlStsFields::TpmSts),
1,
);
}
}
fn reset(&mut self) -> Result<()> {
let cur_buff_size = self.emulator.get_buffer_size().unwrap();
self.regs = [0; TPM_CRB_R_MAX as usize];
set_reg_field(&mut self.regs, CRB_LOC_STATE, "tpmRegValidSts", 1);
set_reg_field(&mut self.regs, CRB_CTRL_STS, "tpmIdle", 1);
let cur_buff_size = self.emulator.get_buffer_size();
self.regs = [0; TPM_CRB_R_MAX];
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"InterfaceType",
CrbRegister::LocState(LocStateFields::TpmRegValidSts),
1,
);
set_reg_field(
&mut self.regs,
CrbRegister::CtrlSts(CtrlStsFields::TpmIdle),
1,
);
set_reg_field(
&mut self.regs,
CrbRegister::IntfId(IntfIdFields::InterfaceType),
CRB_INTF_TYPE_CRB_ACTIVE,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"InterfaceVersion",
CrbRegister::IntfId(IntfIdFields::InterfaceVersion),
CRB_INTF_VERSION_CRB,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"CapLocality",
CrbRegister::IntfId(IntfIdFields::CapLocality),
CRB_INTF_CAP_LOCALITY_0_ONLY,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"CapCRBIdleBypass",
CrbRegister::IntfId(IntfIdFields::CapCRBIdleBypass),
CRB_INTF_CAP_IDLE_FAST,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"CapDataXferSizeSupport",
CrbRegister::IntfId(IntfIdFields::CapDataXferSizeSupport),
CRB_INTF_CAP_XFER_SIZE_64,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"CapFIFO",
CrbRegister::IntfId(IntfIdFields::CapFIFO),
CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"CapCRB",
CrbRegister::IntfId(IntfIdFields::CapCRB),
CRB_INTF_CAP_CRB_SUPPORTED,
);
set_reg_field(
&mut self.regs,
CRB_INTF_ID,
"InterfaceSelector",
CrbRegister::IntfId(IntfIdFields::InterfaceSelector),
CRB_INTF_IF_SELECTOR_CRB,
);
set_reg_field(&mut self.regs, CRB_INTF_ID, "RID", 0b0000);
set_reg_field(&mut self.regs, CRB_INTF_ID2, "VID", PCI_VENDOR_ID_IBM);
set_reg_field(
&mut self.regs,
CrbRegister::IntfId(IntfIdFields::Rid),
0b0000,
);
set_reg_field(
&mut self.regs,
CrbRegister::IntfId2(IntfId2Fields::Vid),
PCI_VENDOR_ID_IBM,
);
self.regs[CRB_CTRL_CMD_SIZE_REG as usize] = CRB_CTRL_CMD_SIZE as u32;
self.regs[CRB_CTRL_CMD_LADDR as usize] = TPM_CRB_ADDR_BASE + CRB_DATA_BUFFER;
@@ -268,7 +338,6 @@ impl Tpm {
}
}
//impl BusDevice for TPM
impl BusDevice for Tpm {
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
let mut offset: u32 = offset as u32;
@@ -367,10 +436,18 @@ impl BusDevice for Tpm {
}
CRB_CTRL_REQ => match v {
CRB_CTRL_REQ_CMD_READY => {
set_reg_field(&mut self.regs, CRB_CTRL_STS, "tpmIdle", 0);
set_reg_field(
&mut self.regs,
CrbRegister::CtrlSts(CtrlStsFields::TpmIdle),
0,
);
}
CRB_CTRL_REQ_GO_IDLE => {
set_reg_field(&mut self.regs, CRB_CTRL_STS, "tpmIdle", 1);
set_reg_field(
&mut self.regs,
CrbRegister::CtrlSts(CtrlStsFields::TpmIdle),
1,
);
}
_ => {
error!("Invalid value passed to CRTL_REQ register");
@@ -393,27 +470,14 @@ impl BusDevice for Tpm {
{
self.regs[CRB_CTRL_START as usize] |= CRB_START_INVOKE;
self.cmd = Some(BackendCmd {
locality: locality as u8,
input: self.data_buff[0..self.data_buff_len].to_vec(),
let mut cmd = BackendCmd {
buffer: &mut self.data_buff,
input_len: cmp::min(self.data_buff_len, TPM_CRB_BUFFER_MAX),
output: self.data_buff.to_vec(),
output_len: TPM_CRB_BUFFER_MAX,
selftest_done: false,
});
};
let mut cmd = self.cmd.as_ref().unwrap().clone();
let output = self.emulator.deliver_request(&mut cmd).map_err(|e| {
Error::DeliverRequest(anyhow!(
"Failed to deliver tpm request. Error :{:?}",
e
))
});
//TODO: drop the copy here
self.data_buff.fill(0);
self.data_buff.clone_from_slice(output.unwrap().as_slice());
let status = self.emulator.deliver_request(&mut cmd).is_ok();
self.request_completed(TPM_SUCCESS as isize);
self.request_completed(status);
}
}
CRB_LOC_CTRL => {
@@ -424,13 +488,33 @@ impl BusDevice for Tpm {
match v {
CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT => {}
CRB_LOC_CTRL_RELINQUISH => {
set_reg_field(&mut self.regs, CRB_LOC_STATE, "locAssigned", 0);
set_reg_field(&mut self.regs, CRB_LOC_STS, "Granted", 0);
set_reg_field(
&mut self.regs,
CrbRegister::LocState(LocStateFields::LocAssigned),
0,
);
set_reg_field(
&mut self.regs,
CrbRegister::LocSts(LocStsFields::Granted),
0,
);
}
CRB_LOC_CTRL_REQUEST_ACCESS => {
set_reg_field(&mut self.regs, CRB_LOC_STS, "Granted", 1);
set_reg_field(&mut self.regs, CRB_LOC_STS, "beenSeized", 0);
set_reg_field(&mut self.regs, CRB_LOC_STATE, "locAssigned", 1);
set_reg_field(
&mut self.regs,
CrbRegister::LocSts(LocStsFields::Granted),
1,
);
set_reg_field(
&mut self.regs,
CrbRegister::LocSts(LocStsFields::BeenSeized),
0,
);
set_reg_field(
&mut self.regs,
CrbRegister::LocState(LocStateFields::LocAssigned),
1,
);
}
_ => {
error!("Invalid value to write in CRB_LOC_CTRL {:#X} ", v);
@@ -456,10 +540,10 @@ mod tests {
#[test]
fn test_set_get_reg_field() {
let mut regs: [u32; TPM_CRB_R_MAX as usize] = [0; TPM_CRB_R_MAX as usize];
set_reg_field(&mut regs, CRB_INTF_ID, "RID", 0xAC);
let mut regs: [u32; TPM_CRB_R_MAX] = [0; TPM_CRB_R_MAX];
set_reg_field(&mut regs, CrbRegister::IntfId(IntfIdFields::Rid), 0xAC);
assert_eq!(
get_reg_field(&regs, CRB_INTF_ID, "RID"),
get_reg_field(&regs, CrbRegister::IntfId(IntfIdFields::Rid)),
0xAC,
concat!("Test: ", stringify!(set_get_reg_field))
);

View File

@@ -78,33 +78,40 @@ The Cloud Hypervisor API exposes the following actions through its endpoints:
#### Virtual Machine (VM) Actions
| Action | Endpoint | Request Body | Response Body | Prerequisites |
| ---------------------------------- | --------------------- | --------------------------- | ------------------------ | -------------------------------- |
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted |
| Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted |
| Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted |
| Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused |
| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused |
| Perform a coredump of the VM | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused |
| Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted |
| Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
| Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
| Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted |
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add userspace PCI device to the VM | `/vm.add-user-device` | `/schemas/VmAddUserDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted |
| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted |
| Action | Endpoint | Request Body | Response Body | Prerequisites |
| ---------------------------------- | ----------------------- | ------------------------------- | ------------------------ | ------------------------------------------------------ |
| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet |
| Delete the VM | `/vm.delete` | N/A | N/A | N/A |
| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted |
| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted |
| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted |
| Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted |
| Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted |
| Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused |
| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused |
| Perform a coredump of the VM* | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused |
| Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted |
| Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
| Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted |
| Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted |
| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created |
| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add userspace PCI device to the VM | `/vm.add-user-device` | `/schemas/VmAddUserDevice` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted |
| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted |
| Prepare to receive a migration | `/vm.receive-migration` | `/schemas/ReceiveMigrationData` | N/A | N/A |
| Start to send migration to target | `/vm.send-migration` | `/schemas/SendMigrationData` | N/A | The VM is booted and (shared mem or hugepages enabled) |
* The `vmcoredump` action is available exclusively for the `x86_64`
architecture and can be executed only when the `guest_debug` feature is
enabled. Without this feature, the corresponding REST API endpoint is not
available.
### REST API Examples
@@ -217,11 +224,11 @@ From the CLI, one can either:
The REST API and the CLI both rely on a common, [internal API](#internal-api).
The CLI options are parsed by the
[clap crate](https://docs.rs/clap/2.33.0/clap/) and then translated into
[argh crate](https://docs.rs/argh/latest/argh/) and then translated into
[internal API](#internal-api) commands.
The REST API is processed by an HTTP thread using the
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
[Firecracker's `micro_http`](https://github.com/firecracker-microvm/micro-http)
crate. As with the CLI, the HTTP requests eventually get translated into
[internal API](#internal-api) commands.
@@ -245,7 +252,7 @@ As a summary, the REST API and the CLI are essentially frontends for the
| | +------------------------+
| +----------+ | VMM
| CLI | | |
+----------->+ clap +--------------+
+----------->+ argh +--------------+
| |
+----------+
@@ -379,5 +386,5 @@ APIs work together, let's look at a complete VM creation flow, from the
```
1. The Cloud Hypervisor HTTP thread sends the formed HTTP response back to the
user. This is abstracted by the
[micro_http](https://github.com/firecracker-microvm/firecracker/tree/master/src/micro_http)
[micro_http](https://github.com/firecracker-microvm/micro-http)
crate.

View File

@@ -27,7 +27,7 @@ distributions please replace the package manager and package name.
# Install basic packages needed. For a package list targeting for more
# functionalities for example the test, please see resources/Dockerfile.
$ sudo apt-get update
$ sudo apt install git build-essential m4 bison flex uuid-dev qemu-utils
$ sudo apt install git build-essential m4 bison flex uuid-dev qemu-utils musl-tools
# Install rust tool chain
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# If you want to build statically linked binary please add musl target

View File

@@ -88,7 +88,7 @@ Ubuntu distributions.
```bash
apt update
apt install fio iperf iperf3 socat stress cpuid
apt install fio iperf iperf3 socat stress cpuid tpm2-tools
```
### Remove counterproductive packages
@@ -170,8 +170,8 @@ We usually start from one of the custom cloud image we have previously created
but we can use a stock cloud image as well.
```bash
wget https://cloud-hypervisor.azureedge.net/jammy-server-cloudimg-amd64-custom-20221118-1.raw
mv jammy-server-cloudimg-amd64-custom-20221118-1.raw jammy-server-cloudimg-amd64-nvidia.raw
wget https://cloud-hypervisor.azureedge.net/jammy-server-cloudimg-amd64-custom-20230119-0.raw
mv jammy-server-cloudimg-amd64-custom-20230119-0.raw jammy-server-cloudimg-amd64-nvidia.raw
```
### Extend the image size

View File

@@ -36,7 +36,7 @@ Assuming parts of the guest software stack have been instrumented to use the
`cloud-hypervisor` debug I/O port, we may want to gather the related logs.
To do so we need to start `cloud-hypervisor` with the right debug level
(`-vvv`). It is also recommended to have it log into a dedicated file in order
(`-v -v -v`). It is also recommended to have it log into a dedicated file in order
to easily grep for the tracing logs (e.g.
`--log-file /tmp/cloud-hypervisor.log`):
@@ -48,7 +48,7 @@ to easily grep for the tracing logs (e.g.
--memory size=1024M \
--rng \
--log-file /tmp/ch-fw.log \
-vvv
-v -v -v
```
After booting the guest, we then have to grep for the debug I/O port traces in

View File

@@ -8,7 +8,7 @@ To enable debugging with GDB, build with the `guest_debug` feature enabled:
cargo build --features guest_debug
```
To use the `--gdb` option, specify the Unix Domain Socket with `--path` that Cloud Hypervisor will use to communicate with the host's GDB:
To use the `--gdb` option, specify the Unix Domain Socket with `path` that Cloud Hypervisor will use to communicate with the host's GDB:
```bash
./cloud-hypervisor \

41
docs/heap-profiling.md Normal file
View File

@@ -0,0 +1,41 @@
# Heap profiling
Cloud Hypervisor supports generating a profile using
[dhat](https://docs.rs/dhat/latest/dhat/) of the heap allocations made during
the runtime of the process.
## Building a suitable binary
This adds the symbol information to the release binary but does not otherwise
affect the performance.
```
$ cargo build --profile profiling --features "dhat-heap"
```
## Generating output
Cloud Hypervisor can then be run as usual. However it is necessary to run with `--seccomp false` as the profiling requires extra syscalls.
```
$ target/profiling/cloud-hypervisor \
--kernel ~/src/linux/vmlinux \
--pmem file=~/workloads/focal.raw \
--cpus boot=1 --memory size=1G \
--cmdline "root=/dev/pmem0p1 console=ttyS0" \
--serial tty --console off \
--api-socket /tmp/api1 \
--seccomp false
```
When the VMM exits a message like the following will be shown:
```
dhat: Total: 384,582 bytes in 3,512 blocks
dhat: At t-gmax: 133,885 bytes in 379 blocks
dhat: At t-end: 12,160 bytes in 20 blocks
dhat: The data has been saved to dhat-heap.json, and is viewable with dhat/dh_view.html
```
The JSON output can then be uploaded to [the dh_view tool](https://nnethercote.github.io/dh_view/dh_view.html) for analysis.

View File

@@ -4,7 +4,7 @@ Currently Cloud Hypervisor supports hot plugging of CPUs devices (x86 only), PCI
## Kernel support
For hotplug on Cloud Hypervisor ACPI GED support is needed. This can either be achieved by turning on `CONFIG_ACPI_REDUCED_HARDWARE_ONLY`
For hotplug on Cloud Hypervisor ACPI GED support is needed. This can either be achieved by turning on `CONFIG_ACPI_REDUCED_HARDWARE_ONLY`
or by using this kernel patch (available in 5.5-rc1 and later): https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/drivers/acpi/Makefile?id=ac36d37e943635fc072e9d4f47e40a48fbcdb3f0
## CPU Hot Plug
@@ -27,16 +27,16 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
--api-socket /tmp/ch-socket
$ 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:
```shell
./ch-remote --api-socket=/tmp/ch-socket resize --cpus 8
./ch-remote --api-socket /tmp/ch-socket resize --cpus 8
```
The extra vCPU threads will be created and advertised to the running kernel. The kernel does not bring up the CPUs immediately and instead the user must "online" them from inside the VM:
@@ -56,7 +56,7 @@ After a reboot the added CPUs will remain.
Removing CPUs works similarly by reducing the number in the "desired_vcpus" field of the reisze API. The CPUs will be automatically offlined inside the guest so there is no need to run any commands inside the guest:
```shell
./ch-remote --api-socket=/tmp/ch-socket resize --cpus 2
./ch-remote --api-socket /tmp/ch-socket resize --cpus 2
```
As per adding CPUs to the guest, after a reboot the VM will be running with the reduced number of vCPUs.
@@ -85,7 +85,7 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
--memory size=1024M,hotplug_size=8192M \
--net "tap=,mac=,ip=,mask=" \
--rng \
--api-socket=/tmp/ch-socket
--api-socket /tmp/ch-socket
$ popd
```
@@ -98,7 +98,7 @@ root@ch-guest ~ # echo online | sudo tee /sys/devices/system/memory/auto_online_
To ask the VMM to expand the RAM for the VM:
```shell
./ch-remote --api-socket=/tmp/ch-socket resize --memory 3G
./ch-remote --api-socket /tmp/ch-socket resize --memory 3G
```
The new memory is now available to use inside the VM:
@@ -134,14 +134,14 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
--disk path=focal-server-cloudimg-amd64.raw \
--memory size=1024M,hotplug_size=8192M,hotplug_method=virtio-mem \
--net "tap=,mac=,ip=,mask=" \
--api-socket=/tmp/ch-socket
--api-socket /tmp/ch-socket
$ popd
```
To ask the VMM to expand the RAM for the VM (request is in bytes):
```shell
./ch-remote --api-socket=/tmp/ch-socket resize --memory 3G
./ch-remote --api-socket /tmp/ch-socket resize --memory 3G
```
The new memory is now available to use inside the VM:
@@ -159,7 +159,7 @@ The same API can also be used to reduce the desired RAM for a VM. It is importan
Extra PCI devices can be added and removed from a running `cloud-hypervisor` instance. This is controlled by making a HTTP API request to the VMM to ask for the additional device to be added, or for the existing device to be removed.
Note: On AArch64 platform, PCI device hotplug can only be achieved using ACPI. Please refer to the [documentation](arm64.md#uefi-booting) for more information.
Note: On AArch64 platform, PCI device hotplug can only be achieved using ACPI. Please refer to the [documentation](uefi.md#building-uefi-firmware-for-aarch64) for more information.
To use PCI device hotplug start the VM with the HTTP server.
@@ -172,17 +172,17 @@ $ ./cloud-hypervisor/target/release/cloud-hypervisor \
--cpus boot=4 \
--memory size=1024M \
--net "tap=,mac=,ip=,mask=" \
--api-socket=/tmp/ch-socket
--api-socket /tmp/ch-socket
```
Notice the addition of `--api-socket=/tmp/ch-socket`.
Notice the addition of `--api-socket /tmp/ch-socket`.
### Add VFIO Device
To ask the VMM to add additional VFIO device then use the `add-device` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-device path=/sys/bus/pci/devices/0000:01:00.0/
./ch-remote --api-socket /tmp/ch-socket add-device path=/sys/bus/pci/devices/0000:01:00.0/
```
### Add Disk Device
@@ -190,7 +190,7 @@ To ask the VMM to add additional VFIO device then use the `add-device` API.
To ask the VMM to add additional disk device then use the `add-disk` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-disk path=/foo/bar/cloud.img
./ch-remote --api-socket /tmp/ch-socket add-disk path=/foo/bar/cloud.img
```
### Add Fs Device
@@ -198,7 +198,7 @@ To ask the VMM to add additional disk device then use the `add-disk` API.
To ask the VMM to add additional fs device then use the `add-fs` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-fs tag=myfs,socket=/foo/bar/virtiofs.sock
./ch-remote --api-socket /tmp/ch-socket add-fs tag=myfs,socket=/foo/bar/virtiofs.sock
```
### Add Net Device
@@ -206,7 +206,7 @@ To ask the VMM to add additional fs device then use the `add-fs` API.
To ask the VMM to add additional network device then use the `add-net` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-net tap=chtap0
./ch-remote --api-socket /tmp/ch-socket add-net tap=chtap0
```
### Add Pmem Device
@@ -214,7 +214,7 @@ To ask the VMM to add additional network device then use the `add-net` API.
To ask the VMM to add additional PMEM device then use the `add-pmem` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-pmem file=/foo/bar.cloud.img
./ch-remote --api-socket /tmp/ch-socket add-pmem file=/foo/bar.cloud.img
```
### Add Vsock Device
@@ -222,7 +222,7 @@ To ask the VMM to add additional PMEM device then use the `add-pmem` API.
To ask the VMM to add additional vsock device then use the `add-vsock` API.
```shell
./ch-remote --api-socket=/tmp/ch-socket add-vsock cid=3,socket=/foo/bar/vsock.sock
./ch-remote --api-socket /tmp/ch-socket add-vsock cid=3,socket=/foo/bar/vsock.sock
```
### Common Across All PCI Devices
@@ -244,7 +244,7 @@ After a reboot the added PCI device will remain.
Removing a PCI device works the same way for all kind of PCI devices. The unique identifier related to the device must be provided. This identifier can be provided by the user when adding the new device, or by default Cloud Hypervisor will assign one.
```shell
./ch-remote --api-socket=/tmp/ch-socket remove-device _disk0
./ch-remote --api-socket /tmp/ch-socket remove-device _disk0
```
As per adding a PCI device to the guest, after a reboot the VM will be running without the removed PCI device.

View File

@@ -2,49 +2,64 @@
Intel® Trust Domain Extensions (Intel® TDX) is an Intel technology designed to
isolate virtual machines from the VMM, hypervisor and any other software on the
host platform.
host platform. Here are some useful links:
For more information about TDX technical aspects, design and specification
please refer to the
[TDX Homepage](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html).
* [TDX Homepage](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html):
more information about TDX technical aspects, design and specification
The required Linux changes for the host side can be found in the
[KVM TDX tree](https://github.com/intel/tdx/tree/kvm) while the changes for
the guest side can be found in the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
* [KVM TDX tree](https://github.com/intel/tdx/tree/kvm): the required
Linux kernel changes for the host side
The TDVF firmware can be found in the
[EDK2 staging project](https://github.com/tianocore/edk2-staging/tree/TDVF).
* [Guest TDX tree](https://github.com/intel/tdx/tree/guest): the Linux
kernel changes for the guest side
The TDShim firmware can be found in the
[Confidential Containers project](https://github.com/confidential-containers/td-shim).
* [EDK2 project](https://github.com/tianocore/edk2): the TDVF firmware
* [Confidential Containers project](https://github.com/confidential-containers/td-shim):
the TDShim firmware
* [TDX Tools](https://github.com/intel/tdx-tools): a collection of tools
and scripts to setup TDX environment for testing purpose (such as
installing required packages on the host, creating guest images, and
building the custom Linux kernel for TDX host and guest)
## Cloud Hypervisor support
First, you must be running on a machine with TDX enabled in hardware, and
It is required to use a machine with TDX enabled in hardware and
with the host OS compiled from the [KVM TDX tree](https://github.com/intel/tdx/tree/kvm).
The host environment can also be setup with the [TDX Tools](https://github.com/intel/tdx-tools).
Cloud Hypervisor can run TDX VM (Trust Domain) by loading a TD firmware,
Cloud Hypervisor can run TDX VM (Trust Domain) by loading a TD firmware ([TDVF](https://github.com/tianocore/edk2)),
which will then load the guest kernel from the image. The image must be custom
as it must include a kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
Cloud Hypervisor can also boot a TDX VM with direct kernel boot using [TDshim](https://github.com/confidential-containers/td-shim).
The custom Linux kernel for the guest can be built with the [TDX Tools](https://github.com/intel/tdx-tools).
> **Note**
> The latest version of custom host and guest kernel being tested is
> from [TDX Tools - 2023ww01](https://github.com/intel/tdx-tools/commits/2023ww01).
### TDVF
> **Note**
> The latest version of TDVF being tested is [_13b9773_](https://github.com/tianocore/edk2/commit/13b97736c876919b9786055829caaa4fa46984b7).
The firmware can be built as follows:
```bash
git clone https://github.com/tianocore/edk2-staging.git
cd edk2-staging
git checkout origin/TDVF
git clone https://github.com/tianocore/edk2.git
cd edk2
git checkout 13b97736c876919b9786055829caaa4fa46984b7
git submodule update --init --recursive
make -C BaseTools
source ./edksetup.sh
build -p OvmfPkg/OvmfCh.dsc -a X64 -t GCC5 -b RELEASE
build -p OvmfPkg/IntelTdx/IntelTdxX64.dsc -a X64 -t GCC5 -b RELEASE
```
If debug logs are needed, here is the alternative command:
```bash
build -p OvmfPkg/OvmfCh.dsc -a X64 -t GCC5 -D DEBUG_ON_SERIAL_PORT=TRUE
build -p OvmfPkg/IntelTdx/IntelTdxX64.dsc -a X64 -t GCC5 -D DEBUG_ON_SERIAL_PORT=TRUE
```
On the Cloud Hypervisor side, all you need is to build the project with the
@@ -62,7 +77,7 @@ meaning it will be printing guest kernel logs to the `virtio-console` device.
```bash
./cloud-hypervisor \
--platform tdx=on
--firmware edk2-staging/Build/OvmfCh/RELEASE_GCC5/FV/OVMF.fd \
--firmware edk2/Build/IntelTdx/RELEASE_GCC5/FV/OVMF.fd \
--cpus boot=1 \
--memory size=1G \
--disk path=tdx_guest_img
@@ -74,7 +89,7 @@ firmware:
```bash
./cloud-hypervisor \
--platform tdx=on
--firmware edk2-staging/Build/OvmfCh/DEBUG_GCC5/FV/OVMF.fd \
--firmware edk2/Build/IntelTdx/DEBUG_GCC5/FV/OVMF.fd \
--cpus boot=1 \
--memory size=1G \
--disk path=tdx_guest_img \
@@ -84,21 +99,60 @@ firmware:
### TDShim
> **Note**
> The latest version of TDShim being tested is [_66bb334_](https://github.com/confidential-containers/td-shim/tree/66bb33451befbf1291abe3cfea7ee9e99d922b0d).
This is a lightweight version of the TDVF, written in Rust and designed for
direct kernel boot, which is useful for containers use cases.
You can find the instructions for building the firmware directly from the
project [documentation](https://github.com/confidential-containers/td-shim/tree/staging#how-to-build).
To build TDShim from source, it is required to install `Rust`, `NASM`,
and `LLVM` first. The TDshim can be build as follows:
```bash
git clone https://github.com/confidential-containers/td-shim
cd td-shim
git checkout 66bb33451befbf1291abe3cfea7ee9e99d922b0d
cargo install cargo-xbuild
export CC=clang
export AR=llvm-ar
export CC_x86_64_unknown_none=clang
export AR_x86_64_unknown_none=llvm-ar
git submodule update --init --recursive
./sh_script/preparation.sh
cargo xbuild -p td-shim --target x86_64-unknown-none --release --features=main,tdx
cargo run -p td-shim-tools --bin td-shim-ld --features=linker -- target/x86_64-unknown-none/release/ResetVector.bin target/x86_64-unknown-none/release/td-shim -o target/release/final.bin
```
If debug logs from the TDShim is needed, here are the alternative
commands:
```bash
cargo xbuild -p td-shim --target x86_64-unknown-none --features=main,tdx
cargo run -p td-shim-tools --bin td-shim-ld --features=linker -- target/x86_64-unknown-none/debug/ResetVector.bin target/x86_64-unknown-none/debug/td-shim -o target/debug/final.bin
```
And run a TDX VM by providing the firmware previously built, along with a guest
kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest).
kernel built from the [Guest TDX tree](https://github.com/intel/tdx/tree/guest)
or the [TDX Tools](https://github.com/intel/tdx-tools).
The appropriate kernel boot options must be provided through the `--cmdline`
option as well.
```bash
./cloud-hypervisor \
--platform tdx=on
--firmware tdshim \
--firmware td-shim/target/release/final.bin \
--kernel bzImage \
--cmdline "root=/dev/vda3 console=hvc0 rw"
--cpus boot=1 \
--memory size=1G \
--disk path=tdx_guest_img
```
And here is the alternative command when looking for debug logs from the
TDShim:
```bash
./cloud-hypervisor \
--platform tdx=on
--firmware td-shim/target/debug/final.bin \
--kernel bzImage \
--cmdline "root=/dev/vda3 console=hvc0 rw"
--cpus boot=1 \

View File

@@ -245,7 +245,7 @@ e.g.
```bash
./cloud-hypervisor \
--api-socket=/tmp/api \
--api-socket /tmp/api \
--cpus boot=1 \
--memory size=4G,hugepages=on \
--disk path=focal-server-cloudimg-amd64.raw \
@@ -260,7 +260,7 @@ requiring the IOMMU then may be hotplugged:
e.g.
```bash
./ch-remote --api-socket=/tmp/api add-device path=/sys/bus/pci/devices/0000:00:04.0,iommu=on,pci_segment=1
./ch-remote --api-socket /tmp/api add-device path=/sys/bus/pci/devices/0000:00:04.0,iommu=on,pci_segment=1
```
Devices that cannot be placed behind an IOMMU (e.g. lacking an `iommu=` option)

View File

@@ -16,22 +16,22 @@ $ target/release/cloud-hypervisor
--disk path=~/workloads/focal.raw \
--cpus boot=1 --memory size=1G,shared=on \
--cmdline "root=/dev/vda1 console=ttyS0" \
--serial tty --console off --api-socket=/tmp/api1
--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
$ 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
$ 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 --local unix:/tmp/sock
$ target/release/ch-remote --api-socket /tmp/api1 send-migration --local unix:/tmp/sock
```
When the above commands completed, the source VM should be successfully
@@ -51,7 +51,7 @@ $ sudo /target/release/cloud-hypervisor \
--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\
--disk path=focal-1.raw path=focal-nested.raw --disk path=tmp.img\
--net ip=192.168.101.1
```
@@ -63,7 +63,7 @@ $ sudo /target/release/cloud-hypervisor \
--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\
--disk path=focal-2.raw path=focal-nested.raw --disk path=tmp.img\
--net ip=192.168.102.1
```
@@ -74,8 +74,8 @@ vm-1:~$ sudo ./cloud-hypervisor \
--memory size=128M \
--kernel vmlinux \
--cmdline "console=ttyS0 root=/dev/vda1" \
--disk path=/dev/vdb path=/dev/vdc \
--api-socket=/tmp/api1 \
--disk path=/dev/vdb --disk 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
@@ -108,7 +108,7 @@ 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:~$ 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
@@ -122,7 +122,7 @@ vm-2:~$ ping 192.168.101.2 # This should succeed
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 ./ch-remote --api-socket /tmp/api2 receive-migration unix:/tmp/sock2
vm-2:~$ sudo socat TCP-LISTEN:6000,reuseaddr UNIX-CLIENT:/tmp/sock2
```
@@ -130,7 +130,7 @@ 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
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

View File

@@ -38,6 +38,6 @@ This level is for the benefit of developers. It should be used for sporadic and
### `debug!()`
Use `-vv` to enable.
Use `-v -v` to enable.
For the most verbose of logging messages. It is acceptable to "spam" the log with repeated invocations of the same message. This level of logging would be combined with `--log-file`.
For the most verbose of logging messages. It is acceptable to "spam" the log with repeated invocations of the same message. This level of logging would be combined with `--log-file`.

View File

@@ -266,11 +266,8 @@ _Example_
### `file`
Path to the file backing the memory zone. This can be either a file or a
directory. In case of a file, it will be opened and used as the backing file
for the `mmap(2)` operation. In case of a directory, a temporary file with no
hard link on the filesystem will be created. This file will be used as the
backing file for the `mmap(2)` operation.
Path to the file backing the memory zone. The file will be opened and used as
the backing file for the `mmap(2)` operation.
This option can be particularly useful when trying to back a part of the guest
RAM with a well known file. In the context of the snapshot/restore feature, and
@@ -519,7 +516,7 @@ different distances, it can be described with the following example.
_Example_
```
--numa guest_numa_id=0,distances=[1@15,2@25] guest_numa_id=1,distances=[0@15,2@20] guest_numa_id=2,distances=[0@25,1@20]
--numa guest_numa_id=0,distances=[1@15,2@25] --numa guest_numa_id=1,distances=[0@15,2@20] guest_numa_id=2,distances=[0@25,1@20]
```
### `memory_zones`
@@ -543,14 +540,14 @@ demarcate the list.
Note that a memory zone must belong to a single NUMA node. The following
configuration is incorrect, therefore not allowed:
`--numa guest_numa_id=0,memory_zones=mem0 guest_numa_id=1,memory_zones=mem0`
`--numa guest_numa_id=0,memory_zones=mem0 --numa guest_numa_id=1,memory_zones=mem0`
_Example_
```
--memory size=0
--memory-zone id=mem0,size=1G id=mem1,size=1G id=mem2,size=1G
--numa guest_numa_id=0,memory_zones=[mem0,mem2] guest_numa_id=1,memory_zones=mem1
--memory-zone id=mem0,size=1G id=mem1,size=1G --memory-zone id=mem2,size=1G
--numa guest_numa_id=0,memory_zones=[mem0,mem2] --numa guest_numa_id=1,memory_zones=mem1
```
### `sgx_epc_sections`
@@ -570,7 +567,7 @@ _Example_
```
--sgx-epc id=epc0,size=32M id=epc1,size=64M id=epc2,size=32M
--numa guest_numa_id=0,sgx_epc_sections=epc1 guest_numa_id=1,sgx_epc_sections=[epc0,epc2]
--numa guest_numa_id=0,sgx_epc_sections=epc1 --numa guest_numa_id=1,sgx_epc_sections=[epc0,epc2]
```
### PCI bus

View File

@@ -4,20 +4,12 @@
## Building a suitable binary
Modify the `Cargo.toml` file to add `debug = 1` to the `[profile.release]` block. It should look like this:
```
[profile.release]
lto = true
debug = 1
```
This adds the symbol information to the release binary but does not otherwise affect the performance.
The binary must also be built with frame pointers included so that the call graph can be captured by the profiler.
```
$ cargo clean && RUSTFLAGS='-C force-frame-pointers=y' cargo build --release
$ cargo clean && RUSTFLAGS='-C force-frame-pointers=y' cargo build --profile profiling
```
## Profiling
@@ -27,13 +19,13 @@ $ cargo clean && RUSTFLAGS='-C force-frame-pointers=y' cargo build --release
e.g.
```
$ perf record -g target/release/cloud-hypervisor \
$ perf record -g target/profiling/cloud-hypervisor \
--kernel ~/src/linux/vmlinux \
--pmem file=~/workloads/focal.raw \
--cpus boot=1 --memory size=1G \
--cmdline "root=/dev/pmem0p1 console=ttyS0" \
--serial tty --console off \
--api-socket=/tmp/api1
--api-socket /tmp/api1
```
For analysing the samples:
@@ -60,5 +52,5 @@ $ perf record --call-graph lbr --all-user --user-callchains -g target/release/cl
--cpus boot=1 --memory size=1G \
--cmdline "root=/dev/pmem0p1 console=ttyS0" \
--serial tty --console off \
--api-socket=/tmp/api1
--api-socket /tmp/api1
```

View File

@@ -25,14 +25,14 @@ First thing, we must run a Cloud Hypervisor VM:
At any point in time when the VM is running, one might choose to pause it:
```bash
./ch-remote --api-socket=/tmp/cloud-hypervisor.sock pause
./ch-remote --api-socket /tmp/cloud-hypervisor.sock pause
```
Once paused, the VM can be safely snapshot into the specified directory and
using the following command:
```bash
./ch-remote --api-socket=/tmp/cloud-hypervisor.sock snapshot file:///home/foo/snapshot
./ch-remote --api-socket /tmp/cloud-hypervisor.sock snapshot file:///home/foo/snapshot
```
Given the directory was present on the system, the snapshot will succeed and
@@ -79,7 +79,7 @@ Or using two different commands from two terminals:
./cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock
# Second terminal
./ch-remote --api-socket=/tmp/cloud-hypervisor.sock restore source_url=file:///home/foo/snapshot
./ch-remote --api-socket /tmp/cloud-hypervisor.sock restore source_url=file:///home/foo/snapshot
```
Remember the VM is restored in a `paused` state, which was the VM's state when
@@ -87,7 +87,7 @@ it was snapshot. For this reason, one must explicitly `resume` the VM before to
start using it.
```bash
./ch-remote --api-socket=/tmp/cloud-hypervisor.sock resume
./ch-remote --api-socket /tmp/cloud-hypervisor.sock resume
```
At this point, the VM is fully restored and is identical to the VM which was

View File

@@ -94,7 +94,7 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
--memory size=1024M,hugepages=on,shared=true \
--kernel linux/arch/x86/boot/compressed/vmlinux.bin \
--cmdline "console=ttyS0 root=/dev/vda1 rw iommu=off" \
--disk path=images/focal-server-cloudimg-amd64.raw vhost_user=true,socket=/var/tmp/vhost.1,num_queues=4,queue_size=128 \
--disk path=images/focal-server-cloudimg-amd64.raw --disk vhost_user=true,socket=/var/tmp/vhost.1,num_queues=4,queue_size=128 \
--console off \
--serial tty \
--rng

View File

@@ -7,4 +7,4 @@ edition = "2021"
[dependencies]
libc = "0.2.139"
serde = { version = "1.0.151", features = ["rc", "derive"] }
serde_json = "1.0.89"
serde_json = "1.0.95"

475
fuzz/Cargo.lock generated
View File

@@ -5,15 +5,16 @@ version = 3
[[package]]
name = "acpi_tables"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#0b892e2c2053c4ecfac8d9e5a52babae75114702"
dependencies = [
"vm-memory",
"zerocopy",
]
[[package]]
name = "anyhow"
version = "1.0.68"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "api_client"
@@ -24,15 +25,15 @@ dependencies = [
[[package]]
name = "arbitrary"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29d47fbf90d5149a107494b15a7dc8d69b351be2db3bb9691740e88ec17fd880"
checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
[[package]]
name = "arc-swap"
version = "1.5.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "arch"
@@ -56,6 +57,34 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "argh"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e"
dependencies = [
"argh_derive",
"argh_shared",
]
[[package]]
name = "argh_derive"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6"
dependencies = [
"argh_shared",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "argh_shared"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
[[package]]
name = "bincode"
version = "1.3.3"
@@ -84,7 +113,7 @@ dependencies = [
"versionize",
"versionize_derive",
"vhdx",
"virtio-bindings",
"virtio-bindings 0.2.0",
"virtio-queue",
"vm-memory",
"vm-virtio",
@@ -99,9 +128,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.78"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
dependencies = [
"jobserver",
]
@@ -112,37 +141,13 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"bitflags",
"clap_lex",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
"terminal_size",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "cloud-hypervisor"
version = "28.0.0"
version = "30.0.0"
dependencies = [
"anyhow",
"api_client",
"clap",
"argh",
"epoll",
"event_monitor",
"hypervisor",
@@ -203,9 +208,9 @@ checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
[[package]]
name = "darling"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core",
"darling_macro",
@@ -213,27 +218,27 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@@ -248,7 +253,6 @@ dependencies = [
"hypervisor",
"libc",
"log",
"phf",
"thiserror",
"tpm",
"versionize",
@@ -269,27 +273,6 @@ dependencies = [
"libc",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "event_monitor"
version = "0.1.0"
@@ -301,9 +284,9 @@ dependencies = [
[[package]]
name = "fdt"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "964f5becd44d069dca0beea2b4bc05639ae7bf3b3f5369c295aff360bb57cca2"
checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
[[package]]
name = "fnv"
@@ -322,15 +305,6 @@ dependencies = [
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hypervisor"
version = "0.1.0"
@@ -365,49 +339,27 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "io-uring"
version = "0.5.11"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9ddf18110cedc09617f5a965bdb51adb0c0fb02c791e4ab22f7a21bb25269b0"
checksum = "dd1e1a01cfb924fd8c5c43b6827965db394f5a3a16c599ce03452266e1cf984c"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "itoa"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "jobserver"
version = "0.1.25"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
@@ -424,9 +376,9 @@ dependencies = [
[[package]]
name = "kvm-ioctls"
version = "0.12.0"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a321cabd827642499c77e27314f388dd83a717a5ca716b86476fb947f73ae4"
checksum = "b8f8dc9c1896e5f144ec5d07169bc29f39a047686d29585a91f30489abfaeb6b"
dependencies = [
"kvm-bindings",
"libc",
@@ -441,15 +393,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libfuzzer-sys"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8fff891139ee62800da71b7fd5b508d570b9ad95e614a53c6f453ca08366038"
checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
dependencies = [
"arbitrary",
"cc",
@@ -465,12 +417,6 @@ dependencies = [
"vm-memory",
]
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "log"
version = "0.4.17"
@@ -483,7 +429,7 @@ dependencies = [
[[package]]
name = "micro_http"
version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#fbef706e28c7ca7cce8dfec7ca073f3b359879d3"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#b538bf89e50be83b6fa9ab1896727ff61e02fa13"
dependencies = [
"libc",
"vmm-sys-util",
@@ -510,7 +456,7 @@ dependencies = [
"thiserror",
"versionize",
"versionize_derive",
"virtio-bindings",
"virtio-bindings 0.2.0",
"virtio-queue",
"vm-memory",
"vm-virtio",
@@ -519,20 +465,14 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.17.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "option_parser"
version = "0.1.0"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "pci"
version = "0.1.0"
@@ -556,53 +496,11 @@ dependencies = [
"vmm-sys-util",
]
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_macros"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
dependencies = [
"siphasher",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
@@ -620,28 +518,13 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rate_limiter"
version = "0.1.0"
@@ -653,13 +536,13 @@ dependencies = [
[[package]]
name = "remain"
version = "0.2.6"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5704e2cda92fd54202f05430725317ba0ea7d0c96b246ca0a92e45177127ba3b"
checksum = "e13cca257d068dd3a390d04b2c3009a3fad2ee5048dfa8f239d048372810470c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.4",
]
[[package]]
@@ -671,25 +554,11 @@ dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "seccompiler"
@@ -702,35 +571,35 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
[[package]]
name = "serde"
version = "1.0.152"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.91"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
dependencies = [
"itoa",
"ryu",
@@ -739,9 +608,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "2.1.0"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bf4a5a814902cd1014dbccfa4d4560fb8432c779471e96e035602519f82eef"
checksum = "331bb8c3bf9b92457ab7abecf07078c13f7d270ba490103e84e8b014490cd0b0"
dependencies = [
"serde",
"serde_with_macros",
@@ -749,14 +618,14 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "2.2.0"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e"
checksum = "859011bddcc11f289f07f467cc1fe01c7a941daa4d8f6c40d4d1c92eb6d9319c"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@@ -765,9 +634,9 @@ version = "0.1.0"
[[package]]
name = "signal-hook"
version = "0.3.14"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
dependencies = [
"libc",
"signal-hook-registry",
@@ -775,19 +644,13 @@ dependencies = [
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]]
name = "smallvec"
version = "1.10.0"
@@ -802,9 +665,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@@ -812,42 +675,34 @@ dependencies = [
]
[[package]]
name = "termcolor"
version = "1.1.3"
name = "syn"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
checksum = "2c622ae390c9302e214c31013517c2061ecb2699935882c60a9b37f82f8625ae"
dependencies = [
"winapi-util",
]
[[package]]
name = "terminal_size"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907"
dependencies = [
"rustix",
"windows-sys",
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.37"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.37"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.4",
]
[[package]]
@@ -858,6 +713,7 @@ dependencies = [
"byteorder",
"libc",
"log",
"net_gen",
"thiserror",
"vmm-sys-util",
]
@@ -875,24 +731,24 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "uuid"
version = "1.2.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
dependencies = [
"getrandom",
]
[[package]]
name = "versionize"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6e2495726cf917e7ba7ec8bf0f0fceab543dd38d0a4195ed6bef331e38a290f"
checksum = "dca4b7062e7e6d685901e815c35f9671e059de97c1c0905eeff8592f3fff442f"
dependencies = [
"bincode",
"crc64",
@@ -900,7 +756,7 @@ dependencies = [
"quote",
"serde",
"serde_derive",
"syn",
"syn 1.0.109",
"versionize_derive",
"vmm-sys-util",
]
@@ -908,17 +764,17 @@ dependencies = [
[[package]]
name = "versionize_derive"
version = "0.1.4"
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#ae35ef7a3ddabd3371ab8ac0193a383aff6e4b1b"
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#e502b1d4aabab342386f0c53780d49f21a6a1df6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
name = "vfio-bindings"
version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#7ef33f6759ae6d37a54cd66f749aa47c1c81509c"
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
dependencies = [
"vmm-sys-util",
]
@@ -926,7 +782,7 @@ dependencies = [
[[package]]
name = "vfio-ioctls"
version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#7ef33f6759ae6d37a54cd66f749aa47c1c81509c"
source = "git+https://github.com/rust-vmm/vfio?branch=main#43439e056ddfa84a4f7906ee7f2f58be70505c08"
dependencies = [
"byteorder",
"kvm-bindings",
@@ -942,7 +798,9 @@ dependencies = [
[[package]]
name = "vfio_user"
version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#afbbd5722885e961ce12baea12efe01d52ce14b0"
dependencies = [
"bitflags",
"libc",
"log",
"serde",
@@ -985,6 +843,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b"
[[package]]
name = "virtio-bindings"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9084faf91b9aa9676ae2cac8f1432df2839d9566e6f19f29dbc13a8b831dff"
[[package]]
name = "virtio-devices"
version = "0.1.0"
@@ -1010,7 +874,7 @@ dependencies = [
"versionize",
"versionize_derive",
"vhost",
"virtio-bindings",
"virtio-bindings 0.2.0",
"virtio-queue",
"vm-allocator",
"vm-device",
@@ -1022,12 +886,12 @@ dependencies = [
[[package]]
name = "virtio-queue"
version = "0.7.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e927d93d54c365034fd7f31a5f458a1f540de4a37c52e892670dad9692173c"
checksum = "3ba81e2bcc21c0d2fc5e6683e79367e26ad219197423a498df801d79d5ba77bd"
dependencies = [
"log",
"virtio-bindings",
"virtio-bindings 0.1.0",
"vm-memory",
"vmm-sys-util",
]
@@ -1102,7 +966,6 @@ dependencies = [
"arch",
"bitflags",
"block_util",
"clap",
"devices",
"epoll",
"event_monitor",
@@ -1137,13 +1000,14 @@ dependencies = [
"vm-migration",
"vm-virtio",
"vmm-sys-util",
"zerocopy",
]
[[package]]
name = "vmm-sys-util"
version = "0.11.0"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc06a16ee8ebf0d9269aed304030b0d20a866b8b3dd3d4ce532596ac567a0d24"
checksum = "dd64fe09d8e880e600c324e7d664760a17f56e9672b7495a86381b49e4f72f46"
dependencies = [
"bitflags",
"libc",
@@ -1173,15 +1037,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -1189,58 +1044,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
name = "zerocopy"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
name = "zerocopy-derive"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]

View File

@@ -12,19 +12,19 @@ cargo-fuzz = true
block_util = { path = "../block_util" }
devices = { path = "../devices" }
epoll = "4.3.1"
libc = "0.2.138"
libfuzzer-sys = "0.4.5"
libc = "0.2.141"
libfuzzer-sys = "0.4.6"
linux-loader = { version = "0.8.1", features = ["elf", "bzimage", "pe"] }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
net_util = { path = "../net_util" }
once_cell = "1.17.0"
once_cell = "1.17.1"
qcow = { path = "../qcow" }
seccompiler = "0.3.0"
vhdx = { path = "../vhdx" }
virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.7.0"
virtio-queue = "0.7.1"
vmm = { path = "../vmm" }
vmm-sys-util = "0.11.0"
vmm-sys-util = "0.11.1"
vm-memory = "0.10.0"
vm-device = { path = "../vm-device" }
vm-virtio = { path = "../vm-virtio" }

View File

@@ -6,22 +6,22 @@ edition = "2021"
license = "Apache-2.0 OR BSD-3-Clause"
[features]
kvm = ["kvm-ioctls", "kvm-bindings"]
mshv = ["mshv-ioctls", "mshv-bindings"]
kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"]
mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv"]
tdx = []
[dependencies]
anyhow = "1.0.68"
anyhow = "1.0.69"
byteorder = "1.4.3"
thiserror = "1.0.38"
thiserror = "1.0.39"
libc = "0.2.139"
log = "0.4.17"
kvm-ioctls = { version = "0.12.0", optional = true }
kvm-ioctls = { version = "0.13.0", optional = true }
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
serde = { version = "1.0.151", features = ["rc", "derive"] }
serde_with = { version = "2.1.0", default-features = false, features = ["macros"] }
serde_with = { version = "2.3.1", default-features = false, features = ["macros"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }

View File

@@ -15,73 +15,89 @@ use crate::arch::x86::emulator::instructions::*;
use crate::arch::x86::regs::DF;
use crate::arch::x86::Exception;
macro_rules! movs {
($bound:ty) => {
fn emulate(
&self,
insn: &Instruction,
state: &mut T,
platform: &mut dyn PlatformEmulator<CpuState = T>,
) -> Result<(), EmulationError<Exception>> {
let mut count: u64 = if insn.has_rep_prefix() {
state
.read_reg(Register::ECX)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?
} else {
1
};
let mut rsi = state
.read_reg(Register::RSI)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let mut rdi = state
.read_reg(Register::RDI)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let df = (state.flags() & DF) != 0;
let len = std::mem::size_of::<$bound>();
while count > 0 {
let mut memory: [u8; 4] = [0; 4];
let src = state
.linearize(Register::DS, rsi, false)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let dst = state
.linearize(Register::ES, rdi, true)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
platform
.read_memory(src, &mut memory[0..len])
.map_err(EmulationError::PlatformEmulationError)?;
platform
.write_memory(dst, &memory[0..len])
.map_err(EmulationError::PlatformEmulationError)?;
if df {
rsi = rsi.wrapping_sub(len as u64);
rdi = rdi.wrapping_sub(len as u64);
} else {
rsi = rsi.wrapping_add(len as u64);
rdi = rdi.wrapping_add(len as u64);
}
count -= 1;
}
state
.write_reg(Register::RSI, rsi)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
state
.write_reg(Register::RDI, rdi)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
if insn.has_rep_prefix() {
state
.write_reg(Register::ECX, 0)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
}
Ok(())
}
};
}
pub struct Movsd_m32_m32;
impl<T: CpuStateManager> InstructionHandler<T> for Movsd_m32_m32 {
fn emulate(
&self,
insn: &Instruction,
state: &mut T,
platform: &mut dyn PlatformEmulator<CpuState = T>,
) -> Result<(), EmulationError<Exception>> {
let mut count: u64 = if insn.has_rep_prefix() {
state
.read_reg(Register::ECX)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?
} else {
1
};
movs!(u32);
}
let mut rsi = state
.read_reg(Register::RSI)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let mut rdi = state
.read_reg(Register::RDI)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
pub struct Movsw_m16_m16;
impl<T: CpuStateManager> InstructionHandler<T> for Movsw_m16_m16 {
movs!(u16);
}
let df = (state.flags() & DF) != 0;
let len = std::mem::size_of::<u32>();
while count > 0 {
let mut memory: [u8; 4] = [0; 4];
let src = state
.linearize(Register::DS, rsi, false)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
let dst = state
.linearize(Register::ES, rdi, true)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
platform
.read_memory(src, &mut memory[0..len])
.map_err(EmulationError::PlatformEmulationError)?;
platform
.write_memory(dst, &memory[0..len])
.map_err(EmulationError::PlatformEmulationError)?;
if df {
rsi = rsi.wrapping_sub(len as u64);
rdi = rdi.wrapping_sub(len as u64);
} else {
rsi = rsi.wrapping_add(len as u64);
rdi = rdi.wrapping_add(len as u64);
}
count -= 1;
}
state
.write_reg(Register::RSI, rsi)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
state
.write_reg(Register::RDI, rdi)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
if insn.has_rep_prefix() {
state
.write_reg(Register::ECX, 0)
.map_err(|e| EmulationError::InvalidOperand(anyhow!(e)))?;
}
Ok(())
}
pub struct Movsb_m8_m8;
impl<T: CpuStateManager> InstructionHandler<T> for Movsb_m8_m8 {
movs!(u8);
}
#[cfg(test)]
@@ -142,4 +158,127 @@ mod tests {
vmm.read_memory(0x8 + 8, &mut data).unwrap();
assert_eq!(0x0, <u32>::from_le_bytes(data));
}
#[test]
fn test_rep_movsw_m16_m16() {
let ip: u64 = 0x1000;
let memory: [u8; 24] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0xdd, 0xcc, 0xbb, 0xaa, // 0xaabbccdd
0xa5, 0x5a, 0xa5, 0x5a, // 0x5aa55aa5
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0x66, 0xf3, 0xa5]; // rep movsw
let regs = vec![(Register::ECX, 6), (Register::ESI, 0), (Register::EDI, 0xc)];
let mut data = [0u8; 2];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0xc, &mut data).unwrap();
assert_eq!(0x5678, <u16>::from_le_bytes(data));
vmm.read_memory(0xc + 2, &mut data).unwrap();
assert_eq!(0x1234, <u16>::from_le_bytes(data));
vmm.read_memory(0xc + 4, &mut data).unwrap();
assert_eq!(0xccdd, <u16>::from_le_bytes(data));
vmm.read_memory(0xc + 6, &mut data).unwrap();
assert_eq!(0xaabb, <u16>::from_le_bytes(data));
vmm.read_memory(0xc + 8, &mut data).unwrap();
assert_eq!(0x5aa5, <u16>::from_le_bytes(data));
vmm.read_memory(0xc + 10, &mut data).unwrap();
assert_eq!(0x5aa5, <u16>::from_le_bytes(data));
// The rest should be default value 0 from MockVmm
vmm.read_memory(0xc + 12, &mut data).unwrap();
assert_eq!(0x0, <u16>::from_le_bytes(data));
}
#[test]
fn test_movsw_m16_m16() {
let ip: u64 = 0x1000;
let memory: [u8; 4] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
];
let insn = [0x66, 0xa5]; // movsw
let regs = vec![(Register::ESI, 0), (Register::EDI, 0x8)];
let mut data = [0u8; 2];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0x5678, <u16>::from_le_bytes(data));
// Only two bytes were copied, so the value at 0xa should be zero
vmm.read_memory(0xa, &mut data).unwrap();
assert_eq!(0x0, <u16>::from_le_bytes(data));
// The rest should be default value 0 from MockVmm
vmm.read_memory(0x4, &mut data).unwrap();
assert_eq!(0x0, <u16>::from_le_bytes(data));
vmm.read_memory(0x8 + 8, &mut data).unwrap();
assert_eq!(0x0, <u16>::from_le_bytes(data));
}
#[test]
fn test_movsb_m8_m8() {
let ip: u64 = 0x1000;
let memory: [u8; 4] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
];
let insn = [0x66, 0xa4]; // movsb
let regs = vec![(Register::ESI, 0), (Register::EDI, 0x8)];
let mut data = [0u8; 1];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0x78, data[0]);
// Only one byte was copied, so the value at 0x9 should be zero
vmm.read_memory(0x9, &mut data).unwrap();
assert_eq!(0x0, data[0]);
// The rest should be default value 0 from MockVmm
vmm.read_memory(0x4, &mut data).unwrap();
assert_eq!(0x0, data[0]);
// the src value is left as is after movb
vmm.read_memory(0x0, &mut data).unwrap();
assert_eq!(0x78, data[0]);
}
#[test]
fn test_rep_movsb_m8_m8() {
let ip: u64 = 0x1000;
let memory: [u8; 16] = [
0x78, 0x56, 0x34, 0x12, // 0x12345678
0xbb, 0xaa, 0x00, 0x00, // 0x0000aabb
0x00, 0x00, 0x00, 0x00, // 0x00000000
0x00, 0x00, 0x00, 0x00, // 0x00000000
];
let insn = [0x66, 0xf3, 0xa4]; // rep movsw
let regs = vec![(Register::ECX, 6), (Register::ESI, 0), (Register::EDI, 0x8)];
let mut data = [0u8; 1];
let mut vmm = MockVmm::new(ip, regs, Some((0, &memory)));
assert!(vmm.emulate_first_insn(0, &insn).is_ok());
vmm.read_memory(0x8, &mut data).unwrap();
assert_eq!(0x78, data[0]);
vmm.read_memory(0x8 + 1, &mut data).unwrap();
assert_eq!(0x56, data[0]);
vmm.read_memory(0x8 + 2, &mut data).unwrap();
assert_eq!(0x34, data[0]);
vmm.read_memory(0x8 + 3, &mut data).unwrap();
assert_eq!(0x12, data[0]);
vmm.read_memory(0x8 + 4, &mut data).unwrap();
assert_eq!(0xbb, data[0]);
vmm.read_memory(0x8 + 5, &mut data).unwrap();
assert_eq!(0xaa, data[0]);
// The rest should be default value 0 from MockVmm
vmm.read_memory(0x8 + 6, &mut data).unwrap();
assert_eq!(0x0, data[0]);
}
}

View File

@@ -526,6 +526,8 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
(mov, Movzx_r64_rm16),
// MOVS
(movs, Movsd_m32_m32),
(movs, Movsw_m16_m16),
(movs, Movsb_m8_m8),
// OR
(or, Or_rm8_r8)
);

View File

@@ -237,6 +237,12 @@ pub enum HypervisorCpuError {
///
#[error("Failed to initialize PMU")]
InitializePmu,
#[cfg(target_arch = "x86_64")]
///
/// Error getting TSC frequency
///
#[error("Failed to get TSC frequency: {0}")]
GetTscKhz(#[source] anyhow::Error),
}
#[derive(Debug)]
@@ -432,4 +438,11 @@ pub trait Vcpu: Send + Sync {
/// Return the list of initial MSR entries for a VCPU
///
fn boot_msr_entries(&self) -> Vec<MsrEntry>;
#[cfg(target_arch = "x86_64")]
///
/// Get the frequency of the TSC if available
///
fn tsc_khz(&self) -> Result<Option<u32>> {
Ok(None)
}
}

View File

@@ -108,7 +108,7 @@ pub trait Hypervisor: Send + Sync {
///
/// Get the supported CpuID
///
fn get_cpuid(&self) -> Result<Vec<CpuIdEntry>>;
fn get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>;
///
/// Check particular extensions if any
///
@@ -133,4 +133,7 @@ pub trait Hypervisor: Send + Sync {
fn get_guest_debug_hw_bps(&self) -> usize {
unimplemented!()
}
/// Get maximum number of vCPUs
fn get_max_vcpus(&self) -> u32;
}

View File

@@ -106,7 +106,7 @@ pub use {
const KVM_CAP_SGX_ATTRIBUTE: u32 = 196;
#[cfg(feature = "tdx")]
const KVM_EXIT_TDX: u32 = 35;
const KVM_EXIT_TDX: u32 = 50;
#[cfg(feature = "tdx")]
const TDG_VP_VMCALL_GET_QUOTE: u64 = 0x10002;
#[cfg(feature = "tdx")]
@@ -330,21 +330,22 @@ impl KvmVm {
Ok(VfioDeviceFd::new_from_kvm(device_fd))
}
/// Checks if a particular `Cap` is available.
fn check_extension(&self, c: Cap) -> bool {
pub fn check_extension(&self, c: Cap) -> bool {
self.fd.check_extension(c)
}
}
///
/// Implementation of Vm trait for KVM
/// Example:
/// #[cfg(feature = "kvm")]
/// extern crate hypervisor
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// vm.set/get().unwrap()
///
/// # Examples
///
/// ```
/// # use hypervisor::kvm::KvmHypervisor;
/// # use std::sync::Arc;
/// let kvm = KvmHypervisor::new().unwrap();
/// let hypervisor = Arc::new(kvm);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// ```
impl vm::Vm for KvmVm {
#[cfg(target_arch = "x86_64")]
///
@@ -746,36 +747,34 @@ impl vm::Vm for KvmVm {
///
#[cfg(feature = "tdx")]
fn tdx_init(&self, cpuid: &[CpuIdEntry], max_vcpus: u32) -> vm::Result<()> {
use std::io::{Error, ErrorKind};
let cpuid: Vec<kvm_bindings::kvm_cpuid_entry2> =
const TDX_ATTR_SEPT_VE_DISABLE: usize = 28;
let mut cpuid: Vec<kvm_bindings::kvm_cpuid_entry2> =
cpuid.iter().map(|e| (*e).into()).collect();
let kvm_cpuid = kvm_bindings::CpuId::from_entries(&cpuid).map_err(|_| {
vm::HypervisorVmError::InitializeTdx(Error::new(
ErrorKind::Other,
"failed to allocate CpuId",
))
})?;
cpuid.resize(256, kvm_bindings::kvm_cpuid_entry2::default());
#[repr(C)]
struct TdxInitVm {
max_vcpus: u32,
tsc_khz: u32,
attributes: u64,
cpuid: u64,
max_vcpus: u32,
padding: u32,
mrconfigid: [u64; 6],
mrowner: [u64; 6],
mrownerconfig: [u64; 6],
reserved: [u64; 43],
cpuid_nent: u32,
cpuid_padding: u32,
cpuid_entries: [kvm_bindings::kvm_cpuid_entry2; 256],
}
let data = TdxInitVm {
attributes: 1 << TDX_ATTR_SEPT_VE_DISABLE,
max_vcpus,
tsc_khz: 0,
attributes: 0,
cpuid: kvm_cpuid.as_fam_struct_ptr() as u64,
padding: 0,
mrconfigid: [0; 6],
mrowner: [0; 6],
mrownerconfig: [0; 6],
reserved: [0; 43],
cpuid_nent: cpuid.len() as u32,
cpuid_padding: 0,
cpuid_entries: cpuid.as_slice().try_into().unwrap(),
};
tdx_command(
@@ -837,19 +836,23 @@ impl vm::Vm for KvmVm {
fn tdx_command(
fd: &RawFd,
command: TdxCommand,
metadata: u32,
flags: u32,
data: u64,
) -> std::result::Result<(), std::io::Error> {
#[repr(C)]
struct TdxIoctlCmd {
command: TdxCommand,
metadata: u32,
flags: u32,
data: u64,
error: u64,
unused: u64,
}
let cmd = TdxIoctlCmd {
command,
metadata,
flags,
data,
error: 0,
unused: 0,
};
// SAFETY: FFI call. All input parameters are valid.
let ret = unsafe {
@@ -915,13 +918,16 @@ impl KvmHypervisor {
}
}
/// Implementation of Hypervisor trait for KVM
/// Example:
/// #[cfg(feature = "kvm")]
/// extern crate hypervisor
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
///
/// # Examples
///
/// ```
/// # use hypervisor::kvm::KvmHypervisor;
/// # use std::sync::Arc;
/// let kvm = KvmHypervisor::new().unwrap();
/// let hypervisor = Arc::new(kvm);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// ```
impl hypervisor::Hypervisor for KvmHypervisor {
///
/// Returns the type of the hypervisor
@@ -930,13 +936,15 @@ impl hypervisor::Hypervisor for KvmHypervisor {
HypervisorType::Kvm
}
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object
/// Example
/// # extern crate hypervisor;
/// # use hypervisor::KvmHypervisor;
/// use hypervisor::KvmVm;
/// let hypervisor = KvmHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm_with_type(KvmVmType::LegacyVm).unwrap()
///
/// # Examples
///
/// ```
/// # use hypervisor::kvm::KvmHypervisor;
/// use hypervisor::kvm::KvmVm;
/// let hypervisor = KvmHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm_with_type(0).unwrap();
/// ```
fn create_vm_with_type(&self, vm_type: u64) -> hypervisor::Result<Arc<dyn vm::Vm>> {
let fd: VmFd;
loop {
@@ -990,13 +998,15 @@ impl hypervisor::Hypervisor for KvmHypervisor {
}
/// Create a KVM vm object and return the object as Vm trait object
/// Example
/// # extern crate hypervisor;
/// # use hypervisor::KvmHypervisor;
/// use hypervisor::KvmVm;
/// let hypervisor = KvmHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm().unwrap()
///
/// # Examples
///
/// ```
/// # use hypervisor::kvm::KvmHypervisor;
/// use hypervisor::kvm::KvmVm;
/// let hypervisor = KvmHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm().unwrap();
/// ```
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
#[allow(unused_mut)]
let mut vm_type: u64 = 0; // Create with default platform type
@@ -1021,7 +1031,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
///
/// X86 specific call to get the system supported CPUID values.
///
fn get_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
let kvm_cpuid = self
.kvm
.get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
@@ -1074,6 +1084,11 @@ impl hypervisor::Hypervisor for KvmHypervisor {
self.kvm.get_guest_debug_hw_bps() as usize
}
}
/// Get maximum number of vCPUs
fn get_max_vcpus(&self) -> u32 {
self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32
}
}
/// Vcpu struct for KVM
pub struct KvmVcpu {
@@ -1085,15 +1100,17 @@ pub struct KvmVcpu {
hyperv_synic: AtomicBool,
}
/// Implementation of Vcpu trait for KVM
/// Example:
/// #[cfg(feature = "kvm")]
/// extern crate hypervisor
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
///
/// # Examples
///
/// ```
/// # use hypervisor::kvm::KvmHypervisor;
/// # use std::sync::Arc;
/// let kvm = KvmHypervisor::new().unwrap();
/// let hypervisor = Arc::new(kvm);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// let vcpu = vm.create_vcpu(0, None).unwrap();
/// vcpu.get/set().unwrap()
///
/// ```
impl cpu::Vcpu for KvmVcpu {
#[cfg(target_arch = "x86_64")]
///
@@ -1795,11 +1812,10 @@ impl cpu::Vcpu for KvmVcpu {
/// # Example
///
/// ```rust
/// # extern crate hypervisor;
/// # use hypervisor::KvmHypervisor;
/// # use hypervisor::kvm::KvmHypervisor;
/// # use std::sync::Arc;
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
/// let kvm = KvmHypervisor::new().unwrap();
/// let hv = Arc::new(kvm);
/// let vm = hv.create_vm().expect("new VM fd creation failed");
/// vm.enable_split_irq().unwrap();
/// let vcpu = vm.create_vcpu(0, None).unwrap();
@@ -1967,11 +1983,10 @@ impl cpu::Vcpu for KvmVcpu {
/// # Example
///
/// ```rust
/// # extern crate hypervisor;
/// # use hypervisor::KvmHypervisor;
/// # use hypervisor::kvm::KvmHypervisor;
/// # use std::sync::Arc;
/// let kvm = hypervisor::kvm::KvmHypervisor::new().unwrap();
/// let hv: Arc<dyn hypervisor::Hypervisor> = Arc::new(kvm);
/// let kvm = KvmHypervisor::new().unwrap();
/// let hv = Arc::new(kvm);
/// let vm = hv.create_vm().expect("new VM fd creation failed");
/// vm.enable_split_irq().unwrap();
/// let vcpu = vm.create_vcpu(0, None).unwrap();
@@ -2154,6 +2169,23 @@ impl cpu::Vcpu for KvmVcpu {
.set_device_attr(&cpu_attr)
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)
}
#[cfg(target_arch = "x86_64")]
///
/// Get the frequency of the TSC if available
///
fn tsc_khz(&self) -> cpu::Result<Option<u32>> {
match self.fd.get_tsc_khz() {
Err(e) => {
if e.errno() == libc::EIO {
Ok(None)
} else {
Err(cpu::HypervisorCpuError::GetTscKhz(e.into()))
}
}
Ok(v) => Ok(Some(v)),
}
}
}
impl KvmVcpu {

View File

@@ -50,6 +50,9 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
if !kvm.check_extension(Cap::ImmediateExit) {
return Err(KvmError::CapabilityMissing(Cap::ImmediateExit));
}
if !kvm.check_extension(Cap::GetTscKhz) {
return Err(KvmError::CapabilityMissing(Cap::GetTscKhz));
}
Ok(())
}
#[derive(Clone, Serialize, Deserialize)]

View File

@@ -48,9 +48,9 @@ mod cpu;
/// Device related module
mod device;
pub use crate::hypervisor::{Hypervisor, HypervisorError};
pub use cpu::{HypervisorCpuError, Vcpu, VmExit};
pub use device::HypervisorDeviceError;
pub use hypervisor::{Hypervisor, HypervisorError};
#[cfg(all(feature = "kvm", target_arch = "aarch64"))]
pub use kvm::{aarch64, GicState};
use std::sync::Arc;

View File

@@ -195,13 +195,16 @@ impl MshvHypervisor {
}
}
/// Implementation of Hypervisor trait for Mshv
/// Example:
/// #[cfg(feature = "mshv")]
/// extern crate hypervisor
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
///
/// # Examples
///
/// ```
/// # use hypervisor::mshv::MshvHypervisor;
/// # use std::sync::Arc;
/// let mshv = MshvHypervisor::new().unwrap();
/// let hypervisor = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// ```
impl hypervisor::Hypervisor for MshvHypervisor {
///
/// Returns the type of the hypervisor
@@ -210,13 +213,16 @@ impl hypervisor::Hypervisor for MshvHypervisor {
HypervisorType::Mshv
}
/// Create a mshv vm object and return the object as Vm trait object
/// Example
/// # extern crate hypervisor;
/// # use hypervisor::MshvHypervisor;
/// use hypervisor::MshvVm;
/// let hypervisor = MshvHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm().unwrap()
///
/// # Examples
///
/// ```
/// # extern crate hypervisor;
/// # use hypervisor::mshv::MshvHypervisor;
/// use hypervisor::mshv::MshvVm;
/// let hypervisor = MshvHypervisor::new().unwrap();
/// let vm = hypervisor.create_vm().unwrap();
/// ```
fn create_vm(&self) -> hypervisor::Result<Arc<dyn vm::Vm>> {
let fd: VmFd;
loop {
@@ -270,9 +276,16 @@ impl hypervisor::Hypervisor for MshvHypervisor {
///
/// Get the supported CpuID
///
fn get_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
fn get_supported_cpuid(&self) -> hypervisor::Result<Vec<CpuIdEntry>> {
Ok(Vec::new())
}
/// Get maximum number of vCPUs
fn get_max_vcpus(&self) -> u32 {
// TODO: Using HV_MAXIMUM_PROCESSORS would be better
// but the ioctl API is limited to u8
256
}
}
/// Vcpu struct for Microsoft Hypervisor
@@ -285,15 +298,17 @@ pub struct MshvVcpu {
}
/// Implementation of Vcpu trait for Microsoft Hypervisor
/// Example:
/// #[cfg(feature = "mshv")]
/// extern crate hypervisor
/// let mshv = hypervisor::mshv::MshvHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// let vcpu = vm.create_vcpu(0).unwrap();
/// vcpu.get/set().unwrap()
///
/// # Examples
///
/// ```
/// # use hypervisor::mshv::MshvHypervisor;
/// # use std::sync::Arc;
/// let mshv = MshvHypervisor::new().unwrap();
/// let hypervisor = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// let vcpu = vm.create_vcpu(0, None).unwrap();
/// ```
impl cpu::Vcpu for MshvVcpu {
#[cfg(target_arch = "x86_64")]
///
@@ -568,8 +583,14 @@ impl cpu::Vcpu for MshvVcpu {
///
/// X86 specific call to setup the CPUID registers.
///
fn set_cpuid2(&self, _cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
Ok(())
fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> cpu::Result<()> {
let cpuid: Vec<mshv_bindings::hv_cpuid_entry> = cpuid.iter().map(|e| (*e).into()).collect();
let mshv_cpuid = <CpuId>::from_entries(&cpuid)
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
self.fd
.register_intercept_result_cpuid(&mshv_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
}
#[cfg(target_arch = "x86_64")]
///
@@ -917,15 +938,17 @@ impl MshvVm {
///
/// Implementation of Vm trait for Mshv
/// Example:
/// #[cfg(feature = "mshv")]
/// # extern crate hypervisor;
/// # use hypervisor::MshvHypervisor;
/// let mshv = MshvHypervisor::new().unwrap();
/// let hypervisor: Arc<dyn hypervisor::Hypervisor> = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// vm.set/get().unwrap()
///
/// # Examples
///
/// ```
/// # extern crate hypervisor;
/// # use hypervisor::mshv::MshvHypervisor;
/// # use std::sync::Arc;
/// let mshv = MshvHypervisor::new().unwrap();
/// let hypervisor = Arc::new(mshv);
/// let vm = hypervisor.create_vm().expect("new VM fd creation failed");
/// ```
impl vm::Vm for MshvVm {
#[cfg(target_arch = "x86_64")]
///

View File

@@ -28,10 +28,12 @@ pub mod inn;
// generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust
// --constified-enum '*' --with-derive-default
pub mod sockios;
pub use if_tun::*;
pub use iff::*;
pub use inn::*;
pub use sockios::*;
pub use if_tun::{
sock_fprog, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_TAP, IFF_VNET_HDR, TUN_F_CSUM, TUN_F_TSO4,
TUN_F_TSO6, TUN_F_TSO_ECN, TUN_F_UFO,
};
pub use iff::{ifreq, net_device_flags_IFF_UP, setsockopt, sockaddr, AF_INET};
pub use inn::sockaddr_in;
pub const TUNTAP: ::std::os::raw::c_uint = 84;

View File

@@ -12,17 +12,17 @@ log = "0.4.17"
net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" }
serde = "1.0.151"
thiserror = "1.0.38"
versionize = "0.1.9"
thiserror = "1.0.39"
versionize = "0.1.10"
versionize_derive = "0.1.4"
virtio-bindings = "0.1.0"
virtio-queue = "0.7.0"
virtio-bindings = "0.2.0"
virtio-queue = "0.7.1"
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.11.0"
[dev-dependencies]
once_cell = "1.16.0"
pnet = "0.31.0"
pnet_datalink = "0.31.0"
serde_json = "1.0.89"
once_cell = "1.17.1"
pnet = "0.33.0"
pnet_datalink = "0.33.0"
serde_json = "1.0.95"

View File

@@ -6,7 +6,7 @@ use crate::GuestMemoryMmap;
use crate::Tap;
use libc::c_uint;
use std::sync::Arc;
use virtio_bindings::bindings::virtio_net::{
use virtio_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,

View File

@@ -21,7 +21,7 @@ use std::{io, mem, net};
use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_bindings::bindings::virtio_net::{
use virtio_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,

View File

@@ -10,20 +10,21 @@ kvm = ["vfio-ioctls/kvm"]
mshv = ["vfio-ioctls/mshv"]
[dependencies]
anyhow = "1.0.68"
anyhow = "1.0.69"
byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" }
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vfio_user = { path = "../vfio_user" }
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
vmm-sys-util = "0.11.0"
libc = "0.2.139"
log = "0.4.17"
serde = { version = "1.0.151", features = ["derive"] }
thiserror = "1.0.38"
versionize = "0.1.9"
thiserror = "1.0.39"
versionize = "0.1.10"
versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" }
vm-memory = "0.10.0"
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" }

View File

@@ -511,6 +511,16 @@ impl MsixCap {
self.pba & 0xffff_fff8
}
pub fn table_set_offset(&mut self, addr: u32) {
self.table &= 0x7;
self.table += addr;
}
pub fn pba_set_offset(&mut self, addr: u32) {
self.pba &= 0x7;
self.pba += addr;
}
pub fn table_bir(&self) -> u32 {
self.table & 0x7
}

View File

@@ -14,6 +14,7 @@ use crate::{
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use hypervisor::HypervisorVmError;
use libc::{sysconf, _SC_PAGESIZE};
use std::any::Any;
use std::collections::{BTreeMap, HashMap};
use std::io;
@@ -27,6 +28,9 @@ use vfio_bindings::bindings::vfio::*;
use vfio_ioctls::{
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
};
use vm_allocator::page_size::{
align_page_size_down, align_page_size_up, is_4k_aligned, is_4k_multiple, is_page_size_aligned,
};
use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
@@ -498,6 +502,29 @@ impl VfioCommon {
Ok(vfio_common)
}
/// In case msix table offset is not page size aligned, we need do some fixup to achive it.
/// Becuse we don't want the MMIO RW region and trap region overlap each other.
fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
let msix = self.interrupt.msix.as_mut().unwrap();
let msix_cap = &mut msix.cap;
// Suppose table_bir equals to pba_bir here. Am I right?
let (table_offset, table_size) = msix_cap.table_range();
if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id {
return region_size;
}
let (pba_offset, pba_size) = msix_cap.pba_range();
let msix_sz = align_page_size_up(table_size + pba_size);
// Expand region to hold RW and trap region which both page size aligned
let size = std::cmp::max(region_size * 2, msix_sz * 2);
// let table starts from the middle of the region
msix_cap.table_set_offset((size / 2) as u32);
msix_cap.pba_set_offset((size / 2 + pba_offset - table_offset) as u32);
size
}
pub(crate) fn allocate_bars(
&mut self,
allocator: &Arc<Mutex<SystemAllocator>>,
@@ -661,9 +688,16 @@ impl VfioCommon {
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
}
PciBarRegionType::Memory64BitRegion => {
// BAR allocation must be naturally aligned
// We need do some fixup to keep MMIO RW region and msix cap region page size
// aligned.
region_size = self.fixup_msix_region(bar_id, region_size);
mmio_allocator
.allocate(restored_bar_addr, region_size, Some(region_size))
.allocate(
restored_bar_addr,
region_size,
// SAFETY: FFI call. Trivially safe.
Some(unsafe { sysconf(_SC_PAGESIZE) as GuestUsize }),
)
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?
}
};
@@ -800,6 +834,23 @@ impl VfioCommon {
});
}
pub(crate) fn get_msix_cap_idx(&self) -> Option<usize> {
let mut cap_next = self
.vfio_wrapper
.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
while cap_next != 0 {
let cap_id = self.vfio_wrapper.read_config_byte(cap_next.into());
if PciCapabilityId::from(cap_id) == PciCapabilityId::MsiX {
return Some(cap_next as usize);
} else {
cap_next = self.vfio_wrapper.read_config_byte((cap_next + 1).into());
}
}
None
}
pub(crate) fn parse_capabilities(&mut self, bdf: PciBdf) {
let mut cap_next = self
.vfio_wrapper
@@ -1154,6 +1205,15 @@ impl VfioCommon {
return self.configuration.read_reg(reg_idx);
}
if let Some(id) = self.get_msix_cap_idx() {
let msix = self.interrupt.msix.as_mut().unwrap();
if reg_idx * 4 == id + 4 {
return msix.cap.table;
} else if reg_idx * 4 == id + 8 {
return msix.cap.pba;
}
}
// Since we don't support passing multi-functions devices, we should
// mask the multi-function bit, bit 7 of the Header Type byte on the
// register 3.
@@ -1316,18 +1376,6 @@ impl VfioPciDevice {
self.iommu_attached
}
fn align_4k(address: u64) -> u64 {
(address + 0xfff) & 0xffff_ffff_ffff_f000
}
fn is_4k_aligned(address: u64) -> bool {
(address & 0xfff) == 0
}
fn is_4k_multiple(size: u64) -> bool {
(size & 0xfff) == 0
}
fn generate_sparse_areas(
caps: &[VfioRegionInfoCap],
region_index: u32,
@@ -1339,14 +1387,14 @@ impl VfioPciDevice {
match cap {
VfioRegionInfoCap::SparseMmap(sparse_mmap) => return Ok(sparse_mmap.areas.clone()),
VfioRegionInfoCap::MsixMappable => {
if !Self::is_4k_aligned(region_start) {
if !is_4k_aligned(region_start) {
error!(
"Region start address 0x{:x} must be at least aligned on 4KiB",
region_start
);
return Err(VfioPciError::RegionAlignment);
}
if !Self::is_4k_multiple(region_size) {
if !is_4k_multiple(region_size) {
error!(
"Region size 0x{:x} must be at least a multiple of 4KiB",
region_size
@@ -1358,7 +1406,8 @@ impl VfioPciDevice {
// the MSI-X PBA table, we must calculate the subregions
// around them, leading to a list of sparse areas.
// We want to make sure we will still trap MMIO accesses
// to these MSI-X specific ranges.
// to these MSI-X specific ranges. If these region don't align
// with pagesize, we can achive it by enlarging its range.
//
// Using a BtreeMap as the list provided through the iterator is sorted
// by key. This ensures proper split of the whole region.
@@ -1366,10 +1415,14 @@ impl VfioPciDevice {
if let Some(msix) = vfio_msix {
if region_index == msix.cap.table_bir() {
let (offset, size) = msix.cap.table_range();
let offset = align_page_size_down(offset);
let size = align_page_size_up(size);
inter_ranges.insert(offset, size);
}
if region_index == msix.cap.pba_bir() {
let (offset, size) = msix.cap.pba_range();
let offset = align_page_size_down(offset);
let size = align_page_size_up(size);
inter_ranges.insert(offset, size);
}
}
@@ -1383,8 +1436,7 @@ impl VfioPciDevice {
size: range_offset - current_offset,
});
}
current_offset = Self::align_4k(range_offset + range_size);
current_offset = align_page_size_down(range_offset + range_size);
}
if region_size > current_offset {
@@ -1482,6 +1534,15 @@ impl VfioPciDevice {
return Err(VfioPciError::MmapArea);
}
if !is_page_size_aligned(area.size) || !is_page_size_aligned(area.offset) {
warn!(
"Could not mmap sparse area that is not page size aligned (offset = 0x{:x}, size = 0x{:x})",
area.offset,
area.size,
);
return Ok(());
}
let user_memory_region = UserMemoryRegion {
slot: (self.memory_slot)(),
start: region.start.0 + area.offset,

View File

@@ -3,13 +3,13 @@ name = "performance-metrics"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
build = "build.rs"
build = "../build.rs"
[dependencies]
clap = { version = "4.0.32", features = ["wrap_help"] }
argh = "0.1.9"
dirs = "4.0.0"
serde = { version = "1.0.151", features = ["rc", "derive"] }
serde_json = "1.0.89"
serde_json = "1.0.95"
test_infra = { path = "../test_infra" }
thiserror = "1.0.38"
thiserror = "1.0.39"
wait-timeout = "0.2.0"

View File

@@ -1,24 +0,0 @@
// Copyright © 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
use std::process::Command;
fn main() {
let mut git_human_readable = "v".to_owned() + env!("CARGO_PKG_VERSION");
if let Ok(git_out) = Command::new("git").args(["describe", "--dirty"]).output() {
if git_out.status.success() {
if let Ok(git_out_str) = String::from_utf8(git_out.stdout) {
git_human_readable = git_out_str;
}
}
}
// This println!() has a special behavior, as it will set the environment
// variable GIT_HUMAN_READABLE, so that it can be reused from the binary.
// Particularly, this is used from the main.rs to display the exact
// version information.
println!("cargo:rustc-env=GIT_HUMAN_READABLE={git_human_readable}");
}

View File

@@ -8,11 +8,11 @@ extern crate test_infra;
mod performance_tests;
use clap::{Arg, ArgAction, Command as ClapCommand};
use argh::FromArgs;
use performance_tests::*;
use serde::{Deserialize, Serialize};
use std::{
env, fmt,
fmt,
process::Command,
sync::{mpsc::channel, Arc},
thread,
@@ -110,18 +110,23 @@ impl Default for MetricsReport {
#[derive(Default)]
pub struct PerformanceTestOverrides {
test_iterations: Option<u32>,
test_timeout: Option<u32>,
}
impl fmt::Display for PerformanceTestOverrides {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(test_iterations) = self.test_iterations {
write!(f, "test_iterations = {test_iterations}")?;
write!(f, "test_iterations = {test_iterations}, ")?;
}
if let Some(test_timeout) = self.test_timeout {
write!(f, "test_timeout = {test_timeout}")?;
}
Ok(())
}
}
#[derive(Clone)]
pub struct PerformanceTestControl {
test_timeout: u32,
test_iterations: u32,
@@ -188,7 +193,14 @@ impl PerformanceTest {
.test_iterations
.unwrap_or(self.control.test_iterations)
{
metrics.push((self.func_ptr)(&self.control));
// update the timeout in control if passed explicitly and run testcase with it
if let Some(test_timeout) = overrides.test_timeout {
let mut control: PerformanceTestControl = self.control.clone();
control.test_timeout = test_timeout;
metrics.push((self.func_ptr)(&control));
} else {
metrics.push((self.func_ptr)(&self.control));
}
}
let mean = (self.unit_adjuster)(mean(&metrics).unwrap());
@@ -207,9 +219,9 @@ impl PerformanceTest {
// Calculate the timeout for each test
// Note: To cover the setup/cleanup time, 20s is added for each iteration of the test
pub fn calc_timeout(&self, test_iterations: &Option<u32>) -> u64 {
((self.control.test_timeout + 20) * test_iterations.unwrap_or(self.control.test_iterations))
as u64
pub fn calc_timeout(&self, test_iterations: &Option<u32>, test_timeout: &Option<u32>) -> u64 {
((test_timeout.unwrap_or(self.control.test_timeout) + 20)
* test_iterations.unwrap_or(self.control.test_iterations)) as u64
}
}
@@ -587,6 +599,7 @@ fn run_test_with_timeout(
) -> Result<PerformanceTestResult, Error> {
let (sender, receiver) = channel::<Result<PerformanceTestResult, Error>>();
let test_iterations = overrides.test_iterations;
let test_timeout = overrides.test_timeout;
let overrides = overrides.clone();
thread::spawn(move || {
println!(
@@ -609,7 +622,7 @@ fn run_test_with_timeout(
});
// Todo: Need to cleanup/kill all hanging child processes
let test_timeout = test.calc_timeout(&test_iterations);
let test_timeout = test.calc_timeout(&test_iterations, &test_timeout);
receiver
.recv_timeout(Duration::from_secs(test_timeout))
.map_err(|_| {
@@ -626,39 +639,41 @@ fn date() -> String {
String::from_utf8_lossy(&output.stdout).trim().to_string()
}
#[derive(FromArgs)]
/// Generate the performance metrics data for Cloud Hypervisor
struct Options {
#[argh(switch, long = "list-tests")]
/// print the list of available metrics tests
list_tests: bool,
#[argh(option, long = "test-filter")]
/// filter metrics tests to run based on provided keywords
keywords: Vec<String>,
#[argh(option, long = "report-file")]
/// report file. Stderr is used if not specified
report_file: Option<String>,
#[argh(option, long = "iterations")]
/// override number of test iterations
iterations: Option<u32>,
#[argh(option, long = "timeout")]
/// override test timeout, Ex. --timeout 5
timeout: Option<u32>,
#[argh(switch, short = 'V', long = "version")]
/// print version information
version: bool,
}
fn main() {
let cmd_arguments = ClapCommand::new("performance-metrics")
.version(env!("GIT_HUMAN_READABLE"))
.author(env!("CARGO_PKG_AUTHORS"))
.about("Generate the performance metrics data for Cloud Hypervisor")
.arg(
Arg::new("test-filter")
.long("test-filter")
.help("Filter metrics tests to run based on provided keywords")
.num_args(1)
.required(false),
)
.arg(
Arg::new("list-tests")
.long("list-tests")
.help("Print the list of availale metrics tests")
.num_args(0)
.action(ArgAction::SetTrue)
.required(false),
)
.arg(
Arg::new("report-file")
.long("report-file")
.help("Report file. Standard error is used if not specified")
.num_args(1),
)
.arg(
Arg::new("iterations")
.long("iterations")
.help("Override number of test iterations")
.num_args(1),
)
.get_matches();
let opts: Options = argh::from_env();
if opts.version {
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
return;
}
// It seems that the tool (ethr) used for testing the virtio-net latency
// is not stable on AArch64, and therefore the latency test is currently
@@ -668,7 +683,7 @@ fn main() {
.filter(|t| !(cfg!(target_arch = "aarch64") && t.name == "virtio_net_latency_us"))
.collect();
if cmd_arguments.get_flag("list-tests") {
if opts.list_tests {
for test in test_list.iter() {
println!("\"{}\" ({})", test.name, test.control);
}
@@ -676,10 +691,7 @@ fn main() {
return;
}
let test_filter = match cmd_arguments.get_many::<String>("test-filter") {
Some(s) => s.collect(),
None => Vec::new(),
};
let test_filter = opts.keywords.iter().collect::<Vec<&String>>();
// Run performance tests sequentially and report results (in both readable/json format)
let mut metrics_report: MetricsReport = Default::default();
@@ -687,11 +699,8 @@ fn main() {
init_tests();
let overrides = Arc::new(PerformanceTestOverrides {
test_iterations: cmd_arguments
.get_one::<String>("iterations")
.map(|s| s.parse())
.transpose()
.unwrap_or_default(),
test_iterations: opts.iterations,
test_timeout: opts.timeout,
});
for test in test_list.iter() {
@@ -710,19 +719,18 @@ fn main() {
cleanup_tests();
let mut report_file: Box<dyn std::io::Write + Send> =
if let Some(file) = cmd_arguments.get_one::<String>("report-file") {
Box::new(
std::fs::File::create(std::path::Path::new(file))
.map_err(|e| {
eprintln!("Error opening report file: {file}: {e}");
std::process::exit(1);
})
.unwrap(),
)
} else {
Box::new(std::io::stdout())
};
let mut report_file: Box<dyn std::io::Write + Send> = if let Some(ref file) = opts.report_file {
Box::new(
std::fs::File::create(std::path::Path::new(file))
.map_err(|e| {
eprintln!("Error opening report file: {file}: {e}");
std::process::exit(1);
})
.unwrap(),
)
} else {
Box::new(std::io::stdout())
};
report_file
.write_all(

View File

@@ -168,7 +168,6 @@ fn parse_boot_time_output(output: &[u8]) -> Result<f64, Error> {
std::panic::catch_unwind(|| {
let l: Vec<String> = String::from_utf8_lossy(output)
.lines()
.into_iter()
.filter(|l| l.contains("Debug I/O port: Kernel code"))
.map(|l| l.to_string())
.collect();
@@ -359,11 +358,13 @@ pub fn performance_block_io(control: &PerformanceTestControl) -> f64 {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={BLK_IO_TEST_IMG}").as_str(),
])
.default_net()

View File

@@ -66,7 +66,7 @@ impl QcowRawFile {
non_zero_flags: u64,
) -> io::Result<()> {
self.file.seek(SeekFrom::Start(offset))?;
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u64>(), &mut self.file);
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
for addr in table {
let val = if *addr == 0 {
0
@@ -91,7 +91,7 @@ impl QcowRawFile {
/// Writes a refcount block to the file.
pub fn write_refcount_block(&mut self, offset: u64, table: &[u16]) -> io::Result<()> {
self.file.seek(SeekFrom::Start(offset))?;
let mut buffer = BufWriter::with_capacity(table.len() * size_of::<u16>(), &mut self.file);
let mut buffer = BufWriter::with_capacity(std::mem::size_of_val(table), &mut self.file);
for count in table {
buffer.write_u16::<BigEndian>(*count)?;
}

View File

@@ -1,3 +1,21 @@
- [v31.2](#v312)
- [v31.1](#v311)
- [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
- [Update Reference Kernel to 6.2](#update-reference-kernel-to-62)
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
- [Documentation Improvements](#documentation-improvements)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors)
- [v30.0](#v300)
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
- [Heap Profiling Support](#heap-profiling-support)
- [Documentation Improvements](#documentation-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-1)
- [v28.2](#v282)
- [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
- [Snapshot/Restore and Live Migration Improvements](#snapshotrestore-and-live-migration-improvements)
@@ -6,10 +24,10 @@
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
- [TCP Offload Control](#tcp-offload-control)
- [Notable Bug Fixes](#notable-bug-fixes)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Removals](#removals)
- [Deprecations](#deprecations)
- [Contributors](#contributors)
- [Contributors](#contributors-2)
- [v28.1](#v281)
- [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder)
@@ -17,9 +35,9 @@
- [Virtualised TPM Support](#virtualised-tpm-support)
- [Transparent Huge Page Support](#transparent-huge-page-support)
- [README Quick Start Improved](#readme-quick-start-improved)
- [Notable Bug Fixes](#notable-bug-fixes-1)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Removals](#removals-1)
- [Contributors](#contributors-1)
- [Contributors](#contributors-3)
- [v27.0](#v270)
- [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages)
@@ -28,41 +46,41 @@
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
- [GDB Support for AArch64](#gdb-support-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-2)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Deprecations](#deprecations-1)
- [Contributors](#contributors-2)
- [Contributors](#contributors-4)
- [v26.0](#v260)
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
- [Notable Bug Fixes](#notable-bug-fixes-3)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Deprecations](#deprecations-2)
- [Removals](#removals-2)
- [Contributors](#contributors-3)
- [Contributors](#contributors-5)
- [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-4)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Removals](#removals-3)
- [Contributors](#contributors-4)
- [Contributors](#contributors-6)
- [v24.0](#v240)
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
- [Sparse Mmap support](#sparse-mmap-support)
- [Expose Platform Serial Number](#expose-platform-serial-number)
- [Notable Bug Fixes](#notable-bug-fixes-5)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website)
- [Contributors](#contributors-5)
- [Contributors](#contributors-7)
- [v23.1](#v231)
- [v23.0](#v230)
- [vDPA Support](#vdpa-support)
- [Updated OS Support list](#updated-os-support-list)
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
- [`AMX` Support](#amx-support)
- [Notable Bug Fixes](#notable-bug-fixes-6)
- [Notable Bug Fixes](#notable-bug-fixes-8)
- [Deprecations](#deprecations-4)
- [Contributors](#contributors-6)
- [Contributors](#contributors-8)
- [v22.1](#v221)
- [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support)
@@ -73,13 +91,13 @@
- [PMU Support for AArch64](#pmu-support-for-aarch64)
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
- [Notable Bug Fixes](#notable-bug-fixes-7)
- [Contributors](#contributors-7)
- [Notable Bug Fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [v21.0](#v210)
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
- [Notable Bug fixes](#notable-bug-fixes-8)
- [Contributors](#contributors-8)
- [Notable Bug fixes](#notable-bug-fixes-10)
- [Contributors](#contributors-10)
- [v20.2](#v202)
- [v20.1](#v201)
- [v20.0](#v200)
@@ -88,8 +106,8 @@
- [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code)
- [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-9)
- [Contributors](#contributors-9)
- [Notable bug fixes](#notable-bug-fixes-11)
- [Contributors](#contributors-11)
- [v19.0](#v190)
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
- [PCI boot time optimisations](#pci-boot-time-optimisations)
@@ -97,8 +115,8 @@
- [Live migration enhancements](#live-migration-enhancements)
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
- [Notable bug fixes](#notable-bug-fixes-10)
- [Contributors](#contributors-10)
- [Notable bug fixes](#notable-bug-fixes-12)
- [Contributors](#contributors-12)
- [v18.0](#v180)
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
@@ -108,23 +126,23 @@
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
- [Power button support on AArch64](#power-button-support-on-aarch64)
- [Notable bug fixes](#notable-bug-fixes-11)
- [Contributors](#contributors-11)
- [Notable bug fixes](#notable-bug-fixes-13)
- [Contributors](#contributors-13)
- [v17.0](#v170)
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
- [Improved SGX support](#improved-sgx-support)
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
- [Notable bug fixes](#notable-bug-fixes-12)
- [Contributors](#contributors-12)
- [Notable bug fixes](#notable-bug-fixes-14)
- [Contributors](#contributors-14)
- [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-13)
- [Notable bug fixes](#notable-bug-fixes-15)
- [Removed functionality](#removed-functionality)
- [Contributors](#contributors-13)
- [Contributors](#contributors-15)
- [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting)
@@ -132,7 +150,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5)
- [Contributors](#contributors-14)
- [Contributors](#contributors-16)
- [v0.14.1](#v0141)
- [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring)
@@ -142,7 +160,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-6)
- [Contributors](#contributors-15)
- [Contributors](#contributors-17)
- [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support)
@@ -150,13 +168,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-16)
- [Contributors](#contributors-18)
- [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-17)
- [Contributors](#contributors-19)
- [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)
@@ -168,15 +186,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-14)
- [Contributors](#contributors-18)
- [Notable Bug Fixes](#notable-bug-fixes-16)
- [Contributors](#contributors-20)
- [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-15)
- [Contributors](#contributors-19)
- [Notable Bug Fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-21)
- [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)
@@ -189,17 +207,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-16)
- [Contributors](#contributors-20)
- [Notable Bug Fixes](#notable-bug-fixes-18)
- [Contributors](#contributors-22)
- [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-17)
- [Notable Bug Fixes](#notable-bug-fixes-19)
- [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-21)
- [Contributors](#contributors-23)
- [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)
@@ -209,14 +227,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-22)
- [Contributors](#contributors-24)
- [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-23)
- [Contributors](#contributors-25)
- [v0.5.1](#v051)
- [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -224,7 +242,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-24)
- [Contributors](#contributors-26)
- [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -233,7 +251,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-25)
- [Contributors](#contributors-27)
- [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend)
@@ -260,6 +278,172 @@
- [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization)
# v31.2
This is a bug fix release. The following issues have been addressed:
* The number of vCPUs is capped at the hypervisor maximum (#5357)
* Fixes for TTY reset (#5414)
* CPU topology fixes on MSHV (#5325)
* Seccomp fixes for older distributions (#5397)
* Report errors explicitly to users when VM failed to boot (#5453)
* Fix VFIO on platforms with non-4k page size (#5450, #5469)
* Fix TDX initialization (#5454)
* Ensure all guest memory regions are page-size aligned (#5496)
* Fix seccomp filter lists related to virtio-console, serial and pty
(#5506, #5524)
* Populate APIC ID properly (#5512)
* Ignore and warn TAP FDs in more situations (#5522)
# v31.1
This is a bug fix release. The following issues have been addressed:
* Ignore and warn TAP FDs sent via the HTTP request body (#5350)
* Properly preserve and close valid FDs for TAP devices (#5373)
* Only use `KVM_ARM_VCPU_PMU_V3` if available (#5360)
* Only touch the tty flags if it's being used (#5343)
* Fix seccomp filter lists for vhost-user devices (#5361)
# v31.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v31.0. The following user visible changes have been made:
### Update to Latest `acpi_tables`
Adapted to the latest [acpi_tables](https://github.com/rust-vmm/acpi_tables).
There has been significant API changes in the crate.
### Update Reference Kernel to 6.2
Updated the recommended guest kernel version from 6.1.6 to 6.2.
### Improvements on Console `SIGWINCH` Handler
A separate thread had been created to capture the `SIGWINCH` signal and resize
the guest console. Now the thread is skipped if the console is not resizable.
Two completely different code paths existed for handling console resizing, one
for `tty` and the other for `pty`. That makes the understanding of the console
handling code unnecessarily complicated. Now the code paths are unified. Both
`tty` and `pty` are supported in single `SIGWINCH` handler. And the new handler
can works with kernel versions earlier than v5.5.
### Remove Directory Support from `MemoryZoneConfig::file`
Setting a directory to `MemoryZoneConfig::file` is no longer supported.
Before this change, user can set a directory to `file` of the `--memory-zone`
option. In that case, a temporary file will be created as the backing file for
the `mmap(2)` operation. This functionality has been unnecessary since we had
the native support for hugepages and allocating anonymous shared memory.
### Documentation Improvements
* Various improvements in API document
* Improvements in Doc comments
* Updated Slack channel information in README
### Notable Bug Fixes
* Fixed the offset setting while removing the entire mapping of `vhost-user` FS
client.
* Fixed the `ShutdownVmm` and `Shutdown` commands to call the correct API
endpoint.
### Contributors
Many thanks to everyone who has contributed to our release:
* Alyssa Ross <hi@alyssa.is>
* Bo Chen <chen.bo@intel.com>
* Daniel Farina <daniel@fdr.io>
* Dom <peng6662001@163.com>
* Hao Xu <howeyxu@tencent.com>
* Muminul Islam <muislam@microsoft.com>
* Omer Faruk Bayram <omer.faruk@sartura.hr>
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
* Rob Bradford <rbradford@rivosinc.com>
* Ruslan Mstoi <ruslan.mstoi@intel.com>
* Smit Gardhariya <gardhariya.smit@gmail.com>
* Yang <ailin.yang@intel.com>
* Yong He <alexyonghe@tencent.com>
# v30.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v30.0. The following user visible changes have been made:
### Command Line Changes for Reduced Binary Size
The `clap` crate was replaced by the `argh` crate to create our command
line, which reduced our release binary size from 3.6MB to 3.3MB. There
were several syntax changes:
* All `--option=value` commands now are `--option value`.
* The `--disk DISK1 DISK2` command now is `--disk DISK1 --disk DISK2`.
* The `-vvv` command now is `-v -v -v`
### Basic vfio-user Server Support
Our `vfio-user` crate is extended to provide basic server side support
with an example of gpio vfio-user device. This crate now is moved to [its
own repository](https://github.com/rust-vmm/vfio-user) under the
`rust-vmm` organization.
### Heap Profiling Support
A new building target is added for profiling purposes with examples of
heap profiling using `dhat` gated by the `dhat-heap` feature.
### Documentation Improvements
The documentation on Intel TDX is expanded with details of the building
and using [TD-Shim](https://github.com/confidential-containers/td-shim),
references to [TDX Tools](https://github.com/intel/tdx-tools), and
version information of guest/host kernel/TDVF/TDShim being tested. Also,
a new 'heap profiling' documentation is added with improvements on the
existing 'profiling' documentation.
### Notable Bug Fixes
* Close FDs for TAP devices that are provided to VM (#5199, #5206)
* Set vcpu thread status properly and signal `exit_evt` upon thread exit (#5211)
* Populate CPUID leaf 0x4000_0010 (TSC frequency) (#5178, #5179)
* Inform the TPM guest driver upon failed TPM requests on the host (#5151)
* Bug fix to OpenAPI specification file (#5186)
### Contributors
Many thanks to everyone who has contributed to our release:
* Anatol Belski <anbelski@linux.microsoft.com>
* Anirudh Rayabharam <anrayabh@linux.microsoft.com>
* Bo Chen <chen.bo@intel.com>
* Jinank Jain <jinankjain@microsoft.com>
* Kaihang Zhang <kaihang.zhang@smartx.com>
* Michael Zhao <michael.zhao@arm.com>
* Muminul Islam <muislam@microsoft.com>
* Philipp Schuster <philipp.schuster@cyberus-technology.de>
* Praveen K Paladugu <prapal@linux.microsoft.com>
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
* Rob Bradford <robert.bradford@intel.com>
* Ruslan Mstoi <ruslan.mstoi@intel.com>
* Sebastien Boeuf <sebastien.boeuf@intel.com>
* Wei Liu <liuwe@microsoft.com>
* Yong He <alexyonghe@tencent.com>
* Yu Li <liyu.yukiteru@bytedance.com>
# v28.2
This is a bug fix release. The following issues have been addressed:
* Fix QCOW2 refcount table size (#5034)
* Fix unpause support on MSHV in dual binary (#5037)
* Threads inside `virtio` devices are now shutdown on reboot (#5095)
# v29.0
This release has been tracked in our [roadmap
@@ -406,7 +590,7 @@ different firmware options and to recommend the use of pre-built binaries.
newer Linux kernels (#4744)
* Error on reboot from race to close TAP devices (#4871)
* Non-spec compliant virtio-block read-only support (#4888)
### Removals
The following functionality has been removed:
@@ -414,7 +598,7 @@ The following functionality has been removed:
* Support for non-PVH firmware booting has been removed (#4511)
* I/O ports used for older versions of firmware have been removed (#3926)
* Deprecated API options for kernel/cmdline/initramfs have been removed (#4737)
### Contributors
Many thanks to everyone who has contributed to our release:
@@ -921,7 +1105,7 @@ Many thanks to everyone who has contributed to our release:
* Sebastien Boeuf <sebastien.boeuf@intel.com>
* Wei Liu <liuwe@microsoft.com>
* Ziye Yang <ziye.yang@intel.com>
# v20.2
This is a bug fix release. The following issues have been addressed:
@@ -1020,7 +1204,7 @@ significant improvements in the boot time of the guest.
### Improved TDX support
When using the latest TDVF firmware the ACPI tables created by the VMM are now
exposed via the firmware to the guest.
exposed via the firmware to the guest.
### Live migration enhancements
@@ -1107,7 +1291,7 @@ tree.
### Power button support on AArch64
Use of the ACPI power button (e.g `ch-remote --api-socket=<API socket> power-button`)
Use of the ACPI power button (e.g `ch-remote --api-socket=<API socket> power-button`)
is now supported when running on AArch64.
### Notable bug fixes
@@ -1519,7 +1703,7 @@ Highlights for `cloud-hypervisor` version 0.11.0 include:
### `io_uring` support by default for `virtio-block`
Provided that the host OS supports it (Linux kernel 5.8+) then `io_uring` will
be used for a significantly higher performance block device.
be used for a significantly higher performance block device.
### Windows Guest Support
@@ -1693,7 +1877,7 @@ A new abstraction has been introduced, in the form of a `hypervisor` crate so as
Multiple improvements have been made to the VM snapshot/restore support that was added in the last release. This includes persisting more vCPU state and in particular preserving the guest paravirtualized clock in order to avoid vCPU hangs inside the guest when running with multiple vCPUs.
### Virtio Memory Ballooning Support
A `virtio-balloon` device has been added, controlled through the `resize` control, which allows the reclamation of host memory by resizing a memory balloon inside the guest.
### Enhancements to ARM64 Support

View File

@@ -1,10 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
#
# When changing this file don't forget to update the tag name in the
# .github/workflows/docker-image.yaml file if doing multiple per day
FROM ubuntu:20.04 as dev
ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.62.0"
ARG RUST_TOOLCHAIN="1.67.1"
ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
@@ -58,7 +60,10 @@ RUN update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-
RUN if [ "$TARGETARCH" = "amd64" ]; then \
apt-get update \
&& apt-get -yq upgrade \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc-multilib \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc-multilib gawk \
libtool expect gnutls-dev gnutls-bin libfuse-dev \
libjson-glib-dev libgmp-dev libtasn1-dev python3-twisted \
net-tools softhsm2 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*; fi
@@ -125,6 +130,25 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
&& cp -r ./scripts/rpc /usr/local/bin/spdk-nvme \
&& cd .. && rm -rf spdk; fi
# install swtpm only for x86_64 arch
RUN if [ "$TARGETARCH" = "amd64" ]; then \
git clone https://github.com/stefanberger/libtpms libtpms_build \
&& cd libtpms_build \
&& git checkout v0.8.8 \
&& ./autogen.sh \
&& make \
&& make install \
&& cd .. \
&& git clone https://github.com/stefanberger/swtpm swtpm_build \
&& cd swtpm_build \
&& git checkout v0.8.0 \
&& ./autogen.sh \
&& make \
&& make install \
&& cd .. \
&& ldconfig \
&& rm -rf swtpm_build libtpms_build; fi
# install ethr tool for performance tests
RUN if [ "$TARGETARCH" = "amd64" ]; then \
wget https://github.com/microsoft/ethr/releases/latest/download/ethr_linux.zip \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,6 @@
from colorsys import hsv_to_rgb
from random import random
import xml
import json
from sys import argv, stderr
import xml.etree.ElementTree as ET

View File

@@ -2,7 +2,7 @@
set -x
rm -f /tmp/ubuntu-cloudinit.img
mkdosfs -n cidata -C /tmp/ubuntu-cloudinit.img 8192
mkdosfs -n CIDATA -C /tmp/ubuntu-cloudinit.img 8192
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/user-data ::
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/meta-data ::
mcopy -oi /tmp/ubuntu-cloudinit.img -s test_data/cloud-init/ubuntu/network-config ::

View File

@@ -6,8 +6,8 @@
CLI_NAME="Cloud Hypervisor"
CTR_IMAGE_TAG="cloudhypervisor/dev"
CTR_IMAGE_VERSION="20220705-0"
CTR_IMAGE_TAG="ghcr.io/cloud-hypervisor/cloud-hypervisor"
CTR_IMAGE_VERSION="20230316-0"
CTR_IMAGE="${CTR_IMAGE_TAG}:${CTR_IMAGE_VERSION}"
DOCKER_RUNTIME="docker"
@@ -168,10 +168,15 @@ process_volumes_args() {
exported_volumes="$exported_volumes --volume $var"
done
}
cmd_help() {
echo ""
echo "Cloud Hypervisor $(basename "$0")"
echo "Usage: $(basename "$0") <command> [<command args>]"
echo "Usage: $(basename "$0") [flags] <command> [<command args>]"
echo ""
echo "Available flags":
echo ""
echo " --local Set the container image version being used to \"local\"."
echo ""
echo "Available commands:"
echo ""
@@ -379,6 +384,10 @@ cmd_tests() {
exported_device="/dev/mshv"
fi
if [ ! -e "${exported_device}" ] ; then
die "${exported_device} does not exist on the system"
fi
set -- '--hypervisor' "$hypervisor" "$@"
ensure_build_dir
@@ -621,6 +630,12 @@ cmd_shell() {
fix_dir_perms $?
}
if [ $# = 0 ]; then
cmd_help
say_err "Please specify command to run!"
exit 1
fi
# Parse main command line args.
#
while [ $# -gt 0 ]; do

View File

@@ -148,7 +148,7 @@ update_workloads() {
popd
# Download Cloud Hypervisor binary from its last stable release
LAST_RELEASE_VERSION="v26.0"
LAST_RELEASE_VERSION="v30.0"
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static-aarch64"
CH_RELEASE_NAME="cloud-hypervisor-static-aarch64"
pushd $WORKLOADS_DIR
@@ -240,7 +240,9 @@ sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
# Both test_vfio and ovs-dpdk rely on hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
# Run all direct kernel boot (Device Tree) test cases in mod `parallel`

View File

@@ -46,7 +46,7 @@ fi
popd
# Download Cloud Hypervisor binary from its last stable release
LAST_RELEASE_VERSION="v26.0"
LAST_RELEASE_VERSION="v30.0"
CH_RELEASE_URL="https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$LAST_RELEASE_VERSION/cloud-hypervisor-static"
CH_RELEASE_NAME="cloud-hypervisor-static"
pushd $WORKLOADS_DIR
@@ -56,26 +56,8 @@ popd
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
if [ ! -f "$VMLINUX_IMAGE" ]; then
SRCDIR=$PWD
pushd $WORKLOADS_DIR
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.15.12" $LINUX_CUSTOM_DIR
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
popd
fi
if [ ! -f "$VMLINUX_IMAGE" ]; then
pushd $LINUX_CUSTOM_DIR
time make bzImage -j `nproc`
cp vmlinux $VMLINUX_IMAGE || exit 1
popd
fi
if [ -d "$LINUX_CUSTOM_DIR" ]; then
rm -rf $LINUX_CUSTOM_DIR
build_custom_linux
fi
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
@@ -89,7 +71,9 @@ fi
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
# Test ovs-dpdk relies on hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
export RUST_BACKTRACE=1

View File

@@ -45,29 +45,7 @@ if [ $? -ne 0 ]; then
fi
popd
# Build custom kernel based on virtio-pmem and virtio-fs upstream patches
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
if [ ! -f "$VMLINUX_IMAGE" ]; then
SRCDIR=$PWD
pushd $WORKLOADS_DIR
time git clone --depth 1 "https://github.com/cloud-hypervisor/linux.git" -b "ch-5.15.12" $LINUX_CUSTOM_DIR
cp $SRCDIR/resources/linux-config-x86_64 $LINUX_CUSTOM_DIR/.config
popd
fi
if [ ! -f "$VMLINUX_IMAGE" ]; then
pushd $LINUX_CUSTOM_DIR
time make bzImage -j `nproc`
cp vmlinux $VMLINUX_IMAGE || exit 1
popd
fi
if [ -d "$LINUX_CUSTOM_DIR" ]; then
rm -rf $LINUX_CUSTOM_DIR
fi
build_custom_linux
BUILD_TARGET="$(uname -m)-unknown-linux-${CH_LIBC}"
CFLAGS=""

View File

@@ -21,7 +21,7 @@ rm -f $FW
time wget --quiet $FW_URL || exit 1
popd
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20221118-1.qcow2"
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_IMAGE" ]; then
@@ -30,7 +30,7 @@ if [ ! -f "$JAMMY_OS_IMAGE" ]; then
popd
fi
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20221118-1.raw"
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.raw"
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR

View File

@@ -12,9 +12,7 @@ FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
FW="$WORKLOADS_DIR/hypervisor-fw"
VMLINUX_IMAGE="$WORKLOADS_DIR/vmlinux"
if [ ! -f "$VMLINUX_IMAGE" ]; then
build_custom_linux
fi
build_custom_linux
BLK_IMAGE="$WORKLOADS_DIR/blk.img"
MNT_DIR="mount_image"
@@ -52,16 +50,13 @@ cp target/$BUILD_TARGET/release/cloud-hypervisor $VFIO_DIR
cp target/$BUILD_TARGET/release/ch-remote $VFIO_DIR
# test_vfio rely on hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
export RUST_BACKTRACE=1
time cargo test "vfio::test_vfio" -- ${test_binary_args[*]}
time cargo test "vfio::test_nvidia" -- --test-threads=1 ${test_binary_args[*]}
RES=$?
if [ $RES -eq 0 ]; then
time cargo test "vfio::test_nvidia" -- --test-threads=1 ${test_binary_args[*]}
RES=$?
fi
exit $RES

View File

@@ -11,7 +11,7 @@ test_features=""
if [ "$hypervisor" = "mshv" ] ; then
test_features="--no-default-features --features mshv"
fi
WIN_IMAGE_FILE="/root/workloads/windows-server-2019.raw"
WIN_IMAGE_FILE="/root/workloads/windows-server-2022-amd64-2.raw"
WORKLOADS_DIR="/root/workloads"
OVMF_FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/edk2/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')

View File

@@ -53,7 +53,7 @@ if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
popd
fi
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20221118-1.qcow2"
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_IMAGE" ]; then
@@ -62,7 +62,7 @@ if [ ! -f "$JAMMY_OS_IMAGE" ]; then
popd
fi
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20221118-1.raw"
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.raw"
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR
@@ -169,7 +169,9 @@ sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs"
sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run"
# Both test_vfio, ovs-dpdk and vDPA tests rely on hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
# Update max locked memory to 'unlimited' to avoid issues with vDPA

View File

@@ -95,7 +95,9 @@ fi
cargo build --no-default-features --features "kvm,mshv" --all --release --target $BUILD_TARGET
# setup hugepages
echo 6144 | sudo tee /proc/sys/vm/nr_hugepages
HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
PAGE_NUM=`echo $((12288 * 1024 / $HUGEPAGESIZE))`
echo $PAGE_NUM | sudo tee /proc/sys/vm/nr_hugepages
sudo chmod a+rwX /dev/hugepages
if [ -n "$test_filter" ]; then

View File

@@ -22,3 +22,4 @@ fi
export RUST_BACKTRACE=1
cargo test --lib --bins --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1
cargo test --doc --target $BUILD_TARGET --workspace ${cargo_args[@]} || exit 1

View File

@@ -1,5 +1,6 @@
d4a44acc6014d5f83dea1c625c43d677a95fa75f alpine-minirootfs-x86_64.tar.gz
f1eccdc5e1b515dbad294426ab081b47ebfb97c0 focal-server-cloudimg-amd64-custom-20210609-0.qcow2
7f5a8358243a96adf61f5c20139b29f308f2c0e3 focal-server-cloudimg-amd64-custom-20210609-0.raw
b12e52203bc78400b2f099420b411b49ef4be7b8 jammy-server-cloudimg-amd64-custom-20221118-1.qcow2
d843d5b249e8db3c0158eaf56ade895ed10342b5 jammy-server-cloudimg-amd64-custom-20221118-1.raw
864c074e2f1bd753667a35188b510d83a1d62793 jammy-server-cloudimg-amd64-custom-20230119-0.qcow2
24358ee053f94e7f710ea4ce9e7a63eff2a1eb25 jammy-server-cloudimg-amd64-custom-20230119-0.raw

View File

@@ -46,7 +46,7 @@ build_custom_linux() {
ARCH=$(uname -m)
SRCDIR=$PWD
LINUX_CUSTOM_DIR="$WORKLOADS_DIR/linux-custom"
LINUX_CUSTOM_BRANCH="ch-5.15.12"
LINUX_CUSTOM_BRANCH="ch-6.2"
LINUX_CUSTOM_URL="https://github.com/cloud-hypervisor/linux.git"
checkout_repo "$LINUX_CUSTOM_DIR" "$LINUX_CUSTOM_URL" "$LINUX_CUSTOM_BRANCH"

View File

@@ -7,7 +7,7 @@ use api_client::simple_api_command;
use api_client::simple_api_command_with_fds;
use api_client::simple_api_full_command;
use api_client::Error as ApiClientError;
use clap::{Arg, ArgAction, ArgMatches, Command};
use argh::FromArgs;
use option_parser::{ByteSized, ByteSizedParseError};
use std::fmt;
use std::io::Read;
@@ -18,7 +18,6 @@ use std::process;
enum Error {
Connect(std::io::Error),
ApiClient(ApiClientError),
InvalidCpuCount(std::num::ParseIntError),
InvalidMemorySize(ByteSizedParseError),
InvalidBalloonSize(ByteSizedParseError),
AddDeviceConfig(vmm::config::Error),
@@ -40,7 +39,6 @@ impl fmt::Display for Error {
match self {
ApiClient(e) => e.fmt(f),
Connect(e) => write!(f, "Error opening HTTP socket: {e}"),
InvalidCpuCount(e) => write!(f, "Error parsing CPU count: {e}"),
InvalidMemorySize(e) => write!(f, "Error parsing memory size: {e:?}"),
InvalidBalloonSize(e) => write!(f, "Error parsing balloon size: {e:?}"),
AddDeviceConfig(e) => write!(f, "Error parsing device syntax: {e}"),
@@ -60,16 +58,10 @@ impl fmt::Display for Error {
fn resize_api_command(
socket: &mut UnixStream,
cpus: Option<&str>,
memory: Option<&str>,
balloon: Option<&str>,
desired_vcpus: Option<u8>,
memory: &Option<String>,
balloon: &Option<String>,
) -> Result<(), Error> {
let desired_vcpus: Option<u8> = if let Some(cpus) = cpus {
Some(cpus.parse().map_err(Error::InvalidCpuCount)?)
} else {
None
};
let desired_ram: Option<u64> = if let Some(memory) = memory {
Some(
memory
@@ -325,366 +317,387 @@ fn create_api_command(socket: &mut UnixStream, path: &str) -> Result<(), Error>
simple_api_command(socket, "PUT", "create", Some(&data)).map_err(Error::ApiClient)
}
fn do_command(matches: &ArgMatches) -> Result<(), Error> {
let mut socket = UnixStream::connect(matches.get_one::<String>("api-socket").unwrap())
.map_err(Error::Connect)?;
fn do_command(toplevel: &TopLevel) -> Result<(), Error> {
let mut socket =
UnixStream::connect(toplevel.api_socket.as_deref().unwrap()).map_err(Error::Connect)?;
match matches.subcommand_name() {
Some("info") => {
match toplevel.command {
SubCommandEnum::Boot(_) => {
simple_api_command(&mut socket, "PUT", "boot", None).map_err(Error::ApiClient)
}
SubCommandEnum::Delete(_) => {
simple_api_command(&mut socket, "PUT", "delete", None).map_err(Error::ApiClient)
}
SubCommandEnum::ShutdownVmm(_) => {
simple_api_full_command(&mut socket, "PUT", "vmm.shutdown", None)
.map_err(Error::ApiClient)
}
SubCommandEnum::Resume(_) => {
simple_api_command(&mut socket, "PUT", "resume", None).map_err(Error::ApiClient)
}
SubCommandEnum::PowerButton(_) => {
simple_api_command(&mut socket, "PUT", "power-button", None).map_err(Error::ApiClient)
}
SubCommandEnum::Reboot(_) => {
simple_api_command(&mut socket, "PUT", "reboot", None).map_err(Error::ApiClient)
}
SubCommandEnum::Pause(_) => {
simple_api_command(&mut socket, "PUT", "pause", None).map_err(Error::ApiClient)
}
SubCommandEnum::Info(_) => {
simple_api_command(&mut socket, "GET", "info", None).map_err(Error::ApiClient)
}
Some("counters") => {
SubCommandEnum::Counters(_) => {
simple_api_command(&mut socket, "GET", "counters", None).map_err(Error::ApiClient)
}
Some("ping") => {
SubCommandEnum::Ping(_) => {
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).map_err(Error::ApiClient)
}
Some("shutdown-vmm") => simple_api_full_command(&mut socket, "PUT", "vmm.shutdown", None)
.map_err(Error::ApiClient),
Some("resize") => resize_api_command(
SubCommandEnum::Shutdown(_) => {
simple_api_command(&mut socket, "PUT", "shutdown", None).map_err(Error::ApiClient)
}
SubCommandEnum::Resize(ref config) => {
resize_api_command(&mut socket, config.cpus, &config.memory, &config.balloon)
}
SubCommandEnum::ResizeZone(ref config) => {
resize_zone_api_command(&mut socket, &config.id, &config.size)
}
SubCommandEnum::AddDevice(ref config) => {
add_device_api_command(&mut socket, &config.device_config)
}
SubCommandEnum::RemoveDevice(ref config) => {
remove_device_api_command(&mut socket, &config.device_config)
}
SubCommandEnum::AddDisk(ref config) => {
add_disk_api_command(&mut socket, &config.disk_config)
}
SubCommandEnum::AddFs(ref config) => add_fs_api_command(&mut socket, &config.fs_config),
SubCommandEnum::AddPmem(ref config) => {
add_pmem_api_command(&mut socket, &config.pmem_config)
}
SubCommandEnum::AddNet(ref config) => add_net_api_command(&mut socket, &config.net_config),
SubCommandEnum::AddUserDevice(ref config) => {
add_user_device_api_command(&mut socket, &config.device_config)
}
SubCommandEnum::AddVdpa(ref config) => {
add_vdpa_api_command(&mut socket, &config.vdpa_config)
}
SubCommandEnum::AddVsock(ref config) => {
add_vsock_api_command(&mut socket, &config.vsock_config)
}
SubCommandEnum::Snapshot(ref config) => {
snapshot_api_command(&mut socket, &config.snapshot_config)
}
SubCommandEnum::Restore(ref config) => {
restore_api_command(&mut socket, &config.restore_config)
}
SubCommandEnum::Coredump(ref config) => {
coredump_api_command(&mut socket, &config.coredump_config)
}
SubCommandEnum::SendMigration(ref config) => send_migration_api_command(
&mut socket,
matches
.subcommand_matches("resize")
.unwrap()
.get_one::<String>("cpus")
.map(|x| x as &str),
matches
.subcommand_matches("resize")
.unwrap()
.get_one::<String>("memory")
.map(|x| x as &str),
matches
.subcommand_matches("resize")
.unwrap()
.get_one::<String>("balloon")
.map(|x| x as &str),
&config.send_migration_config,
config.send_migration_local,
),
Some("resize-zone") => resize_zone_api_command(
&mut socket,
matches
.subcommand_matches("resize-zone")
.unwrap()
.get_one::<String>("id")
.unwrap(),
matches
.subcommand_matches("resize-zone")
.unwrap()
.get_one::<String>("size")
.unwrap(),
),
Some("add-device") => add_device_api_command(
&mut socket,
matches
.subcommand_matches("add-device")
.unwrap()
.get_one::<String>("device_config")
.unwrap(),
),
Some("remove-device") => remove_device_api_command(
&mut socket,
matches
.subcommand_matches("remove-device")
.unwrap()
.get_one::<String>("id")
.unwrap(),
),
Some("add-disk") => add_disk_api_command(
&mut socket,
matches
.subcommand_matches("add-disk")
.unwrap()
.get_one::<String>("disk_config")
.unwrap(),
),
Some("add-fs") => add_fs_api_command(
&mut socket,
matches
.subcommand_matches("add-fs")
.unwrap()
.get_one::<String>("fs_config")
.unwrap(),
),
Some("add-pmem") => add_pmem_api_command(
&mut socket,
matches
.subcommand_matches("add-pmem")
.unwrap()
.get_one::<String>("pmem_config")
.unwrap(),
),
Some("add-net") => add_net_api_command(
&mut socket,
matches
.subcommand_matches("add-net")
.unwrap()
.get_one::<String>("net_config")
.unwrap(),
),
Some("add-user-device") => add_user_device_api_command(
&mut socket,
matches
.subcommand_matches("add-user-device")
.unwrap()
.get_one::<String>("device_config")
.unwrap(),
),
Some("add-vdpa") => add_vdpa_api_command(
&mut socket,
matches
.subcommand_matches("add-vdpa")
.unwrap()
.get_one::<String>("vdpa_config")
.unwrap(),
),
Some("add-vsock") => add_vsock_api_command(
&mut socket,
matches
.subcommand_matches("add-vsock")
.unwrap()
.get_one::<String>("vsock_config")
.unwrap(),
),
Some("snapshot") => snapshot_api_command(
&mut socket,
matches
.subcommand_matches("snapshot")
.unwrap()
.get_one::<String>("snapshot_config")
.unwrap(),
),
Some("restore") => restore_api_command(
&mut socket,
matches
.subcommand_matches("restore")
.unwrap()
.get_one::<String>("restore_config")
.unwrap(),
),
Some("coredump") => coredump_api_command(
&mut socket,
matches
.subcommand_matches("coredump")
.unwrap()
.get_one::<String>("coredump_config")
.unwrap(),
),
Some("send-migration") => send_migration_api_command(
&mut socket,
matches
.subcommand_matches("send-migration")
.unwrap()
.get_one::<String>("send_migration_config")
.unwrap(),
matches
.subcommand_matches("send-migration")
.unwrap()
.get_flag("send_migration_local"),
),
Some("receive-migration") => receive_migration_api_command(
&mut socket,
matches
.subcommand_matches("receive-migration")
.unwrap()
.get_one::<String>("receive_migration_config")
.unwrap(),
),
Some("create") => create_api_command(
&mut socket,
matches
.subcommand_matches("create")
.unwrap()
.get_one::<String>("path")
.unwrap(),
),
Some(c) => simple_api_command(&mut socket, "PUT", c, None).map_err(Error::ApiClient),
None => unreachable!(),
SubCommandEnum::ReceiveMigration(ref config) => {
receive_migration_api_command(&mut socket, &config.receive_migration_config)
}
SubCommandEnum::Create(ref config) => create_api_command(&mut socket, &config.vm_config),
SubCommandEnum::Version(_) => {
// Already handled outside of this function
panic!()
}
}
}
#[derive(FromArgs, PartialEq, Debug)]
#[doc = "Remotely control a cloud-hypervisor VMM.\n\nPlease refer to cloud-hypervisor for configuration syntaxes."]
struct TopLevel {
#[argh(subcommand)]
command: SubCommandEnum,
#[argh(option, long = "api-socket")]
/// HTTP API socket path (UNIX domain socket)
api_socket: Option<String>,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum SubCommandEnum {
AddDevice(AddDeviceSubcommand),
AddDisk(AddDiskSubcommand),
AddFs(AddFsSubcommand),
AddPmem(AddPmemSubcommand),
AddNet(AddNetSubcommand),
AddUserDevice(AddUserDeviceSubcommand),
AddVdpa(AddVdpaSubcommand),
AddVsock(AddVsockSubcommand),
RemoveDevice(RemoveDeviceSubcommand),
Info(InfoSubcommand),
Counters(CountersSubcommand),
Pause(PauseSubcommand),
Reboot(RebootSubcommand),
PowerButton(PowerButtonSubcommand),
Resume(ResumeSubcommand),
Boot(BootSubcommand),
Delete(DeleteSubcommand),
Shutdown(ShutdownSubcommand),
Ping(PingSubcommand),
ShutdownVmm(ShutdownVmmSubcommand),
Resize(ResizeSubcommand),
ResizeZone(ResizeZoneSubcommand),
Snapshot(SnapshotSubcommand),
Restore(RestoreSubcommand),
Coredump(CoredumpSubcommand),
SendMigration(SendMigrationSubcommand),
ReceiveMigration(ReceiveMigrationSubcommand),
Create(CreateSubcommand),
Version(VersionSubcommand),
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-device")]
/// Add VFIO device
struct AddDeviceSubcommand {
#[argh(positional)]
/// device config
device_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-disk")]
/// Add block device
struct AddDiskSubcommand {
#[argh(positional)]
/// disk config
disk_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-fs")]
/// Add virtio-fs backed fs device
struct AddFsSubcommand {
#[argh(positional)]
/// virtio-fs config
fs_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-pmem")]
/// Add virtio-fs backed fs device
struct AddPmemSubcommand {
#[argh(positional)]
/// pmem config
pmem_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-net")]
/// Add virtio-fs backed fs device
struct AddNetSubcommand {
#[argh(positional)]
/// net config
net_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-user-device")]
/// Add userspace device
struct AddUserDeviceSubcommand {
#[argh(positional)]
/// device config
device_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-vdpa")]
/// Add vdpa device
struct AddVdpaSubcommand {
#[argh(positional)]
/// vdpa config
vdpa_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "add-vsock")]
/// Add vsock device
struct AddVsockSubcommand {
#[argh(positional)]
/// vsock config
vsock_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "remove-device")]
/// Remove VFIO device
struct RemoveDeviceSubcommand {
#[argh(positional)]
/// device config
device_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "info")]
/// Information on the VM
struct InfoSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "counters")]
/// Counters from the VM
struct CountersSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "pause")]
/// Pause the VM
struct PauseSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "reboot")]
/// Reboot the VM
struct RebootSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "power-button")]
/// Trigger a power button in the VM
struct PowerButtonSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "resume")]
/// Resume the VM
struct ResumeSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "boot")]
/// Boot a created VM
struct BootSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "delete")]
/// Delete a VM
struct DeleteSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "shutdown")]
/// Shutdown a VM
struct ShutdownSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "ping")]
/// Ping the VMM to check for API server availability
struct PingSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "shutdown-vmm")]
/// Shutdown the VMM
struct ShutdownVmmSubcommand {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "resize")]
/// Resize the VM
struct ResizeSubcommand {
#[argh(option, long = "cpus")]
/// new VCPUs count
cpus: Option<u8>,
#[argh(option, long = "memory")]
/// new memory size in bytes (supports K/M/G suffix)"
memory: Option<String>,
#[argh(option, long = "balloon")]
/// new balloon size in bytes (supports K/M/G suffix)"
balloon: Option<String>,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "resize-zone")]
/// Resize a memory zone
struct ResizeZoneSubcommand {
#[argh(option, long = "id")]
/// memory zone identifier
id: String,
#[argh(option, long = "size")]
/// new memory size in bytes (supports K/M/G suffix)"
size: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "snapshot")]
/// Create a snapshot from VM
struct SnapshotSubcommand {
#[argh(positional)]
/// destination_url
snapshot_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "restore")]
/// Restore VM from a snapshot
struct RestoreSubcommand {
#[argh(positional)]
/// restore config
restore_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "coredump")]
/// Create a coredump from VM
struct CoredumpSubcommand {
#[argh(positional)]
/// coredump config
coredump_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "send-migration")]
/// Initiate a VM migration
struct SendMigrationSubcommand {
#[argh(switch, long = "local")]
/// local migration
send_migration_local: bool,
#[argh(positional)]
/// destination_url
send_migration_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "receive-migration")]
/// Receive a VM migration
struct ReceiveMigrationSubcommand {
#[argh(positional)]
/// receiver url
receive_migration_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "create")]
/// Create a VM from a JSON configuration
struct CreateSubcommand {
#[argh(positional, default = "String::from(\"-\")")]
/// vm config
vm_config: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "version")]
/// Print version information
struct VersionSubcommand {}
fn main() {
let app = Command::new("ch-remote")
.author(env!("CARGO_PKG_AUTHORS"))
.subcommand_required(true)
.about("Remotely control a cloud-hypervisor VMM.")
.arg(
Arg::new("api-socket")
.long("api-socket")
.help("HTTP API socket path (UNIX domain socket).")
.num_args(1)
.required(true),
)
.subcommand(
Command::new("add-device").about("Add VFIO device").arg(
Arg::new("device_config")
.index(1)
.help(vmm::config::DeviceConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-disk").about("Add block device").arg(
Arg::new("disk_config")
.index(1)
.help(vmm::config::DiskConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-fs")
.about("Add virtio-fs backed fs device")
.arg(
Arg::new("fs_config")
.index(1)
.help(vmm::config::FsConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-pmem")
.about("Add persistent memory device")
.arg(
Arg::new("pmem_config")
.index(1)
.help(vmm::config::PmemConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-net").about("Add network device").arg(
Arg::new("net_config")
.index(1)
.help(vmm::config::NetConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-user-device")
.about("Add userspace device")
.arg(
Arg::new("device_config")
.index(1)
.help(vmm::config::UserDeviceConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-vdpa").about("Add vDPA device").arg(
Arg::new("vdpa_config")
.index(1)
.help(vmm::config::VdpaConfig::SYNTAX),
),
)
.subcommand(
Command::new("add-vsock").about("Add vsock device").arg(
Arg::new("vsock_config")
.index(1)
.help(vmm::config::VsockConfig::SYNTAX),
),
)
.subcommand(
Command::new("remove-device")
.about("Remove VFIO device")
.arg(Arg::new("id").index(1).help("<device_id>")),
)
.subcommand(Command::new("info").about("Info on the VM"))
.subcommand(Command::new("counters").about("Counters from the VM"))
.subcommand(Command::new("pause").about("Pause the VM"))
.subcommand(Command::new("reboot").about("Reboot the VM"))
.subcommand(Command::new("power-button").about("Trigger a power button in the VM"))
.subcommand(
Command::new("resize")
.about("Resize the VM")
.arg(
Arg::new("cpus")
.long("cpus")
.help("New vCPUs count")
.num_args(1),
)
.arg(
Arg::new("memory")
.long("memory")
.help("New memory size in bytes (supports K/M/G suffix)")
.num_args(1),
)
.arg(
Arg::new("balloon")
.long("balloon")
.help("New balloon size in bytes (supports K/M/G suffix)")
.num_args(1),
),
)
.subcommand(
Command::new("resize-zone")
.about("Resize a memory zone")
.arg(
Arg::new("id")
.long("id")
.help("Memory zone identifier")
.num_args(1),
)
.arg(
Arg::new("size")
.long("size")
.help("New memory zone size in bytes (supports K/M/G suffix)")
.num_args(1),
),
)
.subcommand(Command::new("resume").about("Resume the VM"))
.subcommand(Command::new("boot").about("Boot a created VM"))
.subcommand(Command::new("delete").about("Delete a VM"))
.subcommand(Command::new("shutdown").about("Shutdown the VM"))
.subcommand(
Command::new("snapshot")
.about("Create a snapshot from VM")
.arg(
Arg::new("snapshot_config")
.index(1)
.help("<destination_url>"),
),
)
.subcommand(
Command::new("restore")
.about("Restore VM from a snapshot")
.arg(
Arg::new("restore_config")
.index(1)
.help(vmm::config::RestoreConfig::SYNTAX),
),
)
.subcommand(
Command::new("coredump")
.about("Create a coredump from VM")
.arg(Arg::new("coredump_config").index(1).help("<file_path>")),
)
.subcommand(
Command::new("send-migration")
.about("Initiate a VM migration")
.arg(
Arg::new("send_migration_config")
.index(1)
.help("<destination_url>"),
)
.arg(
Arg::new("send_migration_local")
.long("local")
.num_args(0)
.action(ArgAction::SetTrue),
),
)
.subcommand(
Command::new("receive-migration")
.about("Receive a VM migration")
.arg(
Arg::new("receive_migration_config")
.index(1)
.help("<receiver_url>"),
),
)
.subcommand(
Command::new("create")
.about("Create VM from a JSON configuration")
.arg(Arg::new("path").index(1).default_value("-")),
)
.subcommand(Command::new("ping").about("Ping the VMM to check for API server availability"))
.subcommand(Command::new("shutdown-vmm").about("Shutdown the VMM"));
let toplevel: TopLevel = argh::from_env();
let matches = app.get_matches();
if matches!(toplevel.command, SubCommandEnum::Version(_)) {
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
return;
}
if let Err(e) = do_command(&matches) {
if toplevel.api_socket.is_none() {
println!("Please specify --api-socket");
process::exit(1)
}
if let Err(e) = do_command(&toplevel) {
eprintln!("Error running command: {e}");
process::exit(1)
};

View File

@@ -6,9 +6,9 @@
#[macro_use]
extern crate event_monitor;
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command};
use argh::FromArgs;
use libc::EFD_NONBLOCK;
use log::LevelFilter;
use log::{warn, LevelFilter};
use option_parser::OptionParser;
use seccompiler::SeccompAction;
use signal_hook::consts::SIGSYS;
@@ -21,7 +21,10 @@ use thiserror::Error;
use vmm::config;
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::signal::block_signal;
use vmm_sys_util::terminal::Terminal;
#[cfg(feature = "dhat-heap")]
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;
#[derive(Error, Debug)]
enum Error {
@@ -30,6 +33,8 @@ enum Error {
#[cfg(feature = "guest_debug")]
#[error("Failed to create Debug EventFd: {0}")]
CreateDebugEventFd(#[source] std::io::Error),
#[error("Failed to create exit EventFd: {0}")]
CreateExitEventFd(#[source] std::io::Error),
#[error("Failed to open hypervisor interface (is hypervisor interface available?): {0}")]
CreateHypervisor(#[source] hypervisor::HypervisorError),
#[error("Failed to start the VMM thread: {0}")]
@@ -87,9 +92,9 @@ impl log::Log for Logger {
let duration = now.duration_since(self.start);
if record.file().is_some() && record.line().is_some() {
writeln!(
write!(
*(*(self.output.lock().unwrap())),
"cloud-hypervisor: {:.6?}: <{}> {}:{}:{} -- {}",
"cloud-hypervisor: {:.6?}: <{}> {}:{}:{} -- {}\r\n",
duration,
std::thread::current().name().unwrap_or("anonymous"),
record.level(),
@@ -98,9 +103,9 @@ impl log::Log for Logger {
record.args()
)
} else {
writeln!(
write!(
*(*(self.output.lock().unwrap())),
"cloud-hypervisor: {:.6?}: <{}> {}:{} -- {}",
"cloud-hypervisor: {:.6?}: <{}> {}:{} -- {}\r\n",
duration,
std::thread::current().name().unwrap_or("anonymous"),
record.level(),
@@ -113,296 +118,273 @@ impl log::Log for Logger {
fn flush(&self) {}
}
fn prepare_default_values() -> (String, String, String) {
let default_vcpus =
format! {"boot={},max_phys_bits={}", config::DEFAULT_VCPUS,config::DEFAULT_MAX_PHYS_BITS};
let default_memory = format! {"size={}M", config::DEFAULT_MEMORY_MB};
let default_rng = format! {"src={}", config::DEFAULT_RNG_SOURCE};
(default_vcpus, default_memory, default_rng)
fn default_vcpus() -> String {
format!(
"boot={},max_phys_bits={}",
config::DEFAULT_VCPUS,
config::DEFAULT_MAX_PHYS_BITS
)
}
fn create_app(default_vcpus: String, default_memory: String, default_rng: String) -> Command {
#[allow(clippy::let_and_return)]
let app = Command::new("cloud-hypervisor")
// 'BUILT_VERSION' is set by the build script 'build.rs' at
// compile time
.version(env!("BUILT_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
.about("Launch a cloud-hypervisor VMM.")
.group(ArgGroup::new("vm-config").multiple(true))
.group(ArgGroup::new("vmm-config").multiple(true))
.group(ArgGroup::new("logging").multiple(true))
.arg(
Arg::new("cpus")
.long("cpus")
.help(
"boot=<boot_vcpus>,max=<max_vcpus>,\
topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,\
kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,\
affinity=<list_of_vcpus_with_their_associated_cpuset>,\
features=<list_of_features_to_enable>",
)
.default_value(default_vcpus)
.group("vm-config"),
)
.arg(
Arg::new("platform")
.long("platform")
.help(
"num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>",
)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("memory")
.long("memory")
.help(
"Memory parameters \
\"size=<guest_memory_size>,mergeable=on|off,shared=on|off,\
hugepages=on|off,hugepage_size=<hugepage_size>,\
hotplug_method=acpi|virtio-mem,\
hotplug_size=<hotpluggable_memory_size>,\
hotplugged_size=<hotplugged_memory_size>,\
prefault=on|off,thp=on|off\"",
)
.default_value(default_memory)
.group("vm-config"),
)
.arg(
Arg::new("memory-zone")
.long("memory-zone")
.help(
"User defined memory zone parameters \
\"size=<guest_memory_region_size>,file=<backing_file>,\
shared=on|off,\
hugepages=on|off,hugepage_size=<hugepage_size>,\
host_numa_node=<node_id>,\
id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,\
hotplugged_size=<hotplugged_memory_size>,\
prefault=on|off\"",
)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("firmware")
.long("firmware")
.help("Path to firmware that is loaded in an architectural specific way")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("kernel")
.long("kernel")
.help(
"Path to kernel to load. This may be a kernel or firmware that supports a PVH \
entry point (e.g. vmlinux) or architecture equivalent",
)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("initramfs")
.long("initramfs")
.help("Path to initramfs image")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("cmdline")
.long("cmdline")
.help("Kernel command line")
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("disk")
.long("disk")
.help(config::DiskConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("net")
.long("net")
.help(config::NetConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("rng")
.long("rng")
.help(
"Random number generator parameters \"src=<entropy_source_path>,iommu=on|off\"",
)
.default_value(default_rng)
.group("vm-config"),
)
.arg(
Arg::new("balloon")
.long("balloon")
.help(config::BalloonConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("fs")
.long("fs")
.help(config::FsConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("pmem")
.long("pmem")
.help(config::PmemConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("serial")
.long("serial")
.help("Control serial port: off|null|pty|tty|file=/path/to/a/file")
.default_value("null")
.group("vm-config"),
)
.arg(
Arg::new("console")
.long("console")
.help(
"Control (virtio) console: \"off|null|pty|tty|file=/path/to/a/file,iommu=on|off\"",
)
.default_value("tty")
.group("vm-config"),
)
.arg(
Arg::new("device")
.long("device")
.help(config::DeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("user-device")
.long("user-device")
.help(config::UserDeviceConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("vdpa")
.long("vdpa")
.help(config::VdpaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("vsock")
.long("vsock")
.help(config::VsockConfig::SYNTAX)
.num_args(1)
.group("vm-config"),
)
.arg(
Arg::new("numa")
.long("numa")
.help(config::NumaConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
)
.arg(
Arg::new("watchdog")
.long("watchdog")
.help("Enable virtio-watchdog")
.num_args(0)
.action(ArgAction::SetTrue)
.group("vm-config"),
)
.arg(
Arg::new("v")
.short('v')
.action(ArgAction::Count)
.help("Sets the level of debugging output")
.group("logging"),
)
.arg(
Arg::new("log-file")
.long("log-file")
.help("Log file. Standard error is used if not specified")
.num_args(1)
.group("logging"),
)
.arg(
Arg::new("api-socket")
.long("api-socket")
.help("HTTP API socket (UNIX domain socket): path=</path/to/a/file> or fd=<fd>.")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("event-monitor")
.long("event-monitor")
.help("File to report events on: path=</path/to/a/file> or fd=<fd>")
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("restore")
.long("restore")
.help(config::RestoreConfig::SYNTAX)
.num_args(1)
.group("vmm-config"),
)
.arg(
Arg::new("seccomp")
.long("seccomp")
.num_args(1)
.value_parser(["true", "false", "log"])
.default_value("true"),
)
.arg(
Arg::new("tpm")
.long("tpm")
.num_args(1)
.help(config::TpmConfig::SYNTAX)
.group("vmm-config"),
fn default_memory() -> String {
format!("size={}M", config::DEFAULT_MEMORY_MB)
}
);
fn default_rng() -> String {
format!("src={}", config::DEFAULT_RNG_SOURCE)
}
#[derive(FromArgs)]
/// Launch a cloud-hypervisor VMM.
pub struct TopLevel {
#[argh(option, long = "cpus", default = "default_vcpus()")]
/// boot=<boot_vcpus>,max=<max_vcpus>,topology=<threads_per_core>:<cores_per_die>:<dies_per_package>:<packages>,kvm_hyperv=on|off,max_phys_bits=<maximum_number_of_physical_bits>,affinity=<list_of_vcpus_with_their_associated_cpuset>,features=<list_of_features_to_enable>
cpus: String,
#[argh(option, long = "platform")]
/// num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>
platform: Option<String>,
#[argh(option, long = "memory", default = "default_memory()")]
/// size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,hugepage_size=<hugepage_size>,hotplug_method=acpi|virtio-mem,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,prefault=on|off,thp=on|off
memory: String,
#[argh(option, long = "memory-zone")]
/// size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,hugepage_size=<hugepage_size>,host_numa_node=<node_id>,id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,prefault=on|off
memory_zone: Vec<String>,
#[argh(option, long = "firmware")]
/// path to firmware that is loaded in an architectural specific way
firmware: Option<String>,
#[argh(option, long = "kernel")]
/// path to kernel or firmware that supports a PVH entry point or architecture equivalent
kernel: Option<String>,
#[argh(option, long = "initramfs")]
/// path to initramfs image
initramfs: Option<String>,
#[argh(option, long = "cmdline")]
/// kernel command line
cmdline: Option<String>,
#[argh(option, long = "disk")]
/// path=<disk_image_path>,readonly=on|off,direct=on|off,iommu=on|off,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,vhost_user=on|off,socket=<vhost_user_socket_path>,bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,id=<device_id>,pci_segment=<segment_id>
disk: Vec<String>,
#[argh(option, long = "net")]
/// tap=<if_name>,ip=<ip_addr>,mask=<net_mask>,mac=<mac_addr>,fd=<fd1,fd2...>,iommu=on|off,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,vhost_user=<vhost_user_enable>,socket=<vhost_user_socket_path>,vhost_mode=client|server,bw_size=<bytes>,bw_one_time_burst=<bytes>,bw_refill_time=<ms>,ops_size=<io_ops>,ops_one_time_burst=<io_ops>,ops_refill_time=<ms>,pci_segment=<segment_id>offload_tso=on|off,offload_ufo=on|off,offload_csum=on|off
net: Vec<String>,
#[argh(option, long = "rng", default = "default_rng()")]
/// src=<entropy_source_path>,iommu=on|off
rng: String,
#[argh(option, long = "balloon")]
/// size=<balloon_size>,deflate_on_oom=on|off,free_page_reporting=on|off
balloon: Option<String>,
#[argh(option, long = "fs")]
/// tag=<tag_name>,socket=<socket_path>,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,id=<device_id>,pci_segment=<segment_id>
fs: Vec<String>,
#[argh(option, long = "pmem")]
/// file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,discard_writes=on|off,id=<device_id>,pci_segment=<segment_id>
pmem: Vec<String>,
#[argh(option, long = "serial", default = "String::from(\"null\")")]
/// off|null|pty|tty|file=/path/to/a/file
serial: String,
#[argh(option, long = "console", default = "String::from(\"tty\")")]
/// off|null|pty|tty|file=/path/to/a/file,iommu=on|off
console: String,
#[argh(option, long = "device")]
/// path=<device_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>
device: Vec<String>,
#[argh(option, long = "user-device")]
/// socket=<socket_path>,id=<device_id>,pci_segment=<segment_id>
user_device: Vec<String>,
#[argh(option, long = "vdpa")]
/// path=<device_path>,num_queues=<number_of_queues>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>
vdpa: Vec<String>,
#[argh(option, long = "vsock")]
/// cid=<context_id>,socket=<socket_path>,iommu=on|off,id=<device_id>,pci_segment=<segment_id>
vsock: Option<String>,
#[argh(option, long = "numa")]
/// guest_numa_id=<node_id>,cpus=<cpus_id>,distances=<list_of_distances_to_destination_nodes>,memory_zones=<list_of_memory_zones>,sgx_epc_sections=<list_of_sgx_epc_sections>
numa: Vec<String>,
#[argh(switch, long = "watchdog")]
/// enable virtio-watchdog
watchdog: bool,
#[argh(switch, short = 'v')]
/// set the level of debugging output
verbosity: u8,
#[argh(option, long = "log-file")]
/// path to log file
log_file: Option<String>,
#[argh(option, long = "api-socket")]
/// path=<path/to/a/file>|fd=<fd>
api_socket: Option<String>,
#[argh(option, long = "event-monitor")]
/// path=<path/to/a/file>|fd=<fd>
event_monitor: Option<String>,
#[argh(option, long = "restore")]
/// source_url=<source_url>,prefault=on|off
restore: Option<String>,
#[argh(option, long = "seccomp", default = "String::from(\"true\")")]
/// seccomp configuration (true, false or log)
seccomp: String,
#[argh(option, long = "tpm")]
/// socket=<path/to/a/socket>
tpm: Option<String>,
#[cfg(target_arch = "x86_64")]
let app = app.arg(
Arg::new("sgx-epc")
.long("sgx-epc")
.help(config::SgxEpcConfig::SYNTAX)
.num_args(1..)
.group("vm-config"),
);
#[argh(option, long = "sgx-epc")]
/// id=<epc_section_identifier>,size=<epc_section_size>,prefault=on|off
sgx_epc: Vec<String>,
#[cfg(feature = "guest_debug")]
let app = app.arg(
Arg::new("gdb")
.long("gdb")
.help("GDB socket (UNIX domain socket): path=</path/to/a/file>")
.num_args(1)
.group("vmm-config"),
);
#[argh(option, long = "gdb")]
/// path=<path/to/a/file>
gdb: Option<String>,
app
#[argh(switch, short = 'V', long = "version")]
/// print version information
version: bool,
}
fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
let log_level = match cmd_arguments.get_count("v") {
impl TopLevel {
fn to_vm_params(&self) -> config::VmParams<'_> {
let cpus = &self.cpus;
let memory = &self.memory;
let memory_zones = if !self.memory_zone.is_empty() {
Some(self.memory_zone.iter().map(|x| x.as_str()).collect())
} else {
None
};
let rng = &self.rng;
let serial = &self.serial;
let firmware = self.firmware.as_deref();
let kernel = self.kernel.as_deref();
let initramfs = self.initramfs.as_deref();
let cmdline = self.cmdline.as_deref();
let disks = if !self.disk.is_empty() {
Some(self.disk.iter().map(|x| x.as_str()).collect())
} else {
None
};
let net = if !self.net.is_empty() {
Some(self.net.iter().map(|x| x.as_str()).collect())
} else {
None
};
let console = &self.console;
let balloon = self.balloon.as_deref();
let fs = if !self.fs.is_empty() {
Some(self.fs.iter().map(|x| x.as_str()).collect())
} else {
None
};
let pmem = if !self.pmem.is_empty() {
Some(self.pmem.iter().map(|x| x.as_str()).collect())
} else {
None
};
let devices = if !self.device.is_empty() {
Some(self.device.iter().map(|x| x.as_str()).collect())
} else {
None
};
let user_devices = if !self.user_device.is_empty() {
Some(self.user_device.iter().map(|x| x.as_str()).collect())
} else {
None
};
let vdpa = if !self.vdpa.is_empty() {
Some(self.vdpa.iter().map(|x| x.as_str()).collect())
} else {
None
};
let vsock = self.vsock.as_deref();
#[cfg(target_arch = "x86_64")]
let sgx_epc = if !self.sgx_epc.is_empty() {
Some(self.sgx_epc.iter().map(|x| x.as_str()).collect())
} else {
None
};
let numa = if !self.numa.is_empty() {
Some(self.numa.iter().map(|x| x.as_str()).collect())
} else {
None
};
let watchdog = self.watchdog;
let platform = self.platform.as_deref();
#[cfg(feature = "guest_debug")]
let gdb = self.gdb.is_some();
let tpm = self.tpm.as_deref();
config::VmParams {
cpus,
memory,
memory_zones,
firmware,
kernel,
initramfs,
cmdline,
disks,
net,
rng,
balloon,
fs,
pmem,
serial,
console,
devices,
user_devices,
vdpa,
vsock,
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
watchdog,
#[cfg(feature = "guest_debug")]
gdb,
platform,
tpm,
}
}
}
fn start_vmm(toplevel: TopLevel) -> Result<Option<String>, Error> {
let log_level = match toplevel.verbosity {
0 => LevelFilter::Warn,
1 => LevelFilter::Info,
2 => LevelFilter::Debug,
_ => LevelFilter::Trace,
};
let log_file: Box<dyn std::io::Write + Send> = if let Some(file) =
cmd_arguments.get_one::<String>("log-file")
{
let log_file: Box<dyn std::io::Write + Send> = if let Some(ref file) = toplevel.log_file {
Box::new(std::fs::File::create(std::path::Path::new(file)).map_err(Error::LogFileCreation)?)
} else {
Box::new(std::io::stderr())
@@ -415,32 +397,26 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
.map(|()| log::set_max_level(log_level))
.map_err(Error::LoggerSetup)?;
let (api_socket_path, api_socket_fd) =
if let Some(socket_config) = cmd_arguments.get_one::<String>("api-socket") {
let mut parser = OptionParser::new();
parser.add("path").add("fd");
parser.parse(socket_config).unwrap_or_default();
let (api_socket_path, api_socket_fd) = if let Some(ref socket_config) = toplevel.api_socket {
let mut parser = OptionParser::new();
parser.add("path").add("fd");
parser.parse(socket_config).unwrap_or_default();
if let Some(fd) = parser.get("fd") {
(
None,
Some(fd.parse::<RawFd>().map_err(Error::ParsingApiSocket)?),
)
} else if let Some(path) = parser.get("path") {
(Some(path), None)
} else {
(
cmd_arguments
.get_one::<String>("api-socket")
.map(|s| s.to_string()),
None,
)
}
if let Some(fd) = parser.get("fd") {
(
None,
Some(fd.parse::<RawFd>().map_err(Error::ParsingApiSocket)?),
)
} else if let Some(path) = parser.get("path") {
(Some(path), None)
} else {
(None, None)
};
(toplevel.api_socket.as_ref().map(|s| s.to_string()), None)
}
} else {
(None, None)
};
if let Some(monitor_config) = cmd_arguments.get_one::<String>("event-monitor") {
if let Some(ref monitor_config) = toplevel.event_monitor {
let mut parser = OptionParser::new();
parser.add("path").add("fd");
parser
@@ -470,18 +446,14 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
let api_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateApiEventFd)?;
let http_sender = api_request_sender.clone();
let seccomp_action = if let Some(seccomp_value) = cmd_arguments.get_one::<String>("seccomp") {
match seccomp_value as &str {
"true" => SeccompAction::Trap,
"false" => SeccompAction::Allow,
"log" => SeccompAction::Log,
_ => {
// The user providing an invalid value will be rejected by clap
panic!("Invalid parameter {seccomp_value} for \"--seccomp\" flag");
}
let seccomp_action = match &toplevel.seccomp as &str {
"true" => SeccompAction::Trap,
"false" => SeccompAction::Allow,
"log" => SeccompAction::Log,
val => {
// The user providing an invalid value will be rejected
panic!("Invalid parameter {val} for \"--seccomp\" flag");
}
} else {
SeccompAction::Trap
};
if seccomp_action == SeccompAction::Trap {
@@ -521,7 +493,7 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
let hypervisor = hypervisor::new().map_err(Error::CreateHypervisor)?;
#[cfg(feature = "guest_debug")]
let gdb_socket_path = if let Some(gdb_config) = cmd_arguments.get_one::<String>("gdb") {
let gdb_socket_path = if let Some(ref gdb_config) = toplevel.gdb {
let mut parser = OptionParser::new();
parser.add("path");
parser.parse(gdb_config).map_err(Error::ParsingGdb)?;
@@ -539,6 +511,8 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
#[cfg(feature = "guest_debug")]
let vm_debug_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateDebugEventFd)?;
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?;
let vmm_thread = vmm::start_vmm_thread(
env!("CARGO_PKG_VERSION").to_string(),
&api_socket_path,
@@ -552,34 +526,46 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
debug_evt.try_clone().unwrap(),
#[cfg(feature = "guest_debug")]
vm_debug_evt.try_clone().unwrap(),
exit_evt.try_clone().unwrap(),
&seccomp_action,
hypervisor,
)
.map_err(Error::StartVmmThread)?;
let payload_present =
cmd_arguments.contains_id("kernel") || cmd_arguments.contains_id("firmware");
let r: Result<(), Error> = (|| {
let payload_present = toplevel.kernel.is_some() || toplevel.firmware.is_some();
if payload_present {
let vm_params = config::VmParams::from_arg_matches(&cmd_arguments);
let vm_config = config::VmConfig::parse(vm_params).map_err(Error::ParsingConfig)?;
if payload_present {
let vm_params = toplevel.to_vm_params();
let vm_config = config::VmConfig::parse(vm_params).map_err(Error::ParsingConfig)?;
// Create and boot the VM based off the VM config we just built.
let sender = api_request_sender.clone();
vmm::api::vm_create(
api_evt.try_clone().unwrap(),
api_request_sender,
Arc::new(Mutex::new(vm_config)),
)
.map_err(Error::VmCreate)?;
vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).map_err(Error::VmBoot)?;
} else if let Some(restore_params) = cmd_arguments.get_one::<String>("restore") {
vmm::api::vm_restore(
api_evt.try_clone().unwrap(),
api_request_sender,
Arc::new(config::RestoreConfig::parse(restore_params).map_err(Error::ParsingRestore)?),
)
.map_err(Error::VmRestore)?;
// Create and boot the VM based off the VM config we just built.
let sender = api_request_sender.clone();
vmm::api::vm_create(
api_evt.try_clone().unwrap(),
api_request_sender,
Arc::new(Mutex::new(vm_config)),
)
.map_err(Error::VmCreate)?;
vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).map_err(Error::VmBoot)?;
} else if let Some(restore_params) = toplevel.restore {
vmm::api::vm_restore(
api_evt.try_clone().unwrap(),
api_request_sender,
Arc::new(
config::RestoreConfig::parse(&restore_params).map_err(Error::ParsingRestore)?,
),
)
.map_err(Error::VmRestore)?;
}
Ok(())
})();
if r.is_err() {
if let Err(e) = exit_evt.write(1) {
warn!("writing to exit EventFd: {e}");
}
}
vmm_thread
@@ -587,17 +573,25 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
.map_err(Error::ThreadJoin)?
.map_err(Error::VmmThread)?;
Ok(api_socket_path)
r.map(|_| api_socket_path)
}
fn main() {
#[cfg(feature = "dhat-heap")]
let _profiler = dhat::Profiler::new_heap();
// Ensure all created files (.e.g sockets) are only accessible by this user
// SAFETY: trivially safe
let _ = unsafe { libc::umask(0o077) };
let (default_vcpus, default_memory, default_rng) = prepare_default_values();
let cmd_arguments = create_app(default_vcpus, default_memory, default_rng).get_matches();
let exit_code = match start_vmm(cmd_arguments) {
let toplevel: TopLevel = argh::from_env();
if toplevel.version {
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
return;
}
let exit_code = match start_vmm(toplevel) {
Ok(path) => {
path.map(|s| std::fs::remove_file(s).ok());
0
@@ -608,13 +602,8 @@ fn main() {
}
};
// SAFETY: trivially safe
let on_tty = unsafe { libc::isatty(libc::STDIN_FILENO) } != 0;
if on_tty {
// Don't forget to set the terminal in canonical mode
// before to exit.
std::io::stdin().lock().set_canon_mode().unwrap();
}
#[cfg(feature = "dhat-heap")]
drop(_profiler);
std::process::exit(exit_code);
}
@@ -622,19 +611,45 @@ fn main() {
#[cfg(test)]
mod unit_tests {
use crate::config::HotplugMethod;
use crate::{create_app, prepare_default_values};
use crate::TopLevel;
use std::path::PathBuf;
use vmm::config::{
ConsoleConfig, ConsoleOutputMode, CpuFeatures, CpusConfig, MemoryConfig, PayloadConfig,
RngConfig, VmConfig, VmParams,
RngConfig, VmConfig,
};
fn get_vm_config_from_vec(args: &[&str]) -> VmConfig {
let (default_vcpus, default_memory, default_rng) = prepare_default_values();
let cmd_arguments =
create_app(default_vcpus, default_memory, default_rng).get_matches_from(args);
// Taken from argh
fn cmd<'a>(default: &'a str, path: &'a str) -> &'a str {
std::path::Path::new(path)
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(default)
}
let vm_params = VmParams::from_arg_matches(&cmd_arguments);
// Some code taken from argh since it does not provide a helper to parse arbitrary strings
fn get_vm_config_from_vec(args: &[&str]) -> VmConfig {
let strings: Vec<String> = args.iter().map(|x| x.to_string()).collect();
let cmd = cmd(&strings[0], &strings[0]);
let strs: Vec<&str> = strings.iter().map(|s| s.as_str()).collect();
let toplevel = <TopLevel as argh::FromArgs>::from_args(&[cmd], &strs[1..]).unwrap_or_else(
|early_exit| {
std::process::exit(match early_exit.status {
Ok(()) => {
println!("{}", early_exit.output);
0
}
Err(()) => {
eprintln!(
"{}\nRun {} --help for more information.",
early_exit.output, cmd
);
1
}
})
},
);
let vm_params = toplevel.to_vm_params();
VmConfig::parse(vm_params).unwrap()
}
@@ -724,6 +739,7 @@ mod unit_tests {
gdb: false,
platform: None,
tpm: None,
preserved_fds: None,
};
assert_eq!(expected_vm_config, result_vm_config);
@@ -893,6 +909,7 @@ mod unit_tests {
"/path/to/kernel",
"--disk",
"path=/path/to/disk/1",
"--disk",
"path=/path/to/disk/2",
],
r#"{
@@ -911,6 +928,7 @@ mod unit_tests {
"/path/to/kernel",
"--disk",
"path=/path/to/disk/1",
"--disk",
"path=/path/to/disk/2",
],
r#"{
@@ -1186,6 +1204,7 @@ mod unit_tests {
"--memory", "shared=true",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1",
"--fs",
"tag=virtiofs2,socket=/path/to/sock2",
],
r#"{
@@ -1204,6 +1223,7 @@ mod unit_tests {
"--memory", "shared=true",
"--fs",
"tag=virtiofs1,socket=/path/to/sock1",
"--fs",
"tag=virtiofs2,socket=/path/to/sock2",
],
r#"{
@@ -1266,6 +1286,7 @@ mod unit_tests {
"/path/to/kernel",
"--pmem",
"file=/path/to/img/1,size=1G",
"--pmem",
"file=/path/to/img/2,size=2G",
],
r#"{
@@ -1432,6 +1453,7 @@ mod unit_tests {
"/path/to/kernel",
"--device",
"path=/path/to/device/1",
"--device",
"path=/path/to/device/2",
],
r#"{
@@ -1450,6 +1472,7 @@ mod unit_tests {
"/path/to/kernel",
"--device",
"path=/path/to/device/1",
"--device",
"path=/path/to/device/2",
],
r#"{
@@ -1526,6 +1549,7 @@ mod unit_tests {
"/path/to/kernel",
"--vdpa",
"path=/path/to/device/1",
"--vdpa",
"path=/path/to/device/2,num_queues=2",
],
r#"{
@@ -1544,6 +1568,7 @@ mod unit_tests {
"/path/to/kernel",
"--vdpa",
"path=/path/to/device/1",
"--vdpa",
"path=/path/to/device/2",
],
r#"{

View File

@@ -8,9 +8,9 @@ edition = "2021"
dirs = "4.0.0"
epoll = "4.3.1"
libc = "0.2.139"
once_cell = "1.16.0"
once_cell = "1.17.1"
serde = { version = "1.0.151", features = ["rc", "derive"] }
serde_json = "1.0.89"
ssh2 = { version = "0.9.3", features = ["vendored-openssl"] }
serde_json = "1.0.95"
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
vmm-sys-util = "0.11.0"
wait-timeout = "0.2.0"

View File

@@ -301,7 +301,7 @@ impl DiskConfig for UbuntuDiskConfig {
.expect("Expected writing out network-config to succeed");
std::process::Command::new("mkdosfs")
.args(["-n", "cidata"])
.args(["-n", "CIDATA"])
.args(["-C", cloudinit_file_path.as_str()])
.arg("8192")
.output()
@@ -1159,7 +1159,7 @@ impl ToString for VerbosityLevel {
match self {
Warn => "".to_string(),
Info => "-v".to_string(),
Debug => "-vv".to_string(),
Debug => "-v -v".to_string(),
}
}
}
@@ -1210,7 +1210,7 @@ impl<'a> GuestCommand<'a> {
self.command.arg("-v");
}
Debug => {
self.command.arg("-vv");
self.command.args(["-v", "-v"]);
}
};
@@ -1278,6 +1278,7 @@ impl<'a> GuestCommand<'a> {
.unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
self.guest.disk_config.disk(DiskType::CloudInit).unwrap()
@@ -1351,6 +1352,7 @@ pub fn parse_iperf3_output(output: &[u8], sender: bool, bandwidth: bool) -> Resu
})
}
#[derive(Clone)]
pub enum FioOps {
Read,
RandomRead,

View File

@@ -10,6 +10,8 @@
extern crate test_infra;
use api_client::simple_api_command;
use api_client::simple_api_full_command;
use net_util::MacAddr;
use std::collections::HashMap;
use std::fs;
@@ -37,8 +39,8 @@ mod x86_64 {
pub const FOCAL_IMAGE_NAME_QCOW2: &str = "focal-server-cloudimg-amd64-custom-20210609-0.qcow2";
pub const FOCAL_IMAGE_NAME_VHD: &str = "focal-server-cloudimg-amd64-custom-20210609-0.vhd";
pub const FOCAL_IMAGE_NAME_VHDX: &str = "focal-server-cloudimg-amd64-custom-20210609-0.vhdx";
pub const JAMMY_IMAGE_NAME: &str = "jammy-server-cloudimg-amd64-custom-20221118-1.raw";
pub const WINDOWS_IMAGE_NAME: &str = "windows-server-2019.raw";
pub const JAMMY_IMAGE_NAME: &str = "jammy-server-cloudimg-amd64-custom-20230119-0.raw";
pub const WINDOWS_IMAGE_NAME: &str = "windows-server-2022-amd64-2.raw";
pub const OVMF_NAME: &str = "CLOUDHV.fd";
pub const GREP_SERIAL_IRQ_CMD: &str = "grep -c 'IO-APIC.*ttyS0' /proc/interrupts || true";
}
@@ -224,29 +226,37 @@ fn prepare_vhost_user_net_daemon(
(command, vunet_socket_path)
}
fn curl_command(api_socket: &str, method: &str, url: &str, http_body: Option<&str>) {
let mut curl_args: Vec<&str> = ["--unix-socket", api_socket, "-i", "-X", method, url].to_vec();
fn prepare_swtpm_daemon(tmp_dir: &TempDir) -> (std::process::Command, String) {
let swtpm_tpm_dir = String::from(tmp_dir.as_path().join("swtpm").to_str().unwrap());
let swtpm_socket_path = String::from(
tmp_dir
.as_path()
.join("swtpm")
.join("swtpm.sock")
.to_str()
.unwrap(),
);
std::fs::create_dir(&swtpm_tpm_dir).unwrap();
if let Some(body) = http_body {
curl_args.push("-H");
curl_args.push("Accept: application/json");
curl_args.push("-H");
curl_args.push("Content-Type: application/json");
curl_args.push("-d");
curl_args.push(body);
}
let mut swtpm_command = Command::new("swtpm");
let swtpm_args = [
"socket",
"--tpmstate",
&format!("dir={swtpm_tpm_dir}"),
"--ctrl",
&format!("type=unixio,path={swtpm_socket_path}"),
"--flags",
"startup-clear",
"--tpm2",
];
swtpm_command.args(swtpm_args);
let status = Command::new("curl")
.args(curl_args)
.status()
.expect("Failed to launch curl command");
assert!(status.success());
(swtpm_command, swtpm_socket_path)
}
fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool {
let mut cmd = Command::new(clh_command("ch-remote"));
cmd.args([&format!("--api-socket={api_socket}"), command]);
cmd.args(["--api-socket", api_socket, command]);
if let Some(arg) = arg {
cmd.arg(arg);
@@ -264,7 +274,7 @@ fn remote_command(api_socket: &str, command: &str, arg: Option<&str>) -> bool {
fn remote_command_w_output(api_socket: &str, command: &str, arg: Option<&str>) -> (bool, Vec<u8>) {
let mut cmd = Command::new(clh_command("ch-remote"));
cmd.args([&format!("--api-socket={api_socket}"), command]);
cmd.args(["--api-socket", api_socket, command]);
if let Some(arg) = arg {
cmd.arg(arg);
@@ -283,18 +293,18 @@ fn resize_command(
event_file: Option<&str>,
) -> bool {
let mut cmd = Command::new(clh_command("ch-remote"));
cmd.args([&format!("--api-socket={api_socket}"), "resize"]);
cmd.args(["--api-socket", api_socket, "resize"]);
if let Some(desired_vcpus) = desired_vcpus {
cmd.arg(format!("--cpus={desired_vcpus}"));
cmd.args(["--cpus", &format!("{desired_vcpus}")]);
}
if let Some(desired_ram) = desired_ram {
cmd.arg(format!("--memory={desired_ram}"));
cmd.args(["--memory", &format!("{desired_ram}")]);
}
if let Some(desired_balloon) = desired_balloon {
cmd.arg(format!("--balloon={desired_balloon}"));
cmd.args(["--balloon", &format!("{desired_balloon}")]);
}
let ret = cmd.status().expect("Failed to launch ch-remote").success();
@@ -319,10 +329,13 @@ fn resize_command(
fn resize_zone_command(api_socket: &str, id: &str, desired_size: &str) -> bool {
let mut cmd = Command::new(clh_command("ch-remote"));
cmd.args([
&format!("--api-socket={api_socket}"),
"--api-socket",
api_socket,
"resize-zone",
&format!("--id={id}"),
&format!("--size={desired_size}"),
"--id",
id,
"--size",
desired_size,
]);
cmd.status().expect("Failed to launch ch-remote").success()
@@ -375,7 +388,7 @@ fn setup_ovs_dpdk_guests(
.args(["--kernel", direct_kernel_boot_path().to_str().unwrap()])
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
.default_disks()
.args(["--net", guest1.default_net_string().as_str(), "vhost_user=true,socket=/tmp/dpdkvhostclient1,num_queues=2,queue_size=256,vhost_mode=server"])
.args(["--net", guest1.default_net_string().as_str(), "--net", "vhost_user=true,socket=/tmp/dpdkvhostclient1,num_queues=2,queue_size=256,vhost_mode=server"])
.capture_output()
.spawn()
.unwrap();
@@ -425,7 +438,7 @@ fn setup_ovs_dpdk_guests(
.args(["--kernel", direct_kernel_boot_path().to_str().unwrap()])
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
.default_disks()
.args(["--net", guest2.default_net_string().as_str(), "vhost_user=true,socket=/tmp/dpdkvhostclient2,num_queues=2,queue_size=256,vhost_mode=server"])
.args(["--net", guest2.default_net_string().as_str(), "--net", "vhost_user=true,socket=/tmp/dpdkvhostclient2,num_queues=2,queue_size=256,vhost_mode=server"])
.capture_output()
.spawn()
.unwrap();
@@ -658,13 +671,17 @@ fn _test_guest_numa_nodes(acpi: bool) {
.args([
"--memory-zone",
"id=mem0,size=1G,hotplug_size=3G",
"--memory-zone",
"id=mem1,size=2G,hotplug_size=3G",
"--memory-zone",
"id=mem2,size=3G,hotplug_size=3G",
])
.args([
"--numa",
"guest_numa_id=0,cpus=[0-2,9],distances=[1@15,2@20],memory_zones=mem0",
"--numa",
"guest_numa_id=1,cpus=[3-4,6-8],distances=[0@20,2@25],memory_zones=mem1",
"--numa",
"guest_numa_id=2,cpus=[5,10-11],distances=[0@25,1@30],memory_zones=mem2",
])
.args(["--kernel", kernel_path.to_str().unwrap()])
@@ -967,11 +984,13 @@ fn test_vhost_user_blk(
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
blk_params.as_str(),
])
.default_net()
@@ -1111,6 +1130,7 @@ fn test_boot_from_vhost_user_blk(
.args([
"--disk",
blk_boot_params.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
@@ -1793,6 +1813,7 @@ fn _test_virtio_iommu(acpi: bool) {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={},iommu=on",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
@@ -1883,7 +1904,7 @@ fn enable_guest_watchdog(guest: &Guest, watchdog_sec: u32) {
}
mod common_parallel {
use std::{fs::OpenOptions, io::SeekFrom};
use std::{fs::OpenOptions, io::SeekFrom, os::unix::net::UnixStream};
use crate::*;
@@ -2025,19 +2046,16 @@ mod common_parallel {
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_cpu_topology_421() {
test_cpu_topology(4, 2, 1, false);
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_cpu_topology_142() {
test_cpu_topology(1, 4, 2, false);
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_cpu_topology_262() {
test_cpu_topology(2, 6, 2, false);
}
@@ -2208,7 +2226,9 @@ mod common_parallel {
.args([
"--memory-zone",
"id=mem0,size=1G,hotplug_size=2G",
"id=mem1,size=1G,file=/dev/shm",
"--memory-zone",
"id=mem1,size=1G,shared=on",
"--memory-zone",
"id=mem2,size=1G,host_numa_node=0,hotplug_size=2G",
])
.args(["--kernel", kernel_path.to_str().unwrap()])
@@ -2460,11 +2480,13 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={test_disk_path},pci_segment=15").as_str(),
])
.capture_output()
@@ -2599,11 +2621,13 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!(
"path={},readonly=on,direct=on,num_queues=4,_disable_io_uring={}",
blk_file_path.to_str().unwrap(),
@@ -2765,11 +2789,13 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={vhdx_path}").as_str(),
])
.default_net()
@@ -2839,6 +2865,7 @@ mod common_parallel {
.args([
"--disk",
format!("path={},direct=on", os_path.as_path().to_str().unwrap()).as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
@@ -3216,7 +3243,9 @@ mod common_parallel {
.args([
"--net",
guest.default_net_string().as_str(),
"--net",
"tap=,mac=8a:6b:6f:5a:de:ac,ip=192.168.3.1,mask=255.255.255.0",
"--net",
"tap=mytap1,mac=fe:1f:9e:e1:60:f2,ip=192.168.4.1,mask=255.255.255.0",
])
.capture_output()
@@ -3694,7 +3723,7 @@ mod common_parallel {
// line (We tag the command line from cloud-hypervisor for that purpose).
// The third device is added to validate that hotplug works correctly since
// it is being added to the L2 VM through hotplugging mechanism.
// Also, we pass-through a vitio-blk device to the L2 VM to test the 32-bit
// Also, we pass-through a virtio-blk device to the L2 VM to test the 32-bit
// vfio device support
fn test_vfio() {
setup_vfio_network_interfaces();
@@ -3756,12 +3785,15 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={}", vfio_disk_path.to_str().unwrap()).as_str(),
"--disk",
format!("path={},iommu=on", blk_file_path.to_str().unwrap()).as_str(),
])
.args([
@@ -3774,16 +3806,19 @@ mod common_parallel {
.args([
"--net",
format!("tap={},mac={}", vfio_tap0, guest.network.guest_mac).as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap1, guest.network.l2_guest_mac1
)
.as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap2, guest.network.l2_guest_mac2
)
.as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap3, guest.network.l2_guest_mac3
@@ -3861,7 +3896,7 @@ mod common_parallel {
let vfio_hotplug_output = guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123",
)
.unwrap();
@@ -3901,7 +3936,7 @@ mod common_parallel {
guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
remove-device vfio123",
)
.unwrap();
@@ -3932,7 +3967,7 @@ mod common_parallel {
guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
resize --memory=1073741824",
)
.unwrap();
@@ -4008,8 +4043,9 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(1, 0));
let mut socket = UnixStream::connect(&api_socket).unwrap();
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
// Create the VM first
let cpu_count: u8 = 4;
@@ -4062,8 +4098,9 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(1, 0));
let mut socket = UnixStream::connect(&api_socket).unwrap();
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
// Create the VM first
let cpu_count: u8 = 4;
@@ -4074,15 +4111,12 @@ mod common_parallel {
);
let r = std::panic::catch_unwind(|| {
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.create",
Some(&http_body),
);
// socket has to be created again inside catch_unwind block to avoid errors
let mut socket = UnixStream::connect(&api_socket).unwrap();
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
// Then boot it
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
guest.wait_vm_boot(None).unwrap();
@@ -4099,15 +4133,10 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(20, 0));
// Then shut it down
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.shutdown",
None,
);
simple_api_command(&mut socket, "PUT", "shutdown", None).unwrap();
// Then boot it again
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
guest.wait_vm_boot(None).unwrap();
@@ -4140,8 +4169,9 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(1, 0));
let mut socket = UnixStream::connect(&api_socket).unwrap();
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
// Create the VM first
let cpu_count: u8 = 4;
@@ -4152,15 +4182,12 @@ mod common_parallel {
);
let r = std::panic::catch_unwind(|| {
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.create",
Some(&http_body),
);
// socket has to be created again inside catch_unwind block to avoid errors
let mut socket = UnixStream::connect(&api_socket).unwrap();
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
// Then boot it
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
guest.wait_vm_boot(None).unwrap();
@@ -4177,22 +4204,12 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(20, 0));
// Then delete it
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.delete",
None,
);
simple_api_command(&mut socket, "PUT", "delete", None).unwrap();
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.create",
Some(&http_body),
);
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
// Then boot it again
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
guest.wait_vm_boot(None).unwrap();
@@ -4226,8 +4243,9 @@ mod common_parallel {
thread::sleep(std::time::Duration::new(1, 0));
let mut socket = UnixStream::connect(&api_socket).unwrap();
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
simple_api_full_command(&mut socket, "GET", "vmm.ping", None).unwrap();
// Create the VM first
let cpu_count: u8 = 4;
@@ -4236,15 +4254,12 @@ mod common_parallel {
direct_kernel_boot_path().to_str().unwrap(),
DIRECT_KERNEL_BOOT_CMDLINE,
);
curl_command(
&api_socket,
"PUT",
"http://localhost/api/v1/vm.create",
Some(&http_body),
);
simple_api_command(&mut socket, "PUT", "create", Some(&http_body)).unwrap();
// Then boot it
curl_command(&api_socket, "PUT", "http://localhost/api/v1/vm.boot", None);
simple_api_command(&mut socket, "PUT", "boot", None).unwrap();
thread::sleep(std::time::Duration::new(20, 0));
let r = std::panic::catch_unwind(|| {
@@ -4320,6 +4335,7 @@ mod common_parallel {
.args([
"--net",
guest.default_net_string().as_str(),
"--net",
"tap=,mac=8a:6b:6f:5a:de:ac,ip=192.168.3.1,mask=255.255.255.0",
])
.capture_output()
@@ -5061,11 +5077,13 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={}", &loop_dev).as_str(),
])
.default_net()
@@ -5178,6 +5196,7 @@ mod common_parallel {
}
#[test]
#[cfg(not(feature = "mshv"))]
fn test_virtio_balloon_free_page_reporting() {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
@@ -5630,6 +5649,7 @@ mod common_parallel {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
cloudinit_params.as_str(),
])
.args(["--net", net_params.as_str()])
@@ -6215,6 +6235,18 @@ mod common_parallel {
.unwrap_or_default(),
2
);
guest.reboot_linux(0, None);
assert_eq!(
guest
.ssh_command("ip -o link | wc -l")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
2
);
});
let _ = child.kill();
@@ -6696,12 +6728,58 @@ mod common_parallel {
handle_child_output(r, &output);
}
#[test]
#[cfg(target_arch = "x86_64")]
fn test_tpm() {
let focal = UbuntuDiskConfig::new(JAMMY_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let (mut swtpm_command, swtpm_socket_path) = prepare_swtpm_daemon(&guest.tmp_dir);
let mut guest_cmd = GuestCommand::new(&guest);
guest_cmd
.args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"])
.args(["--kernel", fw_path(FwType::RustHypervisorFirmware).as_str()])
.args(["--tpm", &format!("socket={swtpm_socket_path}")])
.capture_output()
.default_disks()
.default_net();
// Start swtpm daemon
let mut swtpm_child = swtpm_command.spawn().unwrap();
thread::sleep(std::time::Duration::new(10, 0));
let mut child = guest_cmd.spawn().unwrap();
let r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(None).unwrap();
assert_eq!(
guest.ssh_command("ls /dev/tpm0").unwrap().trim(),
"/dev/tpm0"
);
guest.ssh_command("sudo tpm2_selftest -f").unwrap();
guest
.ssh_command("echo 'hello' > /tmp/checksum_test; ")
.unwrap();
guest.ssh_command("cmp <(sudo tpm2_pcrevent /tmp/checksum_test | grep sha256 | awk '{print $2}') <(sha256sum /tmp/checksum_test| awk '{print $1}')").unwrap();
});
let _ = swtpm_child.kill();
let _d_out = swtpm_child.wait_with_output().unwrap();
let _ = child.kill();
let output = child.wait_with_output().unwrap();
handle_child_output(r, &output);
}
}
mod common_sequential {
#[cfg(not(feature = "mshv"))]
use crate::*;
#[test]
#[cfg(not(feature = "mshv"))]
fn test_memory_mergeable_on() {
test_memory_mergeable(true)
}
@@ -7669,7 +7747,9 @@ mod windows {
.args([
"--net",
windows_guest.guest().default_net_string().as_str(),
"--net",
"tap=,mac=8a:6b:6f:5a:de:ac,ip=192.168.3.1,mask=255.255.255.0",
"--net",
"tap=mytap42,mac=fe:1f:9e:e1:60:f2,ip=192.168.4.1,mask=255.255.255.0",
])
.capture_output()
@@ -7822,12 +7902,15 @@ mod vfio {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
format!("path={}", vfio_disk_path.to_str().unwrap()).as_str(),
"--disk",
format!("path={},iommu=on", blk_file_path.to_str().unwrap()).as_str(),
])
.args([
@@ -7840,16 +7923,19 @@ mod vfio {
.args([
"--net",
format!("tap={},mac={}", vfio_tap0, guest.network.guest_mac).as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap1, guest.network.l2_guest_mac1
)
.as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap2, guest.network.l2_guest_mac2
)
.as_str(),
"--net",
format!(
"tap={},mac={},iommu=on",
vfio_tap3, guest.network.l2_guest_mac3
@@ -7927,7 +8013,7 @@ mod vfio {
let vfio_hotplug_output = guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123",
)
.unwrap();
@@ -7967,7 +8053,7 @@ mod vfio {
guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
remove-device vfio123",
)
.unwrap();
@@ -7998,7 +8084,7 @@ mod vfio {
guest
.ssh_command_l1(
"sudo /mnt/ch-remote \
--api-socket=/tmp/ch_api.sock \
--api-socket /tmp/ch_api.sock \
resize --memory=1073741824",
)
.unwrap();
@@ -8157,7 +8243,8 @@ mod live_migration {
// Start to receive migration from the destintion VM
let mut receive_migration = Command::new(clh_command("ch-remote"))
.args([
&format!("--api-socket={dest_api_socket}"),
"--api-socket",
dest_api_socket,
"receive-migration",
&format! {"unix:{migration_socket}"},
])
@@ -8170,14 +8257,15 @@ mod live_migration {
// Start to send migration from the source VM
let mut args = [
format!("--api-socket={}", &src_api_socket),
"--api-socket".to_string(),
src_api_socket.to_string(),
"send-migration".to_string(),
format! {"unix:{migration_socket}"},
]
.to_vec();
if local {
args.insert(2, "--local".to_string());
args.insert(3, "--local".to_string());
}
let mut send_migration = Command::new(clh_command("ch-remote"))
@@ -8636,11 +8724,15 @@ mod live_migration {
"size=0,hotplug_method=virtio-mem,shared=on",
"--memory-zone",
"id=mem0,size=1G,hotplug_size=4G,shared=on",
"--memory-zone",
"id=mem1,size=1G,hotplug_size=4G,shared=on",
"--memory-zone",
"id=mem2,size=2G,hotplug_size=4G,shared=on",
"--numa",
"guest_numa_id=0,cpus=[0-2,9],distances=[1@15,2@20],memory_zones=mem0",
"--numa",
"guest_numa_id=1,cpus=[3-4,6-8],distances=[0@20,2@25],memory_zones=mem1",
"--numa",
"guest_numa_id=2,cpus=[5,10-11],distances=[0@25,1@30],memory_zones=mem2",
]
} else {
@@ -8649,11 +8741,15 @@ mod live_migration {
"size=0,hotplug_method=virtio-mem",
"--memory-zone",
"id=mem0,size=1G,hotplug_size=4G",
"--memory-zone",
"id=mem1,size=1G,hotplug_size=4G",
"--memory-zone",
"id=mem2,size=2G,hotplug_size=4G",
"--numa",
"guest_numa_id=0,cpus=[0-2,9],distances=[1@15,2@20],memory_zones=mem0",
"--numa",
"guest_numa_id=1,cpus=[3-4,6-8],distances=[0@20,2@25],memory_zones=mem1",
"--numa",
"guest_numa_id=2,cpus=[5,10-11],distances=[0@25,1@30],memory_zones=mem2",
]
};
@@ -9211,51 +9307,43 @@ mod live_migration {
}
#[test]
#[ignore]
fn test_live_upgrade_basic() {
_test_live_migration(true, false)
}
#[test]
#[ignore]
fn test_live_upgrade_local() {
_test_live_migration(true, true)
}
#[test]
#[ignore]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_numa() {
_test_live_migration_numa(true, false)
}
#[test]
#[ignore]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_numa_local() {
_test_live_migration_numa(true, true)
}
#[test]
#[ignore]
fn test_live_upgrade_watchdog() {
_test_live_migration_watchdog(true, false)
}
#[test]
#[ignore]
fn test_live_upgrade_watchdog_local() {
_test_live_migration_watchdog(true, true)
}
#[test]
#[ignore]
fn test_live_upgrade_balloon() {
_test_live_migration_balloon(true, false)
}
#[test]
#[ignore]
fn test_live_upgrade_balloon_local() {
_test_live_migration_balloon(true, true)
}
@@ -9282,7 +9370,6 @@ mod live_migration {
}
#[test]
#[ignore]
#[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_ovs_dpdk() {
@@ -9290,7 +9377,6 @@ mod live_migration {
}
#[test]
#[ignore]
#[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))]
fn test_live_upgrade_ovs_dpdk_local() {
@@ -9491,11 +9577,13 @@ mod rate_limiter {
guest.disk_config.disk(DiskType::OperatingSystem).unwrap()
)
.as_str(),
"--disk",
format!(
"path={}",
guest.disk_config.disk(DiskType::CloudInit).unwrap()
)
.as_str(),
"--disk",
test_blk_params.as_str(),
])
.default_net()

View File

@@ -10,5 +10,6 @@ anyhow = "1.0.66"
byteorder = "1.4.3"
libc = "0.2.138"
log = "0.4.17"
net_gen = { path = "../net_gen" }
thiserror = "1.0.37"
vmm-sys-util = "0.11.0"

View File

@@ -30,8 +30,8 @@ const PTM_CAP_SET_BUFFERSIZE: u64 = 1 << 13;
///Check if the input command is selftest
///
pub fn is_selftest(input: Vec<u8>, in_len: usize) -> bool {
if in_len >= TPM_REQ_HDR_SIZE {
pub fn is_selftest(input: &[u8]) -> bool {
if input.len() >= TPM_REQ_HDR_SIZE {
let ordinal: &[u8; 4] = input[6..6 + 4]
.try_into()
.expect("slice with incorrect length");
@@ -61,18 +61,14 @@ pub enum Error {
type Result<T> = anyhow::Result<T, Error>;
#[derive(Clone)]
pub struct BackendCmd {
pub locality: u8,
pub input: Vec<u8>,
pub struct BackendCmd<'a> {
// This buffer is used for both input and output.
// When used for input, the length of the data is input_len.
pub buffer: &'a mut [u8],
pub input_len: usize,
pub output: Vec<u8>,
pub output_len: usize,
pub selftest_done: bool,
}
pub struct Emulator {
cmd: Option<BackendCmd>,
caps: PtmCap, /* capabilities of the TPM */
control_socket: SocketDev,
data_fd: RawFd,
@@ -100,7 +96,6 @@ impl Emulator {
})?;
let mut emulator = Self {
cmd: None,
caps: 0,
control_socket: socket,
data_fd: -1,
@@ -148,6 +143,27 @@ impl Emulator {
self.run_control_cmd(Commands::CmdSetDatafd, &mut res, 0, mem::size_of::<u32>())?;
debug!("data fd in cloud-hypervisor = {:?}", fds[0]);
self.data_fd = fds[0];
// SAFETY: FFI calls and return value of the unsafe call is checked
unsafe {
let tv = net_gen::iff::timeval {
tv_sec: 0,
tv_usec: 100000, // Set recv timeout to 100ms
};
let ret = net_gen::setsockopt(
fds[0],
net_gen::iff::SOL_SOCKET as i32,
net_gen::iff::SO_RCVTIMEO as i32,
&tv as *const _ as *const libc::c_void,
std::mem::size_of::<net_gen::iff::timeval>() as u32,
);
if ret == -1 {
return Err(Error::PrepareDataFd(anyhow!(
"Failed to set receive timeout on data fd socket. Error Code {:?}",
std::io::Error::last_os_error()
)));
}
}
self.control_socket.set_datafd(fds[0]);
Ok(())
}
@@ -202,18 +218,18 @@ impl Emulator {
debug!("Control Cmd to send : {:02X?}", cmd);
let cmd_no = (cmd as u32).to_be_bytes();
let n: isize = (mem::size_of::<u32>() + msg_len_in) as isize;
let n = mem::size_of::<u32>() + msg_len_in;
let converted_req = msg.ptm_to_request();
debug!("converted request: {:02X?}", converted_req);
let mut buf = Vec::<u8>::with_capacity(n as usize);
let mut buf = Vec::<u8>::with_capacity(n);
buf.extend(cmd_no);
buf.extend(converted_req);
debug!("full Control request {:02X?}", buf);
let _res = self.control_socket.write(&buf).map_err(|e| {
let written = self.control_socket.write(&buf).map_err(|e| {
Error::RunControlCmd(anyhow!(
"Failed while running {:02X?} Control Cmd. Error: {:?}",
cmd,
@@ -221,7 +237,23 @@ impl Emulator {
))
})?;
let mut output = [0_u8; TPM_CRB_BUFFER_MAX];
if written < buf.len() {
return Err(Error::RunControlCmd(anyhow!(
"Truncated write while running {:02X?} Control Cmd",
cmd,
)));
}
// The largest response is 16 bytes so far.
if msg_len_out > 16 {
return Err(Error::RunControlCmd(anyhow!(
"Response size is too large for Cmd {:02X?}, max 16 wanted {}",
cmd,
msg_len_out
)));
}
let mut output = [0u8; 16];
// Every Control Cmd gets atleast a result code in response. Read it
let read_size = self.control_socket.read(&mut output).map_err(|e| {
@@ -277,119 +309,82 @@ impl Emulator {
}
self.established_flag_cached = true;
if est.resp.bit != 0 {
self.established_flag = false;
} else {
self.established_flag = true;
}
self.established_flag = est.resp.bit == 0;
self.established_flag
}
/// Function to write to data socket and read the response from it
fn unix_tx_bufs(&mut self) -> Result<()> {
let isselftest: bool;
pub fn deliver_request(&mut self, cmd: &mut BackendCmd) -> Result<()> {
// SAFETY: type "sockaddr_storage" is valid with an all-zero byte-pattern value
let mut addr: sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
let isselftest = is_selftest(&cmd.buffer[0..cmd.input_len]);
if let Some(ref mut cmd) = self.cmd {
cmd.selftest_done = false;
isselftest = is_selftest(cmd.input.to_vec(), cmd.input_len);
debug!(
"Send cmd: {:02X?} of len {:?} on data_ioc ",
cmd.buffer, cmd.input_len
);
debug!(
"Send cmd: {:02X?} of len {:?} on data_ioc ",
cmd.input, cmd.input_len
let data_vecs = [libc::iovec {
iov_base: cmd.buffer.as_ptr() as *mut libc::c_void,
iov_len: cmd.input_len,
}; 1];
// SAFETY: all zero values from the unsafe method are updated before usage
let mut msghdr: libc::msghdr = unsafe { mem::zeroed() };
msghdr.msg_name = ptr::null_mut();
msghdr.msg_namelen = 0;
msghdr.msg_iov = data_vecs.as_ptr() as *mut libc::iovec;
msghdr.msg_iovlen = data_vecs.len() as _;
msghdr.msg_control = ptr::null_mut();
msghdr.msg_controllen = 0;
msghdr.msg_flags = 0;
// SAFETY: FFI call and the return value of the unsafe method is checked
unsafe {
let ret = libc::sendmsg(self.data_fd, &msghdr, 0);
if ret == -1 {
return Err(Error::SendReceive(anyhow!(
"Failed to send tpm command over Data FD. Error Code {:?}",
std::io::Error::last_os_error()
)));
}
}
let output_len;
// SAFETY: FFI calls and return value from unsafe method is checked
unsafe {
let ret = libc::recvfrom(
self.data_fd,
cmd.buffer.as_mut_ptr() as *mut c_void,
cmd.buffer.len(),
0,
&mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
&mut len as *mut socklen_t,
);
let data_vecs = [libc::iovec {
iov_base: cmd.input.as_mut_ptr() as *mut libc::c_void,
iov_len: cmd.input.len(),
}; 1];
// SAFETY: all zero values from the unsafe method are updated before usage
let mut msghdr: libc::msghdr = unsafe { mem::zeroed() };
msghdr.msg_name = ptr::null_mut();
msghdr.msg_namelen = 0;
msghdr.msg_iov = data_vecs.as_ptr() as *mut libc::iovec;
msghdr.msg_iovlen = data_vecs.len() as _;
msghdr.msg_control = ptr::null_mut();
msghdr.msg_controllen = 0;
msghdr.msg_flags = 0;
// SAFETY: FFI call and the return value of the unsafe method is checked
unsafe {
let ret = libc::sendmsg(self.data_fd, &msghdr, 0);
if ret == -1 {
return Err(Error::SendReceive(anyhow!(
"Failed to send tpm command over Data FD. Error Code {:?}",
std::io::Error::last_os_error()
)));
}
if ret == -1 {
return Err(Error::SendReceive(anyhow!(
"Failed to receive response for tpm command over Data FD. Error Code {:?}",
std::io::Error::last_os_error()
)));
}
output_len = ret as usize;
}
debug!(
"response = {:02X?} len = {:?} selftest = {:?}",
cmd.buffer, output_len, isselftest
);
cmd.output.fill(0);
// SAFETY: FFI calls and return value from unsafe method is checked
unsafe {
let ret = libc::recvfrom(
self.data_fd,
cmd.output.as_ptr() as *mut c_void,
cmd.output.len(),
0,
&mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
&mut len as *mut socklen_t,
);
if ret == -1 {
return Err(Error::SendReceive(anyhow!(
"Failed to receive response for tpm command over Data FD. Error Code {:?}",
std::io::Error::last_os_error()
)));
}
cmd.output_len = ret as usize;
}
debug!(
"response = {:02X?} len = {:?} selftest = {:?}",
cmd.output, cmd.output_len, isselftest
);
if isselftest {
if cmd.output_len < 10 {
return Err(Error::SelfTest(anyhow!(
"Self test response should have 10 bytes. Only {:?} returned",
cmd.output_len
)));
}
let mut errcode: [u8; 4] = [0; 4];
errcode.copy_from_slice(&cmd.output[6..6 + 4]);
cmd.selftest_done = u32::from_ne_bytes(errcode).to_be() == 0;
}
if isselftest && output_len < 10 {
return Err(Error::SelfTest(anyhow!(
"Self test response should have 10 bytes. Only {:?} returned",
output_len
)));
}
Ok(())
}
pub fn deliver_request(&mut self, in_cmd: &mut BackendCmd) -> Result<Vec<u8>> {
if self.cmd.is_some() {
//previous request did not finish cleanly
return Err(Error::DeliverRequest(anyhow!(
"Cannot deliver tpm Request as previous cmd did not complete."
)));
}
self.cmd = Some(in_cmd.clone());
self.unix_tx_bufs()?;
let output = self.cmd.as_ref().unwrap().output.clone();
in_cmd.output.fill(0);
in_cmd.output.clone_from(&output);
self.backend_request_completed();
Ok(output)
}
pub fn backend_request_completed(&mut self) {
self.cmd = None;
}
pub fn cancel_cmd(&mut self) -> Result<()> {
let mut res: PtmResult = 0;
@@ -409,7 +404,7 @@ impl Emulator {
}
/// Configure buffersize to use while communicating with swtpm
fn set_buffer_size(&mut self, wantedsize: usize, actualsize: &mut usize) -> Result<()> {
fn set_buffer_size(&mut self, wantedsize: usize) -> Result<usize> {
let mut psbs: PtmSetBufferSize = PtmSetBufferSize::new(wantedsize as u32);
self.stop_tpm()?;
@@ -421,19 +416,15 @@ impl Emulator {
4 * mem::size_of::<u32>(),
)?;
*actualsize = psbs.get_bufsize() as usize;
Ok(())
Ok(psbs.get_bufsize() as usize)
}
pub fn startup_tpm(&mut self, buffersize: usize) -> Result<()> {
let mut init: PtmInit = PtmInit::new();
let mut actual_size: usize = 0;
if buffersize != 0 {
self.set_buffer_size(buffersize, &mut actual_size)?;
debug!("set tpm buffersize to {:?} during Startup", buffersize);
let actual_size = self.set_buffer_size(buffersize)?;
debug!("set tpm buffersize to {:?} during Startup", actual_size);
}
self.run_control_cmd(
@@ -454,12 +445,7 @@ impl Emulator {
Ok(())
}
pub fn get_buffer_size(&mut self) -> Result<usize> {
let mut curr_buf_size: usize = 0;
match self.set_buffer_size(0, &mut curr_buf_size) {
Err(_) => Ok(TPM_CRB_BUFFER_MAX),
_ => Ok(curr_buf_size),
}
pub fn get_buffer_size(&mut self) -> usize {
self.set_buffer_size(0).unwrap_or(TPM_CRB_BUFFER_MAX)
}
}

View File

@@ -10,7 +10,6 @@ pub mod emulator;
pub mod socket;
use anyhow::anyhow;
use byteorder::{BigEndian, ReadBytesExt};
use std::convert::TryInto;
use thiserror::Error;
@@ -71,7 +70,7 @@ pub trait Ptm {
// Convert PTM Request to bytes to be sent to tpm
fn ptm_to_request(&self) -> Vec<u8>;
// Update PTM from tpm's reponse
// Update PTM from tpm's response
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()>;
// Update tpm result
@@ -90,8 +89,7 @@ pub type PtmResult = u32;
impl Ptm for PtmResult {
fn ptm_to_request(&self) -> Vec<u8> {
let buf: Vec<u8> = Vec::<u8>::new();
buf
Vec::new()
}
fn get_member_type(&self) -> MemberType {
@@ -99,13 +97,15 @@ impl Ptm for PtmResult {
}
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> {
if buf.len() < 4 {
let expected_len = 4;
let len = buf.len();
if len != expected_len {
return Err(Error::ConvertToPtm(anyhow!(
"PtmRes buffer is of insufficient length. Buffer length should be atleast 4"
"PtmRes buffer is of incorrect length. Got {len} expected {expected_len}."
)));
}
*self = u32::from_be_bytes(buf[0..4].try_into().unwrap());
*self = u32::from_be_bytes(buf[..].try_into().unwrap());
Ok(())
}
@@ -126,22 +126,22 @@ impl Ptm for PtmCap {
fn ptm_to_request(&self) -> Vec<u8> {
// tpm's GetCapability call doesn't need any supporting message
// return an empty Buffer
let buf: Vec<u8> = Vec::<u8>::new();
buf
Vec::new()
}
fn get_member_type(&self) -> MemberType {
MemberType::Cap
}
fn update_ptm_with_response(&mut self, mut buf: &[u8]) -> Result<()> {
let buf_len = buf.len();
if buf_len != 8 {
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> {
let expected_len = 8;
let len = buf.len();
if len != expected_len {
return Err(Error::ConvertToPtm(anyhow!(
"Response for GetCapability cmd is of incorrect length: {:?}. Response buffer should be 8 bytes long",
buf_len)));
"Response for GetCapability cmd is of incorrect length. Got {len} expected {expected_len}."
)));
}
*self = buf.read_u64::<BigEndian>().unwrap();
*self = u64::from_be_bytes(buf[..].try_into().unwrap());
Ok(())
}
@@ -187,8 +187,7 @@ impl Ptm for PtmEst {
fn ptm_to_request(&self) -> Vec<u8> {
// tpm's GetTpmEstablished call doesn't need any supporting message
// return an empty Buffer
let buf: Vec<u8> = Vec::<u8>::new();
buf
Vec::new()
}
fn get_member_type(&self) -> MemberType {
@@ -196,15 +195,15 @@ impl Ptm for PtmEst {
}
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> {
if buf.len() < 5 {
let expected_len = 8;
let len = buf.len();
if len != expected_len {
return Err(Error::ConvertToPtm(anyhow!(
"Response for GetTpmEstablished cmd is of incorrect length. Response buffer should be 5 bytes long"
"Response for GetTpmEstablished cmd is of incorrect length. Got {len} expected {expected_len}."
)));
}
let mut res = &buf[0..4];
self.set_result_code(res.read_u32::<BigEndian>().unwrap());
let bit = &buf[4];
self.resp.bit = *bit;
self.set_result_code(u32::from_be_bytes(buf[..4].try_into().unwrap()));
self.resp.bit = buf[4];
Ok(())
}
@@ -258,14 +257,15 @@ impl Ptm for PtmInit {
}
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> {
if buf.len() != 4 {
let expected_len = 4;
let len = buf.len();
if len != expected_len {
return Err(Error::ConvertToPtm(anyhow!(
"Response for Init cmd is of incorrect length. Response buffer should be 4 bytes long"
"Response for Init cmd is of incorrect length. Got {len} expected {expected_len}."
)));
}
self.set_member_type(MemberType::Response);
let mut res = &buf[0..4];
self.set_result_code(res.read_u32::<BigEndian>().unwrap());
self.set_result_code(u32::from_be_bytes(buf[..].try_into().unwrap()));
Ok(())
}
@@ -346,23 +346,24 @@ impl Ptm for PtmSetBufferSize {
}
fn update_ptm_with_response(&mut self, buf: &[u8]) -> Result<()> {
if buf.len() != 16 {
let expected_len = 16;
let len = buf.len();
if len != expected_len {
return Err(Error::ConvertToPtm(anyhow!(
"Response for CmdSetBufferSize cmd is of incorrect length. Response buffer should be 16 bytes long"
"Response for CmdSetBufferSize cmd is of incorrect length. Got {len} expected {expected_len}."
)));
}
self.set_member_type(MemberType::Response);
let mut res = &buf[0..4];
self.set_result_code(res.read_u32::<BigEndian>().unwrap());
self.set_result_code(u32::from_be_bytes(buf[0..4].try_into().unwrap()));
let mut bufsize = &buf[4..8];
self.resp.bufsize = bufsize.read_u32::<BigEndian>().unwrap();
let bufsize = &buf[4..8];
self.resp.bufsize = u32::from_be_bytes(bufsize.try_into().unwrap());
let mut minsize = &buf[8..12];
self.resp.minsize = minsize.read_u32::<BigEndian>().unwrap();
let minsize = &buf[8..12];
self.resp.minsize = u32::from_be_bytes(minsize.try_into().unwrap());
let mut maxsize = &buf[12..16];
self.resp.maxsize = maxsize.read_u32::<BigEndian>().unwrap();
let maxsize = &buf[12..16];
self.resp.maxsize = u32::from_be_bytes(maxsize.try_into().unwrap());
Ok(())
}

View File

@@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0
//
use crate::TPM_CRB_BUFFER_MAX;
use anyhow::anyhow;
use std::io::Read;
use std::os::unix::io::{AsRawFd, RawFd};
@@ -122,23 +121,15 @@ impl SocketDev {
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let newbuf: &mut [u8] = &mut [0; TPM_CRB_BUFFER_MAX];
if self.stream.is_none() {
return Err(Error::ReadFromSocket(anyhow!(
"Stream for tpm socket was not initialized"
)));
}
let mut socket = self.stream.as_ref().unwrap();
let size: usize = socket.read(newbuf).map_err(|e| {
let size: usize = socket.read(buf).map_err(|e| {
Error::ReadFromSocket(anyhow!("Failed to read from socket. Error Code {:?}", e))
})?;
if buf.len() < size {
return Err(Error::ReadFromSocket(anyhow!(
"Input buffer is of insufficient size"
)));
}
buf[0..size].clone_from_slice(&newbuf[0..size]);
Ok(size)
}
}

View File

@@ -7,9 +7,9 @@ edition = "2021"
[dependencies]
libc = "0.2.139"
log = "0.4.17"
once_cell = "1.16.0"
once_cell = "1.17.1"
serde = { version = "1.0.151", features = ["rc", "derive"] }
serde_json = "1.0.89"
serde_json = "1.0.95"
[features]
tracing = []

View File

@@ -1,16 +0,0 @@
[package]
name = "vfio_user"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
[dependencies]
libc = "0.2.139"
log = "0.4.17"
serde = { version = "1.0.151", features = ["rc"] }
serde_derive = "1.0.149"
serde_json = "1.0.89"
thiserror = "1.0.38"
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
vm-memory = { version = "0.10.0", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = "0.11.0"

View File

@@ -1,796 +0,0 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
use std::ffi::CString;
use std::fs::File;
use std::io::{IoSlice, Read, Write};
use std::mem::size_of;
use std::num::Wrapping;
use std::os::unix::net::UnixStream;
use std::os::unix::prelude::RawFd;
use std::path::Path;
use thiserror::Error;
use vfio_bindings::bindings::vfio::*;
use vm_memory::{ByteValued, FileOffset};
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate log;
#[allow(dead_code)]
#[repr(u16)]
#[derive(Clone, Copy, Debug)]
enum Command {
Unknown = 0,
Version = 1,
DmaMap = 2,
DmaUnmap = 3,
DeviceGetInfo = 4,
DeviceGetRegionInfo = 5,
GetRegionIoFds = 6,
GetIrqInfo = 7,
SetIrqs = 8,
RegionRead = 9,
RegionWrite = 10,
DmaRead = 11,
DmaWrite = 12,
DeviceReset = 13,
UserDirtyPages = 14,
}
impl Default for Command {
fn default() -> Self {
Command::Unknown
}
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum HeaderFlags {
Command = 0,
Reply = 1,
NoReply = 1 << 4,
Error = 1 << 5,
}
impl Default for HeaderFlags {
fn default() -> Self {
HeaderFlags::Command
}
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct Header {
message_id: u16,
command: Command,
message_size: u32,
flags: u32,
error: u32,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct Version {
header: Header,
major: u16,
minor: u16,
}
#[derive(Serialize, Deserialize, Debug)]
struct MigrationCapabilities {
pgsize: u32,
}
const fn default_max_msg_fds() -> u32 {
1
}
const fn default_max_data_xfer_size() -> u32 {
1048576
}
const fn default_migration_capabilities() -> MigrationCapabilities {
MigrationCapabilities { pgsize: 4096 }
}
#[repr(u32)]
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
enum DmaMapFlags {
Unknown = 0,
ReadOnly = 1,
WriteOnly = 2,
ReadWrite = 3,
}
impl Default for DmaMapFlags {
fn default() -> Self {
Self::Unknown
}
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct DmaMap {
header: Header,
argsz: u32,
flags: DmaMapFlags,
offset: u64,
address: u64,
size: u64,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct DmaUnmap {
header: Header,
argsz: u32,
flags: u32,
address: u64,
size: u64,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct DeviceGetInfo {
header: Header,
argsz: u32,
flags: u32,
num_regions: u32,
num_irqs: u32,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct DeviceGetRegionInfo {
header: Header,
region_info: vfio_region_info,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct RegionAccess {
header: Header,
offset: u64,
region: u32,
count: u32,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct GetIrqInfo {
header: Header,
argsz: u32,
flags: u32,
index: u32,
count: u32,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct SetIrqs {
header: Header,
argsz: u32,
flags: u32,
index: u32,
start: u32,
count: u32,
}
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct DeviceReset {
header: Header,
}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for Header {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for Version {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for DmaMap {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for DmaUnmap {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for DeviceGetInfo {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for DeviceGetRegionInfo {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for RegionAccess {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for GetIrqInfo {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for SetIrqs {}
// SAFETY: data structure only contain a sereis of integers
unsafe impl ByteValued for DeviceReset {}
#[derive(Serialize, Deserialize, Debug)]
struct Capabilities {
#[serde(default = "default_max_msg_fds")]
max_msg_fds: u32,
#[serde(default = "default_max_data_xfer_size")]
max_data_xfer_size: u32,
#[serde(default = "default_migration_capabilities")]
migration: MigrationCapabilities,
}
impl Default for Capabilities {
fn default() -> Self {
Self {
max_msg_fds: default_max_msg_fds(),
max_data_xfer_size: default_max_data_xfer_size(),
migration: default_migration_capabilities(),
}
}
}
pub struct Client {
stream: UnixStream,
next_message_id: Wrapping<u16>,
num_irqs: u32,
resettable: bool,
regions: Vec<Region>,
}
#[derive(Debug)]
pub struct Region {
pub flags: u32,
pub index: u32,
pub size: u64,
pub file_offset: Option<FileOffset>,
pub sparse_areas: Vec<vfio_region_sparse_mmap_area>,
}
#[derive(Debug)]
pub struct IrqInfo {
pub index: u32,
pub flags: u32,
pub count: u32,
}
#[derive(Error, Debug)]
pub enum Error {
#[error("Error connecting: {0}")]
Connect(#[source] std::io::Error),
#[error("Error serializing capabilities: {0}")]
SerializeCapabilites(#[source] serde_json::Error),
#[error("Error deserializing capabilities: {0}")]
DeserializeCapabilites(#[source] serde_json::Error),
#[error("Error writing to stream: {0}")]
StreamWrite(#[source] std::io::Error),
#[error("Error reading from stream: {0}")]
StreamRead(#[source] std::io::Error),
#[error("Error shutting down stream: {0}")]
StreamShutdown(#[source] std::io::Error),
#[error("Error writing with file descriptors: {0}")]
SendWithFd(#[source] vmm_sys_util::errno::Error),
#[error("Error reading with file descriptors: {0}")]
ReceiveWithFd(#[source] vmm_sys_util::errno::Error),
#[error("Not a PCI device")]
NotPciDevice,
}
impl Client {
pub fn new(path: &Path) -> Result<Client, Error> {
let stream = UnixStream::connect(path).map_err(Error::Connect)?;
let mut client = Client {
next_message_id: Wrapping(0),
stream,
num_irqs: 0,
resettable: false,
regions: Vec::new(),
};
client.negotiate_version()?;
client.regions = client.get_regions()?;
Ok(client)
}
fn negotiate_version(&mut self) -> Result<(), Error> {
let caps = Capabilities::default();
let version_data = serde_json::to_string(&caps).map_err(Error::SerializeCapabilites)?;
let version = Version {
header: Header {
message_id: self.next_message_id.0,
command: Command::Version,
flags: HeaderFlags::Command as u32,
message_size: (size_of::<Version>() + version_data.len() + 1) as u32,
..Default::default()
},
major: 0,
minor: 1,
};
debug!("Command: {:?}", version);
let version_data = CString::new(version_data.as_bytes()).unwrap();
let bufs = vec![
IoSlice::new(version.as_slice()),
IoSlice::new(version_data.as_bytes_with_nul()),
];
// TODO: Use write_all_vectored() when ready
let _ = self
.stream
.write_vectored(&bufs)
.map_err(Error::StreamWrite)?;
debug!(
"Sent client version information: major = {} minor = {} capabilities = {:?}",
version.major, version.minor, &caps
);
self.next_message_id += Wrapping(1);
let mut server_version: Version = Version::default();
self.stream
.read_exact(server_version.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", server_version);
let mut server_version_data = Vec::new();
server_version_data.resize(
server_version.header.message_size as usize - size_of::<Version>(),
0,
);
self.stream
.read_exact(server_version_data.as_mut_slice())
.map_err(Error::StreamRead)?;
let server_caps: Capabilities =
serde_json::from_slice(&server_version_data[0..server_version_data.len() - 1])
.map_err(Error::DeserializeCapabilites)?;
debug!(
"Received server version information: major = {} minor = {} capabilities = {:?}",
server_version.major, server_version.minor, &server_caps
);
Ok(())
}
pub fn dma_map(
&mut self,
offset: u64,
address: u64,
size: u64,
fd: RawFd,
) -> Result<(), Error> {
let dma_map = DmaMap {
header: Header {
message_id: self.next_message_id.0,
command: Command::DmaMap,
flags: HeaderFlags::Command as u32,
message_size: size_of::<DmaMap>() as u32,
..Default::default()
},
argsz: (size_of::<DmaMap>() - size_of::<Header>()) as u32,
flags: DmaMapFlags::ReadWrite,
offset,
address,
size,
};
debug!("Command: {:?}", dma_map);
self.next_message_id += Wrapping(1);
self.stream
.send_with_fd(dma_map.as_slice(), fd)
.map_err(Error::SendWithFd)?;
let mut reply = Header::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(())
}
pub fn dma_unmap(&mut self, address: u64, size: u64) -> Result<(), Error> {
let dma_unmap = DmaUnmap {
header: Header {
message_id: self.next_message_id.0,
command: Command::DmaUnmap,
flags: HeaderFlags::Command as u32,
message_size: size_of::<DmaUnmap>() as u32,
..Default::default()
},
argsz: (size_of::<DmaUnmap>() - size_of::<Header>()) as u32,
flags: 0,
address,
size,
};
debug!("Command: {:?}", dma_unmap);
self.next_message_id += Wrapping(1);
self.stream
.write_all(dma_unmap.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = DmaUnmap::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(())
}
pub fn reset(&mut self) -> Result<(), Error> {
let reset = DeviceReset {
header: Header {
message_id: self.next_message_id.0,
command: Command::DeviceReset,
flags: HeaderFlags::Command as u32,
message_size: size_of::<DeviceReset>() as u32,
..Default::default()
},
};
debug!("Command: {:?}", reset);
self.next_message_id += Wrapping(1);
self.stream
.write_all(reset.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = Header::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(())
}
fn get_regions(&mut self) -> Result<Vec<Region>, Error> {
let get_info = DeviceGetInfo {
header: Header {
message_id: self.next_message_id.0,
command: Command::DeviceGetInfo,
flags: HeaderFlags::Command as u32,
message_size: size_of::<DeviceGetInfo>() as u32,
..Default::default()
},
argsz: size_of::<DeviceGetInfo>() as u32,
..Default::default()
};
debug!("Command: {:?}", get_info);
self.next_message_id += Wrapping(1);
self.stream
.write_all(get_info.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = DeviceGetInfo::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
self.num_irqs = reply.num_irqs;
if reply.flags & VFIO_DEVICE_FLAGS_PCI != VFIO_DEVICE_FLAGS_PCI {
return Err(Error::NotPciDevice);
}
self.resettable = reply.flags & VFIO_DEVICE_FLAGS_RESET != VFIO_DEVICE_FLAGS_RESET;
let num_regions = reply.num_regions;
let mut regions = Vec::new();
for index in 0..num_regions {
let (region_info, fd, sparse_areas) = self.get_region_info(index)?;
regions.push(Region {
flags: region_info.flags,
index: region_info.index,
size: region_info.size,
file_offset: fd.map(|fd| FileOffset::new(fd, region_info.offset)),
sparse_areas,
});
}
Ok(regions)
}
fn get_region_info(
&mut self,
index: u32,
) -> Result<
(
vfio_region_info,
Option<File>,
Vec<vfio_region_sparse_mmap_area>,
),
Error,
> {
// Retrieve the region info without capability
let mut get_region_info = DeviceGetRegionInfo {
header: Header {
message_id: self.next_message_id.0,
command: Command::DeviceGetRegionInfo,
flags: HeaderFlags::Command as u32,
message_size: std::mem::size_of::<DeviceGetRegionInfo>() as u32,
..Default::default()
},
region_info: vfio_region_info {
argsz: size_of::<vfio_region_info>() as u32,
index,
..Default::default()
},
};
debug!("Command: {:?}", get_region_info);
self.next_message_id += Wrapping(1);
self.stream
.write_all(get_region_info.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = DeviceGetRegionInfo::default();
let (_, fd) = self
.stream
.recv_with_fd(reply.as_mut_slice())
.map_err(Error::ReceiveWithFd)?;
debug!("Reply: {:?}", reply);
// Retrieve the region info again with capabilities if needed
if reply.region_info.argsz > std::mem::size_of::<vfio_region_info>() as u32 {
get_region_info.region_info.argsz = reply.region_info.argsz;
debug!("Command: {:?}", get_region_info);
self.next_message_id += Wrapping(1);
self.stream
.write_all(get_region_info.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = DeviceGetRegionInfo::default();
let (_, fd) = self
.stream
.recv_with_fd(reply.as_mut_slice())
.map_err(Error::ReceiveWithFd)?;
debug!("Reply: {:?}", reply);
let cap_size = reply.region_info.argsz - std::mem::size_of::<vfio_region_info>() as u32;
assert_eq!(
cap_size,
reply.header.message_size - size_of::<DeviceGetRegionInfo>() as u32
);
let mut cap_data = vec![0; cap_size as usize];
self.stream
.read_exact(cap_data.as_mut_slice())
.map_err(Error::StreamRead)?;
let sparse_areas = Self::parse_region_caps(&cap_data, &reply.region_info)?;
Ok((reply.region_info, fd, sparse_areas))
} else {
Ok((reply.region_info, fd, Vec::new()))
}
}
fn parse_region_caps(
cap_data: &[u8],
region_info: &vfio_region_info,
) -> Result<Vec<vfio_region_sparse_mmap_area>, Error> {
let mut sparse_areas: Vec<vfio_region_sparse_mmap_area> = Vec::new();
let cap_size = cap_data.len() as u32;
let cap_header_size = size_of::<vfio_info_cap_header>() as u32;
let mmap_cap_size = size_of::<vfio_region_info_cap_sparse_mmap>() as u32;
let mmap_area_size = size_of::<vfio_region_sparse_mmap_area>() as u32;
let cap_data_ptr = cap_data.as_ptr() as *const u8;
let mut region_info_offset = region_info.cap_offset;
while region_info_offset != 0 {
// calculate the offset from the begining of the cap_data based on the offset
// that is relative to the begining of the VFIO region info structure
let cap_offset = region_info_offset - size_of::<vfio_region_info>() as u32;
if cap_offset + cap_header_size > cap_size {
warn!(
"Unexpected end of cap data: 'cap_offset + cap_header_size > cap_size' \
cap_offset = {}, cap_header_size = {}, cap_size = {}",
cap_offset, cap_header_size, cap_size
);
break;
}
// SAFETY: `cap_data_ptr` is valid and the `cap_offset` is checked above
let cap_ptr = unsafe { cap_data_ptr.offset(cap_offset as isize) };
// SAFETY: `cap_ptr` is valid
let cap_header = unsafe { &*(cap_ptr as *const vfio_info_cap_header) };
match cap_header.id as u32 {
VFIO_REGION_INFO_CAP_SPARSE_MMAP => {
if cap_offset + mmap_cap_size > cap_size {
warn!(
"Unexpected end of cap data: 'cap_offset + mmap_cap_size > cap_size' \
cap_offset = {}, mmap_cap_size = {}, cap_size = {}",
cap_offset, mmap_cap_size, cap_size
);
break;
}
// SAFETY: `cap_ptr` is valid and its size is also checked above
let sparse_mmap = unsafe {
&*(cap_ptr as *mut u8 as *const vfio_region_info_cap_sparse_mmap)
};
let area_num = sparse_mmap.nr_areas;
if cap_offset + mmap_cap_size + area_num * mmap_area_size > cap_size {
warn!("Unexpected end of cap data: 'cap_offset + mmap_cap_size + area_num * mmap_area_size > cap_size' \
cap_offset = {}, mmap_cap_size = {}, area_num = {}, mmap_area_size = {}, cap_size = {}",
cap_offset, mmap_cap_size, area_num, mmap_area_size, cap_size);
break;
}
let areas =
// SAFETY: `sparse_mmap` is valid and its size is also checked above
unsafe { sparse_mmap.areas.as_slice(sparse_mmap.nr_areas as usize) };
for area in areas.iter() {
sparse_areas.push(*area);
}
}
_ => {
warn!(
"Ignoring unsupported vfio region capability (id = '{}')",
cap_header.id
);
}
}
region_info_offset = cap_header.next;
}
Ok(sparse_areas)
}
pub fn region_read(&mut self, region: u32, offset: u64, data: &mut [u8]) -> Result<(), Error> {
let region_read = RegionAccess {
header: Header {
message_id: self.next_message_id.0,
command: Command::RegionRead,
flags: HeaderFlags::Command as u32,
message_size: size_of::<RegionAccess>() as u32,
..Default::default()
},
offset,
count: data.len() as u32,
region,
};
debug!("Command: {:?}", region_read);
self.next_message_id += Wrapping(1);
self.stream
.write_all(region_read.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = RegionAccess::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
self.stream.read_exact(data).map_err(Error::StreamRead)?;
Ok(())
}
pub fn region_write(&mut self, region: u32, offset: u64, data: &[u8]) -> Result<(), Error> {
let region_write = RegionAccess {
header: Header {
message_id: self.next_message_id.0,
command: Command::RegionWrite,
flags: HeaderFlags::Command as u32,
message_size: (size_of::<RegionAccess>() + data.len()) as u32,
..Default::default()
},
offset,
count: data.len() as u32,
region,
};
debug!("Command: {:?}", region_write);
self.next_message_id += Wrapping(1);
let bufs = vec![IoSlice::new(region_write.as_slice()), IoSlice::new(data)];
// TODO: Use write_all_vectored() when ready
let _ = self
.stream
.write_vectored(&bufs)
.map_err(Error::StreamWrite)?;
let mut reply = RegionAccess::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(())
}
pub fn get_irq_info(&mut self, index: u32) -> Result<IrqInfo, Error> {
let get_irq_info = GetIrqInfo {
header: Header {
message_id: self.next_message_id.0,
command: Command::GetIrqInfo,
flags: HeaderFlags::Command as u32,
message_size: size_of::<GetIrqInfo>() as u32,
..Default::default()
},
argsz: (size_of::<GetIrqInfo>() - size_of::<Header>()) as u32,
flags: 0,
index,
count: 0,
};
debug!("Command: {:?}", get_irq_info);
self.next_message_id += Wrapping(1);
self.stream
.write_all(get_irq_info.as_slice())
.map_err(Error::StreamWrite)?;
let mut reply = GetIrqInfo::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(IrqInfo {
index: reply.index,
flags: reply.flags,
count: reply.count,
})
}
pub fn set_irqs(
&mut self,
index: u32,
flags: u32,
start: u32,
count: u32,
fds: &[RawFd],
) -> Result<(), Error> {
let set_irqs = SetIrqs {
header: Header {
message_id: self.next_message_id.0,
command: Command::SetIrqs,
flags: HeaderFlags::Command as u32,
message_size: size_of::<SetIrqs>() as u32,
..Default::default()
},
argsz: (size_of::<SetIrqs>() - size_of::<Header>()) as u32,
flags,
start,
index,
count,
};
debug!("Command: {:?}", set_irqs);
self.next_message_id += Wrapping(1);
self.stream
.send_with_fds(&[set_irqs.as_slice()], fds)
.map_err(Error::SendWithFd)?;
let mut reply = Header::default();
self.stream
.read_exact(reply.as_mut_slice())
.map_err(Error::StreamRead)?;
debug!("Reply: {:?}", reply);
Ok(())
}
pub fn region(&self, region_index: u32) -> Option<&Region> {
self.regions
.iter()
.find(|&region| region.index == region_index)
}
pub fn resettable(&self) -> bool {
self.resettable
}
pub fn shutdown(&self) -> Result<(), Error> {
self.stream
.shutdown(std::net::Shutdown::Both)
.map_err(Error::StreamShutdown)
}
}

View File

@@ -11,5 +11,5 @@ crc32c = "0.6.3"
libc = "0.2.139"
log = "0.4.17"
remain = "0.2.6"
thiserror = "1.0.38"
uuid = { version = "1.2.2", features = ["v4"] }
thiserror = "1.0.39"
uuid = { version = "1.3.0", features = ["v4"] }

View File

@@ -145,11 +145,7 @@ impl DiskSpec {
let bits = f
.read_u32::<LittleEndian>()
.map_err(VhdxMetadataError::ReadMetadata)?;
if bits & BLOCK_HAS_PARENT != 0 {
disk_spec.has_parent = true;
} else {
disk_spec.has_parent = false;
}
disk_spec.has_parent = bits & BLOCK_HAS_PARENT != 0;
metadata_presence |= METADATA_FILE_PARAMETER_PRESENT;
} else if metadata_entry.item_id

View File

@@ -3,10 +3,11 @@ name = "vhost_user_block"
version = "0.1.0"
authors = ["The Cloud Hypervisor Authors"]
edition = "2021"
build = "../build.rs"
[dependencies]
argh = "0.1.9"
block_util = { path = "../block_util" }
clap = { version = "4.0.32", features = ["wrap_help"] }
env_logger = "0.10.0"
epoll = "4.3.1"
libc = "0.2.139"
@@ -15,8 +16,8 @@ option_parser = { path = "../option_parser" }
qcow = { path = "../qcow" }
vhost = { version = "0.6.0", features = ["vhost-user-slave"] }
vhost-user-backend = "0.8.0"
virtio-bindings = "0.1.0"
virtio-queue = "0.7.0"
virtio-bindings = "0.2.0"
virtio-queue = "0.7.1"
vm-memory = "0.10.0"
vmm-sys-util = "0.11.0"

View File

@@ -31,8 +31,9 @@ use std::{convert, error, fmt, io};
use vhost::vhost_user::message::*;
use vhost::vhost_user::Listener;
use vhost_user_backend::{VhostUserBackendMut, VhostUserDaemon, VringRwLock, VringState, VringT};
use virtio_bindings::bindings::virtio_blk::*;
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use virtio_bindings::virtio_blk::*;
use virtio_bindings::virtio_config::VIRTIO_F_VERSION_1;
use virtio_bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use virtio_queue::QueueT;
use vm_memory::GuestAddressSpace;
use vm_memory::{bitmap::AtomicBitmap, ByteValued, Bytes, GuestMemoryAtomic};
@@ -70,11 +71,6 @@ enum Error {
SocketParameterMissing,
}
pub const SYNTAX: &str = "vhost-user-block backend parameters \
\"path=<image_path>,socket=<socket_path>,num_queues=<number_of_queues>,\
queue_size=<size_of_each_queue>,readonly=true|false,direct=true|false,\
poll_queue=true|false\"";
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "vhost_user_block_error: {self:?}")

View File

@@ -10,25 +10,36 @@
extern crate vhost_user_block;
use clap::{Arg, Command};
use argh::FromArgs;
use vhost_user_block::start_block_backend;
#[derive(FromArgs)]
/// Launch a vhost-user-blk backend.
struct TopLevel {
#[argh(option, long = "block-backend")]
/// vhost-user-block backend parameters
/// path=<image_path>,socket=<socket_path>,num_queues=<number_of_queues>,queue_size=<size_of_each_queue>,readonly=true|false,direct=true|false,poll_queue=true|false
backend_command: Option<String>,
#[argh(switch, short = 'V', long = "version")]
/// print version information
version: bool,
}
fn main() {
env_logger::init();
let cmd_arguments = Command::new("vhost-user-blk backend")
.version(env!("CARGO_PKG_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
.about("Launch a vhost-user-blk backend.")
.arg(
Arg::new("block-backend")
.long("block-backend")
.help(vhost_user_block::SYNTAX)
.num_args(1)
.required(true),
)
.get_matches();
let toplevel: TopLevel = argh::from_env();
let backend_command = cmd_arguments.get_one::<String>("block-backend").unwrap();
start_block_backend(backend_command);
if toplevel.version {
println!("{} {}", env!("CARGO_BIN_NAME"), env!("BUILT_VERSION"));
return;
}
if toplevel.backend_command.is_none() {
println!("Please specify --block-backend");
std::process::exit(1)
}
start_block_backend(&toplevel.backend_command.unwrap());
}

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